diff --git a/runtime/include/sandbox.h b/runtime/include/sandbox.h index 5a2974d..dcad022 100644 --- a/runtime/include/sandbox.h +++ b/runtime/include/sandbox.h @@ -279,3 +279,4 @@ sandbox_print_perf(struct sandbox *sandbox) 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); diff --git a/runtime/src/local_runqueue_minheap.c b/runtime/src/local_runqueue_minheap.c index ec11f64..e252823 100644 --- a/runtime/src/local_runqueue_minheap.c +++ b/runtime/src/local_runqueue_minheap.c @@ -93,8 +93,8 @@ local_runqueue_minheap_get_next() sandbox = sandbox_allocate(sandbox_request); if (!sandbox) goto sandbox_allocate_err; - sandbox->state = SANDBOX_RUNNABLE; - local_runqueue_minheap_add(sandbox); + sandbox_set_as_runnable(sandbox); + } else if (sandbox_rc == -2) { /* Unable to take lock, so just return NULL and try later */ assert(sandbox == NULL); @@ -157,8 +157,7 @@ local_runqueue_minheap_preempt(ucontext_t *user_context) if (!next_sandbox) goto err_sandbox_allocate; /* Set as runnable and add it to the runqueue */ - next_sandbox->state = SANDBOX_RUNNABLE; - local_runqueue_add(next_sandbox); + sandbox_set_as_runnable(next_sandbox); /* Save the context of the currently executing sandbox before switching from it */ arch_mcontext_save(¤t_sandbox->ctxt, &user_context->uc_mcontext); diff --git a/runtime/src/sandbox.c b/runtime/src/sandbox.c index 5149245..3c5083c 100644 --- a/runtime/src/sandbox.c +++ b/runtime/src/sandbox.c @@ -7,6 +7,7 @@ #include "current_sandbox.h" #include "http_parser_settings.h" #include "libuv_callbacks.h" +#include "local_runqueue.h" #include "panic.h" #include "runtime.h" #include "sandbox.h" @@ -528,6 +529,49 @@ sandbox_set_as_initialized(struct sandbox *sandbox, struct sandbox_request *sand sandbox->state = SANDBOX_INITIALIZED; } +/** + * Transitions a sandbox to the SANDBOX_RUNNABLE state. + * + * This occurs in the following scenarios: + * - A sandbox in the SANDBOX_INITIALIZED state completes initialization and is ready to be run + * - A sandbox in the SANDBOX_BLOCKED state completes what was blocking it and is ready to be run + * - A sandbox in the SANDBOX_RUNNING state is preempted before competion and is ready to be run + * + * @param sandbox + **/ +void +sandbox_set_as_runnable(struct sandbox *sandbox) +{ + assert(sandbox); + assert(sandbox->last_state_change_timestamp > 0); + uint64_t now = __getcycles(); + uint64_t duration_of_last_state = now - sandbox->last_state_change_timestamp; + sandbox_state_t last_state = sandbox->state; + sandbox->state = SANDBOX_SET_AS_RUNNABLE; + debuglog("Thread %lu | Sandbox %lu | %s => Runnable\n", pthread_self(), sandbox->allocation_timestamp, + sandbox_state_stringify(last_state)); + + switch (last_state) { + case SANDBOX_INITIALIZED: { + sandbox->initializing_duration += duration_of_last_state; + local_runqueue_add(sandbox); + break; + } + case SANDBOX_BLOCKED: { + sandbox->blocked_duration += duration_of_last_state; + local_runqueue_add(sandbox); + break; + } + default: { + panic("Thread %lu | Sandbox %lu | Illegal transition from %s to Runnable\n", pthread_self(), + sandbox->allocation_timestamp, sandbox_state_stringify(last_state)); + } + } + + sandbox->last_state_change_timestamp = now; + sandbox->state = SANDBOX_RUNNABLE; +} + /** * Allocates a new sandbox from a sandbox request diff --git a/runtime/src/worker_thread.c b/runtime/src/worker_thread.c index e3ae20b..49d789c 100644 --- a/runtime/src/worker_thread.c +++ b/runtime/src/worker_thread.c @@ -116,12 +116,7 @@ worker_thread_wakeup_sandbox(struct sandbox *sandbox) assert(sandbox->state == SANDBOX_BLOCKED); software_interrupt_disable(); - - sandbox->state = SANDBOX_RUNNABLE; - debuglog("Marking blocked sandbox as runnable\n"); - local_runqueue_add(sandbox); - -done: + sandbox_set_as_runnable(sandbox); software_interrupt_enable(); }