Fixes potential race with SCPs blocking (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 19 Oct 2012 23:00:05 +0000 (16:00 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 19 Oct 2012 23:00:05 +0000 (16:00 -0700)
If we ever received an event/notif after registering the ev_q and before
yielding, that event would cause us to clear notif_pending.  This would
cause us to sleep permanently in yield, since we already both received
the 'syscall done' event and marked its reception.

If you want to write similar code, the important thing was that we need
notifs disabled before we check the syscall's SC_DONE.

tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/syscall.c

index 2f1efcf..e20f83f 100644 (file)
@@ -65,6 +65,10 @@ static bool register_evq(struct syscall *sysc, struct event_queue *ev_q)
  * never can, like for RTLD).  MCPs will need the 'uthread-aware' blockon. */
 void __ros_scp_syscall_blockon(struct syscall *sysc)
 {
+       /* Need to disable notifs before registering, so we don't take an __notify
+        * that drops us into VC ctx and forces us to eat the notif_pending that was
+        * meant to prevent us from yielding if the syscall completed early. */
+       __procdata.vcore_preempt_data[0].notif_disabled = FALSE;
        /* Ask for a SYSCALL event when the sysc is done.  We don't need a handler,
         * we just need the kernel to restart us from proc_yield.  If register
         * fails, we're already done. */
@@ -73,6 +77,11 @@ void __ros_scp_syscall_blockon(struct syscall *sysc)
                 * wait (piggybacking on the MCP meaning of this variable) */
                __ros_syscall(SYS_yield, FALSE, 0, 0, 0, 0, 0, 0);
        }
+       /* Manually doing an enable_notifs for VC 0 */
+       __procdata.vcore_preempt_data[0].notif_disabled = TRUE;
+       wrmb(); /* need to read after the write that enabled notifs */
+       if (__procdata.vcore_preempt_data[0].notif_pending)
+               __ros_syscall(SYS_self_notify, 0, EV_NONE, 0, TRUE, 0, 0, 0);
 }
 
 /* Function pointer for the blockon function.  MCPs need to switch to the parlib