diff --git a/runtime/include/arch/aarch64/context.h b/runtime/include/arch/aarch64/context.h index 57b5775..f58e22c 100644 --- a/runtime/include/arch/aarch64/context.h +++ b/runtime/include/arch/aarch64/context.h @@ -29,7 +29,6 @@ arch_context_init(struct arch_context *actx, reg_t ip, reg_t sp) actx->regs[UREG_SP] = sp; actx->regs[UREG_IP] = ip; - actx->preemptable = false; } /** diff --git a/runtime/include/arch/arch_context_t.h b/runtime/include/arch/arch_context_t.h index ef5ef5c..bb8483b 100644 --- a/runtime/include/arch/arch_context_t.h +++ b/runtime/include/arch/arch_context_t.h @@ -10,5 +10,4 @@ struct arch_context { arch_context_variant_t variant; reg_t regs[UREG_COUNT]; mcontext_t mctx; - bool preemptable; }; diff --git a/runtime/include/arch/x86_64/context.h b/runtime/include/arch/x86_64/context.h index 5b5543c..657e8e1 100644 --- a/runtime/include/arch/x86_64/context.h +++ b/runtime/include/arch/x86_64/context.h @@ -20,8 +20,6 @@ arch_context_init(struct arch_context *actx, reg_t ip, reg_t sp) actx->variant = ARCH_CONTEXT_VARIANT_FAST; } - actx->preemptable = false; - if (sp) { /* * context_switch conventions: bp is expected to be on top of the stack diff --git a/runtime/include/sandbox_functions.h b/runtime/include/sandbox_functions.h index 055ee3f..4c45fef 100644 --- a/runtime/include/sandbox_functions.h +++ b/runtime/include/sandbox_functions.h @@ -96,50 +96,16 @@ sandbox_print_perf(struct sandbox *sandbox) * becomes more intelligent, then peak linear memory size needs to be tracked * seperately from current linear memory size. */ - fprintf(runtime_sandbox_perf_log, "%lu,%s,%d,%s,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%u,%u\n", sandbox->id, + fprintf(runtime_sandbox_perf_log, + "%lu,%s,%d,%s,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%u,%u\n", sandbox->id, sandbox->module->name, sandbox->module->port, sandbox_state_stringify(sandbox->state), sandbox->module->relative_deadline, sandbox->total_time, queued_duration, - sandbox->duration_of_state.initializing, sandbox->duration_of_state.runnable, - sandbox->duration_of_state.preempted, sandbox->duration_of_state.running_kernel, - sandbox->duration_of_state.running_user, sandbox->duration_of_state.blocked, - sandbox->duration_of_state.returned, runtime_processor_speed_MHz, sandbox->memory.size); -} - -static inline void -sandbox_enable_preemption(struct sandbox *sandbox) -{ -#ifdef LOG_PREEMPTION - debuglog("Sandbox %lu - enabling preemption - Missed %d SIGALRM\n", sandbox->id, - software_interrupt_deferred_sigalrm); - fflush(stderr); -#endif - if (__sync_bool_compare_and_swap(&sandbox->ctxt.preemptable, 0, 1) == false) { - panic("Recursive call to current_sandbox_enable_preemption\n"); - } - - if (software_interrupt_deferred_sigalrm > 0) { - /* Update Max */ - if (software_interrupt_deferred_sigalrm > software_interrupt_deferred_sigalrm_max[worker_thread_idx]) { - software_interrupt_deferred_sigalrm_max[worker_thread_idx] = - software_interrupt_deferred_sigalrm; - } - - software_interrupt_deferred_sigalrm = 0; - - // TODO: Replay. Does the replay need to be before or after enabling preemption? - } -} - -static inline void -sandbox_disable_preemption(struct sandbox *sandbox) -{ -#ifdef LOG_PREEMPTION - debuglog("Sandbox %lu - disabling preemption\n", sandbox->id); - fflush(stderr); -#endif - if (__sync_bool_compare_and_swap(&sandbox->ctxt.preemptable, 1, 0) == false) { - panic("Recursive call to current_sandbox_disable_preemption\n"); - } + sandbox->duration_of_state[SANDBOX_UNINITIALIZED], sandbox->duration_of_state[SANDBOX_ALLOCATED], + sandbox->duration_of_state[SANDBOX_INITIALIZED], sandbox->duration_of_state[SANDBOX_RUNNABLE], + sandbox->duration_of_state[SANDBOX_PREEMPTED], sandbox->duration_of_state[SANDBOX_RUNNING_KERNEL], + sandbox->duration_of_state[SANDBOX_RUNNING_USER], sandbox->duration_of_state[SANDBOX_BLOCKED], + sandbox->duration_of_state[SANDBOX_RETURNED], sandbox->duration_of_state[SANDBOX_COMPLETE], + sandbox->duration_of_state[SANDBOX_ERROR], runtime_processor_speed_MHz, sandbox->memory.size); } static inline void diff --git a/runtime/include/sandbox_set_as_blocked.h b/runtime/include/sandbox_set_as_blocked.h index e3eb24e..f003526 100644 --- a/runtime/include/sandbox_set_as_blocked.h +++ b/runtime/include/sandbox_set_as_blocked.h @@ -20,16 +20,11 @@ static inline void sandbox_set_as_blocked(struct sandbox *sandbox, sandbox_state_t last_state) { assert(sandbox); - - uint64_t now = __getcycles(); - uint64_t duration_of_last_state = now - sandbox->timestamp_of.last_state_change; - - sandbox->state = SANDBOX_SET_AS_BLOCKED; - sandbox_state_history_append(sandbox, SANDBOX_SET_AS_BLOCKED); + sandbox->state = SANDBOX_BLOCKED; + uint64_t now = __getcycles(); switch (last_state) { case SANDBOX_RUNNING_KERNEL: { - sandbox->duration_of_state.running_kernel += duration_of_last_state; local_runqueue_delete(sandbox); break; } @@ -39,10 +34,9 @@ sandbox_set_as_blocked(struct sandbox *sandbox, sandbox_state_t last_state) } } - sandbox->timestamp_of.last_state_change = now; - sandbox->state = SANDBOX_BLOCKED; - /* State Change Bookkeeping */ + sandbox->duration_of_state[last_state] += (now - sandbox->timestamp_of.last_state_change); + sandbox->timestamp_of.last_state_change = now; sandbox_state_history_append(sandbox, SANDBOX_BLOCKED); runtime_sandbox_total_increment(SANDBOX_BLOCKED); runtime_sandbox_total_decrement(last_state); diff --git a/runtime/include/sandbox_set_as_complete.h b/runtime/include/sandbox_set_as_complete.h index f22395a..f2b6b3f 100644 --- a/runtime/include/sandbox_set_as_complete.h +++ b/runtime/include/sandbox_set_as_complete.h @@ -22,17 +22,12 @@ static inline void sandbox_set_as_complete(struct sandbox *sandbox, sandbox_state_t last_state) { assert(sandbox); - - uint64_t now = __getcycles(); - uint64_t duration_of_last_state = now - sandbox->timestamp_of.last_state_change; - - sandbox->state = SANDBOX_SET_AS_COMPLETE; - sandbox_state_history_append(sandbox, SANDBOX_SET_AS_COMPLETE); + sandbox->state = SANDBOX_COMPLETE; + uint64_t now = __getcycles(); switch (last_state) { case SANDBOX_RETURNED: { sandbox->timestamp_of.completion = now; - sandbox->duration_of_state.returned += duration_of_last_state; break; } default: { @@ -41,17 +36,17 @@ sandbox_set_as_complete(struct sandbox *sandbox, sandbox_state_t last_state) } } - sandbox->timestamp_of.last_state_change = now; - sandbox->state = SANDBOX_COMPLETE; - /* State Change Bookkeeping */ + sandbox->duration_of_state[last_state] += (now - sandbox->timestamp_of.last_state_change); + sandbox->timestamp_of.last_state_change = now; sandbox_state_history_append(sandbox, SANDBOX_COMPLETE); runtime_sandbox_total_increment(SANDBOX_COMPLETE); runtime_sandbox_total_decrement(last_state); /* Admissions Control Post Processing */ admissions_info_update(&sandbox->module->admissions_info, - sandbox->duration_of_state.running_user + sandbox->duration_of_state.running_kernel); + sandbox->duration_of_state[SANDBOX_RUNNING_USER] + + sandbox->duration_of_state[SANDBOX_RUNNING_KERNEL]); admissions_control_subtract(sandbox->admissions_estimate); /* Terminal State Logging */ diff --git a/runtime/include/sandbox_set_as_error.h b/runtime/include/sandbox_set_as_error.h index f6d9146..bad7ab2 100644 --- a/runtime/include/sandbox_set_as_error.h +++ b/runtime/include/sandbox_set_as_error.h @@ -27,20 +27,14 @@ static inline void sandbox_set_as_error(struct sandbox *sandbox, sandbox_state_t last_state) { assert(sandbox); - - uint64_t now = __getcycles(); - uint64_t duration_of_last_state = now - sandbox->timestamp_of.last_state_change; - - sandbox->state = SANDBOX_SET_AS_ERROR; - sandbox_state_history_append(sandbox, SANDBOX_SET_AS_ERROR); + sandbox->state = SANDBOX_ERROR; + uint64_t now = __getcycles(); switch (last_state) { - case SANDBOX_SET_AS_INITIALIZED: + case SANDBOX_UNINITIALIZED: /* Technically, this is a degenerate sandbox that we generate by hand */ - sandbox->duration_of_state.initializing += duration_of_last_state; break; case SANDBOX_RUNNING_KERNEL: { - sandbox->duration_of_state.running_kernel += duration_of_last_state; local_runqueue_delete(sandbox); break; } @@ -50,17 +44,17 @@ sandbox_set_as_error(struct sandbox *sandbox, sandbox_state_t last_state) } } - uint64_t sandbox_id = sandbox->id; - sandbox->state = SANDBOX_ERROR; + /* State Change Bookkeeping */ + uint64_t duration_of_last_state = now - sandbox->timestamp_of.last_state_change; + sandbox->duration_of_state[last_state] += duration_of_last_state; + sandbox_state_history_append(sandbox, SANDBOX_ERROR); + runtime_sandbox_total_increment(SANDBOX_ERROR); + runtime_sandbox_total_decrement(last_state); + sandbox_print_perf(sandbox); sandbox_summarize_page_allocations(sandbox); sandbox_free_linear_memory(sandbox); admissions_control_subtract(sandbox->admissions_estimate); /* Do not touch sandbox after adding to completion queue to avoid use-after-free bugs */ local_completion_queue_add(sandbox); - - /* State Change Bookkeeping */ - sandbox_state_history_append(sandbox, SANDBOX_ERROR); - runtime_sandbox_total_increment(SANDBOX_ERROR); - runtime_sandbox_total_decrement(last_state); } diff --git a/runtime/include/sandbox_set_as_initialized.h b/runtime/include/sandbox_set_as_initialized.h index 017d920..0b7f8f9 100644 --- a/runtime/include/sandbox_set_as_initialized.h +++ b/runtime/include/sandbox_set_as_initialized.h @@ -21,18 +21,22 @@ static inline void sandbox_set_as_initialized(struct sandbox *sandbox, struct sandbox_request *sandbox_request, uint64_t allocation_timestamp) { - assert(sandbox != NULL); + assert(sandbox); assert(sandbox->state == SANDBOX_ALLOCATED); assert(sandbox_request != NULL); assert(allocation_timestamp > 0); - - sandbox->id = sandbox_request->id; - sandbox->admissions_estimate = sandbox_request->admissions_estimate; - + sandbox->state = SANDBOX_INITIALIZED; + uint64_t now = __getcycles(); + + /* Copy State from Sandbox Request */ + sandbox->id = sandbox_request->id; + sandbox->absolute_deadline = sandbox_request->absolute_deadline; + sandbox->admissions_estimate = sandbox_request->admissions_estimate; + sandbox->client_socket_descriptor = sandbox_request->socket_descriptor; sandbox->timestamp_of.request_arrival = sandbox_request->request_arrival_timestamp; - sandbox->timestamp_of.allocation = allocation_timestamp; - sandbox->state = SANDBOX_SET_AS_INITIALIZED; - sandbox_state_history_append(sandbox, SANDBOX_SET_AS_INITIALIZED); + /* Copy the socket descriptor and address of the client invocation */ + memcpy(&sandbox->client_address, &sandbox_request->socket_address, sizeof(struct sockaddr)); + /* Initialize the sandbox's context, stack, and instruction pointer */ /* stack.start points to the bottom of the usable stack, so add stack_size to get to top */ @@ -42,15 +46,11 @@ sandbox_set_as_initialized(struct sandbox *sandbox, struct sandbox_request *sand /* Initialize Parsec control structures */ ps_list_init_d(sandbox); - /* Copy the socket descriptor and address of the client invocation */ - sandbox->absolute_deadline = sandbox_request->absolute_deadline; - sandbox->client_socket_descriptor = sandbox_request->socket_descriptor; - memcpy(&sandbox->client_address, &sandbox_request->socket_address, sizeof(struct sockaddr)); - - sandbox->timestamp_of.last_state_change = allocation_timestamp; /* We use arg to include alloc */ - sandbox->state = SANDBOX_INITIALIZED; /* State Change Bookkeeping */ + sandbox->duration_of_state[SANDBOX_ALLOCATED] = now - allocation_timestamp; + sandbox->timestamp_of.allocation = allocation_timestamp; + sandbox->timestamp_of.last_state_change = allocation_timestamp; sandbox_state_history_append(sandbox, SANDBOX_INITIALIZED); runtime_sandbox_total_increment(SANDBOX_INITIALIZED); } diff --git a/runtime/include/sandbox_set_as_preempted.h b/runtime/include/sandbox_set_as_preempted.h index f46efe1..87e9884 100644 --- a/runtime/include/sandbox_set_as_preempted.h +++ b/runtime/include/sandbox_set_as_preempted.h @@ -23,21 +23,11 @@ static inline void sandbox_set_as_preempted(struct sandbox *sandbox, sandbox_state_t last_state) { assert(sandbox); - - /* Preemption occurs indirectly via the SANDBOX_RUNNING_KERNEL state, so preemptable is set - * to false during the process of preemption. - */ - assert(sandbox->ctxt.preemptable == false); - - uint64_t now = __getcycles(); - uint64_t duration_of_last_state = now - sandbox->timestamp_of.last_state_change; - - sandbox->state = SANDBOX_SET_AS_PREEMPTED; - sandbox_state_history_append(sandbox, SANDBOX_SET_AS_PREEMPTED); + sandbox->state = SANDBOX_PREEMPTED; + uint64_t now = __getcycles(); switch (last_state) { case SANDBOX_RUNNING_KERNEL: { - sandbox->duration_of_state.preempted += duration_of_last_state; current_sandbox_set(NULL); break; } @@ -47,10 +37,9 @@ sandbox_set_as_preempted(struct sandbox *sandbox, sandbox_state_t last_state) } } - sandbox->timestamp_of.last_state_change = now; - sandbox->state = SANDBOX_PREEMPTED; - /* State Change Bookkeeping */ + sandbox->duration_of_state[last_state] += (now - sandbox->timestamp_of.last_state_change); + sandbox->timestamp_of.last_state_change = now; sandbox_state_history_append(sandbox, SANDBOX_PREEMPTED); runtime_sandbox_total_increment(SANDBOX_PREEMPTED); runtime_sandbox_total_decrement(last_state); diff --git a/runtime/include/sandbox_set_as_returned.h b/runtime/include/sandbox_set_as_returned.h index e5b286d..90bedd4 100644 --- a/runtime/include/sandbox_set_as_returned.h +++ b/runtime/include/sandbox_set_as_returned.h @@ -23,18 +23,13 @@ static inline void sandbox_set_as_returned(struct sandbox *sandbox, sandbox_state_t last_state) { assert(sandbox); - - uint64_t now = __getcycles(); - uint64_t duration_of_last_state = now - sandbox->timestamp_of.last_state_change; - - sandbox->state = SANDBOX_SET_AS_RETURNED; - sandbox_state_history_append(sandbox, SANDBOX_SET_AS_RETURNED); + sandbox->state = SANDBOX_RETURNED; + uint64_t now = __getcycles(); switch (last_state) { case SANDBOX_RUNNING_KERNEL: { sandbox->timestamp_of.response = now; sandbox->total_time = now - sandbox->timestamp_of.request_arrival; - sandbox->duration_of_state.running_kernel += duration_of_last_state; local_runqueue_delete(sandbox); sandbox_free_linear_memory(sandbox); break; @@ -45,10 +40,9 @@ sandbox_set_as_returned(struct sandbox *sandbox, sandbox_state_t last_state) } } - sandbox->timestamp_of.last_state_change = now; - sandbox->state = SANDBOX_RETURNED; - /* State Change Bookkeeping */ + sandbox->duration_of_state[last_state] += (now - sandbox->timestamp_of.last_state_change); + sandbox->timestamp_of.last_state_change = now; sandbox_state_history_append(sandbox, SANDBOX_RETURNED); runtime_sandbox_total_increment(SANDBOX_RETURNED); runtime_sandbox_total_decrement(last_state); diff --git a/runtime/include/sandbox_set_as_runnable.h b/runtime/include/sandbox_set_as_runnable.h index df56101..b043e0f 100644 --- a/runtime/include/sandbox_set_as_runnable.h +++ b/runtime/include/sandbox_set_as_runnable.h @@ -23,21 +23,15 @@ static inline void sandbox_set_as_runnable(struct sandbox *sandbox, sandbox_state_t last_state) { assert(sandbox); - - uint64_t now = __getcycles(); - uint64_t duration_of_last_state = now - sandbox->timestamp_of.last_state_change; - - sandbox->state = SANDBOX_SET_AS_RUNNABLE; - sandbox_state_history_append(sandbox, SANDBOX_SET_AS_RUNNABLE); + sandbox->state = SANDBOX_RUNNABLE; + uint64_t now = __getcycles(); switch (last_state) { case SANDBOX_INITIALIZED: { - sandbox->duration_of_state.initializing += duration_of_last_state; local_runqueue_add(sandbox); break; } case SANDBOX_BLOCKED: { - sandbox->duration_of_state.blocked += duration_of_last_state; local_runqueue_add(sandbox); break; } @@ -47,10 +41,9 @@ sandbox_set_as_runnable(struct sandbox *sandbox, sandbox_state_t last_state) } } - sandbox->timestamp_of.last_state_change = now; - sandbox->state = SANDBOX_RUNNABLE; - /* State Change Bookkeeping */ + sandbox->duration_of_state[last_state] += (now - sandbox->timestamp_of.last_state_change); + sandbox->timestamp_of.last_state_change = now; sandbox_state_history_append(sandbox, SANDBOX_RUNNABLE); runtime_sandbox_total_increment(SANDBOX_RUNNABLE); runtime_sandbox_total_decrement(last_state); diff --git a/runtime/include/sandbox_set_as_running_kernel.h b/runtime/include/sandbox_set_as_running_kernel.h index 2af5440..39311e6 100644 --- a/runtime/include/sandbox_set_as_running_kernel.h +++ b/runtime/include/sandbox_set_as_running_kernel.h @@ -13,31 +13,17 @@ static inline void sandbox_set_as_running_kernel(struct sandbox *sandbox, sandbox_state_t last_state) { assert(sandbox); - - /* Disable preemption at start of state transition */ - if (last_state == SANDBOX_RUNNING_USER) { - assert(sandbox->ctxt.preemptable == true); - sandbox_disable_preemption(sandbox); - } else { - assert(sandbox->ctxt.preemptable == false); - } - - uint64_t now = __getcycles(); - uint64_t duration_of_last_state = now - sandbox->timestamp_of.last_state_change; - - sandbox->state = SANDBOX_SET_AS_RUNNING_KERNEL; - sandbox_state_history_append(sandbox, SANDBOX_SET_AS_RUNNING_KERNEL); + sandbox->state = SANDBOX_RUNNING_KERNEL; + uint64_t now = __getcycles(); switch (last_state) { case SANDBOX_RUNNING_USER: { assert(sandbox == current_sandbox_get()); - sandbox->duration_of_state.running_user += duration_of_last_state; assert(runtime_worker_threads_deadline[worker_thread_idx] == sandbox->absolute_deadline); break; } case SANDBOX_RUNNABLE: { assert(sandbox); - sandbox->duration_of_state.runnable += duration_of_last_state; current_sandbox_set(sandbox); /* Does not handle context switch because the caller knows if we need to use fast or slow switched. We * can fix this by breakout out SANDBOX_RUNNABLE and SANDBOX_PREEMPTED */ @@ -46,7 +32,6 @@ sandbox_set_as_running_kernel(struct sandbox *sandbox, sandbox_state_t last_stat case SANDBOX_PREEMPTED: { assert(sandbox); assert(sandbox->interrupted_state == SANDBOX_RUNNING_USER); - sandbox->duration_of_state.preempted += duration_of_last_state; current_sandbox_set(sandbox); /* Does not handle context switch because the caller knows if we need to use fast or slow switched. We * can fix this by breakout out SANDBOX_RUNNABLE and SANDBOX_PREEMPTED */ @@ -58,10 +43,9 @@ sandbox_set_as_running_kernel(struct sandbox *sandbox, sandbox_state_t last_stat } } - sandbox->timestamp_of.last_state_change = now; - sandbox->state = SANDBOX_RUNNING_KERNEL; - /* State Change Bookkeeping */ + sandbox->duration_of_state[last_state] += (now - sandbox->timestamp_of.last_state_change); + sandbox->timestamp_of.last_state_change = now; sandbox_state_history_append(sandbox, SANDBOX_RUNNING_KERNEL); runtime_sandbox_total_increment(SANDBOX_RUNNING_KERNEL); runtime_sandbox_total_decrement(last_state); diff --git a/runtime/include/sandbox_set_as_running_user.h b/runtime/include/sandbox_set_as_running_user.h index 5063441..16f861c 100644 --- a/runtime/include/sandbox_set_as_running_user.h +++ b/runtime/include/sandbox_set_as_running_user.h @@ -14,14 +14,10 @@ sandbox_set_as_running_user(struct sandbox *sandbox, sandbox_state_t last_state) { assert(sandbox); - uint64_t now = __getcycles(); - uint64_t duration_of_last_state = now - sandbox->timestamp_of.last_state_change; - - sandbox->state = SANDBOX_SET_AS_RUNNING_USER; + uint64_t now = __getcycles(); switch (last_state) { case SANDBOX_RUNNING_KERNEL: { - sandbox->duration_of_state.running_user += duration_of_last_state; assert(sandbox == current_sandbox_get()); assert(runtime_worker_threads_deadline[worker_thread_idx] == sandbox->absolute_deadline); @@ -33,16 +29,15 @@ sandbox_set_as_running_user(struct sandbox *sandbox, sandbox_state_t last_state) } } - sandbox->timestamp_of.last_state_change = now; - sandbox->state = SANDBOX_RUNNING_USER; /* State Change Bookkeeping */ + sandbox->duration_of_state[last_state] += (now - sandbox->timestamp_of.last_state_change); + sandbox->timestamp_of.last_state_change = now; sandbox_state_history_append(sandbox, SANDBOX_RUNNING_USER); runtime_sandbox_total_increment(SANDBOX_RUNNING_USER); runtime_sandbox_total_decrement(last_state); - /* Enable preemption at the end of state transition*/ - assert(last_state == SANDBOX_RUNNING_KERNEL); - - sandbox_enable_preemption(sandbox); + /* WARNING: This state change needs to be at the end of this transition because all code below this assignment + * is preemptable */ + sandbox->state = SANDBOX_RUNNING_USER; } diff --git a/runtime/include/sandbox_state.h b/runtime/include/sandbox_state.h index 6914834..bf10f49 100644 --- a/runtime/include/sandbox_state.h +++ b/runtime/include/sandbox_state.h @@ -10,40 +10,18 @@ typedef enum { SANDBOX_UNINITIALIZED = 0, /* Assumption: mmap zeros out structure */ SANDBOX_ALLOCATED, - SANDBOX_SET_AS_INITIALIZED, SANDBOX_INITIALIZED, - SANDBOX_SET_AS_RUNNABLE, SANDBOX_RUNNABLE, - SANDBOX_SET_AS_PREEMPTED, SANDBOX_PREEMPTED, - SANDBOX_SET_AS_RUNNING_KERNEL, SANDBOX_RUNNING_KERNEL, - SANDBOX_SET_AS_RUNNING_USER, SANDBOX_RUNNING_USER, - SANDBOX_SET_AS_BLOCKED, SANDBOX_BLOCKED, - SANDBOX_SET_AS_RETURNED, SANDBOX_RETURNED, - SANDBOX_SET_AS_COMPLETE, SANDBOX_COMPLETE, - SANDBOX_SET_AS_ERROR, SANDBOX_ERROR, SANDBOX_STATE_COUNT } sandbox_state_t; -/* Duration of time (in cycles) that the sandbox is in each state */ -struct sandbox_state_durations { - uint64_t initializing; - uint64_t runnable; - uint64_t running_kernel; - uint64_t running_user; - uint64_t preempted; - uint64_t blocked; - uint64_t returned; -}; - -extern const bool sandbox_state_is_terminal[SANDBOX_STATE_COUNT]; - extern const char *sandbox_state_labels[SANDBOX_STATE_COUNT]; static inline const char * @@ -69,7 +47,6 @@ static inline void runtime_sandbox_total_increment(sandbox_state_t state) { #ifdef LOG_SANDBOX_COUNT - if (!sandbox_state_is_terminal[state]) panic("Unexpectedly logging intermediate transition state"); atomic_fetch_add(&sandbox_state_count[state], 1); #endif } diff --git a/runtime/include/sandbox_types.h b/runtime/include/sandbox_types.h index a8fea4c..d384253 100644 --- a/runtime/include/sandbox_types.h +++ b/runtime/include/sandbox_types.h @@ -101,8 +101,8 @@ struct sandbox { struct wasm_memory memory; /* Scheduling and Temporal State */ - struct sandbox_timestamps timestamp_of; - struct sandbox_state_durations duration_of_state; + struct sandbox_timestamps timestamp_of; + uint64_t duration_of_state[SANDBOX_STATE_COUNT]; uint64_t absolute_deadline; uint64_t admissions_estimate; /* estimated execution time (cycles) * runtime_admissions_granularity / relative diff --git a/runtime/include/worker_thread_execute_epoll_loop.h b/runtime/include/worker_thread_execute_epoll_loop.h index 96b922f..c9d86de 100644 --- a/runtime/include/worker_thread_execute_epoll_loop.h +++ b/runtime/include/worker_thread_execute_epoll_loop.h @@ -60,11 +60,8 @@ worker_thread_execute_epoll_loop(void) } switch (sandbox->state) { - case SANDBOX_SET_AS_RETURNED: case SANDBOX_RETURNED: - case SANDBOX_SET_AS_COMPLETE: case SANDBOX_COMPLETE: - case SANDBOX_SET_AS_ERROR: case SANDBOX_ERROR: panic("Expected to have closed socket"); default: diff --git a/runtime/src/current_sandbox.c b/runtime/src/current_sandbox.c index 2505f5c..e4f8a36 100644 --- a/runtime/src/current_sandbox.c +++ b/runtime/src/current_sandbox.c @@ -59,9 +59,7 @@ current_sandbox_start(void) /* Executing the function */ int32_t argument_count = 0; assert(sandbox->state == SANDBOX_RUNNING_KERNEL); - assert(sandbox->ctxt.preemptable == false); sandbox_set_as_running_user(sandbox, SANDBOX_RUNNING_KERNEL); - assert(sandbox->ctxt.preemptable == true); sandbox->return_value = module_entrypoint(current_module, argument_count, sandbox->arguments_offset); assert(sandbox->state == SANDBOX_RUNNING_USER); sandbox_set_as_running_kernel(sandbox, SANDBOX_RUNNING_USER); diff --git a/runtime/src/sandbox.c b/runtime/src/sandbox.c index 45b07a0..0841e82 100644 --- a/runtime/src/sandbox.c +++ b/runtime/src/sandbox.c @@ -73,6 +73,8 @@ sandbox_allocate_memory(struct module *module) sandbox->memory.size = memory_size; sandbox->memory.max = memory_max; + for (int i = 0; i < SANDBOX_STATE_COUNT; i++) { sandbox->duration_of_state[i] = 0; } + done: return sandbox; set_rw_failed: @@ -171,14 +173,14 @@ err_stack_allocation_failed: * This is a degenerate sandbox that never successfully completed initialization, so we need to * hand jam some things to be able to cleanly transition to ERROR state */ - sandbox->state = SANDBOX_SET_AS_INITIALIZED; + sandbox->state = SANDBOX_UNINITIALIZED; sandbox->timestamp_of.last_state_change = now; #ifdef LOG_SANDBOX_MEMORY_PROFILE sandbox->timestamp_of.page_allocations_size = 0; #endif ps_list_init_d(sandbox); err_memory_allocation_failed: - sandbox_set_as_error(sandbox, SANDBOX_SET_AS_INITIALIZED); + sandbox_set_as_error(sandbox, SANDBOX_UNINITIALIZED); perror(error_message); sandbox = NULL; goto done; diff --git a/runtime/src/sandbox_state.c b/runtime/src/sandbox_state.c index 0356292..72b366a 100644 --- a/runtime/src/sandbox_state.c +++ b/runtime/src/sandbox_state.c @@ -7,41 +7,19 @@ #include "debuglog.h" #include "sandbox_state.h" -const bool sandbox_state_is_terminal[SANDBOX_STATE_COUNT] = { - [SANDBOX_UNINITIALIZED] = false, [SANDBOX_ALLOCATED] = false, - [SANDBOX_INITIALIZED] = true, [SANDBOX_SET_AS_RUNNABLE] = false, - [SANDBOX_RUNNABLE] = true, [SANDBOX_SET_AS_PREEMPTED] = false, - [SANDBOX_PREEMPTED] = true, [SANDBOX_SET_AS_RUNNING_KERNEL] = false, - [SANDBOX_RUNNING_KERNEL] = true, [SANDBOX_SET_AS_RUNNING_USER] = false, - [SANDBOX_RUNNING_USER] = true, [SANDBOX_SET_AS_BLOCKED] = false, - [SANDBOX_BLOCKED] = true, [SANDBOX_SET_AS_RETURNED] = false, - [SANDBOX_RETURNED] = true, [SANDBOX_SET_AS_COMPLETE] = false, - [SANDBOX_COMPLETE] = true, [SANDBOX_SET_AS_ERROR] = false, - [SANDBOX_ERROR] = true -}; - const char *sandbox_state_labels[SANDBOX_STATE_COUNT] = { - [SANDBOX_UNINITIALIZED] = "Uninitialized", - [SANDBOX_ALLOCATED] = "Allocated", - [SANDBOX_SET_AS_INITIALIZED] = "Transitioning to Initialized", - [SANDBOX_INITIALIZED] = "Initialized", - [SANDBOX_SET_AS_RUNNABLE] = "Transitioning to Runnable", - [SANDBOX_RUNNABLE] = "Runnable", - [SANDBOX_SET_AS_PREEMPTED] = "Transitioning to Preempted", - [SANDBOX_PREEMPTED] = "Preempted", - [SANDBOX_SET_AS_RUNNING_KERNEL] = "Transitioning to Running Kernel", - [SANDBOX_RUNNING_KERNEL] = "Running Kernel", - [SANDBOX_SET_AS_RUNNING_USER] = "Transitioning to Running User", - [SANDBOX_RUNNING_USER] = "Running User", - [SANDBOX_SET_AS_BLOCKED] = "Transitioning to Blocked", - [SANDBOX_BLOCKED] = "Blocked", - [SANDBOX_SET_AS_RETURNED] = "Transitioning to Returned", - [SANDBOX_RETURNED] = "Returned", - [SANDBOX_SET_AS_COMPLETE] = "Transitioning to Complete", - [SANDBOX_COMPLETE] = "Complete", - [SANDBOX_SET_AS_ERROR] = "Transitioning to Error", - [SANDBOX_ERROR] = "Error" + [SANDBOX_UNINITIALIZED] = "Uninitialized", + [SANDBOX_ALLOCATED] = "Allocated", + [SANDBOX_INITIALIZED] = "Initialized", + [SANDBOX_RUNNABLE] = "Runnable", + [SANDBOX_PREEMPTED] = "Preempted", + [SANDBOX_RUNNING_KERNEL] = "Running Kernel", + [SANDBOX_RUNNING_USER] = "Running User", + [SANDBOX_BLOCKED] = "Blocked", + [SANDBOX_RETURNED] = "Returned", + [SANDBOX_COMPLETE] = "Complete", + [SANDBOX_ERROR] = "Error" }; #ifdef LOG_SANDBOX_COUNT diff --git a/runtime/src/software_interrupt.c b/runtime/src/software_interrupt.c index 24d19c0..e6d181c 100644 --- a/runtime/src/software_interrupt.c +++ b/runtime/src/software_interrupt.c @@ -139,7 +139,6 @@ software_interrupt_handle_signals(int signal_type, siginfo_t *signal_info, void assert(runtime_preemption_enabled); /* Signals should not nest */ - /* TODO: Better atomic instruction here to check and set? */ assert(software_interrupt_signal_depth == 0); atomic_fetch_add(&software_interrupt_signal_depth, 1); @@ -148,18 +147,17 @@ software_interrupt_handle_signals(int signal_type, siginfo_t *signal_info, void switch (signal_type) { case SIGALRM: { - bool preemptable = false; - if (current_sandbox) { - preemptable = current_sandbox->ctxt.preemptable; - current_sandbox->interrupted_state = current_sandbox->state; - if (preemptable && current_sandbox->state == SANDBOX_RUNNING_USER) { - sandbox_set_as_running_kernel(current_sandbox, SANDBOX_RUNNING_USER); - } - } - sigalrm_propagate_workers(signal_info); - if (preemptable) { + /* Current Sandbox is NULL when the base worker context is active. This already executes scheduling + * logic, so just return. */ + if (!current_sandbox) goto done; + + /* We need to track what state was interrupted to conditionally restore user running after preemption */ + current_sandbox->interrupted_state = current_sandbox->state; + + if (current_sandbox->state == SANDBOX_RUNNING_USER) { + sandbox_set_as_running_kernel(current_sandbox, SANDBOX_RUNNING_USER); atomic_store(&software_interrupt_deferred_sigalrm, 0); current_sandbox = scheduler_preempt(interrupted_context); } else {