parlib: Add __uth_sync_swap and __uth_sync_is_empty
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 28 Apr 2017 16:14:19 +0000 (12:14 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 3 May 2017 16:16:41 +0000 (12:16 -0400)
These are helper methods, useful for bulk wakeups.

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 8ce3e20..6b54c4a 100644 (file)
@@ -95,6 +95,8 @@ void __uth_sync_destroy(uth_sync_t *sync);
 void __uth_sync_enqueue(struct uthread *uth, uth_sync_t *sync);
 struct uthread *__uth_sync_get_next(uth_sync_t *sync);
 bool __uth_sync_get_uth(uth_sync_t *sync, struct uthread *uth);
+void __uth_sync_swap(uth_sync_t *a, uth_sync_t *b);
+bool __uth_sync_is_empty(uth_sync_t *sync);
 
 /* 2L-Scheduler operations.  Examples in pthread.c. */
 struct schedule_ops {
@@ -114,6 +116,8 @@ struct schedule_ops {
        void (*sync_enqueue)(struct uthread *, uth_sync_t *);
        struct uthread *(*sync_get_next)(uth_sync_t *);
        bool (*sync_get_uth)(uth_sync_t *, struct uthread *);
+       void (*sync_swap)(uth_sync_t *, uth_sync_t *);
+       bool (*sync_is_empty)(uth_sync_t *);
        void (*preempt_pending)(void);
 };
 extern struct schedule_ops *sched_ops;
index a9a3bb6..ca7ed3b 100644 (file)
@@ -784,6 +784,21 @@ static bool uth_default_sync_get_uth(uth_sync_t *sync, struct uthread *uth)
        return FALSE;
 }
 
+static void uth_default_sync_swap(uth_sync_t *a, uth_sync_t *b)
+{
+       struct uth_tailq *tq_a = (struct uth_tailq*)a;
+       struct uth_tailq *tq_b = (struct uth_tailq*)b;
+
+       TAILQ_SWAP(tq_a, tq_b, uthread, sync_next);
+}
+
+static bool uth_default_sync_is_empty(uth_sync_t *sync)
+{
+       struct uth_tailq *tq = (struct uth_tailq*)sync;
+
+       return TAILQ_EMPTY(tq);
+}
+
 /************** External uthread sync interface **************/
 
 /* Called by 2LS-independent sync code when a sync object needs initialized. */
@@ -832,3 +847,21 @@ bool __uth_sync_get_uth(uth_sync_t *sync, struct uthread *uth)
                return sched_ops->sync_get_uth(sync, uth);
        return uth_default_sync_get_uth(sync, uth);
 }
+
+/* Called by 2LS-independent sync code to swap members of sync objects. */
+void __uth_sync_swap(uth_sync_t *a, uth_sync_t *b)
+{
+       if (sched_ops->sync_swap) {
+               sched_ops->sync_swap(a, b);
+               return;
+       }
+       uth_default_sync_swap(a, b);
+}
+
+/* Called by 2LS-independent sync code */
+bool __uth_sync_is_empty(uth_sync_t *sync)
+{
+       if (sched_ops->sync_is_empty)
+               return sched_ops->sync_is_empty(sync);
+       return uth_default_sync_is_empty(sync);
+}
index 5c7e97d..e43f770 100644 (file)
@@ -31,6 +31,8 @@ static void thread0_sync_destroy(uth_sync_t *s);
 static void thread0_sync_enqueue(struct uthread *uth, uth_sync_t *s);
 static struct uthread *thread0_sync_get_next(uth_sync_t *s);
 static bool thread0_sync_get_uth(uth_sync_t *s, struct uthread *uth);
+static void thread0_sync_swap(uth_sync_t *a, uth_sync_t *b);
+static bool thread0_sync_is_empty(uth_sync_t *s);
 
 /* externed into uthread.c */
 struct schedule_ops thread0_2ls_ops = {
@@ -48,6 +50,8 @@ struct schedule_ops thread0_2ls_ops = {
        .sync_enqueue = thread0_sync_enqueue,
        .sync_get_next = thread0_sync_get_next,
        .sync_get_uth = thread0_sync_get_uth,
+       .sync_swap = thread0_sync_swap,
+       .sync_is_empty = thread0_sync_is_empty,
 };
 
 struct schedule_ops *sched_ops __attribute__((weak)) = &thread0_2ls_ops;
@@ -209,3 +213,12 @@ static bool thread0_sync_get_uth(uth_sync_t *s, struct uthread *uth)
        }
        return FALSE;
 }
+
+static void thread0_sync_swap(uth_sync_t *a, uth_sync_t *b)
+{
+}
+
+static bool thread0_sync_is_empty(uth_sync_t *s)
+{
+       return !thread0_info.is_blocked;
+}