Uses vcore_yield() for the preempt_pending path
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 12 Sep 2011 21:21:03 +0000 (14:21 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:36:06 +0000 (17:36 -0700)
I'm considering getting rid of the preemption pending business
completely, and just dealing with it afterwards.  But so long as we have
it, we need to make it work so that we don't lose INDIR messages by
yielding without checking events, etc.

user/c3po/threads/threadlib.c
user/parlib/include/vcore.h
user/parlib/uthread.c
user/parlib/vcore.c
user/pthread/pthread.c

index cb633bd..b10f3e8 100644 (file)
@@ -362,7 +362,7 @@ void run_next_thread()
        if(gflags.exit_func_done) {
       bool yieldcore = __query_vcore_yield();
       mcs_lock_unlock(&thread_lock, &local_qn);
-      if(yieldcore) vcore_yield();
+      if(yieldcore) vcore_yield(FALSE);
     }
                
     // Otherwise, grab a thread from the scheduler queue 
@@ -376,7 +376,7 @@ void run_next_thread()
     if(t == NULL) {
       bool yieldcore = __query_vcore_yield();
       mcs_lock_unlock(&thread_lock, &local_qn);
-      if(yieldcore) vcore_yield();
+      if(yieldcore) vcore_yield(FALSE);
     }
        // Otherwise, if the thread is in the ZOMBIE state, then it must have been
        // detached and added back to the queue for the scheduler to reap.  
@@ -988,7 +988,7 @@ void thread_exit(void *ret)
 
   /* If we were told to yield the vcore, do it! */
   if(yieldcore)
-    vcore_yield();
+    vcore_yield(FALSE);
          
   /* Otherwise switch back to vcore context to schedule the next thread. */
   switch_to_vcore();
index fd5faf1..1c481f8 100644 (file)
@@ -47,7 +47,7 @@ static inline void disable_notifs(uint32_t vcoreid);
 static inline bool notif_is_enabled(uint32_t vcoreid);
 int vcore_init(void);
 int vcore_request(size_t k);
-void vcore_yield(void);
+void vcore_yield(bool preempt_pending);
 void clear_notif_pending(uint32_t vcoreid);
 void enable_notifs(uint32_t vcoreid);
 void vcore_idle(void);
index 11671b9..fc182b6 100644 (file)
@@ -302,8 +302,10 @@ bool check_preempt_pending(uint32_t vcoreid)
                if (sched_ops->preempt_pending)
                        sched_ops->preempt_pending();
                /* this tries to yield, but will pop back up if this was a spurious
-                * preempt_pending. */
-               sys_yield(TRUE);
+                * preempt_pending.  Note this will handle events internally, and then
+                * recurse once per event in the queue.  This sucks, but keeps us from
+                * missing messages for now. */
+               vcore_yield(TRUE);
        }
        return retval;
 }
index b521fdf..b11f53e 100644 (file)
@@ -196,7 +196,7 @@ fail:
 }
 
 /* This can return, if you failed to yield due to a concurrent event. */
-void vcore_yield()
+void vcore_yield(bool preempt_pending)
 {
        uint32_t vcoreid = vcore_id();
        struct preempt_data *vcpd = &__procdata.vcore_preempt_data[vcoreid];
@@ -208,7 +208,7 @@ void vcore_yield()
                return;
        }
        /* o/w, we can safely yield */
-       sys_yield(0);
+       sys_yield(preempt_pending);
 }
 
 /* Clear pending, and try to handle events that came in between a previous call
@@ -227,7 +227,9 @@ void clear_notif_pending(uint32_t vcoreid)
 }
 
 /* Enables notifs, and deals with missed notifs by self notifying.  This should
- * be rare, so the syscall overhead isn't a big deal. */
+ * be rare, so the syscall overhead isn't a big deal.  The other alternative
+ * would be to uthread_yield(), which would require us to revert some uthread
+ * interface changes. */
 void enable_notifs(uint32_t vcoreid)
 {
        __enable_notifs(vcoreid);
index 1fad3ad..cbfa68f 100644 (file)
@@ -92,7 +92,7 @@ void __attribute__((noreturn)) pth_sched_entry(void)
                printd("[P] No threads, vcore %d is yielding\n", vcore_id());
                /* TODO: you can imagine having something smarter here, like spin for a
                 * bit before yielding (or not at all if you want to be greedy). */
-               vcore_yield();
+               vcore_yield(FALSE);
        } while (1);
        assert(((struct uthread*)new_thread)->state != UT_RUNNING);
        run_uthread((struct uthread*)new_thread);