Uthread helpers for disabling notifs
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 11 Oct 2011 00:40:36 +0000 (17:40 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:36:08 +0000 (17:36 -0700)
The DONT_MIGRATE bit is tricky, and that code is about to get repeated a
lot, so it makes sense to have a helper.  Other code might be able to
use this, though I left them as is.  uthread_init() seems clear as is,
and might be getting mucked with in a concurrent patch set.

user/parlib/include/uthread.h
user/parlib/mcs.c
user/parlib/uthread.c

index f5e367f..5d30d56 100644 (file)
@@ -57,8 +57,10 @@ void uthread_yield(bool save_state);
 /* Block the calling uthread on sysc until it makes progress or is done */
 void ros_syscall_blockon(struct syscall *sysc);
 
-/* Utility function.  Event code also calls this. */
+/* Utility functions */
 bool check_preempt_pending(uint32_t vcoreid);
+void uth_disable_notifs(void);
+void uth_enable_notifs(void);
 
 bool register_evq(struct syscall *sysc, struct event_queue *ev_q);
 void deregister_evq(struct syscall *sysc);
index 99a3865..6a961f7 100644 (file)
@@ -104,12 +104,7 @@ void mcs_lock_unlock_cas(struct mcs_lock *lock, struct mcs_lock_qnode *qnode)
  * (when switching into the TLS, etc). */
 void mcs_lock_notifsafe(struct mcs_lock *lock, struct mcs_lock_qnode *qnode)
 {
-       if (!in_vcore_context() && in_multi_mode()) {
-               if (current_uthread)
-                       current_uthread->flags |= UTHREAD_DONT_MIGRATE;
-               cmb();  /* don't issue the flag write before the vcore_id() read */
-               disable_notifs(vcore_id());
-       }
+       uth_disable_notifs();
        mcs_lock_lock(lock, qnode);
 }
 
@@ -120,12 +115,7 @@ void mcs_lock_notifsafe(struct mcs_lock *lock, struct mcs_lock_qnode *qnode)
 void mcs_unlock_notifsafe(struct mcs_lock *lock, struct mcs_lock_qnode *qnode)
 {
        mcs_lock_unlock(lock, qnode);
-       if (!in_vcore_context() && in_multi_mode()) {
-               if (current_uthread)
-                       current_uthread->flags &= ~UTHREAD_DONT_MIGRATE;
-               cmb();  /* don't enable before ~DONT_MIGRATE */
-               enable_notifs(vcore_id());
-       }
+       uth_enable_notifs();
 }
 
 // MCS dissemination barrier!
index fd47485..22222bd 100644 (file)
@@ -333,6 +333,30 @@ bool check_preempt_pending(uint32_t vcoreid)
        return retval;
 }
 
+/* Helper: This is a safe way for code to disable notifs if it *might* be called
+ * from uthread context (like from a notif_safe lock).  Pair this with
+ * uth_enable_notifs() unless you know what you're doing. */
+void uth_disable_notifs(void)
+{
+       if (!in_vcore_context() && in_multi_mode()) {
+               if (current_uthread)
+                       current_uthread->flags |= UTHREAD_DONT_MIGRATE;
+               cmb();  /* don't issue the flag write before the vcore_id() read */
+               disable_notifs(vcore_id());
+       }
+}
+
+/* Helper: Pair this with uth_disable_notifs(). */
+void uth_enable_notifs(void)
+{
+       if (!in_vcore_context() && in_multi_mode()) {
+               if (current_uthread)
+                       current_uthread->flags &= ~UTHREAD_DONT_MIGRATE;
+               cmb();  /* don't enable before ~DONT_MIGRATE */
+               enable_notifs(vcore_id());
+       }
+}
+
 /* Attempts to register ev_q with sysc, so long as sysc is not done/progress.
  * Returns true if it succeeded, and false otherwise.  False means that the
  * syscall is done, and does not need an event set (and should be handled