diff --git a/runtime/include/sandbox.h b/runtime/include/sandbox.h index 7c7db14..39fa83e 100644 --- a/runtime/include/sandbox.h +++ b/runtime/include/sandbox.h @@ -151,7 +151,7 @@ static inline void switch_to_sandbox(struct sandbox *next_sandbox) { arch_context_t *next_register_context = next_sandbox == NULL ? NULL : &next_sandbox->ctxt; - softint_disable(); + softint__disable(); struct sandbox *current_sandbox = get_current_sandbox(); arch_context_t *current_register_context = current_sandbox == NULL ? NULL : ¤t_sandbox->ctxt; set_current_sandbox(next_sandbox); @@ -159,7 +159,7 @@ switch_to_sandbox(struct sandbox *next_sandbox) if (current_sandbox && current_sandbox->state == RETURNED) add_sandbox_to_completion_queue(current_sandbox); next_context = next_register_context; arch_context_switch(current_register_context, next_register_context); - softint_enable(); + softint__enable(); } /** diff --git a/runtime/include/softint.h b/runtime/include/softint.h index b526d04..c730a22 100644 --- a/runtime/include/softint.h +++ b/runtime/include/softint.h @@ -5,8 +5,37 @@ #include #include +/*************************************** + * Externs + ***************************************/ + +extern __thread volatile sig_atomic_t softint_off; + +/*************************************** + * Public Static Inlines + ***************************************/ + +static inline void +softint__disable(void) +{ + while (__sync_bool_compare_and_swap(&softint_off, 0, 1) == false) + ; +} + +static inline void +softint__enable(void) +{ + if (__sync_bool_compare_and_swap(&softint_off, 1, 0) == false) assert(0); +} + +static inline int +softint__is_enabled(void) +{ + return (softint_off == 0); +} + static inline int -softint_mask(int signal) +softint__mask(int signal) { sigset_t set; int return_code; @@ -26,7 +55,7 @@ softint_mask(int signal) } static inline int -softint_unmask(int signal) +softint__unmask(int signal) { sigset_t set; int return_code; @@ -45,30 +74,12 @@ softint_unmask(int signal) return 0; } -extern __thread volatile sig_atomic_t softint_off; - -static inline void -softint_disable(void) -{ - while (__sync_bool_compare_and_swap(&softint_off, 0, 1) == false) - ; -} - -static inline void -softint_enable(void) -{ - if (__sync_bool_compare_and_swap(&softint_off, 1, 0) == false) assert(0); -} - -static inline int -softint_enabled(void) -{ - return (softint_off == 0); -} - -void softint_init(void); +/*************************************** + * Exports from module.c + ***************************************/ -void softint_timer_arm(void); -void softint_timer_disarm(void); +void softint__initialize(void); +void softint__arm_timer(void); +void softint__disarm_timer(void); #endif /* SFRT_SOFTINT_H */ diff --git a/runtime/src/runtime.c b/runtime/src/runtime.c index 8fb5087..c467b15 100644 --- a/runtime/src/runtime.c +++ b/runtime/src/runtime.c @@ -43,8 +43,8 @@ initialize_runtime(void) deque_init_sandbox(global_deque, SBOX_MAX_REQS); // Mask Signals - softint_mask(SIGUSR1); - softint_mask(SIGALRM); + softint__mask(SIGUSR1); + softint__mask(SIGALRM); // Initialize http_parser_settings global http_parser_settings__initialize(&global__http_parser_settings); @@ -129,8 +129,8 @@ initialize_listener_thread(void) ret = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cs); assert(ret == 0); - softint_init(); - softint_timer_arm(); + softint__initialize(); + softint__arm_timer(); } /*************************** @@ -169,7 +169,7 @@ static inline void add_sandbox_to_local_run_queue(struct sandbox *sandbox); void wakeup_sandbox(sandbox_t *sandbox) { - softint_disable(); + softint__disable(); debuglog("[%p: %s]\n", sandbox, sandbox->module->name); if (sandbox->state != BLOCKED) goto done; assert(sandbox->state == BLOCKED); @@ -177,7 +177,7 @@ wakeup_sandbox(sandbox_t *sandbox) sandbox->state = RUNNABLE; ps_list_head_append_d(&local_run_queue, sandbox); done: - softint_enable(); + softint__enable(); } @@ -188,13 +188,13 @@ void block_current_sandbox(void) { assert(in_callback == 0); - softint_disable(); + softint__disable(); struct sandbox *current_sandbox = get_current_sandbox(); ps_list_rem_d(current_sandbox); current_sandbox->state = BLOCKED; struct sandbox *next_sandbox = get_next_sandbox_from_local_run_queue(0); debuglog("[%p: %next_sandbox, %p: %next_sandbox]\n", current_sandbox, current_sandbox->module->name, next_sandbox, next_sandbox ? next_sandbox->module->name : ""); - softint_enable(); + softint__enable(); switch_to_sandbox(next_sandbox); } @@ -373,9 +373,9 @@ worker_thread_single_loop(void) if (!in_callback) execute_libuv_event_loop(); // Get and return the sandbox at the head of the thread local runqueue - softint_disable(); + softint__disable(); struct sandbox *sandbox = get_next_sandbox_from_local_run_queue(0); - softint_enable(); + softint__enable(); assert(sandbox == NULL || sandbox->state == RUNNABLE); return sandbox; } @@ -395,8 +395,8 @@ worker_thread_main(void *return_code) softint_off = 0; next_context = NULL; #ifndef PREEMPT_DISABLE - softint_unmask(SIGALRM); - softint_unmask(SIGUSR1); + softint__unmask(SIGALRM); + softint__unmask(SIGUSR1); #endif uv_loop_init(&uvio_handle); in_callback = 0; @@ -426,13 +426,13 @@ exit_current_sandbox(void) { struct sandbox *current_sandbox = get_current_sandbox(); assert(current_sandbox); - softint_disable(); + softint__disable(); remove_sandbox_from_local_run_queue(current_sandbox); current_sandbox->state = RETURNED; struct sandbox *next_sandbox = get_next_sandbox_from_local_run_queue(0); assert(next_sandbox != current_sandbox); - softint_enable(); + softint__enable(); // free resources from "main function execution", as stack still in use. // unmap linear memory only! munmap(current_sandbox->linear_memory_start, SBOX_MAX_MEM + PAGE_SIZE); diff --git a/runtime/src/sandbox.c b/runtime/src/sandbox.c index 95c2b32..49119e4 100644 --- a/runtime/src/sandbox.c +++ b/runtime/src/sandbox.c @@ -277,10 +277,10 @@ sandbox_main(void) // FIXME: is this right? this is the first time this sandbox is running.. so it wont // return to switch_to_sandbox() api.. // we'd potentially do what we'd in switch_to_sandbox() api here for cleanup.. - if (!softint_enabled()) { + if (!softint__is_enabled()) { arch_context_init(¤t_sandbox->ctxt, 0, 0); next_context = NULL; - softint_enable(); + softint__enable(); } struct module *current_module = get_sandbox_module(current_sandbox); int argument_count = module__get_argument_count(current_module); diff --git a/runtime/src/softint.c b/runtime/src/softint.c index 30a54a7..9d8bcda 100644 --- a/runtime/src/softint.c +++ b/runtime/src/softint.c @@ -13,91 +13,32 @@ #include #include -__thread static volatile sig_atomic_t SIGALRM_count = 0; -__thread static volatile sig_atomic_t SIGUSR_count = 0; - -__thread volatile sig_atomic_t softint_off = 0; +/*************************************** + * Process Globals + ***************************************/ static const int softints[] = { SIGALRM, SIGUSR1 }; -/** - * Arms the Interval Timer to start in 10ms and then trigger a SIGALRM every 5ms - **/ -void -softint_timer_arm(void) -{ -#ifndef PREEMPT_DISABLE - struct itimerval interval_timer; - - memset(&interval_timer, 0, sizeof(struct itimerval)); - interval_timer.it_value.tv_usec = SOFTINT_TIMER_START_USEC; - interval_timer.it_interval.tv_usec = SOFTINT_TIMER_PERIOD_USEC; - - int return_code = setitimer(ITIMER_REAL, &interval_timer, NULL); - if (return_code) { - perror("setitimer"); - exit(1); - } -#endif -} - -/** - * Disarm the Interval Timer - **/ -void -softint_timer_disarm(void) -{ - struct itimerval interval_timer; - - memset(&interval_timer, 0, sizeof(struct itimerval)); - interval_timer.it_value.tv_sec = 0; - interval_timer.it_interval.tv_usec = 0; - - int return_code = setitimer(ITIMER_REAL, &interval_timer, NULL); - if (return_code) { - perror("setitimer"); - exit(1); - } -} - -/** - * Preempt the current sandbox and start executing the next sandbox - * @param user_context_raw void* to a user_context struct - **/ -static inline void -softint_alarm_schedule(void *user_context_raw) -{ - softint_disable(); // no nesting! +/*************************************** + * Thread Globals + ***************************************/ - struct sandbox *curr = get_current_sandbox(); - ucontext_t * user_context = (ucontext_t *)user_context_raw; - - // no sandboxes running..so nothing to preempt..let the "main" scheduler run its course. - if (curr == NULL) goto done; - - // find a next sandbox to run.. - struct sandbox *next = get_next_sandbox_from_local_run_queue(1); - if (next == NULL) goto done; - if (next == curr) goto done; // only this sandbox to schedule.. return to it! - // save the current sandbox, state from user_context! - arch_mcontext_save(&curr->ctxt, &user_context->uc_mcontext); +__thread static volatile sig_atomic_t SIGALRM_count = 0; +__thread static volatile sig_atomic_t SIGUSR_count = 0; +__thread volatile sig_atomic_t softint_off = 0; - // set_current_sandbox on it. restore through *user_context.. - set_current_sandbox(next); +/*************************************** + * Externs + ***************************************/ - if (arch_mcontext_restore(&user_context->uc_mcontext, &next->ctxt)) goto skip; - // reset if SIGALRM happens before SIGUSR1 and if don't preempt..OR - // perhaps switch here for SIGUSR1 and see if we can clear that signal - // so it doesn't get called on SIGALRM return.. - // next_context = NULL; +extern pthread_t worker_threads[]; -done: - softint_enable(); -skip: - return; -} +/*************************************** + * Private Static Inlines + ***************************************/ -extern pthread_t worker_threads[]; +static inline void softint__handle_signals(int signal_type, siginfo_t *signal_info, void *user_context_raw); +static inline void softint__schedule_alarm(void *user_context_raw); /** * The handler function for Software Interrupts (signals) @@ -108,7 +49,7 @@ extern pthread_t worker_threads[]; * @param user_context_raw void* to a user_context struct **/ static inline void -softint_handler(int signal_type, siginfo_t *signal_info, void *user_context_raw) +softint__handle_signals(int signal_type, siginfo_t *signal_info, void *user_context_raw) { #ifdef PREEMPT_DISABLE assert(0); @@ -139,14 +80,14 @@ softint_handler(int signal_type, siginfo_t *signal_info, void *user_context_raw) // softints per-core.. if (curr && curr->state == RETURNED) return; if (next_context) return; - if (!softint_enabled()) return; - softint_alarm_schedule(user_context_raw); + if (!softint__is_enabled()) return; + softint__schedule_alarm(user_context_raw); break; } case SIGUSR1: { // make sure sigalrm doesn't mess this up if nested.. - assert(!softint_enabled()); + assert(!softint__is_enabled()); /* we set current before calling pthread_kill! */ assert(next_context && (&curr->ctxt == next_context)); assert(signal_info->si_code == SI_TKILL); @@ -159,7 +100,7 @@ softint_handler(int signal_type, siginfo_t *signal_info, void *user_context_raw) // memcpy from next context.. arch_mcontext_restore(&user_context->uc_mcontext, &curr->ctxt); next_context = NULL; - softint_enable(); + softint__enable(); break; } default: @@ -168,16 +109,99 @@ softint_handler(int signal_type, siginfo_t *signal_info, void *user_context_raw) #endif } +/** + * Preempt the current sandbox and start executing the next sandbox + * @param user_context_raw void* to a user_context struct + **/ +static inline void +softint__schedule_alarm(void *user_context_raw) +{ + softint__disable(); // no nesting! + + struct sandbox *curr = get_current_sandbox(); + ucontext_t * user_context = (ucontext_t *)user_context_raw; + + // no sandboxes running..so nothing to preempt..let the "main" scheduler run its course. + if (curr == NULL) goto done; + + // find a next sandbox to run.. + struct sandbox *next = get_next_sandbox_from_local_run_queue(1); + if (next == NULL) goto done; + if (next == curr) goto done; // only this sandbox to schedule.. return to it! + // save the current sandbox, state from user_context! + arch_mcontext_save(&curr->ctxt, &user_context->uc_mcontext); + + // set_current_sandbox on it. restore through *user_context.. + set_current_sandbox(next); + + if (arch_mcontext_restore(&user_context->uc_mcontext, &next->ctxt)) goto skip; + // reset if SIGALRM happens before SIGUSR1 and if don't preempt..OR + // perhaps switch here for SIGUSR1 and see if we can clear that signal + // so it doesn't get called on SIGALRM return.. + // next_context = NULL; + +done: + softint__enable(); +skip: + return; +} + +/*************************************** + * Public Functions + ***************************************/ + +/** + * Arms the Interval Timer to start in 10ms and then trigger a SIGALRM every 5ms + **/ +void +softint__arm_timer(void) +{ +#ifndef PREEMPT_DISABLE + struct itimerval interval_timer; + + memset(&interval_timer, 0, sizeof(struct itimerval)); + interval_timer.it_value.tv_usec = SOFTINT_TIMER_START_USEC; + interval_timer.it_interval.tv_usec = SOFTINT_TIMER_PERIOD_USEC; + + int return_code = setitimer(ITIMER_REAL, &interval_timer, NULL); + if (return_code) { + perror("setitimer"); + exit(1); + } +#endif +} + +/** + * Disarm the Interval Timer + **/ +void +softint__disarm_timer(void) +{ + struct itimerval interval_timer; + + memset(&interval_timer, 0, sizeof(struct itimerval)); + interval_timer.it_value.tv_sec = 0; + interval_timer.it_interval.tv_usec = 0; + + int return_code = setitimer(ITIMER_REAL, &interval_timer, NULL); + if (return_code) { + perror("setitimer"); + exit(1); + } +} + + + /** * Initialize software Interrupts * Register sonftint_handler to execute on SIGALRM and SIGUSR1 **/ void -softint_init(void) +softint__initialize(void) { struct sigaction signal_action; memset(&signal_action, 0, sizeof(struct sigaction)); - signal_action.sa_sigaction = softint_handler; + signal_action.sa_sigaction = softint__handle_signals; signal_action.sa_flags = SA_SIGINFO | SA_RESTART; for (int i = 0; i < (sizeof(softints) / sizeof(softints[0])); i++) {