uth: Use a thread0 sched ops for SCPs without 2LSs
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 13 Jul 2015 21:39:36 +0000 (17:39 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 16 Jul 2015 19:08:18 +0000 (15:08 -0400)
Instead of assuming the lack of a sched_entry means we are an SCP, we
can use the default sched ops still for a "thread0" scheduler.  All
processes, even those that link in a real 2LS capable of handling MCPs
or other things, will use this scheduler for at least a brief period.

As far as the functionality, goes, this changes nothing.  We still
insist on running current_uthread.  But this also removes one runtime
branch from the common-case code!

user/parlib/thread0_sched.c [new file with mode: 0644]
user/parlib/uthread.c

diff --git a/user/parlib/thread0_sched.c b/user/parlib/thread0_sched.c
new file mode 100644 (file)
index 0000000..f7294ec
--- /dev/null
@@ -0,0 +1,30 @@
+/* Copyright (c) 2015 Google, Inc.
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * thread0_sched: a basic scheduler for thread0, used by SCPs without a
+ * multithreaded 2LS linked in.
+ *
+ * This is closely coupled with uthread.c */
+
+#include <ros/arch/membar.h>
+#include <parlib/arch/atomic.h>
+#include <parlib/parlib.h>
+#include <parlib/vcore.h>
+#include <parlib/uthread.h>
+#include <parlib/event.h>
+#include <stdlib.h>
+
+static void thread0_sched_entry(void);
+
+/* externed into uthread.c */
+struct schedule_ops thread0_2ls_ops = {
+       .sched_entry = thread0_sched_entry,
+};
+
+/* Thread0 scheduler ops (for processes that haven't linked in a full 2LS) */
+static void thread0_sched_entry(void)
+{
+       if (current_uthread)
+               run_current_uthread();
+}
index e18509d..01e616b 100644 (file)
@@ -1,3 +1,7 @@
+/* Copyright (c) 2011-2014 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details. */
+
 #include <ros/arch/membar.h>
 #include <parlib/arch/atomic.h>
 #include <parlib/parlib.h>
 #include <parlib/event.h>
 #include <stdlib.h>
 
-/* By default there is no 2LS, but we still want sched_ops set so we can check
- * its individual function pointers. A 2LS should override sched_ops in its
- * init code. */
-struct schedule_ops default_2ls_ops = {0};
-struct schedule_ops *sched_ops = &default_2ls_ops;
+/* SCPs have a default 2LS that only manages thread 0.  Any other 2LS, such as
+ * pthreads, should override sched_ops in its init code. */
+extern struct schedule_ops thread0_2ls_ops;
+struct schedule_ops *sched_ops = &thread0_2ls_ops;
 
 __thread struct uthread *current_uthread = 0;
 /* ev_q for all preempt messages (handled here to keep 2LSs from worrying
  * extensively about the details.  Will call out when necessary. */
-struct event_queue *preempt_ev_q;
+static struct event_queue *preempt_ev_q;
 
 /* Helpers: */
 #define UTH_TLSDESC_NOTLS (void*)(-1)
@@ -227,17 +230,8 @@ void __attribute__((noreturn)) uthread_vcore_entry(void)
        handle_events(vcoreid);
        __check_preempt_pending(vcoreid);
        assert(in_vcore_context());     /* double check, in case an event changed it */
-       /* Consider using the default_2ls_op for this, though it's a bit weird. */
-       if (sched_ops->sched_entry) {
-               sched_ops->sched_entry();
-       } else if (current_uthread) {
-               run_current_uthread();
-       }
-       /* 2LS sched_entry should never return */
-       /* Either the 2LS sched_entry returned, run_cur_uth() returned, or we
-        * didn't have a current_uthread.  If we didn't have a 2LS op, we should be
-        * in _S mode and always have a current_uthread. */
-       assert(0);
+       sched_ops->sched_entry();
+       assert(0); /* 2LS sched_entry should never return */
 }
 
 /* Does the uthread initialization of a uthread that the caller created.  Call