diff --git a/runtime/include/sandbox.h b/runtime/include/sandbox.h index 30b84bf..cfe4912 100644 --- a/runtime/include/sandbox.h +++ b/runtime/include/sandbox.h @@ -84,6 +84,7 @@ struct sandbox_request { char * args; int sock; struct sockaddr *addr; + unsigned long long int start_time_in_cycles; }; typedef struct sandbox_request sbox_request_t; #else @@ -108,7 +109,12 @@ typedef struct sandbox sandbox_t; void sandbox_run(sbox_request_t *s); static inline sbox_request_t * -sbox_request_alloc(struct module *mod, char *args, int sock, const struct sockaddr *addr) +sbox_request_alloc( + struct module *mod, + char *args, + int sock, + const struct sockaddr *addr, + unsigned long long int start_time_in_cycles) { #ifndef STANDALONE #ifdef SBOX_SCALE_ALLOC @@ -118,6 +124,7 @@ sbox_request_alloc(struct module *mod, char *args, int sock, const struct sockad s->args = args; s->sock = sock; s->addr = (struct sockaddr *)addr; + s->start_time_in_cycles = start_time_in_cycles; sandbox_run(s); return s; #else /* SBOX_SCALE_ALLOC */ @@ -147,50 +154,56 @@ sandbox_current_set(struct sandbox *sbox) module_indirect_table = sbox->mod->indirect_table; } +/** + * @brief Safety checks around linear memory base and bounds and the Wasm function indirect table + */ static inline void sandbox_current_check(void) { struct sandbox *c = sandbox_current(); - assert(c && c->linear_start == sandbox_lmbase && c->linear_size == sandbox_lmbound); assert(c->mod->indirect_table == module_indirect_table); } +/** + * @return the module of the current sandbox + */ static inline struct module * sandbox_module(struct sandbox *s) { if (!s) return NULL; - return s->mod; } extern void sandbox_local_end(struct sandbox *s); + +/** + * @brief Switches to the next sandbox, placing the current sandbox of the completion queue if in RETURNED state + * @param next The Sandbox Context to switch to or NULL + * @return void + */ static inline void -sandbox_switch(struct sandbox *next) +sandbox_switch(struct sandbox *next_sandbox) { - arch_context_t *n = next == NULL ? NULL : &next->ctxt; - - // disable interrupts (signals) + arch_context_t *next_register_context = next_sandbox == NULL ? NULL : &next_sandbox->ctxt; softint_disable(); - // switch sandbox (register context & base/bound/table) - struct sandbox *curr = sandbox_current(); - arch_context_t *c = curr == NULL ? NULL : &curr->ctxt; - sandbox_current_set(next); - if (curr && curr->state == SANDBOX_RETURNED) sandbox_local_end(curr); - // save current's registers and restore next's registers. - next_context = n; - arch_context_switch(c, n); - next_context = NULL; - - // enable interrupts (signals) + struct sandbox *current_sandbox = sandbox_current(); + arch_context_t *current_register_context = current_sandbox == NULL ? NULL : ¤t_sandbox->ctxt; + sandbox_current_set(next_sandbox); + // If the current sandbox we're switching from is in a RETURNED state, add to completion queue + if (current_sandbox && current_sandbox->state == SANDBOX_RETURNED) sandbox_local_end(current_sandbox); + next_context = next_register_context; + arch_context_switch(current_register_context, next_register_context); softint_enable(); } +/** + * @return the arguments of the current sandbox + */ static inline char * sandbox_args(void) { struct sandbox *c = sandbox_current(); - return (char *)c->args; } diff --git a/runtime/src/runtime.c b/runtime/src/runtime.c index 2cb26ab..cef7816 100644 --- a/runtime/src/runtime.c +++ b/runtime/src/runtime.c @@ -15,8 +15,8 @@ struct deque_sandbox *global_deque; pthread_mutex_t global_deque_mutex = PTHREAD_MUTEX_INITIALIZER; int epoll_file_descriptor; -__thread static struct ps_list_head runq; // per-thread(core) run queue (doubly-linked list) -__thread static struct ps_list_head endq; // per-thread(core) completion queue (doubly-linked list) +__thread static struct ps_list_head local_run_queue; +__thread static struct ps_list_head local_completion_queue; // current sandbox that is active.. __thread sandbox_t *current_sandbox = NULL; @@ -31,7 +31,7 @@ __thread arch_context_t base_context; __thread uv_loop_t uvio; /** - * Append the sandbox to the runqueue + * Append the sandbox to the local_run_queueueue * @param s sandbox to add */ static inline void @@ -39,7 +39,7 @@ sandbox_local_run(struct sandbox *s) { assert(ps_list_singleton_d(s)); // fprintf(stderr, "(%d,%lu) %s: run %p, %s\n", sched_getcpu(), pthread_self(), __func__, s, s->mod->name); - ps_list_head_append_d(&runq, s); + ps_list_head_append_d(&local_run_queue, s); } static inline int @@ -94,7 +94,7 @@ struct sandbox * sandbox_schedule(int interrupt) { struct sandbox *s = NULL; - if (ps_list_head_empty(&runq)) { + if (ps_list_head_empty(&local_run_queue)) { // this is in an interrupt context, don't steal work here! if (interrupt) return NULL; if (sandbox_pull() == 0) { @@ -103,25 +103,28 @@ sandbox_schedule(int interrupt) } } - s = ps_list_head_first_d(&runq, struct sandbox); + s = ps_list_head_first_d(&local_run_queue, struct sandbox); assert(s->state != SANDBOX_RETURNED); // round-robin ps_list_rem_d(s); - ps_list_head_append_d(&runq, s); + ps_list_head_append_d(&local_run_queue, s); debuglog("[%p: %s]\n", s, s->mod->name); return s; } +/** + * @brief Remove and free n requests from the completion queue + * @param number_to_free The number of requests to free + * @return void + */ static inline void -sandbox_local_free(unsigned int n) +sandbox_local_free(unsigned int number_to_free) { - int i = 0; - - while (i < n && !ps_list_head_empty(&endq)) { - i++; - struct sandbox *s = ps_list_head_first_d(&endq, struct sandbox); + for (int i = 0; i < number_to_free; i++){ + if (ps_list_head_empty(&local_completion_queue)) break; + struct sandbox *s = ps_list_head_first_d(&local_completion_queue, struct sandbox); if (!s) break; ps_list_rem_d(s); sandbox_free(s); @@ -153,7 +156,7 @@ sandbox_wakeup(sandbox_t *s) assert(s->state == SANDBOX_BLOCKED); assert(ps_list_singleton_d(s)); s->state = SANDBOX_RUNNABLE; - ps_list_head_append_d(&runq, s); + ps_list_head_append_d(&local_run_queue, s); done: softint_enable(); #endif @@ -213,7 +216,7 @@ void sandbox_local_end(struct sandbox *s) { assert(ps_list_singleton_d(s)); - ps_list_head_append_d(&endq, s); + ps_list_head_append_d(&local_completion_queue, s); } void * @@ -221,8 +224,8 @@ sandbox_run_func(void *data) { arch_context_init(&base_context, 0, 0); - ps_list_head_init(&runq); - ps_list_head_init(&endq); + ps_list_head_init(&local_run_queue); + ps_list_head_init(&local_completion_queue); softint_off = 0; next_context = NULL; #ifndef PREEMPT_DISABLE @@ -301,6 +304,7 @@ runtime_accept_thdfn(void *d) int total_requests = 0; while (true) { int ready = epoll_wait(epoll_file_descriptor, epoll_events, EPOLL_MAX, -1); + unsigned long long int start_time_in_cycles = rdtsc(); for (int i = 0; i < ready; i++) { if (epoll_events[i].events & EPOLLERR) { perror("epoll_wait"); @@ -318,10 +322,10 @@ runtime_accept_thdfn(void *d) assert(0); } total_requests++; - printf("Handling Request %d\n", total_requests); + printf("Received Request %d at %lld\n", total_requests, start_time_in_cycles); // struct sandbox *sb = sandbox_alloc(m, m->name, s, (const struct sockaddr *)&client); - sbox_request_t *sb = sbox_request_alloc(m, m->name, s, (const struct sockaddr *)&client); + sbox_request_t *sb = sbox_request_alloc(m, m->name, s, (const struct sockaddr *)&client, start_time_in_cycles); assert(sb); } }