parlib: Add trylock to uthread mutexes
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 6 Mar 2017 20:14:50 +0000 (15:14 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 3 May 2017 16:13:02 +0000 (12:13 -0400)
GCC needs this, and other people might too.

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

index 5cf1b06..3d1679b 100644 (file)
@@ -61,6 +61,7 @@ struct schedule_ops {
        uth_mutex_t (*mutex_alloc)(void);
        void (*mutex_free)(uth_mutex_t);
        void (*mutex_lock)(uth_mutex_t);
+       bool (*mutex_trylock)(uth_mutex_t);
        void (*mutex_unlock)(uth_mutex_t);
        uth_cond_var_t (*cond_var_alloc)(void);
        void (*cond_var_free)(uth_cond_var_t);
@@ -159,6 +160,7 @@ static inline struct user_context *get_cur_uth_ctx(void)
 uth_mutex_t uth_mutex_alloc(void);
 void uth_mutex_free(uth_mutex_t m);
 void uth_mutex_lock(uth_mutex_t m);
+bool uth_mutex_trylock(uth_mutex_t m);
 void uth_mutex_unlock(uth_mutex_t m);
 
 /* Generic Uthread Condition Variables.  2LSs can implement their own methods.
index c293197..891a567 100644 (file)
@@ -95,6 +95,19 @@ static void uth_default_mtx_lock(struct uth_default_mtx *mtx)
        uthread_yield(TRUE, __mutex_cb, &link);
 }
 
+static bool uth_default_mtx_trylock(struct uth_default_mtx *mtx)
+{
+       bool ret = FALSE;
+
+       spin_pdr_lock(&mtx->lock);
+       if (!mtx->locked) {
+               mtx->locked = TRUE;
+               ret = TRUE;
+       }
+       spin_pdr_unlock(&mtx->lock);
+       return ret;
+}
+
 static void uth_default_mtx_unlock(struct uth_default_mtx *mtx)
 {
        struct uth_mtx_link *first;
@@ -139,6 +152,13 @@ void uth_mutex_lock(uth_mutex_t m)
        uth_default_mtx_lock((struct uth_default_mtx*)m);
 }
 
+bool uth_mutex_trylock(uth_mutex_t m)
+{
+       if (sched_ops->mutex_trylock)
+               return sched_ops->mutex_trylock(m);
+       return uth_default_mtx_trylock((struct uth_default_mtx*)m);
+}
+
 void uth_mutex_unlock(uth_mutex_t m)
 {
        if (sched_ops->mutex_unlock) {
index b5b2d84..4367d9e 100644 (file)
@@ -25,6 +25,7 @@ static void thread0_thread_has_blocked(struct uthread *uth, int flags);
 static uth_mutex_t thread0_mtx_alloc(void);
 static void thread0_mtx_free(uth_mutex_t m);
 static void thread0_mtx_lock(uth_mutex_t m);
+static bool thread0_mtx_trylock(uth_mutex_t m);
 static void thread0_mtx_unlock(uth_mutex_t m);
 
 /* externed into uthread.c */
@@ -38,6 +39,7 @@ struct schedule_ops thread0_2ls_ops = {
        .mutex_alloc = thread0_mtx_alloc,
        .mutex_free = thread0_mtx_free,
        .mutex_lock = thread0_mtx_lock,
+       .mutex_trylock = thread0_mtx_trylock,
        .mutex_unlock = thread0_mtx_unlock,
 };
 
@@ -172,6 +174,16 @@ static void thread0_mtx_lock(uth_mutex_t m)
        *mtx = TRUE;
 }
 
+static bool thread0_mtx_trylock(uth_mutex_t m)
+{
+       bool *mtx = (bool*)m;
+
+       if (*mtx)
+               return FALSE;
+       *mtx = TRUE;
+       return TRUE;
+}
+
 static void thread0_mtx_unlock(uth_mutex_t m)
 {
        bool *mtx = (bool*)m;