Push control over vcores into parlib variables
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 3 May 2016 20:42:20 +0000 (16:42 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 3 May 2016 20:54:30 +0000 (16:54 -0400)
We had an extension to pthreads: pthread_can_vcore_request().  It was a way
for an application to tell the 2LS to not request vcores or to yield
vcores.  The problem with making it a pthread extension is that it is 2LS
specific: an app needs to know/care about it's 2LS, and every 2LS needed to
reimplement the same logic.

By pushing it into parlib, we avoid all of that.  The app also gets
finer-grained control over what it needs (i.e., there's a minor difference
between not yielding and not requesting more cores).

Be careful using this new variable.  It'll prevent *any* vcores from being
requested, so you want to use it after the app requests whatever vcores it
wants (not including the one VC you get from being an MCP).  This variable
is a minor pain, and might not be worth keeping around.  We'll see.

This is actually a problem of having 2LSs that aren't app-specific enough.
The app knows what it wants, but the 2LS doesn't.  We're trying to find a
way to deal with that in a way that doesn't duplicate too much code.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
12 files changed:
tests/lock_test.c
tests/old/condvar_test.c
tests/old/fpperf.cc
tests/pthread_barrier_test.c
tests/pthread_switch.c
tests/pthread_test.c
user/parlib/include/parlib/parlib.h
user/parlib/parlib.c
user/parlib/vcore.c
user/pthread/pthread.c
user/pthread/pthread.h
user/utest/pvcalarm.c

index 80e2a2a..4b8a5db 100644 (file)
@@ -732,7 +732,7 @@ static void os_prep_work(pthread_t *worker_threads, int nr_threads)
        atomic_init(&indir_idx, 0);
        atomic_init(&preempt_cnt, 0);
        atomic_init(&indir_cnt, 0);
-       pthread_can_vcore_request(FALSE);       /* 2LS won't manage vcores */
+       parlib_never_yield = TRUE;
        pthread_need_tls(FALSE);
        pthread_mcp_init();                                     /* gives us one vcore */
        register_ev_handler(EV_VCORE_PREEMPT, trace_preempt, 0);
@@ -744,6 +744,7 @@ static void os_prep_work(pthread_t *worker_threads, int nr_threads)
                clear_kevent_q(EV_CHECK_MSGS);
        }
        vcore_request_total(nr_threads);
+       parlib_never_vc_request = TRUE;
        for (int i = 0; i < nr_threads; i++) {
                printd("Vcore %d mapped to pcore %d\n", i,
                       __procinfo.vcoremap[i].pcoreid);
index d7397a4..927338d 100644 (file)
@@ -122,9 +122,10 @@ int main(void)
         *
         * Need to make sure we are running in parallel here.  Temp turned off the
         * 2LSs VC management and got up to 2 VC.  Assuming no preemption. */
-       pthread_can_vcore_request(FALSE);       /* 2LS won't manage vcores */
+       parlib_never_yield = TRUE;
        while (num_vcores() < 2)
                vcore_request_more(1);
+       parlib_never_vc_request = TRUE;
        for (long i = 0; i < 1000; i++) {
                for (int j = 0; j < 10; j++) {  /* some extra chances at each point */
                        state = FALSE;
@@ -147,6 +148,7 @@ int main(void)
                        pthread_join(my_threads[0], my_retvals[0]);
                }
        }
-       pthread_can_vcore_request(TRUE);        /* 2LS controls VCs again */
+       parlib_never_yield = FALSE;
+       parlib_never_vc_request = FALSE;
        printf("test_cv: single sender/receiver complete\n");
 }
index 55b0f29..6363f1f 100644 (file)
@@ -72,7 +72,8 @@ int main(int argc, char **argv)
        #if 1
        # ifdef __ros__
        if (argc == 4) {
-               pthread_can_vcore_request(FALSE);
+               parlib_never_yield = TRUE;
+               parlib_never_vc_request = TRUE;
                pthread_mcp_init();
                printf("Vcore %d mapped to pcore %d\n", 0, __procinfo.vcoremap[0].pcoreid);
        }
index 1ab1fc6..76abc04 100644 (file)
@@ -46,9 +46,10 @@ int main(int argc, char** argv)
                perror("Init threads/malloc");
        if (nr_vcores) {
                /* Only do the vcore trickery if requested */
-               pthread_can_vcore_request(FALSE);       /* 2LS won't manage vcores */
+               parlib_never_yield = TRUE;
                pthread_mcp_init();                                     /* gives us one vcore */
                vcore_request_total(nr_vcores);
+               parlib_never_vc_request = TRUE;
                for (int i = 0; i < nr_vcores; i++) {
                        printd("Vcore %d mapped to pcore %d\n", i,
                                   __procinfo.vcoremap[i].pcoreid);
index 3093c79..70df52e 100644 (file)
@@ -68,7 +68,8 @@ int main(int argc, char** argv)
                nr_switch_loops = strtol(argv[1], 0, 10);
        printf("Making 2 threads of %d switches each\n", nr_switch_loops);
 
-       pthread_can_vcore_request(FALSE);       /* 2LS won't manage vcores */
+       parlib_never_yield = TRUE;
+       parlib_never_vc_request = TRUE;
        pthread_need_tls(FALSE);
        pthread_mcp_init();                                     /* gives us one vcore */
 
index e0c7709..bfd7037 100644 (file)
@@ -82,10 +82,11 @@ int main(int argc, char** argv)
 #ifdef __ros__
        if (nr_vcores) {
                /* Only do the vcore trickery if requested */
-               pthread_can_vcore_request(FALSE);       /* 2LS won't manage vcores */
+               parlib_never_yield = TRUE;
                pthread_need_tls(FALSE);
                pthread_mcp_init();                                     /* gives us one vcore */
                vcore_request_total(nr_vcores);
+               parlib_never_vc_request = TRUE;
                for (int i = 0; i < nr_vcores; i++) {
                        printf_safe("Vcore %d mapped to pcore %d\n", i,
                                    __procinfo.vcoremap[i].pcoreid);
index 4bca2db..891f683 100644 (file)
@@ -60,6 +60,7 @@ void          syscall_async(struct syscall *sysc, unsigned long num, ...);
 /* Control variables */
 extern bool parlib_wants_to_be_mcp;    /* instructs the 2LS to be an MCP */
 extern bool parlib_never_yield;                /* instructs the 2LS to not yield vcores */
+extern bool parlib_never_vc_request;/* 2LS: do not request vcores */
 
 __END_DECLS
 
index cc55850..a6caa00 100644 (file)
@@ -7,3 +7,4 @@
 /* Control variables */
 bool parlib_wants_to_be_mcp = TRUE;
 bool parlib_never_yield = FALSE;
+bool parlib_never_vc_request = FALSE;
index fd22f86..ae76bcc 100644 (file)
@@ -253,6 +253,8 @@ void vcore_request_total(long nr_vcores_wanted)
 {
        static long nr_vc_wanted;
 
+       if (parlib_never_vc_request)
+               return;
        if (nr_vcores_wanted == __procdata.res_req[RES_CORES].amt_wanted)
                return;
 
index e089ff9..9a6691e 100644 (file)
@@ -24,7 +24,6 @@ struct mcs_pdr_lock queue_lock;
 int threads_ready = 0;
 int threads_active = 0;
 atomic_t threads_total;
-bool can_adjust_vcores = TRUE;
 bool need_tls = TRUE;
 
 /* Array of per-vcore structs to manage waiting on syscalls and handling
@@ -107,11 +106,8 @@ static void __attribute__((noreturn)) pth_sched_entry(void)
                /* no new thread, try to yield */
                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). */
-               if (can_adjust_vcores)
-                       vcore_yield(FALSE);
-               if (!parlib_wants_to_be_mcp)
-                       sys_yield(FALSE);
+                * bit before yielding. */
+               vcore_yield(FALSE);
        } while (1);
        /* Prep the pthread to run any pending posix signal handlers registered
      * via pthread_kill once it is restored. */
@@ -160,8 +156,7 @@ static void pth_thread_runnable(struct uthread *uthread)
        mcs_pdr_unlock(&queue_lock);
        /* Smarter schedulers should look at the num_vcores() and how much work is
         * going on to make a decision about how many vcores to request. */
-       if (can_adjust_vcores)
-               vcore_request_more(threads_ready);
+       vcore_request_more(threads_ready);
 }
 
 /* For some reason not under its control, the uthread stopped running (compared
@@ -339,14 +334,6 @@ static void pth_thread_refl_fault(struct uthread *uth,
 
 /* Akaros pthread extensions / hacks */
 
-/* Tells the pthread 2LS to not change the number of vcores.  This means it will
- * neither request vcores nor yield vcores.  Only used for testing. */
-void pthread_can_vcore_request(bool can)
-{
-       /* checked when we would request or yield */
-       can_adjust_vcores = can;
-}
-
 void pthread_need_tls(bool need)
 {
        need_tls = need;
@@ -541,13 +528,6 @@ void pthread_mcp_init()
        /* Prevent this from happening more than once. */
        init_once_racy(return);
 
-       if (!parlib_wants_to_be_mcp) {
-               /* sign to whether or not we ask for more vcores.  actually, if we're
-                * an SCP, the current kernel will ignore our requests, but best to not
-                * rely on that. */
-               can_adjust_vcores = FALSE;
-               return;
-       }
        uthread_mcp_init();
        /* From here forward we are an MCP running on vcore 0. Could consider doing
         * other pthread specific initialization based on knowing we are an mcp
@@ -923,8 +903,7 @@ static void wake_slist(struct pthread_list *to_wake)
        }
        threads_ready += nr_woken;
        mcs_pdr_unlock(&queue_lock);
-       if (can_adjust_vcores)
-               vcore_request_more(threads_ready);
+       vcore_request_more(threads_ready);
 }
 
 int pthread_cond_broadcast(pthread_cond_t *c)
index a98df07..ca5a3cc 100644 (file)
@@ -8,6 +8,7 @@
 #include <parlib/dtls.h>
 #include <parlib/spinlock.h>
 #include <parlib/signal.h>
+#include <parlib/parlib.h>
 /* GNU / POSIX scheduling crap */
 #include <sched.h>
 
@@ -152,7 +153,6 @@ typedef int pthread_once_t;
 typedef dtls_key_t pthread_key_t;
 
 /* Akaros pthread extensions / hacks */
-void pthread_can_vcore_request(bool can);      /* default is TRUE */
 void pthread_need_tls(bool need);                      /* default is TRUE */
 void pthread_lib_init(void);
 void pthread_mcp_init(void);
index 8cb8ec2..cb9f554 100644 (file)
@@ -14,9 +14,10 @@ bool test_pvcalarms(void) {
                __sync_fetch_and_add(&count[vcore_id()], 1);
        }
 
-       pthread_can_vcore_request(FALSE);
+       parlib_never_yield = TRUE;
        pthread_mcp_init();
        vcore_request_total(max_vcores());
+       parlib_never_vc_request = TRUE;
        for (int i=0; i<max_vcores(); i++)
                count[i] = 0;
        
@@ -65,7 +66,8 @@ bool test_sigperf(void)
        }
 
        pthread_lib_init();
-       pthread_can_vcore_request(TRUE);
+       parlib_never_yield = FALSE;
+       parlib_never_vc_request = FALSE;
 
        sigset_t s;
        sigemptyset(&s);