diff --git a/runtime/compiletime/memory/64bit_nix.c b/runtime/compiletime/memory/64bit_nix.c index 3967f14..892d374 100644 --- a/runtime/compiletime/memory/64bit_nix.c +++ b/runtime/compiletime/memory/64bit_nix.c @@ -1,5 +1,5 @@ /* https://github.com/gwsystems/silverfish/blob/master/runtime/memory/64bit_nix.c */ -#include +#include "types.h" #ifdef USE_MEM_VM @@ -7,7 +7,7 @@ INLINE float get_f32(i32 offset) { - char *mem_as_chars = (char *)sandbox_lmbase; + char *mem_as_chars = (char *)local_sandbox_member_cache.linear_memory_start; void *address = &mem_as_chars[offset]; return *(float *)address; @@ -16,7 +16,7 @@ get_f32(i32 offset) INLINE double get_f64(i32 offset) { - char *mem_as_chars = (char *)sandbox_lmbase; + char *mem_as_chars = (char *)local_sandbox_member_cache.linear_memory_start; void *address = &mem_as_chars[offset]; return *(double *)address; @@ -25,7 +25,7 @@ get_f64(i32 offset) INLINE i8 get_i8(i32 offset) { - char *mem_as_chars = (char *)sandbox_lmbase; + char *mem_as_chars = (char *)local_sandbox_member_cache.linear_memory_start; void *address = &mem_as_chars[offset]; return *(i8 *)address; @@ -34,7 +34,7 @@ get_i8(i32 offset) INLINE i16 get_i16(i32 offset) { - char *mem_as_chars = (char *)sandbox_lmbase; + char *mem_as_chars = (char *)local_sandbox_member_cache.linear_memory_start; void *address = &mem_as_chars[offset]; return *(i16 *)address; @@ -43,7 +43,7 @@ get_i16(i32 offset) INLINE i32 get_i32(i32 offset) { - char *mem_as_chars = (char *)sandbox_lmbase; + char *mem_as_chars = (char *)local_sandbox_member_cache.linear_memory_start; void *address = &mem_as_chars[offset]; return *(i32 *)address; @@ -52,7 +52,7 @@ get_i32(i32 offset) INLINE i64 get_i64(i32 offset) { - char *mem_as_chars = (char *)sandbox_lmbase; + char *mem_as_chars = (char *)local_sandbox_member_cache.linear_memory_start; void *address = &mem_as_chars[offset]; return *(i64 *)address; @@ -61,7 +61,7 @@ get_i64(i32 offset) INLINE i32 get_global_i32(i32 offset) { - char *mem_as_chars = (char *)sandbox_lmbase; + char *mem_as_chars = (char *)local_sandbox_member_cache.linear_memory_start; void *address = &mem_as_chars[offset]; return *(i32 *)address; @@ -70,7 +70,7 @@ get_global_i32(i32 offset) INLINE i64 get_global_i64(i32 offset) { - char *mem_as_chars = (char *)sandbox_lmbase; + char *mem_as_chars = (char *)local_sandbox_member_cache.linear_memory_start; void *address = &mem_as_chars[offset]; return *(i64 *)address; @@ -80,7 +80,7 @@ get_global_i64(i32 offset) INLINE void set_f32(i32 offset, float v) { - char *mem_as_chars = (char *)sandbox_lmbase; + char *mem_as_chars = (char *)local_sandbox_member_cache.linear_memory_start; void *address = &mem_as_chars[offset]; *(float *)address = v; @@ -89,7 +89,7 @@ set_f32(i32 offset, float v) INLINE void set_f64(i32 offset, double v) { - char *mem_as_chars = (char *)sandbox_lmbase; + char *mem_as_chars = (char *)local_sandbox_member_cache.linear_memory_start; void *address = &mem_as_chars[offset]; *(double *)address = v; @@ -98,7 +98,7 @@ set_f64(i32 offset, double v) INLINE void set_i8(i32 offset, i8 v) { - char *mem_as_chars = (char *)sandbox_lmbase; + char *mem_as_chars = (char *)local_sandbox_member_cache.linear_memory_start; void *address = &mem_as_chars[offset]; *(i8 *)address = v; @@ -107,7 +107,7 @@ set_i8(i32 offset, i8 v) INLINE void set_i16(i32 offset, i16 v) { - char *mem_as_chars = (char *)sandbox_lmbase; + char *mem_as_chars = (char *)local_sandbox_member_cache.linear_memory_start; void *address = &mem_as_chars[offset]; *(i16 *)address = v; @@ -116,7 +116,7 @@ set_i16(i32 offset, i16 v) INLINE void set_i32(i32 offset, i32 v) { - char *mem_as_chars = (char *)sandbox_lmbase; + char *mem_as_chars = (char *)local_sandbox_member_cache.linear_memory_start; void *address = &mem_as_chars[offset]; *(i32 *)address = v; @@ -125,7 +125,7 @@ set_i32(i32 offset, i32 v) INLINE void set_i64(i32 offset, i64 v) { - char *mem_as_chars = (char *)sandbox_lmbase; + char *mem_as_chars = (char *)local_sandbox_member_cache.linear_memory_start; void *address = &mem_as_chars[offset]; *(i64 *)address = v; @@ -134,7 +134,7 @@ set_i64(i32 offset, i64 v) INLINE void set_global_i32(i32 offset, i32 v) { - char *mem_as_chars = (char *)sandbox_lmbase; + char *mem_as_chars = (char *)local_sandbox_member_cache.linear_memory_start; void *address = &mem_as_chars[offset]; *(i32 *)address = v; @@ -143,7 +143,7 @@ set_global_i32(i32 offset, i32 v) INLINE void set_global_i64(i32 offset, i64 v) { - char *mem_as_chars = (char *)sandbox_lmbase; + char *mem_as_chars = (char *)local_sandbox_member_cache.linear_memory_start; void *address = &mem_as_chars[offset]; *(i64 *)address = v; @@ -155,7 +155,7 @@ get_function_from_table(u32 idx, u32 type_id) { assert(idx < INDIRECT_TABLE_SIZE); - struct indirect_table_entry f = module_indirect_table[idx]; + struct indirect_table_entry f = local_sandbox_member_cache.module_indirect_table[idx]; // assert(f.type_id == type_id); assert(f.func_pointer); diff --git a/runtime/include/types.h b/runtime/include/types.h index 5e4136f..67a3ac0 100644 --- a/runtime/include/types.h +++ b/runtime/include/types.h @@ -73,11 +73,14 @@ struct indirect_table_entry { void *func_pointer; }; -extern __thread struct indirect_table_entry *module_indirect_table; +/* Cache of Frequently Accessed Members used to avoid pointer chasing */ +struct sandbox_member_cache { + struct indirect_table_entry *module_indirect_table; + void * linear_memory_start; + u32 linear_memory_size; +}; -/* for sandbox linear memory isolation */ -extern __thread void *sandbox_lmbase; -extern __thread u32 sandbox_lmbound; +extern __thread struct sandbox_member_cache local_sandbox_member_cache; /* TODO: LOG_TO_FILE logic is untested */ extern i32 runtime_log_file_descriptor; diff --git a/runtime/src/current_sandbox.c b/runtime/src/current_sandbox.c index e2aef12..e762ede 100644 --- a/runtime/src/current_sandbox.c +++ b/runtime/src/current_sandbox.c @@ -1,8 +1,15 @@ #include "current_sandbox.h" +#include "types.h" /* current sandbox that is active.. */ static __thread sandbox_t *worker_thread_current_sandbox = NULL; +__thread struct sandbox_member_cache local_sandbox_member_cache = { + .linear_memory_start = NULL, + .linear_memory_size = 0, + .module_indirect_table = NULL, +}; + /** * Getter for the current sandbox executing on this thread * @returns the current sandbox executing on this thread @@ -22,15 +29,19 @@ current_sandbox_set(struct sandbox *sandbox) { /* Unpack hierarchy to avoid pointer chasing */ if (sandbox == NULL) { + local_sandbox_member_cache = (struct sandbox_member_cache){ + .linear_memory_start = NULL, + .linear_memory_size = 0, + .module_indirect_table = NULL, + }; worker_thread_current_sandbox = NULL; - sandbox_lmbase = NULL; - sandbox_lmbound = 0; - module_indirect_table = NULL; } else { + local_sandbox_member_cache = (struct sandbox_member_cache){ + .linear_memory_start = sandbox->linear_memory_start, + .linear_memory_size = sandbox->linear_memory_size, + .module_indirect_table = sandbox->module->indirect_table, + }; worker_thread_current_sandbox = sandbox; - sandbox_lmbase = sandbox->linear_memory_start; - sandbox_lmbound = sandbox->linear_memory_size; - module_indirect_table = sandbox->module->indirect_table; } } diff --git a/runtime/src/libc/uvio.c b/runtime/src/libc/uvio.c index 45232ae..0691f41 100644 --- a/runtime/src/libc/uvio.c +++ b/runtime/src/libc/uvio.c @@ -1,9 +1,11 @@ -#include -#include -#include #include -#include -#include + +#include "current_sandbox.h" +#include "http_request.h" +#include "runtime.h" +#include "sandbox.h" +#include "types.h" +#include "worker_thread.h" // What should we tell the child program its UID and GID are? #define UID 0xFF @@ -462,7 +464,7 @@ wasm_mmap(i32 addr, i32 len, i32 prot, i32 flags, i32 file_descriptor, i32 offse assert(len % WASM_PAGE_SIZE == 0); - i32 result = sandbox_lmbound; + i32 result = local_sandbox_member_cache.linear_memory_size; for (int i = 0; i < len / WASM_PAGE_SIZE; i++) { expand_memory(); } return result; diff --git a/runtime/src/memory/64bit_nix.c b/runtime/src/memory/64bit_nix.c index fd6c040..ed88b98 100644 --- a/runtime/src/memory/64bit_nix.c +++ b/runtime/src/memory/64bit_nix.c @@ -1,7 +1,8 @@ /* Code from https://github.com/gwsystems/silverfish/blob/master/runtime/memory/64bit_nix.c */ -#include -#include -#include +#include "current_sandbox.h" +#include "runtime.h" +#include "sandbox.h" +#include "types.h" #ifdef USE_MEM_VM @@ -27,10 +28,11 @@ expand_memory(void) struct sandbox *sandbox = current_sandbox_get(); // max_pages = 0 => no limit: FIXME - assert((sandbox->sandbox_size + sandbox_lmbound) / WASM_PAGE_SIZE < WASM_MAX_PAGES); + assert((sandbox->sandbox_size + local_sandbox_member_cache.linear_memory_size) / WASM_PAGE_SIZE + < WASM_MAX_PAGES); // Remap the relevant wasm page to readable - char *mem_as_chars = sandbox_lmbase; - char *page_address = &mem_as_chars[sandbox_lmbound]; + char *mem_as_chars = local_sandbox_member_cache.linear_memory_start; + char *page_address = &mem_as_chars[local_sandbox_member_cache.linear_memory_size]; void *map_result = mmap(page_address, WASM_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); @@ -40,12 +42,13 @@ expand_memory(void) } // TODO: check sandbox->linear_memory_max_size - if (sandbox_lmbound > sandbox->linear_memory_max_size) { + if (local_sandbox_member_cache.linear_memory_size > sandbox->linear_memory_max_size) { printf("expand_memory - Out of Memory!\n"); exit(EXIT_FAILURE); } - sandbox_lmbound += WASM_PAGE_SIZE; - sandbox->linear_memory_size = sandbox_lmbound; + local_sandbox_member_cache.linear_memory_size += WASM_PAGE_SIZE; + // local_sandbox_member_cache is "forked state", so update authoritative member + sandbox->linear_memory_size = local_sandbox_member_cache.linear_memory_size; } INLINE char * @@ -54,9 +57,10 @@ get_memory_ptr_for_runtime(u32 offset, u32 bounds_check) // Due to how we setup memory for x86, the virtual memory mechanism will catch the error, if bounds < // WASM_PAGE_SIZE assert(bounds_check < WASM_PAGE_SIZE - || (sandbox_lmbound > bounds_check && offset <= sandbox_lmbound - bounds_check)); + || (local_sandbox_member_cache.linear_memory_size > bounds_check + && offset <= local_sandbox_member_cache.linear_memory_size - bounds_check)); - char *mem_as_chars = (char *)sandbox_lmbase; + char *mem_as_chars = (char *)local_sandbox_member_cache.linear_memory_start; char *address = &mem_as_chars[offset]; return address; diff --git a/runtime/src/memory/common.c b/runtime/src/memory/common.c index db2a45a..71bd879 100644 --- a/runtime/src/memory/common.c +++ b/runtime/src/memory/common.c @@ -1,15 +1,12 @@ -#include - -__thread struct indirect_table_entry *module_indirect_table = NULL; -__thread void * sandbox_lmbase = NULL; -__thread u32 sandbox_lmbound = 0; +#include "runtime.h" +#include "types.h" /* Region initialization helper function */ EXPORT void initialize_region(u32 offset, u32 data_count, char *data) { - assert(sandbox_lmbound >= data_count); - assert(offset < sandbox_lmbound - data_count); + assert(local_sandbox_member_cache.linear_memory_size >= data_count); + assert(offset < local_sandbox_member_cache.linear_memory_size - data_count); /* FIXME: Hack around segmented and unsegmented access */ memcpy(get_memory_ptr_for_runtime(offset, data_count), data, data_count); @@ -19,11 +16,16 @@ void add_function_to_table(u32 idx, u32 type_id, char *pointer) { assert(idx < INDIRECT_TABLE_SIZE); + assert(local_sandbox_member_cache.module_indirect_table != NULL); /* TODO: atomic for multiple concurrent invocations? */ - if (module_indirect_table[idx].type_id == type_id && module_indirect_table[idx].func_pointer == pointer) return; + if (local_sandbox_member_cache.module_indirect_table[idx].type_id == type_id + && local_sandbox_member_cache.module_indirect_table[idx].func_pointer == pointer) + return; - module_indirect_table[idx] = (struct indirect_table_entry){ .type_id = type_id, .func_pointer = pointer }; + local_sandbox_member_cache.module_indirect_table[idx] = (struct indirect_table_entry){ + .type_id = type_id, .func_pointer = pointer + }; } /* If we are using runtime globals, we need to populate them */ diff --git a/runtime/src/module.c b/runtime/src/module.c index 2552685..d0ae976 100644 --- a/runtime/src/module.c +++ b/runtime/src/module.c @@ -4,9 +4,10 @@ #include #include -#include -#include -#include +#include "types.h" +#include "module.h" +#include "module_database.h" +#include "runtime.h" /************************* * Private Static Inline * @@ -148,20 +149,22 @@ module_new(char *name, char *path, i32 argument_count, u32 stack_size, u32 max_m module->max_request_or_response_size = round_up_to_page(response_size); } - /* module_indirect_table is a thread-local struct */ - struct indirect_table_entry *cache_tbl = module_indirect_table; - - /* assumption: All modules are created at program start before we enable preemption or enable the execution - of any worker threads We are checking that thread-local module_indirect_table is NULL to prove that we aren't - yet preempting If we want to be able to do this later, we can possibly defer module_initialize_table until - the first invocation */ - assert(cache_tbl == NULL); - - /* TODO: determine why we have to set the module_indirect_table state before calling table init and then - * restore the existing value. What is the relationship between these things? */ - module_indirect_table = module->indirect_table; + /* 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 module_indirect_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 local_sandbox_member_cache.module_indirect_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 + */ + + assert(local_sandbox_member_cache.module_indirect_table == NULL); + local_sandbox_member_cache.module_indirect_table = module->indirect_table; module_initialize_table(module); - module_indirect_table = cache_tbl; + local_sandbox_member_cache.module_indirect_table = NULL; /* Add the module to the in-memory module DB */ module_database_add(module); diff --git a/runtime/src/sandbox.c b/runtime/src/sandbox.c index edb8491..6d1800e 100644 --- a/runtime/src/sandbox.c +++ b/runtime/src/sandbox.c @@ -1,14 +1,16 @@ #include -#include -#include -#include #include #include #include #include -#include -#include -#include + +#include "current_sandbox.h" +#include "http_parser_settings.h" +#include "libuv_callbacks.h" +#include "runtime.h" +#include "sandbox.h" +#include "types.h" +#include "worker_thread.h" /** * Takes the arguments from the sandbox struct and writes them into the WebAssembly linear memory @@ -21,8 +23,8 @@ sandbox_setup_arguments(struct sandbox *sandbox) i32 argument_count = module_get_argument_count(sandbox->module); /* whatever gregor has, to be able to pass arguments to a module! */ - sandbox->arguments_offset = sandbox_lmbound; - assert(sandbox_lmbase == sandbox->linear_memory_start); + sandbox->arguments_offset = local_sandbox_member_cache.linear_memory_size; + assert(local_sandbox_member_cache.linear_memory_start == sandbox->linear_memory_start); expand_memory(); i32 *array_ptr = worker_thread_get_memory_ptr_void(sandbox->arguments_offset, argument_count * sizeof(i32));