From 35b83ba090845df077a52c098029929ea9db63de Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Thu, 16 Dec 2021 13:54:26 -0500 Subject: [PATCH] refactor: Eliminate _new and _delete functions --- runtime/include/module.h | 55 +++++++-- runtime/include/sandbox_functions.h | 8 +- runtime/include/sandbox_set_as_error.h | 2 +- runtime/include/sandbox_set_as_returned.h | 2 +- runtime/include/vec_u8.h | 35 +----- runtime/include/wasm_memory.h | 86 +++++++------- runtime/include/wasm_stack.h | 26 ++--- runtime/include/wasm_table.h | 14 +-- runtime/src/listener_thread.c | 6 +- runtime/src/main.c | 2 +- runtime/src/module.c | 130 +++++++++++----------- runtime/src/sandbox.c | 56 ++++------ 12 files changed, 200 insertions(+), 222 deletions(-) diff --git a/runtime/include/module.h b/runtime/include/module.h index 2d4afd5..89ae955 100644 --- a/runtime/include/module.h +++ b/runtime/include/module.h @@ -8,12 +8,14 @@ #include "admissions_control.h" #include "admissions_info.h" #include "awsm_abi.h" +#include "current_wasm_module_instance.h" #include "http.h" #include "panic.h" #include "pool.h" #include "types.h" #include "wasm_stack.h" #include "wasm_memory.h" +#include "wasm_table.h" #define MODULE_DEFAULT_REQUEST_RESPONSE_SIZE (PAGE_SIZE) @@ -22,8 +24,8 @@ extern thread_local int worker_thread_idx; -INIT_POOL(wasm_memory, wasm_memory_delete) -INIT_POOL(wasm_stack, wasm_stack_delete) +INIT_POOL(wasm_memory, wasm_memory_free) +INIT_POOL(wasm_stack, wasm_stack_free) /* * Defines the listen backlog, the queue length for completely established socketeds waiting to be accepted @@ -102,13 +104,50 @@ module_initialize_globals(struct module *module) } /** - * Invoke a module's initialize_tables + * @brief Invoke a module's initialize_tables * @param module + * + * Table initialization calls a function that runs within the sandbox. Rather than setting the current sandbox, + * we partially fake this out by only setting the table and then clearing after table + * initialization is complete. + * + * assumption: This approach depends on module_alloc only being invoked at program start before preemption is + * enabled. We are check that current_wasm_module_instance.table is NULL to gain confidence that + * we are not invoking this in a way that clobbers a current module. + * + * If we want to be able to do this later, we can possibly defer module_initialize_table until the first + * invocation. Alternatively, we can maintain the table per sandbox and call initialize + * on each sandbox if this "assumption" is too restrictive and we're ready to pay a per-sandbox performance hit. */ static inline void module_initialize_table(struct module *module) { + assert(current_wasm_module_instance.table == NULL); + current_wasm_module_instance.table = module->indirect_table; module->abi.initialize_tables(); + current_wasm_module_instance.table = NULL; +} + +static inline int +module_alloc_table(struct module *module) +{ + /* WebAssembly Indirect Table */ + /* TODO: Should this be part of the module or per-sandbox? */ + /* TODO: How should this table be sized? */ + module->indirect_table = wasm_table_alloc(INDIRECT_TABLE_SIZE); + if (module->indirect_table == NULL) return -1; + + module_initialize_table(module); + return 0; +} + +static inline void +module_initialize_pools(struct module *module) +{ + for (int i = 0; i < MAX_WORKER_THREADS; i++) { + wasm_memory_pool_init(&module->pools[i].memory, false); + wasm_stack_pool_init(&module->pools[i].stack, false); + } } /** @@ -166,7 +205,7 @@ module_allocate_stack(struct module *module) struct wasm_stack *stack = wasm_stack_pool_remove_nolock(&module->pools[worker_thread_idx].stack); if (stack == NULL) { - stack = wasm_stack_new(module->stack_size); + stack = wasm_stack_alloc(module->stack_size); if (unlikely(stack == NULL)) return NULL; } @@ -193,7 +232,7 @@ module_allocate_linear_memory(struct module *module) struct wasm_memory *linear_memory = wasm_memory_pool_remove_nolock(&module->pools[worker_thread_idx].memory); if (linear_memory == NULL) { - linear_memory = wasm_memory_new(initial, max); + linear_memory = wasm_memory_alloc(initial, max); if (unlikely(linear_memory == NULL)) return NULL; } @@ -212,6 +251,6 @@ module_free_linear_memory(struct module *module, struct wasm_memory *memory) *******************************/ void module_free(struct module *module); -struct module *module_new(char *mod_name, char *mod_path, uint32_t stack_sz, uint32_t relative_deadline_us, int port, - int req_sz, int resp_sz, int admissions_percentile, uint32_t expected_execution_us); -int module_new_from_json(char *filename); +struct module *module_alloc(char *mod_name, char *mod_path, uint32_t stack_sz, uint32_t relative_deadline_us, int port, + int req_sz, int resp_sz, int admissions_percentile, uint32_t expected_execution_us); +int module_alloc_from_json(char *filename); diff --git a/runtime/include/sandbox_functions.h b/runtime/include/sandbox_functions.h index 05726ad..1203b9f 100644 --- a/runtime/include/sandbox_functions.h +++ b/runtime/include/sandbox_functions.h @@ -12,8 +12,8 @@ * Public API * **************************/ -struct sandbox *sandbox_new(struct module *module, int socket_descriptor, const struct sockaddr *socket_address, - uint64_t request_arrival_timestamp, uint64_t admissions_estimate); +struct sandbox *sandbox_alloc(struct module *module, int socket_descriptor, const struct sockaddr *socket_address, + uint64_t request_arrival_timestamp, uint64_t admissions_estimate); int sandbox_prepare_execution_environment(struct sandbox *sandbox); void sandbox_free(struct sandbox *sandbox); void sandbox_main(struct sandbox *sandbox); @@ -43,11 +43,11 @@ sandbox_free_linear_memory(struct sandbox *sandbox) } /** - * Free Linear Memory, leaving stack in place + * Deinitialize Linear Memory, cleaning up the backing buffer * @param sandbox */ static inline void -sandbox_free_http_buffers(struct sandbox *sandbox) +sandbox_deinit_http_buffers(struct sandbox *sandbox) { assert(sandbox); vec_u8_deinit(&sandbox->request); diff --git a/runtime/include/sandbox_set_as_error.h b/runtime/include/sandbox_set_as_error.h index 55bcb4c..4a684f1 100644 --- a/runtime/include/sandbox_set_as_error.h +++ b/runtime/include/sandbox_set_as_error.h @@ -38,7 +38,7 @@ sandbox_set_as_error(struct sandbox *sandbox, sandbox_state_t last_state) case SANDBOX_RUNNING_SYS: { local_runqueue_delete(sandbox); sandbox_free_linear_memory(sandbox); - sandbox_free_http_buffers(sandbox); + sandbox_deinit_http_buffers(sandbox); break; } default: { diff --git a/runtime/include/sandbox_set_as_returned.h b/runtime/include/sandbox_set_as_returned.h index d57801d..83e77dd 100644 --- a/runtime/include/sandbox_set_as_returned.h +++ b/runtime/include/sandbox_set_as_returned.h @@ -33,7 +33,7 @@ sandbox_set_as_returned(struct sandbox *sandbox, sandbox_state_t last_state) sandbox->total_time = now - sandbox->timestamp_of.request_arrival; local_runqueue_delete(sandbox); sandbox_free_linear_memory(sandbox); - sandbox_free_http_buffers(sandbox); + sandbox_deinit_http_buffers(sandbox); break; } default: { diff --git a/runtime/include/vec_u8.h b/runtime/include/vec_u8.h index 343f54b..0ddc46f 100644 --- a/runtime/include/vec_u8.h +++ b/runtime/include/vec_u8.h @@ -9,22 +9,10 @@ struct vec_u8 { uint8_t *buffer; /* Backing heap allocation. Different lifetime because realloc might move this */ }; -static inline struct vec_u8 *vec_u8_alloc(void); static inline int vec_u8_init(struct vec_u8 *vec_u8, size_t capacity); -static inline struct vec_u8 *vec_u8_new(size_t capacity); +static inline struct vec_u8 *vec_u8_alloc(size_t capacity); static inline void vec_u8_deinit(struct vec_u8 *vec_u8); static inline void vec_u8_free(struct vec_u8 *vec_u8); -static inline void vec_u8_delete(struct vec_u8 *vec_u8); - -/** - * Allocates an uninitialized vec on the heap' - * @returns a pointer to an uninitialized vec on the heap - */ -static inline struct vec_u8 * -vec_u8_alloc(void) -{ - return (struct vec_u8 *)calloc(1, sizeof(struct vec_u8)); -} /** * Initializes a vec, allocating a backing buffer for the provided capcity @@ -54,9 +42,9 @@ vec_u8_init(struct vec_u8 *vec_u8, size_t capacity) * @returns a pointer to an initialized vec on the heap, ready for use */ static inline struct vec_u8 * -vec_u8_new(size_t capacity) +vec_u8_alloc(size_t capacity) { - struct vec_u8 *vec_u8 = vec_u8_alloc(); + struct vec_u8 *vec_u8 = (struct vec_u8 *)malloc(sizeof(struct vec_u8)); if (vec_u8 == NULL) return vec_u8; int rc = vec_u8_init(vec_u8, capacity); @@ -88,26 +76,13 @@ vec_u8_deinit(struct vec_u8 *vec_u8) vec_u8->capacity = 0; } -/** - * Frees a vec struct allocated on the heap - * Assumes that the vec has already been deinitialized - */ -static inline void -vec_u8_free(struct vec_u8 *vec_u8) -{ - assert(vec_u8->buffer == NULL); - assert(vec_u8->length == 0); - assert(vec_u8->capacity == 0); - free(vec_u8); -} - /** * Deinitializes and frees a vec allocated to the heap * @param vec_u8 */ static inline void -vec_u8_delete(struct vec_u8 *vec_u8) +vec_u8_free(struct vec_u8 *vec_u8) { vec_u8_deinit(vec_u8); - vec_u8_free(vec_u8); + free(vec_u8); } diff --git a/runtime/include/wasm_memory.h b/runtime/include/wasm_memory.h index e47cff7..054edad 100644 --- a/runtime/include/wasm_memory.h +++ b/runtime/include/wasm_memory.h @@ -22,18 +22,51 @@ struct wasm_memory { uint8_t * buffer; /* Backing heap allocation. Different lifetime because realloc might move this */ }; -static INLINE struct wasm_memory *wasm_memory_alloc(void); +/* Object Lifecycle Functions */ +static INLINE struct wasm_memory *wasm_memory_alloc(size_t initial, size_t max); static INLINE int wasm_memory_init(struct wasm_memory *wasm_memory, size_t initial, size_t max); -static INLINE struct wasm_memory *wasm_memory_new(size_t initial, size_t max); static INLINE void wasm_memory_deinit(struct wasm_memory *wasm_memory); static INLINE void wasm_memory_free(struct wasm_memory *wasm_memory); -static INLINE void wasm_memory_delete(struct wasm_memory *wasm_memory); +static INLINE void wasm_memory_reinit(struct wasm_memory *wasm_memory, size_t initial); +/* Memory Size */ +static INLINE int wasm_memory_expand(struct wasm_memory *wasm_memory, size_t size_to_expand); +static INLINE size_t wasm_memory_get_size(struct wasm_memory *wasm_memory); +static INLINE uint32_t wasm_memory_get_page_count(struct wasm_memory *wasm_memory); + +/* Reading and writing to wasm_memory */ +static INLINE void +wasm_memory_initialize_region(struct wasm_memory *wasm_memory, uint32_t offset, uint32_t region_size, uint8_t region[]); +static INLINE void * wasm_memory_get_ptr_void(struct wasm_memory *wasm_memory, uint32_t offset, uint32_t size); +static INLINE int8_t wasm_memory_get_i8(struct wasm_memory *wasm_memory, uint32_t offset); +static INLINE int16_t wasm_memory_get_i16(struct wasm_memory *wasm_memory, uint32_t offset); +static INLINE int32_t wasm_memory_get_i32(struct wasm_memory *wasm_memory, uint32_t offset); +static INLINE int64_t wasm_memory_get_i64(struct wasm_memory *wasm_memory, uint32_t offset); +static INLINE float wasm_memory_get_f32(struct wasm_memory *wasm_memory, uint32_t offset); +static INLINE double wasm_memory_get_f64(struct wasm_memory *wasm_memory, uint32_t offset); +static INLINE char wasm_memory_get_char(struct wasm_memory *wasm_memory, uint32_t offset); +static INLINE char * wasm_memory_get_string(struct wasm_memory *wasm_memory, uint32_t offset, uint32_t size); +static INLINE void wasm_memory_set_i8(struct wasm_memory *wasm_memory, uint32_t offset, int8_t value); +static INLINE void wasm_memory_set_i16(struct wasm_memory *wasm_memory, uint32_t offset, int16_t value); +static INLINE void wasm_memory_set_i32(struct wasm_memory *wasm_memory, uint32_t offset, int32_t value); +static INLINE void wasm_memory_set_i64(struct wasm_memory *wasm_memory, uint64_t offset, int64_t value); +static INLINE void wasm_memory_set_f32(struct wasm_memory *wasm_memory, uint32_t offset, float value); +static INLINE void wasm_memory_set_f64(struct wasm_memory *wasm_memory, uint32_t offset, double value); static INLINE struct wasm_memory * -wasm_memory_alloc(void) +wasm_memory_alloc(size_t initial, size_t max) { - return malloc(sizeof(struct wasm_memory)); + struct wasm_memory *wasm_memory = malloc(sizeof(struct wasm_memory)); + if (wasm_memory == NULL) return wasm_memory; + + int rc = wasm_memory_init(wasm_memory, initial, max); + if (rc < 0) { + assert(0); + wasm_memory_free(wasm_memory); + return NULL; + } + + return wasm_memory; } static INLINE int @@ -68,22 +101,6 @@ wasm_memory_init(struct wasm_memory *wasm_memory, size_t initial, size_t max) return 0; } -static INLINE struct wasm_memory * -wasm_memory_new(size_t initial, size_t max) -{ - struct wasm_memory *wasm_memory = wasm_memory_alloc(); - if (wasm_memory == NULL) return wasm_memory; - - int rc = wasm_memory_init(wasm_memory, initial, max); - if (rc < 0) { - assert(0); - wasm_memory_free(wasm_memory); - return NULL; - } - - return wasm_memory; -} - static INLINE void wasm_memory_deinit(struct wasm_memory *wasm_memory) { @@ -101,31 +118,14 @@ static INLINE void wasm_memory_free(struct wasm_memory *wasm_memory) { assert(wasm_memory != NULL); - /* Assume prior deinitialization so we don't leak buffers */ - assert(wasm_memory->buffer == NULL); - - free(wasm_memory); -} - -static INLINE void -wasm_memory_delete(struct wasm_memory *wasm_memory) -{ - assert(wasm_memory != NULL); - wasm_memory_deinit(wasm_memory); - wasm_memory_free(wasm_memory); -} - -static INLINE void -wasm_memory_wipe(struct wasm_memory *wasm_memory) -{ - memset(wasm_memory->buffer, 0, wasm_memory->size); + free(wasm_memory); } static INLINE void wasm_memory_reinit(struct wasm_memory *wasm_memory, size_t initial) { - wasm_memory_wipe(wasm_memory); + memset(wasm_memory->buffer, 0, wasm_memory->size); wasm_memory->size = initial; } @@ -158,12 +158,6 @@ wasm_memory_expand(struct wasm_memory *wasm_memory, size_t size_to_expand) return 0; } -static INLINE void -wasm_memory_set_size(struct wasm_memory *wasm_memory, size_t size) -{ - wasm_memory->size = size; -} - static INLINE size_t wasm_memory_get_size(struct wasm_memory *wasm_memory) { diff --git a/runtime/include/wasm_stack.h b/runtime/include/wasm_stack.h index 71c627a..7e79ec5 100644 --- a/runtime/include/wasm_stack.h +++ b/runtime/include/wasm_stack.h @@ -7,7 +7,6 @@ #include "sandbox_types.h" #include "types.h" - /** * @brief wasm_stack is a stack used to execute an AOT-compiled WebAssembly instance. It is allocated with a static size * and a guard page beneath the lowest usuable address. Because the stack grows down, this protects against stack @@ -29,11 +28,11 @@ struct wasm_stack { uint8_t * buffer; /* Points base address of backing heap allocation (Guard Page) */ }; -static inline struct wasm_stack * -wasm_stack_allocate(void) -{ - return calloc(1, sizeof(struct wasm_stack)); -} +static struct wasm_stack *wasm_stack_alloc(size_t capacity); +static inline int wasm_stack_init(struct wasm_stack *wasm_stack, size_t capacity); +static inline void wasm_stack_reinit(struct wasm_stack *wasm_stack); +static inline void wasm_stack_deinit(struct wasm_stack *wasm_stack); +static inline void wasm_stack_free(struct wasm_stack *wasm_stack); /** * Allocates a static sized stack for a sandbox with a guard page underneath @@ -79,17 +78,10 @@ err_stack_allocation_failed: goto done; } -static INLINE void -wasm_stack_free(struct wasm_stack *wasm_stack) -{ - free(wasm_stack); -} - - static struct wasm_stack * -wasm_stack_new(size_t capacity) +wasm_stack_alloc(size_t capacity) { - struct wasm_stack *wasm_stack = wasm_stack_allocate(); + struct wasm_stack *wasm_stack = calloc(1, sizeof(struct wasm_stack)); int rc = wasm_stack_init(wasm_stack, capacity); if (rc < 0) { wasm_stack_free(wasm_stack); @@ -113,12 +105,12 @@ wasm_stack_deinit(struct wasm_stack *wasm_stack) } static inline void -wasm_stack_delete(struct wasm_stack *wasm_stack) +wasm_stack_free(struct wasm_stack *wasm_stack) { assert(wasm_stack != NULL); assert(wasm_stack->buffer != NULL); wasm_stack_deinit(wasm_stack); - wasm_stack_free(wasm_stack); + free(wasm_stack); } static inline void diff --git a/runtime/include/wasm_table.h b/runtime/include/wasm_table.h index 64344ff..ce463aa 100644 --- a/runtime/include/wasm_table.h +++ b/runtime/include/wasm_table.h @@ -20,18 +20,10 @@ struct wasm_table { struct wasm_table_entry *buffer; /* Backing heap allocation */ }; -static INLINE struct wasm_table *wasm_table_alloc(void); static INLINE int wasm_table_init(struct wasm_table *wasm_table, size_t capacity); -static INLINE struct wasm_table *wasm_table_new(size_t capacity); +static INLINE struct wasm_table *wasm_table_alloc(size_t capacity); static INLINE void wasm_table_deinit(struct wasm_table *wasm_table); static INLINE void wasm_table_free(struct wasm_table *wasm_table); -static INLINE void wasm_table_delete(struct wasm_table *wasm_table); - -static INLINE struct wasm_table * -wasm_table_alloc(void) -{ - return (struct wasm_table *)malloc(sizeof(struct wasm_table)); -} static INLINE int wasm_table_init(struct wasm_table *wasm_table, size_t capacity) @@ -50,9 +42,9 @@ wasm_table_init(struct wasm_table *wasm_table, size_t capacity) } static INLINE struct wasm_table * -wasm_table_new(size_t capacity) +wasm_table_alloc(size_t capacity) { - struct wasm_table *wasm_table = wasm_table_alloc(); + struct wasm_table *wasm_table = (struct wasm_table *)malloc(sizeof(struct wasm_table)); if (wasm_table == NULL) return NULL; int rc = wasm_table_init(wasm_table, capacity); diff --git a/runtime/src/listener_thread.c b/runtime/src/listener_thread.c index e47470c..e4b2da6 100644 --- a/runtime/src/listener_thread.c +++ b/runtime/src/listener_thread.c @@ -179,9 +179,9 @@ listener_thread_main(void *dummy) } /* Allocate a Sandbox */ - struct sandbox *sandbox = sandbox_new(module, client_socket, - (const struct sockaddr *)&client_address, - request_arrival_timestamp, work_admitted); + struct sandbox *sandbox = sandbox_alloc(module, client_socket, + (const struct sockaddr *)&client_address, + request_arrival_timestamp, work_admitted); if (unlikely(sandbox == NULL)) { client_socket_send_oneshot(sandbox->client_socket_descriptor, http_header_build(503), http_header_len(503)); diff --git a/runtime/src/main.c b/runtime/src/main.c index 7819b2c..15c5fdf 100644 --- a/runtime/src/main.c +++ b/runtime/src/main.c @@ -369,7 +369,7 @@ main(int argc, char **argv) #ifdef LOG_MODULE_LOADING debuglog("Parsing modules file [%s]\n", argv[1]); #endif - if (module_new_from_json(argv[1])) panic("failed to initialize module(s) defined in %s\n", argv[1]); + if (module_alloc_from_json(argv[1])) panic("failed to initialize module(s) defined in %s\n", argv[1]); for (int i = 0; i < runtime_worker_threads_count; i++) { diff --git a/runtime/src/module.c b/runtime/src/module.c index 45a96f2..0978075 100644 --- a/runtime/src/module.c +++ b/runtime/src/module.c @@ -126,53 +126,42 @@ module_free(struct module *module) free(module); } - -/** - * Module Contructor - * Creates a new module, invokes initialize_tables to initialize the indirect table, adds it to the module DB, and - *starts listening for HTTP Requests - * - * @param name - * @param path - * @param stack_size - * @param relative_deadline_us - * @param port - * @param request_size - * @returns A new module or NULL in case of failure - */ - -struct module * -module_new(char *name, char *path, uint32_t stack_size, uint32_t relative_deadline_us, int port, int request_size, - int response_size, int admissions_percentile, uint32_t expected_execution_us) +static inline int +module_init(struct module *module, char *name, char *path, uint32_t stack_size, uint32_t relative_deadline_us, int port, + int request_size, int response_size, int admissions_percentile, uint32_t expected_execution_us) { - int rc = 0; + assert(module != NULL); + assert(name != NULL); + assert(strlen(name) > 0); + assert(strlen(name) < MODULE_MAX_NAME_LENGTH); + assert(path != NULL); + assert(strlen(path) > 0); + assert(strlen(path) < MODULE_MAX_PATH_LENGTH); + assert(stack_size > 0); + assert(relative_deadline_us > 0); + assert(relative_deadline_us < RUNTIME_RELATIVE_DEADLINE_US_MAX); + assert(port > 0); + assert(admissions_percentile > 0); + assert(expected_execution_us > 0); - struct module *module = (struct module *)calloc(1, sizeof(struct module)); - if (!module) { - fprintf(stderr, "Failed to allocate module: %s\n", strerror(errno)); - goto err; - }; + int rc = 0; atomic_init(&module->reference_count, 0); rc = awsm_abi_init(&module->abi, path); - if (rc != 0) goto awsm_abi_init_err; + if (rc != 0) goto err; /* Set fields in the module struct */ strncpy(module->name, name, MODULE_MAX_NAME_LENGTH); strncpy(module->path, path, MODULE_MAX_PATH_LENGTH); - module->stack_size = ((uint32_t)(round_up_to_page(stack_size == 0 ? WASM_STACK_SIZE : stack_size))); - debuglog("Stack Size: %u", module->stack_size); + module->stack_size = ((uint32_t)(round_up_to_page(stack_size == 0 ? WASM_STACK_SIZE : stack_size))); module->socket_descriptor = -1; module->port = port; /* Deadlines */ module->relative_deadline_us = relative_deadline_us; - /* This should have been handled when a module was loaded */ - assert(relative_deadline_us < RUNTIME_RELATIVE_DEADLINE_US_MAX); - /* This can overflow a uint32_t, so be sure to cast appropriately */ module->relative_deadline = (uint64_t)relative_deadline_us * runtime_processor_speed_MHz; @@ -181,49 +170,58 @@ module_new(char *name, char *path, uint32_t stack_size, uint32_t relative_deadli admissions_info_initialize(&module->admissions_info, admissions_percentile, expected_execution, module->relative_deadline); - /* WebAssembly Indirect Table */ - /* TODO: Should this be part of the module or per-sandbox? */ - /* TODO: How should this table be sized? */ - module->indirect_table = wasm_table_new(INDIRECT_TABLE_SIZE); - /* Request Response Buffer */ if (request_size == 0) request_size = MODULE_DEFAULT_REQUEST_RESPONSE_SIZE; if (response_size == 0) response_size = MODULE_DEFAULT_REQUEST_RESPONSE_SIZE; module->max_request_size = round_up_to_page(request_size); module->max_response_size = round_up_to_page(response_size); - /* Table initialization calls a function that runs within the sandbox. Rather than setting the current sandbox, - * we partially fake this out by only setting the table and then clearing after table - * initialization is complete. - * - * assumption: This approach depends on module_new only being invoked at program start before preemption is - * enabled. We are check that current_wasm_module_instance.table is NULL to gain confidence that - * we are not invoking this in a way that clobbers a current module. - * - * If we want to be able to do this later, we can possibly defer module_initialize_table until the first - * invocation. Alternatively, we can maintain the table per sandbox and call initialize - * on each sandbox if this "assumption" is too restrictive and we're ready to pay a per-sandbox performance hit. - */ - - assert(current_wasm_module_instance.table == NULL); - current_wasm_module_instance.table = module->indirect_table; - module_initialize_table(module); - current_wasm_module_instance.table = NULL; - - for (int i = 0; i < MAX_WORKER_THREADS; i++) { - wasm_memory_pool_init(&module->pools[i].memory, false); - wasm_stack_pool_init(&module->pools[i].stack, false); - } + module_alloc_table(module); + module_initialize_pools(module); /* Start listening for requests */ rc = module_listen(module); - if (rc < 0) goto err_listen; + if (rc < 0) goto err; + +done: + return rc; +err: + rc = -1; + goto done; +} + +/** + * Module Contructor + * Creates a new module, invokes initialize_tables to initialize the indirect table, adds it to the module DB, and + *starts listening for HTTP Requests + * + * @param name + * @param path + * @param stack_size + * @param relative_deadline_us + * @param port + * @param request_size + * @returns A new module or NULL in case of failure + */ + +struct module * +module_alloc(char *name, char *path, uint32_t stack_size, uint32_t relative_deadline_us, int port, int request_size, + int response_size, int admissions_percentile, uint32_t expected_execution_us) +{ + struct module *module = (struct module *)calloc(1, sizeof(struct module)); + if (!module) { + fprintf(stderr, "Failed to allocate module: %s\n", strerror(errno)); + goto err; + }; + + int rc = module_init(module, name, path, stack_size, relative_deadline_us, port, request_size, response_size, + admissions_percentile, expected_execution_us); + if (rc < 0) goto init_err; done: return module; -err_listen: -awsm_abi_init_err: +init_err: free(module); err: module = NULL; @@ -236,7 +234,7 @@ err: * @return RC 0 on Success. -1 on Error */ int -module_new_from_json(char *file_name) +module_alloc_from_json(char *file_name) { assert(file_name != NULL); int return_code = -1; @@ -424,10 +422,10 @@ module_new_from_json(char *file_name) #endif /* Allocate a module based on the values from the JSON */ - struct module *module = module_new(module_name, module_path, 0, relative_deadline_us, port, - request_size, response_size, admissions_percentile, - expected_execution_us); - if (module == NULL) goto module_new_err; + struct module *module = module_alloc(module_name, module_path, 0, relative_deadline_us, port, + request_size, response_size, admissions_percentile, + expected_execution_us); + if (module == NULL) goto module_alloc_err; assert(module); module_set_http_info(module, response_content_type); @@ -444,7 +442,7 @@ module_new_from_json(char *file_name) done: return return_code; -module_new_err: +module_alloc_err: json_parse_err: fclose_err: /* We will retry fclose when we fall through into stat_buffer_alloc_err */ diff --git a/runtime/src/sandbox.c b/runtime/src/sandbox.c index 1326ec8..bce1052 100644 --- a/runtime/src/sandbox.c +++ b/runtime/src/sandbox.c @@ -82,15 +82,6 @@ sandbox_allocate_http_buffers(struct sandbox *sandbox) return 0; } -static inline struct sandbox * -sandbox_allocate(void) -{ - struct sandbox *sandbox = NULL; - size_t page_aligned_sandbox_size = round_up_to_page(sizeof(struct sandbox)); - sandbox = calloc(1, page_aligned_sandbox_size); - sandbox_set_as_allocated(sandbox); - return sandbox; -} /** * Allocates HTTP buffers and performs our approximation of "WebAssembly instantiation" @@ -180,12 +171,15 @@ sandbox_init(struct sandbox *sandbox, struct module *module, int socket_descript * @return the new sandbox request */ struct sandbox * -sandbox_new(struct module *module, int socket_descriptor, const struct sockaddr *socket_address, - uint64_t request_arrival_timestamp, uint64_t admissions_estimate) +sandbox_alloc(struct module *module, int socket_descriptor, const struct sockaddr *socket_address, + uint64_t request_arrival_timestamp, uint64_t admissions_estimate) { - struct sandbox *sandbox = sandbox_allocate(); - assert(sandbox); + struct sandbox *sandbox = NULL; + size_t page_aligned_sandbox_size = round_up_to_page(sizeof(struct sandbox)); + sandbox = calloc(1, page_aligned_sandbox_size); + if (unlikely(sandbox == NULL)) return NULL; + sandbox_set_as_allocated(sandbox); sandbox_init(sandbox, module, socket_descriptor, socket_address, request_arrival_timestamp, admissions_estimate); @@ -193,39 +187,33 @@ sandbox_new(struct module *module, int socket_descriptor, const struct sockaddr return sandbox; } - -/** - * Free stack and heap resources.. also any I/O handles. - * @param sandbox - */ void -sandbox_free(struct sandbox *sandbox) +sandbox_deinit(struct sandbox *sandbox) { assert(sandbox != NULL); assert(sandbox != current_sandbox_get()); assert(sandbox->state == SANDBOX_ERROR || sandbox->state == SANDBOX_COMPLETE); - int rc; - module_release(sandbox->module); /* Linear Memory and Guard Page should already have been munmaped and set to NULL */ assert(sandbox->memory == NULL); - /* Free Sandbox Struct and HTTP Request and Response Buffers */ - + /* Free Sandbox Struct*/ if (likely(sandbox->stack != NULL)) sandbox_free_stack(sandbox); - free(sandbox); +} - if (rc == -1) { - debuglog("Failed to unmap Sandbox %lu\n", sandbox->id); - goto err_free_sandbox_failed; - }; +/** + * Free stack and heap resources.. also any I/O handles. + * @param sandbox + */ +void +sandbox_free(struct sandbox *sandbox) +{ + assert(sandbox != NULL); + assert(sandbox != current_sandbox_get()); + assert(sandbox->state == SANDBOX_ERROR || sandbox->state == SANDBOX_COMPLETE); -done: - return; -err_free_sandbox_failed: -err_free_stack_failed: - /* Errors freeing memory is a fatal error */ - panic("Failed to free Sandbox %lu\n", sandbox->id); + sandbox_deinit(sandbox); + free(sandbox); }