DONT_MIGRATE set more carefully
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 5 Oct 2011 22:28:00 +0000 (15:28 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:36:08 +0000 (17:36 -0700)
It's held the entire time throughout an mcs_notif_safe lock, since it
doesn't make sense to migrate or otherwise try to restart/run that
thread (could be holding the lock, etc).

Also, after turning off DONT_MIGRATE, you need to check messages (which
enable_notifs() does).  This isn't critical right now, but future
patches will require it.  It's harmless to turn them on before
enable_notif(), since the protection it provides is in the process of
disabling notifs.  Once that is done, you won't get migrated anyways.

Finally, this makes sure we only do the DONT_MIGRATE / notif_disabling
business if we're in _M mode.  This wasn't pairing properly, and we were
getting our thread0 set with DONT_MIGRATE the first time it ran.

user/parlib/mcs.c
user/parlib/uthread.c

index d06e361..ae4d23a 100644 (file)
@@ -62,29 +62,27 @@ void mcs_lock_unlock(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()) {
+       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());
-               cmb();  /* don't issue the flag write before the disable */
-               if (current_uthread)
-                       current_uthread->flags &= ~UTHREAD_DONT_MIGRATE;
        }
        mcs_lock_lock(lock, qnode);
 }
 
+/* Note we turn off the DONT_MIGRATE flag before enabling notifs.  This is fine,
+ * since we wouldn't receive any notifs that could lead to us migrating after we
+ * set DONT_MIGRATE but before enable_notifs().  We need it to be in this order,
+ * since we need to check messages after ~DONT_MIGRATE. */
 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 issue the flag write before the vcore_id() read */
-               enable_notifs(vcore_id());
-               cmb();  /* don't issue the flag write before the enable */
-               if (current_uthread)
                        current_uthread->flags &= ~UTHREAD_DONT_MIGRATE;
+               cmb();  /* don't enable before ~DONT_MIGRATE */
+               enable_notifs(vcore_id());
        }
 }
 
index 6d93793..821ca9f 100644 (file)
@@ -114,10 +114,10 @@ void uthread_init(struct uthread *new_thread)
        set_tls_desc(caller->tls_desc, vcoreid);
        /* Okay to migrate now, and enable interrupts/notifs.  This could be called
         * from vcore context, so only enable if we're in _M and in vcore context. */
+       caller->flags &= ~UTHREAD_DONT_MIGRATE;         /* turn this on first */
        if (!in_vcore_context() && in_multi_mode())
                enable_notifs(vcoreid);
        cmb();  /* issue this write after we're done with vcoreid */
-       caller->flags &= ~UTHREAD_DONT_MIGRATE;
 }
 
 void uthread_runnable(struct uthread *uthread)