Cleans up vcore/uth/pth init code
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 20 Dec 2012 02:37:56 +0000 (18:37 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 20 Dec 2012 02:37:56 +0000 (18:37 -0800)
All init routines fail loudly, instead of passing values back where we
just assert or printf profanities.

Some of the code can be called from a few places - some for testing
reasons (pth), and others for todo-reasons (vcore, in case we have a
separate vc slim init).

tests/eth_audio.c
tests/msr_get_cores.c
tests/msr_get_singlecore.c
user/c3po/threads/vcore.c
user/parlib/include/uthread.h
user/parlib/include/vcore.h
user/parlib/uthread.c
user/parlib/vcore.c
user/pthread/pthread.c
user/pthread/pthread.h

index 7e74b1c..977edbf 100644 (file)
@@ -51,8 +51,7 @@ int main()
        //strncpy(out_buf, "Nanwan loves you!\n", 19);
 
 /* begin: stuff userspace needs to do before switching to multi-mode */
-       if (vcore_init())
-               printf("vcore_init() failed, we're fucked!\n");
+       vcore_init();
 
        /* ETHAUD Turn on Free apple pie (which is the network packet) */
        enable_kevent(EV_FREE_APPLE_PIE, 0, EVENT_IPI);
index e9fc88c..62b564b 100644 (file)
@@ -41,8 +41,7 @@ int main(int argc, char** argv)
        mcs_barrier_init(&b, max_vcores());
 
 /* begin: stuff userspace needs to do before switching to multi-mode */
-       if (vcore_init())
-               printf("vcore_init() failed, we're fucked!\n");
+       vcore_init();
        #if 0
        /* tell the kernel where and how we want to receive notifications */
        struct notif_method *nm;
index e15f0f6..a998c0f 100644 (file)
@@ -34,8 +34,7 @@ int main(int argc, char** argv)
        mcs_barrier_init(&b, max_vcores());
 
 /* begin: stuff userspace needs to do before switching to multi-mode */
-       if (vcore_init())
-               printf("vcore_init() failed, we're fucked!\n");
+       vcore_init();
        #if 0
        /* tell the kernel where and how we want to receive notifications */
        struct notif_method *nm;
index 48524f5..eba3604 100644 (file)
@@ -68,8 +68,7 @@ void __attribute__ ((constructor)) ctors()
 void vcore_startup()
 {
        /* Initilize the bootstrap code for using the vcores */
-       if (vcore_init())
-               printf("vcore_init() failed, we're fucked!\n");
+       vcore_init();
        assert(vcore_id() == 0);
 
        /* Tell the kernel where and how we want to receive events.  This is just an
index 6ec9d07..3c26e3d 100644 (file)
@@ -48,7 +48,7 @@ extern struct schedule_ops *sched_ops;
 
 /* Call this, passing it a uthread representing thread0, from your 2LS init
  * routines.  When it returns, you're in _M mode (thread0 on vcore0) */
-int uthread_lib_init(struct uthread *uthread);
+void uthread_lib_init(struct uthread *uthread);
 
 /* Functions to make/manage uthreads.  Can be called by functions such as
  * pthread_create(), which can wrap these with their own stuff (like attrs,
index ccc8a57..d906de2 100644 (file)
@@ -50,7 +50,7 @@ static inline bool vcore_is_preempted(uint32_t vcoreid);
 static inline struct preempt_data *vcpd_of(uint32_t vcoreid);
 static inline bool preempt_is_pending(uint32_t vcoreid);
 static inline bool __preempt_is_pending(uint32_t vcoreid);
-int vcore_init(void);
+void vcore_init(void);
 void vcore_event_init(void);
 void vcore_change_to_m(void);
 int vcore_request(long nr_new_vcores);
index f702c53..c7bac00 100644 (file)
@@ -60,15 +60,10 @@ static void uthread_manage_thread0(struct uthread *uthread)
 
 /* The real 2LS calls this, passing in a uthread representing thread0.  When it
  * returns, you're in _M mode, still running thread0, on vcore0 */
-int uthread_lib_init(struct uthread *uthread)
-{
-       /* Make sure this only initializes once */
-       static bool initialized = FALSE;
-       if (initialized)
-               return 0;
-       initialized = TRUE;
-       /* Init the vcore system */
-       assert(!vcore_init());
+void uthread_lib_init(struct uthread *uthread)
+{
+       init_once(return);
+       vcore_init();
        uthread_manage_thread0(uthread);
        /* Receive preemption events.  Note that this merely tells the kernel how to
         * send the messages, and does not necessarily provide storage space for the
@@ -90,7 +85,6 @@ int uthread_lib_init(struct uthread *uthread)
               preempt_ev_q, preempt_ev_q->ev_flags);
        /* Get ourselves into _M mode.  Could consider doing this elsewhere... */
        vcore_change_to_m();
-       return 0;
 }
 
 /* Helper: tells the kernel our SCP is capable of going into vcore context on
@@ -126,8 +120,8 @@ void uthread_slim_init(void)
 {
        struct uthread *uthread = malloc(sizeof(*uthread));
        struct event_queue *posix_sig_ev_q;
-       /* TODO: consider a vcore_init_vc0 call.  Init the vcore system */
-       assert(!vcore_init());
+       /* TODO: consider a vcore_init_vc0 call. */
+       vcore_init();
        uthread_manage_thread0(uthread);
        scp_vcctx_ready();
        /* Register an ev_q for posix signals */
index 5354ae7..0440852 100644 (file)
@@ -20,6 +20,7 @@ atomic_t nr_new_vcores_wanted;
 atomic_t vc_req_being_handled;
 
 extern void** vcore_thread_control_blocks;
+bool vc_initialized = FALSE;
 __thread struct syscall __vcore_one_sysc = {.flags = (atomic_t)SC_DONE, 0};
 
 /* TODO: probably don't want to dealloc.  Considering caching */
@@ -73,14 +74,11 @@ static int allocate_transition_stack(int id)
        return 0;
 }
 
-int vcore_init()
+void vcore_init(void)
 {
-       static int initialized = 0;
        uintptr_t mmap_block;
-       /* Note this is racy, but okay.  The only time it'll be 0 is the first time
-        * through, when we are _S */
-       if(initialized)
-               return 0;
+       /* Note this is racy, but okay.  The first time through, we are _S */
+       init_once(return);
 
        vcore_thread_control_blocks = (void**)calloc(max_vcores(),sizeof(void*));
 
@@ -114,16 +112,15 @@ int vcore_init()
        }
        atomic_init(&vc_req_being_handled, 0);
        assert(!in_vcore_context());
-       initialized = 1;
        /* no longer need to enable notifs on vcore 0, it is set like that by
         * default (so you drop into vcore context immediately on transtioning to
         * _M) */
-       return 0;
+       vc_initialized = TRUE;
+       return;
 vcore_init_tls_fail:
        free(vcore_thread_control_blocks);
 vcore_init_fail:
-       errno = ENOMEM;
-       return -1;
+       assert(0);
 }
 
 /* This gets called in glibc before calling the programs 'main'.  Need to set
@@ -199,8 +196,7 @@ int vcore_request(long nr_new_vcores)
 {
        long nr_to_prep_now, nr_vcores_wanted;
 
-       if (vcore_init() < 0)
-               return -1;      /* consider ERRNO */
+       assert(vc_initialized);
        /* Early sanity checks */
        if ((nr_new_vcores < 0) || (nr_new_vcores + num_vcores() > max_vcores()))
                return -1;      /* consider ERRNO */
index a488727..20c0cfc 100644 (file)
@@ -322,14 +322,14 @@ int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
 
 /* Do whatever init you want.  At some point call uthread_lib_init() and pass it
  * a uthread representing thread0 (int main()) */
-int pthread_lib_init(void)
+void pthread_lib_init(void)
 {
-       /* Make sure this only initializes once */
-       static bool initialized = FALSE;
-       if (initialized)
-               return 0;
-       initialized = TRUE;
        uintptr_t mmap_block;
+       /* Some testing code might call this more than once (once for a slimmed down
+        * pth 2LS, and another from pthread_create().  Also, this is racy, but the
+        * first time through we are an SCP. */
+       init_once(return);
+       assert(!in_multi_mode());
        mcs_pdr_init(&queue_lock);
        /* Create a pthread_tcb for the main thread */
        pthread_t t = (pthread_t)calloc(1, sizeof(struct pthread_tcb));
@@ -397,21 +397,18 @@ int pthread_lib_init(void)
 #endif
        /* Initialize the uthread code (we're in _M mode after this).  Doing this
         * last so that all the event stuff is ready when we're in _M mode.  Not a
-        * big deal one way or the other.  Note that vcore_init() hasn't happened
-        * yet, so if a 2LS somehow wants to have its init stuff use things like
-        * vcore stacks or TLSs, we'll need to change this. */
-       assert(!uthread_lib_init((struct uthread*)t));
-       return 0;
+        * big deal one way or the other.  Note that vcore_init() probably has
+        * happened, but don't rely on this.  Careful if your 2LS somehow wants to
+        * have its init stuff use things like vcore stacks or TLSs, we'll need to
+        * change this. */
+       uthread_lib_init((struct uthread*)t);
 }
 
 int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                    void *(*start_routine)(void *), void *arg)
 {
-       static bool first = TRUE;
-       if (first) {
-               assert(!pthread_lib_init());
-               first = FALSE;
-       }
+       /* Racy, but the first time through we are an SCP */
+       run_once(pthread_lib_init());
        /* Create the actual thread */
        struct pthread_tcb *pthread;
        pthread = (pthread_t)calloc(1, sizeof(struct pthread_tcb));
index bfdd216..73b4462 100644 (file)
@@ -127,7 +127,7 @@ typedef dtls_key_t pthread_key_t;
 
 /* Akaros pthread extensions / hacks */
 void pthread_can_vcore_request(bool can);      /* default is TRUE */
-int pthread_lib_init(void);
+void pthread_lib_init(void);
 
 /* The pthreads API */
 int pthread_attr_init(pthread_attr_t *);