diff --git a/runtime/include/arch/common.h b/runtime/include/arch/common.h index 95ed123..0f4148f 100644 --- a/runtime/include/arch/common.h +++ b/runtime/include/arch/common.h @@ -12,6 +12,7 @@ #include "arch/reg_t.h" #include "arch/ureg_t.h" #include "software_interrupt.h" +#include "worker_thread.h" /* * This file contains the common dependencies of the architecture-dependent code. @@ -27,7 +28,6 @@ * This is the slowpath switch to a preempted sandbox! * SIGUSR1 on the current thread and restore mcontext there! */ -extern __thread struct arch_context worker_thread_base_context; /* Cannot be inlined because called in assembly */ void __attribute__((noinline)) __attribute__((noreturn)) arch_context_restore_preempted(void); diff --git a/runtime/include/arch/x86_64/context.h b/runtime/include/arch/x86_64/context.h index 7cf9685..67afedc 100644 --- a/runtime/include/arch/x86_64/context.h +++ b/runtime/include/arch/x86_64/context.h @@ -86,7 +86,7 @@ static inline int arch_context_switch(struct arch_context *a, struct arch_context *b) { /* Assumption: Software Interrupts are disabled by caller */ - assert(software_interrupt_is_disabled); + assert(!software_interrupt_is_enabled()); /* if both a and b are NULL, there is no state change */ assert(a != NULL || b != NULL); diff --git a/runtime/include/current_sandbox.h b/runtime/include/current_sandbox.h index 668f8ec..05fadd6 100644 --- a/runtime/include/current_sandbox.h +++ b/runtime/include/current_sandbox.h @@ -4,3 +4,4 @@ struct sandbox *current_sandbox_get(void); void current_sandbox_set(struct sandbox *sandbox); +void current_sandbox_block(void); diff --git a/runtime/include/sandbox.h b/runtime/include/sandbox.h index f360fbe..b377d56 100644 --- a/runtime/include/sandbox.h +++ b/runtime/include/sandbox.h @@ -114,15 +114,58 @@ void sandbox_free_linear_memory(struct sandbox *sandbox); int sandbox_get_file_descriptor(struct sandbox *sandbox, int io_handle_index); int sandbox_initialize_io_handle(struct sandbox *sandbox); void sandbox_main(struct sandbox *sandbox); - -void sandbox_close_http(struct sandbox *sandbox); - -INLINE void sandbox_set_as_initialized(struct sandbox *sandbox, struct sandbox_request *sandbox_request, - uint64_t allocation_timestamp); -INLINE void sandbox_set_as_runnable(struct sandbox *sandbox, sandbox_state_t last_state); -INLINE void sandbox_set_as_running(struct sandbox *sandbox, sandbox_state_t last_state); -INLINE void sandbox_set_as_blocked(struct sandbox *sandbox, sandbox_state_t last_state); -INLINE void sandbox_set_as_preempted(struct sandbox *sandbox, sandbox_state_t last_state); -INLINE void sandbox_set_as_returned(struct sandbox *sandbox, sandbox_state_t last_state); -INLINE void sandbox_set_as_complete(struct sandbox *sandbox, sandbox_state_t last_state); -INLINE void sandbox_set_as_error(struct sandbox *sandbox, sandbox_state_t last_state); +void sandbox_set_as_initialized(struct sandbox *sandbox, struct sandbox_request *sandbox_request, + uint64_t allocation_timestamp); +void sandbox_set_as_runnable(struct sandbox *sandbox, sandbox_state_t last_state); +void sandbox_set_as_running(struct sandbox *sandbox, sandbox_state_t last_state); +void sandbox_set_as_blocked(struct sandbox *sandbox, sandbox_state_t last_state); +void sandbox_set_as_preempted(struct sandbox *sandbox, sandbox_state_t last_state); +void sandbox_set_as_returned(struct sandbox *sandbox, sandbox_state_t last_state); +void sandbox_set_as_complete(struct sandbox *sandbox, sandbox_state_t last_state); +void sandbox_set_as_error(struct sandbox *sandbox, sandbox_state_t last_state); +void sandbox_switch_to(struct sandbox *next_sandbox); + + +/** + * Conditionally triggers appropriate state changes for exiting sandboxes + * @param exiting_sandbox - The sandbox that ran to completion + */ +static inline void +sandbox_exit(struct sandbox *exiting_sandbox) +{ + assert(exiting_sandbox != NULL); + + switch (exiting_sandbox->state) { + case SANDBOX_RETURNED: + /* + * We draw a distinction between RETURNED and COMPLETED because a sandbox cannot add itself to the + * completion queue + */ + sandbox_set_as_complete(exiting_sandbox, SANDBOX_RETURNED); + break; + case SANDBOX_BLOCKED: + /* Cooperative yield, so just break */ + break; + case SANDBOX_ERROR: + /* Terminal State, so just break */ + break; + default: + panic("Cooperatively switching from a sandbox in a non-terminal %s state\n", + sandbox_state_stringify(exiting_sandbox->state)); + } +} + +/** + * Mark a blocked sandbox as runnable and add it to the runqueue + * @param sandbox the sandbox to check and update if blocked + */ +static inline void +sandbox_wakeup(struct sandbox *sandbox) +{ + assert(sandbox != NULL); + assert(sandbox->state == SANDBOX_BLOCKED); + + software_interrupt_disable(); + sandbox_set_as_runnable(sandbox, SANDBOX_BLOCKED); + software_interrupt_enable(); +} diff --git a/runtime/include/software_interrupt.h b/runtime/include/software_interrupt.h index b587e90..1a6325c 100644 --- a/runtime/include/software_interrupt.h +++ b/runtime/include/software_interrupt.h @@ -16,7 +16,6 @@ ***********/ extern __thread volatile sig_atomic_t software_interrupt_is_disabled; -extern uint64_t software_interrupt_interval_duration_in_cycles; /************************* * Public Static Inlines * @@ -30,7 +29,6 @@ software_interrupt_disable(void) } } - /** * Enables signals */ @@ -107,3 +105,4 @@ software_interrupt_unmask_signal(int signal) void software_interrupt_initialize(void); void software_interrupt_arm_timer(void); void software_interrupt_disarm_timer(void); +void software_interrupt_set_interval_duration(uint64_t cycles); diff --git a/runtime/include/worker_thread.h b/runtime/include/worker_thread.h index 92f064f..a95818e 100644 --- a/runtime/include/worker_thread.h +++ b/runtime/include/worker_thread.h @@ -3,8 +3,9 @@ #include "generic_thread.h" #include "runtime.h" -extern __thread int worker_thread_epoll_file_descriptor; -extern __thread int worker_thread_idx; +extern __thread struct arch_context worker_thread_base_context; +extern __thread int worker_thread_epoll_file_descriptor; +extern __thread int worker_thread_idx; void *worker_thread_main(void *return_code); @@ -48,5 +49,4 @@ worker_thread_get_memory_string(uint32_t offset, uint32_t max_length) return NULL; } -void worker_thread_block_current_sandbox(void); -__attribute__((noreturn)) void worker_thread_on_sandbox_exit(); +void worker_thread_switch_to_base_context(); diff --git a/runtime/src/current_sandbox.c b/runtime/src/current_sandbox.c index 296e563..f6f8f27 100644 --- a/runtime/src/current_sandbox.c +++ b/runtime/src/current_sandbox.c @@ -1,4 +1,6 @@ #include "current_sandbox.h" +#include "local_runqueue.h" +#include "worker_thread.h" /* current sandbox that is active.. */ static __thread struct sandbox *worker_thread_current_sandbox = NULL; @@ -43,3 +45,29 @@ current_sandbox_set(struct sandbox *sandbox) worker_thread_current_sandbox = sandbox; } } + +/** + * Mark the currently executing sandbox as blocked, remove it from the local runqueue, + * and switch to base context + */ +void +current_sandbox_block(void) +{ + software_interrupt_disable(); + + /* Remove the sandbox we were just executing from the runqueue and mark as blocked */ + struct sandbox *current_sandbox = current_sandbox_get(); + + assert(current_sandbox->state == SANDBOX_RUNNING); + sandbox_set_as_blocked(current_sandbox, SANDBOX_RUNNING); + generic_thread_dump_lock_overhead(); + + /* The worker thread seems to "spin" on a blocked sandbox, so try to execute another sandbox for one quantum + * after blocking to give time for the action to resolve */ + struct sandbox *next_sandbox = local_runqueue_get_next(); + if (next_sandbox != NULL) { + sandbox_switch_to(next_sandbox); + } else { + worker_thread_switch_to_base_context(); + }; +} diff --git a/runtime/src/libc/syscall.c b/runtime/src/libc/syscall.c index 588b304..39c9054 100644 --- a/runtime/src/libc/syscall.c +++ b/runtime/src/libc/syscall.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "current_sandbox.h" @@ -111,7 +112,7 @@ wasm_read(int32_t filedes, int32_t buf_offset, int32_t nbyte) int32_t length_read = (int32_t)read(filedes, buf, nbyte); if (length_read < 0) { if (errno == EAGAIN) - worker_thread_block_current_sandbox(); + current_sandbox_block(); else { /* All other errors */ debuglog("Error reading socket %d - %s\n", filedes, strerror(errno)); @@ -154,7 +155,7 @@ wasm_write(int32_t fd, int32_t buf_offset, int32_t buf_size) int32_t length_written = (int32_t)write(f, buf, buf_size); if (length_written < 0) { if (errno == EAGAIN) - worker_thread_block_current_sandbox(); + current_sandbox_block(); else { /* All other errors */ debuglog("Error reading socket %d - %s\n", fd, strerror(errno)); diff --git a/runtime/src/main.c b/runtime/src/main.c index 2534416..67a4715 100644 --- a/runtime/src/main.c +++ b/runtime/src/main.c @@ -341,7 +341,8 @@ main(int argc, char **argv) runtime_processor_speed_MHz = runtime_get_processor_speed_MHz(); if (unlikely(runtime_processor_speed_MHz == 0)) panic("Failed to detect processor speed\n"); - software_interrupt_interval_duration_in_cycles = (uint64_t)runtime_quantum_us * runtime_processor_speed_MHz; + software_interrupt_set_interval_duration(runtime_quantum_us * runtime_processor_speed_MHz); + printf("\tProcessor Speed: %u MHz\n", runtime_processor_speed_MHz); runtime_set_resource_limits_to_max(); diff --git a/runtime/src/sandbox.c b/runtime/src/sandbox.c index 2f88d05..b083765 100644 --- a/runtime/src/sandbox.c +++ b/runtime/src/sandbox.c @@ -154,7 +154,7 @@ sandbox_receive_and_parse_client_request(struct sandbox *sandbox) if (recved < 0) { if (errno == EAGAIN) { - worker_thread_block_current_sandbox(); + current_sandbox_block(); continue; } else { /* All other errors */ @@ -297,7 +297,7 @@ sandbox_build_and_send_client_response(struct sandbox *sandbox) response_cursor - sent); if (rc < 0) { if (errno == EAGAIN) - worker_thread_block_current_sandbox(); + current_sandbox_block(); else { perror("write"); return -1; @@ -505,7 +505,8 @@ sandbox_start(void) done: /* Cleanup connection and exit sandbox */ - worker_thread_on_sandbox_exit(sandbox); + generic_thread_dump_lock_overhead(); + worker_thread_switch_to_base_context(); /* This assert prevents a segfault discussed in * https://github.com/phanikishoreg/awsm-Serverless-Framework/issues/66 @@ -932,9 +933,7 @@ sandbox_set_as_error(struct sandbox *sandbox, sandbox_state_t last_state) uint64_t sandbox_id = sandbox->id; sandbox->state = SANDBOX_ERROR; sandbox_print_perf(sandbox); -#ifdef LOG_SANDBOX_MEMORY_PROFILE sandbox_summarize_page_allocations(sandbox); -#endif 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 */ @@ -979,9 +978,7 @@ sandbox_set_as_complete(struct sandbox *sandbox, sandbox_state_t last_state) uint64_t sandbox_id = sandbox->id; sandbox->state = SANDBOX_COMPLETE; sandbox_print_perf(sandbox); -#ifdef LOG_SANDBOX_MEMORY_PROFILE sandbox_summarize_page_allocations(sandbox); -#endif /* Admissions Control Post Processing */ admissions_info_update(&sandbox->module->admissions_info, sandbox->running_duration); admissions_control_subtract(sandbox->admissions_estimate); @@ -1116,3 +1113,65 @@ err: /* Errors freeing memory is a fatal error */ panic("Failed to free Sandbox %lu\n", sandbox->id); } + +/** + * @brief Switches to the next sandbox, placing the current sandbox on the completion queue if in SANDBOX_RETURNED state + * @param next_sandbox The Sandbox Context to switch to + */ +void +sandbox_switch_to(struct sandbox *next_sandbox) +{ + /* Assumption: The caller disables interrupts */ + assert(!software_interrupt_is_enabled()); + + assert(next_sandbox != NULL); + struct arch_context *next_context = &next_sandbox->ctxt; + + /* Get the old sandbox we're switching from */ + struct sandbox *current_sandbox = current_sandbox_get(); + + /* Update the worker's absolute deadline */ + runtime_worker_threads_deadline[worker_thread_idx] = next_sandbox->absolute_deadline; + + if (current_sandbox == NULL) { + /* Switching from "Base Context" */ + + sandbox_set_as_running(next_sandbox, next_sandbox->state); + +#ifdef LOG_CONTEXT_SWITCHES + debuglog("Base Context (@%p) (%s) > Sandbox %lu (@%p) (%s)\n", &worker_thread_base_context, + arch_context_variant_print(worker_thread_base_context.variant), next_sandbox->id, next_context, + arch_context_variant_print(next_context->variant)); +#endif + /* Assumption: If a slow context switch, current sandbox should be set to the target */ + assert(next_context->variant != ARCH_CONTEXT_VARIANT_SLOW + || ¤t_sandbox_get()->ctxt == next_context); + + arch_context_switch(NULL, next_context); + } else { + /* Set the current sandbox to the next */ + assert(next_sandbox != current_sandbox); + + struct arch_context *current_context = ¤t_sandbox->ctxt; + +#ifdef LOG_CONTEXT_SWITCHES + debuglog("Sandbox %lu (@%p) (%s) > Sandbox %lu (@%p) (%s)\n", current_sandbox->id, + ¤t_sandbox->ctxt, arch_context_variant_print(current_sandbox->ctxt.variant), + next_sandbox->id, &next_sandbox->ctxt, arch_context_variant_print(next_context->variant)); +#endif + + sandbox_exit(current_sandbox); + + sandbox_set_as_running(next_sandbox, next_sandbox->state); + +#ifndef NDEBUG + assert(next_context->variant != ARCH_CONTEXT_VARIANT_SLOW + || ¤t_sandbox_get()->ctxt == next_context); +#endif + + /* Switch to the associated context. */ + arch_context_switch(current_context, next_context); + } + + software_interrupt_enable(); +} diff --git a/runtime/src/software_interrupt.c b/runtime/src/software_interrupt.c index fe45d1e..e014f2b 100644 --- a/runtime/src/software_interrupt.c +++ b/runtime/src/software_interrupt.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -24,7 +25,7 @@ ******************/ static const int software_interrupt_supported_signals[] = { SIGALRM, SIGUSR1 }; -uint64_t software_interrupt_interval_duration_in_cycles; +static uint64_t software_interrupt_interval_duration_in_cycles; /****************** * Thread Globals * @@ -45,9 +46,6 @@ extern pthread_t runtime_worker_threads[]; * Private Static Inlines * *************************/ -static inline void software_interrupt_handle_signals(int signal_type, siginfo_t *signal_info, void *user_context_raw); - - /** * A POSIX signal is delivered to only one thread. * This function broadcasts the sigalarm signal to all other worker threads @@ -68,15 +66,20 @@ sigalrm_propagate_workers(siginfo_t *signal_info) assert(runtime_worker_threads[i] != 0); /* If using EDF, conditionally send signals. If not, broadcast */ - if (runtime_sigalrm_handler == RUNTIME_SIGALRM_HANDLER_TRIAGED) { + switch (runtime_sigalrm_handler) { + case RUNTIME_SIGALRM_HANDLER_TRIAGED: { uint64_t local_deadline = runtime_worker_threads_deadline[i]; uint64_t global_deadline = global_request_scheduler_peek(); if (global_deadline < local_deadline) pthread_kill(runtime_worker_threads[i], SIGALRM); - return; - } else if (runtime_sigalrm_handler == RUNTIME_SIGALRM_HANDLER_BROADCAST) { + continue; + } + case RUNTIME_SIGALRM_HANDLER_BROADCAST: { pthread_kill(runtime_worker_threads[i], SIGALRM); - } else { - panic("Unexpected SIGALRM Handler: %d\n", runtime_sigalrm_handler) + continue; + } + default: { + panic("Unexpected SIGALRM Handler: %d\n", runtime_sigalrm_handler); + } } } } else { @@ -100,7 +103,6 @@ sigalrm_handler(siginfo_t *signal_info, ucontext_t *user_context, struct sandbox { sigalrm_propagate_workers(signal_info); - /* NOOP if software interrupts not enabled */ if (!software_interrupt_is_enabled()) return; @@ -279,3 +281,9 @@ software_interrupt_initialize(void) } } } + +void +software_interrupt_set_interval_duration(uint64_t cycles) +{ + software_interrupt_interval_duration_in_cycles = cycles; +} diff --git a/runtime/src/worker_thread.c b/runtime/src/worker_thread.c index e528a8b..a57c383 100644 --- a/runtime/src/worker_thread.c +++ b/runtime/src/worker_thread.c @@ -34,102 +34,10 @@ __thread int worker_thread_idx; * Worker Thread Logic * **********************/ -/** - * Conditionally triggers appropriate state changes for exiting sandboxes - * @param exiting_sandbox - The sandbox that ran to completion - */ -static inline void -worker_thread_transition_exiting_sandbox(struct sandbox *exiting_sandbox) -{ - assert(exiting_sandbox != NULL); - - switch (exiting_sandbox->state) { - case SANDBOX_RETURNED: - /* - * We draw a distinction between RETURNED and COMPLETED because a sandbox cannot add itself to the - * completion queue - */ - sandbox_set_as_complete(exiting_sandbox, SANDBOX_RETURNED); - break; - case SANDBOX_BLOCKED: - /* Cooperative yield, so just break */ - break; - case SANDBOX_ERROR: - /* Terminal State, so just break */ - break; - default: - panic("Cooperatively switching from a sandbox in a non-terminal %s state\n", - sandbox_state_stringify(exiting_sandbox->state)); - } -} - -/** - * @brief Switches to the next sandbox, placing the current sandbox on the completion queue if in SANDBOX_RETURNED state - * @param next_sandbox The Sandbox Context to switch to - */ -static inline void -worker_thread_switch_to_sandbox(struct sandbox *next_sandbox) -{ - /* Assumption: The caller disables interrupts */ - assert(software_interrupt_is_disabled); - - assert(next_sandbox != NULL); - struct arch_context *next_context = &next_sandbox->ctxt; - - /* Get the old sandbox we're switching from */ - struct sandbox *current_sandbox = current_sandbox_get(); - - /* Update the worker's absolute deadline */ - runtime_worker_threads_deadline[worker_thread_idx] = next_sandbox->absolute_deadline; - - if (current_sandbox == NULL) { - /* Switching from "Base Context" */ - - sandbox_set_as_running(next_sandbox, next_sandbox->state); - -#ifdef LOG_CONTEXT_SWITCHES - debuglog("Base Context (@%p) (%s) > Sandbox %lu (@%p) (%s)\n", &worker_thread_base_context, - arch_context_variant_print(worker_thread_base_context.variant), next_sandbox->id, next_context, - arch_context_variant_print(next_context->variant)); -#endif - /* Assumption: If a slow context switch, current sandbox should be set to the target */ - assert(next_context->variant != ARCH_CONTEXT_VARIANT_SLOW - || ¤t_sandbox_get()->ctxt == next_context); - - arch_context_switch(NULL, next_context); - } else { - /* Set the current sandbox to the next */ - assert(next_sandbox != current_sandbox); - - struct arch_context *current_context = ¤t_sandbox->ctxt; - -#ifdef LOG_CONTEXT_SWITCHES - debuglog("Sandbox %lu (@%p) (%s) > Sandbox %lu (@%p) (%s)\n", current_sandbox->id, - ¤t_sandbox->ctxt, arch_context_variant_print(current_sandbox->ctxt.variant), - next_sandbox->id, &next_sandbox->ctxt, arch_context_variant_print(next_context->variant)); -#endif - - worker_thread_transition_exiting_sandbox(current_sandbox); - - sandbox_set_as_running(next_sandbox, next_sandbox->state); - -#ifndef NDEBUG - assert(next_context->variant != ARCH_CONTEXT_VARIANT_SLOW - || ¤t_sandbox_get()->ctxt == next_context); -#endif - - /* Switch to the associated context. */ - arch_context_switch(current_context, next_context); - } - - software_interrupt_enable(); -} - - /** * @brief Switches to the base context, placing the current sandbox on the completion queue if in RETURNED state */ -static inline void +void worker_thread_switch_to_base_context() { assert(!software_interrupt_is_enabled()); @@ -148,12 +56,12 @@ worker_thread_switch_to_base_context() assert(current_context != &worker_thread_base_context); #ifdef LOG_CONTEXT_SWITCHES - debuglog("Sandbox %lu (@%p) (%s)> Base Context (@%p) (%s)\n", current_sandbox->id, current_context, + debuglog("Sandbox %lu (@%p) (%s) > Base Context (@%p) (%s)\n", current_sandbox->id, current_context, arch_context_variant_print(current_sandbox->ctxt.variant), &worker_thread_base_context, arch_context_variant_print(worker_thread_base_context.variant)); #endif - worker_thread_transition_exiting_sandbox(current_sandbox); + sandbox_exit(current_sandbox); current_sandbox_set(NULL); assert(worker_thread_base_context.variant == ARCH_CONTEXT_VARIANT_FAST); runtime_worker_threads_deadline[worker_thread_idx] = UINT64_MAX; @@ -161,48 +69,6 @@ worker_thread_switch_to_base_context() software_interrupt_enable(); } -/** - * Mark a blocked sandbox as runnable and add it to the runqueue - * @param sandbox the sandbox to check and update if blocked - */ -void -worker_thread_wakeup_sandbox(struct sandbox *sandbox) -{ - assert(sandbox != NULL); - assert(sandbox->state == SANDBOX_BLOCKED); - - software_interrupt_disable(); - sandbox_set_as_runnable(sandbox, SANDBOX_BLOCKED); - software_interrupt_enable(); -} - - -/** - * Mark the currently executing sandbox as blocked, remove it from the local runqueue, - * and switch to base context - */ -void -worker_thread_block_current_sandbox(void) -{ - software_interrupt_disable(); - - /* Remove the sandbox we were just executing from the runqueue and mark as blocked */ - struct sandbox *current_sandbox = current_sandbox_get(); - - assert(current_sandbox->state == SANDBOX_RUNNING); - sandbox_set_as_blocked(current_sandbox, SANDBOX_RUNNING); - - /* The worker thread seems to "spin" on a blocked sandbox, so try to execute another sandbox for one quantum - * after blocking to give time for the action to resolve */ - struct sandbox *next_sandbox = local_runqueue_get_next(); - if (next_sandbox != NULL) { - worker_thread_switch_to_sandbox(next_sandbox); - } else { - worker_thread_switch_to_base_context(); - }; -} - - /** * Run all outstanding events in the local thread's epoll loop */ @@ -228,7 +94,7 @@ worker_thread_execute_epoll_loop(void) struct sandbox *sandbox = (struct sandbox *)epoll_events[i].data.ptr; assert(sandbox); - if (sandbox->state == SANDBOX_BLOCKED) worker_thread_wakeup_sandbox(sandbox); + if (sandbox->state == SANDBOX_BLOCKED) sandbox_wakeup(sandbox); } else if (epoll_events[i].events & (EPOLLERR | EPOLLHUP)) { /* Mystery: This seems to never fire. Why? Issue #130 */ @@ -298,8 +164,7 @@ worker_thread_main(void *argument) local_completion_queue_initialize(); /* Initialize Flags */ - software_interrupt_is_disabled = false; - + software_interrupt_disable(); /* Unmask signals */ if (runtime_preemption_enabled) { @@ -323,7 +188,7 @@ worker_thread_main(void *argument) software_interrupt_disable(); next_sandbox = local_runqueue_get_next(); if (next_sandbox != NULL) { - worker_thread_switch_to_sandbox(next_sandbox); + sandbox_switch_to(next_sandbox); } else { software_interrupt_enable(); }; @@ -334,17 +199,3 @@ worker_thread_main(void *argument) panic("Worker Thread unexpectedly completed run loop."); } - -/** - * Called when the function in the sandbox exits - * Removes the standbox from the thread-local runqueue, sets its state to SANDBOX_RETURNED, - * releases the linear memory, and then returns to the base context - */ -__attribute__((noreturn)) void -worker_thread_on_sandbox_exit() -{ - assert(!software_interrupt_is_enabled()); - generic_thread_dump_lock_overhead(); - worker_thread_switch_to_base_context(); - panic("Unexpected return\n"); -}