chore: Initial buggy port

master
Sean McBride 5 years ago
parent 236e39b263
commit 2db5f84f11

@ -20,6 +20,7 @@ arch_context_init(struct arch_context *actx, reg_t ip, reg_t sp)
actx->regs[UREG_RSP] = sp; actx->regs[UREG_RSP] = sp;
actx->regs[UREG_RIP] = ip; actx->regs[UREG_RIP] = ip;
actx->variant = ARCH_CONTEXT_QUICK;
} }
/** /**

@ -22,9 +22,20 @@ enum UREGS
UREG_COUNT UREG_COUNT
}; };
/* The enum is compared directly in assembly, so maintain integral values! */
enum ARCH_CONTEXT
{
ARCH_CONTEXT_UNUSED = 0,
ARCH_CONTEXT_QUICK = 1,
ARCH_CONTEXT_SLOW = 2,
ARCH_CONTEXT_RUNNING = 3
};
struct arch_context { struct arch_context {
reg_t regs[UREG_COUNT]; enum ARCH_CONTEXT variant;
mcontext_t mctx; reg_t regs[UREG_COUNT];
mcontext_t mctx;
}; };
/* /*
@ -35,3 +46,5 @@ extern __thread struct arch_context worker_thread_base_context;
/* Cannot be inlined because called in Assembly */ /* Cannot be inlined because called in Assembly */
void __attribute__((noinline)) __attribute__((noreturn)) arch_context_mcontext_restore(void); void __attribute__((noinline)) __attribute__((noreturn)) arch_context_mcontext_restore(void);
extern __thread volatile bool worker_thread_is_switching_context;

@ -21,48 +21,81 @@
/** /**
* Preempt the current sandbox and start executing the next sandbox * Restore a full mcontext
* @param mc - the context of the current thread of execution * Writes sandbox_context to active_context and then zeroes sandbox_context out
* @param ctx - the context that we want to restore * @param active_context - the context of the current worker thread
* @return Return code in {0,1} * @param sandbox_context - the context that we want to restore
* 0 = context restored successfully.
* 1 = special processing because thread was last in a user-level context switch state
*/ */
static inline int static inline void
arch_mcontext_restore(mcontext_t *mc, struct arch_context *ctx) arch_mcontext_restore(mcontext_t *active_context, struct arch_context *sandbox_context)
{ {
assert(ctx != &worker_thread_base_context);
assert(!software_interrupt_is_enabled()); assert(!software_interrupt_is_enabled());
/* if ctx->regs[0] is set, this was last in a user-level context switch state! assert(active_context != NULL);
* else restore mcontext.. assert(sandbox_context != NULL);
*/
bool did_user_level_context_switch = ctx->regs[UREG_RSP]; /* Validate that the sandbox_context is well formed */
if (did_user_level_context_switch) { assert(sandbox_context->variant == ARCH_CONTEXT_SLOW);
mc->gregs[REG_RSP] = ctx->regs[UREG_RSP]; assert(sandbox_context->mctx.gregs[REG_RSP] != 0);
mc->gregs[REG_RIP] = ctx->regs[UREG_RIP] + ARCH_SIG_JMP_OFF; assert(sandbox_context->mctx.gregs[REG_RIP] != 0);
ctx->regs[UREG_RSP] = 0;
return 1; assert(sandbox_context != &worker_thread_base_context);
}
/* Restore mcontext */ /* Restore mcontext */
memcpy(mc, &ctx->mctx, sizeof(mcontext_t)); memcpy(active_context, &sandbox_context->mctx, sizeof(mcontext_t));
memset(&ctx->mctx, 0, sizeof(mcontext_t)); memset(&sandbox_context->mctx, 0, sizeof(mcontext_t));
}
/**
* Restore a sandbox that was previously executing and preempted for higher-priority work.
* This method restores only the instruction pointer and stack pointer registers rather than
* a full mcontext, so it is less expensive than arch_mcontext_restore.
* @param active_context - the context of the current worker thread
* @param sandbox_context - the context that we want to restore
*/
static void
arch_context_restore(mcontext_t *active_context, struct arch_context *sandbox_context)
{
assert(active_context != NULL);
assert(sandbox_context != NULL);
assert(sandbox_context->variant == ARCH_CONTEXT_QUICK);
assert(sandbox_context != &worker_thread_base_context);
return 0; /* TODO: Phani explained that we need to be able to restore a sandbox with an IP of 0. Why is this? */
assert(sandbox_context->regs[UREG_RSP]);
active_context->gregs[REG_RSP] = sandbox_context->regs[UREG_RSP];
active_context->gregs[REG_RIP] = sandbox_context->regs[UREG_RIP] + ARCH_SIG_JMP_OFF;
sandbox_context->regs[UREG_RSP] = 0;
sandbox_context->regs[UREG_RIP] = 0;
} }
/** /**
* Save the context of the currently executing process * Save the full mcontext of the currently executing process
* @param ctx - destination * @param sandbox_context - destination
* @param mc - source * @param active_context - source
*/ */
static inline void static inline void
arch_mcontext_save(struct arch_context *ctx, mcontext_t *mc) arch_mcontext_save(struct arch_context *sandbox_context, const mcontext_t *active_context)
{ {
assert(ctx != &worker_thread_base_context); assert(sandbox_context != NULL);
assert(active_context != NULL);
/* Assumption: Only called indirectly via signal handler, so interrupts should be disabled */
assert(!software_interrupt_is_enabled());
/* Assumption: The base context should never be modified */
assert(sandbox_context != &worker_thread_base_context);
/* Assumption: The executing process has sane IP and SP values */
assert(active_context->gregs[REG_RIP] != 0);
assert(active_context->gregs[REG_RSP] != 0);
/* Set variant to slow */
sandbox_context->variant = ARCH_CONTEXT_SLOW;
sandbox_context->regs[UREG_RSP] = 0;
sandbox_context->regs[UREG_RIP] = 0;
ctx->regs[UREG_RSP] = 0; /* Copy mcontext */
memcpy(&ctx->mctx, mc, sizeof(mcontext_t)); memcpy(&sandbox_context->mctx, active_context, sizeof(mcontext_t));
} }

@ -37,6 +37,7 @@ static void __attribute__((noinline)) arch_context_init(struct arch_context *act
actx->regs[UREG_RSP] = sp; actx->regs[UREG_RSP] = sp;
actx->regs[UREG_RIP] = ip; actx->regs[UREG_RIP] = ip;
actx->variant = ARCH_CONTEXT_QUICK;
} }
@ -64,6 +65,9 @@ arch_context_switch(struct arch_context *current, struct arch_context *next)
if (current == NULL) current = &worker_thread_base_context; if (current == NULL) current = &worker_thread_base_context;
if (next == NULL) next = &worker_thread_base_context; if (next == NULL) next = &worker_thread_base_context;
/* Assumption: The context we are switching to should have saved a context in some form */
assert(next->variant == ARCH_CONTEXT_QUICK || next->variant != ARCH_CONTEXT_UNUSED);
reg_t *current_registers = current->regs, *next_registers = next->regs; reg_t *current_registers = current->regs, *next_registers = next->regs;
assert(current_registers && next_registers); assert(current_registers && next_registers);
@ -77,12 +81,13 @@ arch_context_switch(struct arch_context *current, struct arch_context *next)
*/ */
"movq $2f, 8(%%rax)\n\t" /* Write the address of label 2 to current_registers[1] (instruction_pointer). */ "movq $2f, 8(%%rax)\n\t" /* Write the address of label 2 to current_registers[1] (instruction_pointer). */
"movq %%rsp, (%%rax)\n\t" /* current_registers[0] (stack_pointer) = stack_pointer */ "movq %%rsp, (%%rax)\n\t" /* current_registers[0] (stack_pointer) = stack_pointer */
"movq $1, (%%rcx)\n\t" /* current->variant = ARCH_CONTEXT_QUICK; */
/* /*
* Check if the variant of the context we're trying to switch to is SLOW (mcontext-based) * Check if the variant of the context we're trying to switch to is SLOW (mcontext-based)
* If it is, jump to label 1 to restore the preempted sandbox * If it is, jump to label 1 to restore the preempted sandbox
*/ */
"cmpq $0, (%%rbx)\n\t" /* if (stack pointer == 0) */ "cmpq $2, (%%rcx)\n\t" /* if (next->variant == ARCH_CONTEXT_SLOW); */
"je 1f\n\t" /* goto 1; restore the existing sandbox using mcontext */ "je 1f\n\t" /* goto 1; restore the existing sandbox using mcontext */
/* /*
@ -94,7 +99,7 @@ arch_context_switch(struct arch_context *current, struct arch_context *next)
/* /*
* Slow Path * Slow Path
* If the stack pointer equaled 0, that means the sandbox was preempted and we need to * If the variant is ARCH_CONTEXT_SLOW, that means the sandbox was preempted and we need to
* fallback to a full mcontext-based context switch. We do this by invoking * fallback to a full mcontext-based context switch. We do this by invoking
* arch_context_mcontext_restore, which fires a SIGUSR1 signal. The SIGUSR1 signal handler * arch_context_mcontext_restore, which fires a SIGUSR1 signal. The SIGUSR1 signal handler
* executes the mcontext-based context switch. * executes the mcontext-based context switch.
@ -104,21 +109,23 @@ arch_context_switch(struct arch_context *current, struct arch_context *next)
".align 8\n\t" ".align 8\n\t"
/* /*
* Where preempted sandbox resumes * This label was written to the instruction pointer of the sandbox that was switched away from
* rbx contains the preempted sandbox's IP and SP in this context * The sandbox either resumes at label 2 or 3 depending on if an offset of 8 is used.
*/ */
"2:\n\t" "2:\n\t"
"movq $0, (%%rbx)\n\t" /* stack pointer = 0 */ "movq $3, (%%rdx)\n\t" /* next->variant = ARCH_CONTEXT_QUICK; */
".align 8\n\t" ".align 8\n\t"
/* This label is used in conjunction with a static offset */ /* This label is used in conjunction with a static offset */
"3:\n\t" "3:\n\t"
/* TODO: Should we set next->variant = ARCH_CONTEXT_SLOW here?;*/
"popq %%rbp\n\t" /* base_pointer = stack[--stack_len]; Base Pointer is restored */ "popq %%rbp\n\t" /* base_pointer = stack[--stack_len]; Base Pointer is restored */
: :
: "a"(current_registers), "b"(next_registers) : "a"(current_registers), "b"(next_registers), "c"(&current->variant), "d"(&next->variant)
: "memory", "cc", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", : "memory", "cc", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2",
"xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14",
"xmm14", "xmm15"); "xmm15");
worker_thread_is_switching_context = false;
return 0; return 0;
} }

@ -81,7 +81,7 @@ struct sandbox {
**************************/ **************************/
extern __thread struct arch_context *worker_thread_next_context; extern __thread volatile bool worker_thread_is_switching_context;
extern void worker_thread_block_current_sandbox(void); extern void worker_thread_block_current_sandbox(void);
extern void worker_thread_on_sandbox_exit(struct sandbox *sandbox); extern void worker_thread_on_sandbox_exit(struct sandbox *sandbox);

@ -161,6 +161,8 @@ local_runqueue_minheap_preempt(ucontext_t *user_context)
next_sandbox->state = SANDBOX_RUNNABLE; next_sandbox->state = SANDBOX_RUNNABLE;
local_runqueue_add(next_sandbox); local_runqueue_add(next_sandbox);
worker_thread_is_switching_context = true;
/* Save the context of the currently executing sandbox before switching from it */ /* Save the context of the currently executing sandbox before switching from it */
arch_mcontext_save(&current_sandbox->ctxt, &user_context->uc_mcontext); arch_mcontext_save(&current_sandbox->ctxt, &user_context->uc_mcontext);
@ -168,12 +170,16 @@ local_runqueue_minheap_preempt(ucontext_t *user_context)
current_sandbox_set(next_sandbox); current_sandbox_set(next_sandbox);
/* /*
* And load the context of this new sandbox * Restore the context of this new sandbox
* RC of 1 indicates that sandbox was last in a user-level context switch state, * If last in a user-level context switch state,
* so do not enable software interrupts. * do not enable software interrupts.
*/ */
if (arch_mcontext_restore(&user_context->uc_mcontext, &next_sandbox->ctxt) == 1) if (next_sandbox->ctxt.variant == ARCH_CONTEXT_SLOW) {
arch_mcontext_restore(&user_context->uc_mcontext, &next_sandbox->ctxt);
} else {
arch_context_restore(&user_context->uc_mcontext, &next_sandbox->ctxt);
should_enable_software_interrupt = false; should_enable_software_interrupt = false;
}
} }
done: done:
if (should_enable_software_interrupt) software_interrupt_enable(); if (should_enable_software_interrupt) software_interrupt_enable();

@ -252,7 +252,7 @@ current_sandbox_main(void)
assert(!software_interrupt_is_enabled()); assert(!software_interrupt_is_enabled());
arch_context_init(&sandbox->ctxt, 0, 0); arch_context_init(&sandbox->ctxt, 0, 0);
worker_thread_next_context = NULL; worker_thread_is_switching_context = false;
software_interrupt_enable(); software_interrupt_enable();
sandbox_initialize_io_handles_and_file_descriptors(sandbox); sandbox_initialize_io_handles_and_file_descriptors(sandbox);
@ -410,7 +410,7 @@ sandbox_allocate(struct sandbox_request *sandbox_request)
sandbox->state = SANDBOX_INITIALIZING; sandbox->state = SANDBOX_INITIALIZING;
/* Allocate the Stack */ /* Allocate the Stack */
if (sandbox_allocate_stack(sandbox) == -1) { if (sandbox_allocate_stack(sandbox) < 0) {
error_message = "failed to allocate sandbox heap and linear memory"; error_message = "failed to allocate sandbox heap and linear memory";
goto err_stack_allocation_failed; goto err_stack_allocation_failed;
} }

@ -88,7 +88,7 @@ software_interrupt_handle_signals(int signal_type, siginfo_t *signal_info, void
if (!software_interrupt_is_enabled()) return; if (!software_interrupt_is_enabled()) return;
/* Do not allow more than one layer of preemption */ /* Do not allow more than one layer of preemption */
if (worker_thread_next_context) return; if (worker_thread_is_switching_context) return;
/* /*
* if a SIGALRM fires while the worker thread is between sandboxes, executing libuv, completion queue * if a SIGALRM fires while the worker thread is between sandboxes, executing libuv, completion queue
@ -122,13 +122,19 @@ software_interrupt_handle_signals(int signal_type, siginfo_t *signal_info, void
assert(!software_interrupt_is_enabled()); assert(!software_interrupt_is_enabled());
/* Assumption: Caller sets current_sandbox to the preempted sandbox */ /* Assumption: Caller sets current_sandbox to the preempted sandbox */
assert(worker_thread_next_context && (&current_sandbox->ctxt == worker_thread_next_context)); assert(current_sandbox);
/* Extra checks to verify that preemption properly set context state */
assert(current_sandbox->ctxt.variant == ARCH_CONTEXT_SLOW);
assert(current_sandbox->ctxt.regs[UREG_RSP] != 0);
assert(current_sandbox->ctxt.regs[UREG_RIP] != 0);
software_interrupt_SIGUSR_count++; software_interrupt_SIGUSR_count++;
debuglog("usr1:%d\n", software_interrupt_SIGUSR_count); debuglog("usr1:%d\n", software_interrupt_SIGUSR_count);
arch_mcontext_restore(&user_context->uc_mcontext, &current_sandbox->ctxt); arch_mcontext_restore(&user_context->uc_mcontext, &current_sandbox->ctxt);
worker_thread_next_context = NULL;
worker_thread_is_switching_context = false;
software_interrupt_enable(); software_interrupt_enable();
return; return;

@ -20,9 +20,6 @@
* Worker Thread State * * Worker Thread State *
**************************/ **************************/
/* context pointer used to store and restore a preempted sandbox. SIGUSR1 */
__thread struct arch_context *worker_thread_next_context = NULL;
/* context of the runtime thread before running sandboxes or to resume its "main". */ /* context of the runtime thread before running sandboxes or to resume its "main". */
__thread struct arch_context worker_thread_base_context; __thread struct arch_context worker_thread_base_context;
@ -32,14 +29,18 @@ __thread uv_loop_t worker_thread_uvio_handle;
/* Flag to signify if the thread is currently running callbacks in the libuv event loop */ /* Flag to signify if the thread is currently running callbacks in the libuv event loop */
static __thread bool worker_thread_is_in_libuv_event_loop = false; static __thread bool worker_thread_is_in_libuv_event_loop = false;
/* Flag to signify if the thread is currently undergoing a context switch */
__thread volatile bool worker_thread_is_switching_context = false;
/*********************** /***********************
* Worker Thread Logic * * Worker Thread Logic *
**********************/ **********************/
/** /**
* @brief Switches to the next sandbox, placing the current sandbox on the completion queue if in SANDBOX_RETURNED 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 or NULL, which forces return to base context * @param next_sandbox The Sandbox Context to switch to
* @return void *
* TODO: Confirm that this can gracefully resume sandboxes in a PREEMPTED state
*/ */
static inline void static inline void
worker_thread_switch_to_sandbox(struct sandbox *next_sandbox) worker_thread_switch_to_sandbox(struct sandbox *next_sandbox)
@ -47,36 +48,72 @@ worker_thread_switch_to_sandbox(struct sandbox *next_sandbox)
/* Assumption: The caller disables interrupts */ /* Assumption: The caller disables interrupts */
assert(software_interrupt_is_disabled); assert(software_interrupt_is_disabled);
struct arch_context *next_register_context = NULL; assert(next_sandbox != NULL);
if (next_sandbox != NULL) next_register_context = &next_sandbox->ctxt; struct arch_context *next_context = &next_sandbox->ctxt;
worker_thread_is_switching_context = true;
/* Get the old sandbox we're switching from */ /* Get the old sandbox we're switching from */
struct sandbox * previous_sandbox = current_sandbox_get(); struct sandbox *current_sandbox = current_sandbox_get();
struct arch_context *previous_register_context = NULL;
if (previous_sandbox != NULL) previous_register_context = &previous_sandbox->ctxt; if (current_sandbox == NULL) {
/* Switching from "Base Context" */
/* Set the current sandbox to the next */ current_sandbox_set(next_sandbox);
current_sandbox_set(next_sandbox);
debuglog("Thread %lu | Switching from Base Context to Sandbox %lu\n", pthread_self(),
/* ...and switch to the associated context. next_sandbox->allocation_timestamp);
* Save the context pointer to worker_thread_next_context in case of preemption
*/ arch_context_switch(NULL, next_context);
worker_thread_next_context = next_register_context;
arch_context_switch(previous_register_context, next_register_context); if (current_sandbox != NULL && current_sandbox->state == SANDBOX_RETURNED) {
panic("Unexpectedly returned to a sandbox in a RETURNED state\n");
/* If previous sandbox is not NULL, ensure a valid state */ }
assert(previous_sandbox == NULL || previous_sandbox->state != SANDBOX_INITIALIZING); } else {
/* Set the current sandbox to the next */
/* If the current sandbox we're switching from is in a SANDBOX_RETURNED state, add to completion queue */ assert(next_sandbox != current_sandbox);
if (previous_sandbox != NULL && previous_sandbox->state == SANDBOX_RETURNED) {
panic("Unexpectedly returned to a sandbox in a RETURNED state\n"); struct arch_context *current_context = &current_sandbox->ctxt;
} else if (previous_sandbox != NULL) {
debuglog("Resumed a sandbox in state %d\n", previous_sandbox->state); current_sandbox_set(next_sandbox);
debuglog("Thread %lu | Switching from Sandbox %lu to Sandbox %lu\n", pthread_self(),
current_sandbox->allocation_timestamp, next_sandbox->allocation_timestamp);
/* Switch to the associated context. */
arch_context_switch(current_context, next_context);
} }
software_interrupt_enable(); software_interrupt_enable();
} }
/**
* @brief Switches to the base context, placing the current sandbox on the completion queue if in RETURNED state
*/
static inline void
worker_thread_switch_to_base_context()
{
software_interrupt_disable();
assert(worker_thread_is_switching_context == false);
worker_thread_is_switching_context = true;
struct sandbox *current_sandbox = current_sandbox_get();
/* Assumption: Base Context should never switch to Base Context */
assert(current_sandbox != NULL);
assert(&current_sandbox->ctxt != &worker_thread_base_context);
current_sandbox_set(NULL);
debuglog("Thread %lu | Switching from Sandbox %lu to Base Context\n", pthread_self(),
current_sandbox->allocation_timestamp);
arch_context_switch(&current_sandbox->ctxt, &worker_thread_base_context);
software_interrupt_enable();
worker_thread_is_switching_context = false;
}
/** /**
* Mark a blocked sandbox as runnable and add it to the runqueue * Mark a blocked sandbox as runnable and add it to the runqueue
* @param sandbox the sandbox to check and update if blocked * @param sandbox the sandbox to check and update if blocked
@ -99,9 +136,12 @@ done:
/** /**
* Mark the currently executing sandbox as blocked, remove it from the local runqueue, and pull the sandbox at the head * Mark the currently executing sandbox as blocked, remove it from the local runqueue,
* of the runqueue * and pull the sandbox at the head of the runqueue
*/ *
* FIXME : What happens if we block on a sandbox that has preempted something ? Should we try to restore first?
* Is this accomplished by the runqueue design?
**/
void void
worker_thread_block_current_sandbox(void) worker_thread_block_current_sandbox(void)
{ {
@ -109,15 +149,24 @@ worker_thread_block_current_sandbox(void)
software_interrupt_disable(); software_interrupt_disable();
/* Remove the sandbox we were just executing from the runqueue and mark as blocked */ /* Remove the sandbox we were just executing from the runqueue and mark as blocked */
struct sandbox *previous_sandbox = current_sandbox_get(); struct sandbox *current_sandbox = current_sandbox_get();
local_runqueue_delete(previous_sandbox); local_runqueue_delete(current_sandbox);
previous_sandbox->state = SANDBOX_BLOCKED; current_sandbox->state = SANDBOX_BLOCKED;
/* Switch to the next sandbox */ /* Switch to the next sandbox */
struct sandbox *next_sandbox = local_runqueue_get_next(); struct sandbox *next_sandbox = local_runqueue_get_next();
debuglog("[%p: %next_sandbox, %p: %next_sandbox]\n", previous_sandbox, previous_sandbox->module->name, debuglog("[%p: %next_sandbox, %p: %next_sandbox]\n", current_sandbox, current_sandbox->module->name,
next_sandbox, next_sandbox ? next_sandbox->module->name : ""); next_sandbox, next_sandbox ? next_sandbox->module->name : "");
worker_thread_switch_to_sandbox(next_sandbox);
/* If able to get one, switch to it. Otherwise, return to base context */
if (next_sandbox == NULL) {
worker_thread_switch_to_base_context();
} else {
debuglog("[%p: %p, %p: %p]\n", current_sandbox, current_sandbox->module->name, next_sandbox,
next_sandbox ? next_sandbox->module->name : "");
// TODO: Looks like a zombie: software_interrupt_enable();
worker_thread_switch_to_sandbox(next_sandbox);
}
} }
@ -129,9 +178,9 @@ worker_thread_process_io(void)
{ {
#ifdef USE_HTTP_UVIO #ifdef USE_HTTP_UVIO
#ifdef USE_HTTP_SYNC #ifdef USE_HTTP_SYNC
/* realistically, we're processing all async I/O on this core when a sandbox blocks on http processing, not /* realistically, we're processing all async I/O on this core when a sandbox blocks on http processing,
* great! if there is a way (TODO), perhaps RUN_ONCE and check if your I/O is processed, if yes, return else do * not great! if there is a way (TODO), perhaps RUN_ONCE and check if your I/O is processed, if yes,
* async block! */ * return else do async block! */
uv_run(worker_thread_get_libuv_handle(), UV_RUN_DEFAULT); uv_run(worker_thread_get_libuv_handle(), UV_RUN_DEFAULT);
#else /* USE_HTTP_SYNC */ #else /* USE_HTTP_SYNC */
worker_thread_block_current_sandbox(); worker_thread_block_current_sandbox();
@ -178,7 +227,7 @@ worker_thread_main(void *return_code)
/* Initialize Flags */ /* Initialize Flags */
software_interrupt_is_disabled = false; software_interrupt_is_disabled = false;
worker_thread_is_in_libuv_event_loop = false; worker_thread_is_in_libuv_event_loop = false;
worker_thread_next_context = NULL; worker_thread_is_switching_context = false;
/* Unmask signals */ /* Unmask signals */
#ifndef PREEMPT_DISABLE #ifndef PREEMPT_DISABLE
@ -227,9 +276,8 @@ worker_thread_on_sandbox_exit(struct sandbox *exiting_sandbox)
/* Because the stack is still in use, only unmap linear memory and defer free resources until "main /* Because the stack is still in use, only unmap linear memory and defer free resources until "main
function execution" */ function execution" */
errno = 0;
int rc = munmap(exiting_sandbox->linear_memory_start, SBOX_MAX_MEM + PAGE_SIZE); int rc = munmap(exiting_sandbox->linear_memory_start, SBOX_MAX_MEM + PAGE_SIZE);
if (rc == -1) panic("worker_thread_on_sandbox_exit - munmap failed with errno - %s\n", strerror(errno)); if (rc == -1) perror("worker_thread_on_sandbox_exit - munmap failed\n");
/* TODO: I do not understand when software interrupts must be disabled? */ /* TODO: I do not understand when software interrupts must be disabled? */
software_interrupt_disable(); software_interrupt_disable();
@ -238,7 +286,7 @@ worker_thread_on_sandbox_exit(struct sandbox *exiting_sandbox)
local_completion_queue_add(exiting_sandbox); local_completion_queue_add(exiting_sandbox);
/* This should force return to main event loop */ /* This should force return to main event loop */
worker_thread_switch_to_sandbox(NULL); worker_thread_switch_to_base_context();
assert(0); assert(0);
} }

Loading…
Cancel
Save