Update akaros to hook in the new topology stuff
[akaros.git] / user / parlib / thread0_sched.c
index f5c838d..926d6e8 100644 (file)
 #include <stdlib.h>
 
 static void thread0_sched_entry(void);
+static void thread0_thread_blockon_sysc(struct uthread *uthread, void *sysc);
+static void thread0_thread_refl_fault(struct uthread *uthread,
+                                      unsigned int trap_nr, unsigned int err,
+                                      unsigned long aux);
 
 /* externed into uthread.c */
 struct schedule_ops thread0_2ls_ops = {
        .sched_entry = thread0_sched_entry,
+       .thread_blockon_sysc = thread0_thread_blockon_sysc,
+       .thread_refl_fault = thread0_thread_refl_fault,
 };
 
 /* externed into uthread.c */
@@ -33,3 +39,43 @@ static void thread0_sched_entry(void)
        else
                run_uthread(thread0_uth);
 }
+
+static void thread0_thread_blockon_sysc(struct uthread *uthread, void *arg)
+{
+       struct syscall *sysc = (struct syscall*)arg;
+       /* We're in vcore context.  Regardless of what we do here, we'll pop back in
+        * to vcore entry, just like with any uthread_yield.  We don't have a 2LS,
+        * but we always have one uthread: the SCP's thread0.  Note that at this
+        * point, current_uthread is still set, but will be cleared as soon as the
+        * callback returns (and before we start over in vcore_entry).
+        *
+        * If notif_pending is already set (due to a concurrent signal), we'll fail
+        * to yield.  Once in VC ctx, we'll handle any other signals/events that
+        * arrived, then restart the uthread that issued the syscall, which if the
+        * syscall isn't done yet, will just blockon again.
+        *
+        * The one trick is that we don't want to register the evq twice.  The way
+        * register_evq currently works, if a SC completed (SC_DONE) while we were
+        * registering, we could end up clearing sysc->ev_q before the kernel sees
+        * it.  We'll use u_data to track whether we registered or not. */
+       #define U_DATA_BLOB ((void*)0x55555555)
+       if ((sysc->u_data == U_DATA_BLOB)
+           || register_evq(sysc, &__ros_scp_simple_evq)) {
+               sysc->u_data = U_DATA_BLOB;
+               /* Sending false for now - we want to signal proc code that we want to
+                * wait (piggybacking on the MCP meaning of this variable).  If
+                * notif_pending is set, the kernel will immediately return us. */
+               __ros_syscall_noerrno(SYS_yield, FALSE, 0, 0, 0, 0, 0);
+       }
+}
+
+static void thread0_thread_refl_fault(struct uthread *uthread,
+                                      unsigned int trap_nr, unsigned int err,
+                                      unsigned long aux)
+{
+       printf("SCP has unhandled fault: %d, err: %d, aux: %p\n", trap_nr, err,
+              aux);
+       print_user_context(&uthread->u_ctx);
+       printf("Turn on printx to spew unhandled, malignant trap info\n");
+       exit(-1);
+}