parlib: Don't double-lock a mutex to sleep
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 20 Jan 2017 22:08:46 +0000 (17:08 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 20 Jan 2017 22:08:46 +0000 (17:08 -0500)
Yes, double-locking mutexes will normally sleep forever, but it's a little
hacky.  Especially considering how the thread0 scheduler doesn't currently
use mutexes!  Other schedulers / frameworks might treat locking a locked
mutex as a bug too.

Yes!  This means that any app using uthread_sleep_forever() that was using
the thread0 scheduler (e.g. daemonize) would always return immediately.  In
fact, daemonize probably never worked, unless it happened to have pthreads
or something linked in.  That's responsible for two things: /net/ndb wasn't
written before we moved past ipconfig in the ifconfig script, and
occasionally you'd get an "Unable to open cs" complaint from srv.
daemonize was returning early.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
user/parlib/include/parlib/uthread.h
user/parlib/uthread.c

index baff2b1..3390a88 100644 (file)
@@ -98,7 +98,7 @@ void uthread_yield(bool save_state, void (*yield_func)(struct uthread*, void*),
                    void *yield_arg);
 void uthread_sleep(unsigned int seconds);
 void uthread_usleep(unsigned int usecs);
-void uthread_sleep_forever(void);
+void __attribute__((noreturn)) uthread_sleep_forever(void);
 void uthread_has_blocked(struct uthread *uthread, int flags);
 void uthread_paused(struct uthread *uthread);
 
index 74de3d8..1cacdee 100644 (file)
@@ -479,12 +479,15 @@ void uthread_usleep(unsigned int usecs)
        sys_block(usecs);       /* usec sleep */
 }
 
-void uthread_sleep_forever(void)
+static void __sleep_forever_cb(struct uthread *uth, void *arg)
 {
-       uth_mutex_t mtx = uth_mutex_alloc();
+       uthread_has_blocked(uth, UTH_EXT_BLK_JUSTICE);
+}
 
-       uth_mutex_lock(mtx);
-       uth_mutex_lock(mtx);
+void __attribute__((noreturn)) uthread_sleep_forever(void)
+{
+       uthread_yield(FALSE, __sleep_forever_cb, NULL);
+       assert(0);
 }
 
 /* Cleans up the uthread (the stuff we did in uthread_init()).  If you want to