From 9720f82441aac76da14db4b1823aa6bff7916f26 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Tue, 28 Jul 2020 16:12:53 -0400 Subject: [PATCH] chore: require min 2 cores --- runtime/include/types.h | 8 +++-- runtime/src/global_request_scheduler_deque.c | 21 +------------ runtime/src/main.c | 32 ++++++++++---------- 3 files changed, 22 insertions(+), 39 deletions(-) diff --git a/runtime/include/types.h b/runtime/include/types.h index 8de81e0..780205e 100644 --- a/runtime/include/types.h +++ b/runtime/include/types.h @@ -147,6 +147,8 @@ typedef void (*mod_libc_fn_t)(int32_t, int32_t); #define SOFTWARE_INTERRUPT_TIME_TO_START_IN_USEC (10 * 1000) /* 10 ms */ #define SOFTWARE_INTERRUPT_INTERVAL_DURATION_IN_USEC (5 * 1000) /* 5 ms */ -/* If multicore, use all but the dedicated listener core -If there are fewer cores than this, main dynamically overrides this and uses all available */ -#define WORKER_THREAD_CORE_COUNT (NCORES > 1 ? NCORES - 1 : NCORES) +/* + * The runtime explicitly requires at least two cores, allocating all as worker threads + * minus the dedicated listener core + */ +#define WORKER_THREAD_CORE_COUNT (NCORES - 1) diff --git a/runtime/src/global_request_scheduler_deque.c b/runtime/src/global_request_scheduler_deque.c index b75d167..b31c86b 100644 --- a/runtime/src/global_request_scheduler_deque.c +++ b/runtime/src/global_request_scheduler_deque.c @@ -14,15 +14,8 @@ global_request_scheduler_deque_add(void *sandbox_request_raw) struct sandbox_request *sandbox_request = (struct sandbox_request *)sandbox_request_raw; int return_code = 1; -/* TODO: Running the runtime and listener cores on a single shared core is untested -We are unsure if the locking behavior is correct, so there may be deadlocks */ -#if NCORES == 1 - pthread_mutex_lock(&global_request_scheduler_deque_mutex); -#endif return_code = deque_push_sandbox(global_request_scheduler_deque, &sandbox_request); -#if NCORES == 1 - pthread_mutex_unlock(&global_request_scheduler_deque_mutex); -#endif + if (return_code != 0) return NULL; return sandbox_request_raw; } @@ -34,22 +27,12 @@ We are unsure if the locking behavior is correct, so there may be deadlocks */ * * Relevant Read: https://www.dre.vanderbilt.edu/~schmidt/PDF/work-stealing-dequeue.pdf * - * TODO: Notice the mutex_lock for NCORES == 1 in both push/pop functions and steal calling 'pop' for NCORES == 1. - * Ideally you don't call steal for same core consumption but I just made the steal API wrap that logic. Which is - * perhaps not good. We might just add the #if in the scheduling code which should explicitly call "pop" for single core - * and add an assert in "steal" function for NCORES == 1. - * * @returns 0 if successfully returned a sandbox request, -1 if empty, -2 if atomic instruction unsuccessful */ static int global_request_scheduler_deque_remove(struct sandbox_request **removed_sandbox_request) { int return_code; -#if NCORES == 1 - pthread_mutex_lock(&global_request_scheduler_deque_mutex); - return_code = deque_pop_sandbox(global_request_scheduler_deque, *removed_sandbox_request); - pthread_mutex_unlock(&global_request_scheduler_deque_mutex); -#else return_code = deque_steal_sandbox(global_request_scheduler_deque, removed_sandbox_request); /* The Deque uses different return codes other than 0, so map here */ if (return_code == -2) { @@ -57,8 +40,6 @@ global_request_scheduler_deque_remove(struct sandbox_request **removed_sandbox_r } else if (return_code == -11) { return_code = -2; } - -#endif return return_code; } diff --git a/runtime/src/main.c b/runtime/src/main.c index 27cc4dd..4cb2b19 100644 --- a/runtime/src/main.c +++ b/runtime/src/main.c @@ -75,22 +75,18 @@ runtime_allocate_available_cores() /* Find the number of processors currently online */ runtime_total_online_processors = sysconf(_SC_NPROCESSORS_ONLN); - /* If multicore, we'll pin one core as a listener and run sandbox threads on all others */ - if (runtime_total_online_processors > 1) { - runtime_first_worker_processor = 1; - /* WORKER_THREAD_CORE_COUNT can be used as a cap on the number of cores to use, but if there are few - * cores that WORKER_THREAD_CORE_COUNT, just use what is available */ - uint32_t max_possible_workers = runtime_total_online_processors - 1; - runtime_total_worker_processors = max_possible_workers; - if (max_possible_workers >= WORKER_THREAD_CORE_COUNT) - runtime_total_worker_processors = WORKER_THREAD_CORE_COUNT; - - assert(runtime_total_worker_processors == WORKER_THREAD_CORE_COUNT); - } else { - /* If single core, we'll do everything on CPUID 0 */ - runtime_first_worker_processor = 0; - runtime_total_worker_processors = 1; - } + if (runtime_total_online_processors < 2) panic("Runtime requires at least two cores!"); + + runtime_first_worker_processor = 1; + /* WORKER_THREAD_CORE_COUNT can be used as a cap on the number of cores to use, but if there are few + * cores that WORKER_THREAD_CORE_COUNT, just use what is available */ + uint32_t max_possible_workers = runtime_total_online_processors - 1; + runtime_total_worker_processors = max_possible_workers; + if (max_possible_workers >= WORKER_THREAD_CORE_COUNT) + runtime_total_worker_processors = WORKER_THREAD_CORE_COUNT; + + assert(runtime_total_worker_processors == WORKER_THREAD_CORE_COUNT); + printf("Number of cores %u, sandboxing cores %u (start: %u) and module reqs %u\n", runtime_total_online_processors, runtime_total_worker_processors, runtime_first_worker_processor, LISTENER_THREAD_CORE_ID); @@ -195,6 +191,10 @@ main(int argc, char **argv) runtime_process_debug_log_behavior(); #endif +#if NCORES == 1 + panic("Runtime requires at least two cores!"); +#endif + debuglog("Initializing the runtime\n"); if (argc != 2) { runtime_usage(argv[0]);