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 <[email protected]> --- tests/lock_test.c | 3 ++- tests/old/condvar_test.c | 6 ++++-- tests/old/fpperf.cc | 3 ++- tests/pthread_barrier_test.c | 3 ++- tests/pthread_switch.c | 3 ++- tests/pthread_test.c | 3 ++- user/parlib/include/parlib/parlib.h | 1 + user/parlib/parlib.c | 1 + user/parlib/vcore.c | 2 ++ user/pthread/pthread.c | 29 ++++------------------------- user/pthread/pthread.h | 2 +- user/utest/pvcalarm.c | 6 ++++-- 12 files changed, 27 insertions(+), 35 deletions(-) diff --git a/tests/lock_test.c b/tests/lock_test.c index 80e2a2a365d9..4b8a5db2aaac 100644 --- a/tests/lock_test.c +++ b/tests/lock_test.c @@ -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); diff --git a/tests/old/condvar_test.c b/tests/old/condvar_test.c index d7397a49598c..927338dcc384 100644 --- a/tests/old/condvar_test.c +++ b/tests/old/condvar_test.c @@ -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"); } diff --git a/tests/old/fpperf.cc b/tests/old/fpperf.cc index 55b0f290e4b3..6363f1f7d43f 100644 --- a/tests/old/fpperf.cc +++ b/tests/old/fpperf.cc @@ -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); } diff --git a/tests/pthread_barrier_test.c b/tests/pthread_barrier_test.c index 1ab1fc6b6ea4..76abc045bcff 100644 --- a/tests/pthread_barrier_test.c +++ b/tests/pthread_barrier_test.c @@ -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); diff --git a/tests/pthread_switch.c b/tests/pthread_switch.c index 3093c7920baa..70df52ecafb1 100644 --- a/tests/pthread_switch.c +++ b/tests/pthread_switch.c @@ -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 */ diff --git a/tests/pthread_test.c b/tests/pthread_test.c index e0c77093a581..bfd703798fe0 100644 --- a/tests/pthread_test.c +++ b/tests/pthread_test.c @@ -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); diff --git a/user/parlib/include/parlib/parlib.h b/user/parlib/include/parlib/parlib.h index 4bca2db25f95..891f6831d1f0 100644 --- a/user/parlib/include/parlib/parlib.h +++ b/user/parlib/include/parlib/parlib.h @@ -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 diff --git a/user/parlib/parlib.c b/user/parlib/parlib.c index cc558502dbbe..a6caa0073668 100644 --- a/user/parlib/parlib.c +++ b/user/parlib/parlib.c @@ -7,3 +7,4 @@ /* Control variables */ bool parlib_wants_to_be_mcp = TRUE; bool parlib_never_yield = FALSE; +bool parlib_never_vc_request = FALSE; diff --git a/user/parlib/vcore.c b/user/parlib/vcore.c index fd22f8677efa..ae76bcc12355 100644 --- a/user/parlib/vcore.c +++ b/user/parlib/vcore.c @@ -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; diff --git a/user/pthread/pthread.c b/user/pthread/pthread.c index e089ff938ea0..9a6691ec9b33 100644 --- a/user/pthread/pthread.c +++ b/user/pthread/pthread.c @@ -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) diff --git a/user/pthread/pthread.h b/user/pthread/pthread.h index a98df07c8dd1..ca5a3cc65b8c 100644 --- a/user/pthread/pthread.h +++ b/user/pthread/pthread.h @@ -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); diff --git a/user/utest/pvcalarm.c b/user/utest/pvcalarm.c index 8cb8ec20d768..cb9f55477d80 100644 --- a/user/utest/pvcalarm.c +++ b/user/utest/pvcalarm.c @@ -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); -- 2.8.0.rc3.226.g39d4020 -- You received this message because you are subscribed to the Google Groups "Akaros" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. For more options, visit https://groups.google.com/d/optout.
