Add a helper for stopping current_uthread
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 22 Feb 2016 17:01:53 +0000 (12:01 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 2 May 2016 21:11:15 +0000 (17:11 -0400)
A 2LS could use this to swap threads in response to an event, e.g. a timer
tick.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
user/parlib/include/parlib/uthread.h
user/parlib/uthread.c

index fff5312..8e2d6e4 100644 (file)
@@ -98,6 +98,7 @@ void uth_enable_notifs(void);
 
 /* Helpers, which sched_entry() can call */
 void highjack_current_uthread(struct uthread *uthread);
+struct uthread *stop_current_uthread(void);
 void __attribute__((noreturn)) run_current_uthread(void);
 void __attribute__((noreturn)) run_uthread(struct uthread *uthread);
 
index e092a22..3503115 100644 (file)
@@ -579,6 +579,28 @@ static void handle_refl_fault(struct uthread *uth, struct user_context *ctx)
        sched_ops->thread_refl_fault(uth, ctx);
 }
 
+/* 2LS helper: stops the current uthread, saves its state, and returns a pointer
+ * to it.  Unlike __uthread_pause, which is called by non-specific 2LS code,
+ * this function is called by a specific 2LS to stop it's current uthread. */
+struct uthread *stop_current_uthread(void)
+{
+       struct uthread *uth;
+       struct preempt_data *vcpd = vcpd_of(vcore_id());
+
+       uth = current_uthread;
+       current_uthread = 0;
+       if (!(uth->flags & UTHREAD_SAVED)) {
+               uth->u_ctx = vcpd->uthread_ctx;
+               uth->flags |= UTHREAD_SAVED;
+       }
+       if ((uth->u_ctx.type != ROS_SW_CTX) && !(uth->flags & UTHREAD_FPSAVED)) {
+               save_fp_state(&uth->as);
+               uth->flags |= UTHREAD_FPSAVED;
+       }
+       uth->state = UT_NOT_RUNNING;
+       return uth;
+}
+
 /* Run the thread that was current_uthread, from a previous run.  Should be
  * called only when the uthread already was running, and we were interrupted by
  * the kernel (event, etc).  Do not call this to run a fresh uthread, even if
@@ -600,12 +622,7 @@ void __attribute__((noreturn)) run_current_uthread(void)
                /* we preemptively copy out and make non-running, so that there is a
                 * consistent state for the handler.  it can then block the uth or
                 * whatever. */
-               uth = current_uthread;
-               current_uthread = 0;
-               uth->u_ctx = vcpd->uthread_ctx;
-               save_fp_state(&uth->as);
-               uth->state = UT_NOT_RUNNING;
-               uth->flags |= UTHREAD_SAVED | UTHREAD_FPSAVED;
+               uth = stop_current_uthread();
                handle_refl_fault(uth, &vcpd->uthread_ctx);
                /* we abort no matter what.  up to the 2LS to reschedule the thread */
                set_stack_pointer((void*)vcpd->vcore_stack);