chore: combine thread locals into struct

main
Sean McBride 4 years ago
parent b822f82584
commit 68e91a8853

@ -1,5 +1,5 @@
/* https://github.com/gwsystems/silverfish/blob/master/runtime/memory/64bit_nix.c */ /* https://github.com/gwsystems/silverfish/blob/master/runtime/memory/64bit_nix.c */
#include <types.h> #include "types.h"
#ifdef USE_MEM_VM #ifdef USE_MEM_VM
@ -7,7 +7,7 @@
INLINE float INLINE float
get_f32(i32 offset) 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]; void *address = &mem_as_chars[offset];
return *(float *)address; return *(float *)address;
@ -16,7 +16,7 @@ get_f32(i32 offset)
INLINE double INLINE double
get_f64(i32 offset) 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]; void *address = &mem_as_chars[offset];
return *(double *)address; return *(double *)address;
@ -25,7 +25,7 @@ get_f64(i32 offset)
INLINE i8 INLINE i8
get_i8(i32 offset) 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]; void *address = &mem_as_chars[offset];
return *(i8 *)address; return *(i8 *)address;
@ -34,7 +34,7 @@ get_i8(i32 offset)
INLINE i16 INLINE i16
get_i16(i32 offset) 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]; void *address = &mem_as_chars[offset];
return *(i16 *)address; return *(i16 *)address;
@ -43,7 +43,7 @@ get_i16(i32 offset)
INLINE i32 INLINE i32
get_i32(i32 offset) 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]; void *address = &mem_as_chars[offset];
return *(i32 *)address; return *(i32 *)address;
@ -52,7 +52,7 @@ get_i32(i32 offset)
INLINE i64 INLINE i64
get_i64(i32 offset) 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]; void *address = &mem_as_chars[offset];
return *(i64 *)address; return *(i64 *)address;
@ -61,7 +61,7 @@ get_i64(i32 offset)
INLINE i32 INLINE i32
get_global_i32(i32 offset) 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]; void *address = &mem_as_chars[offset];
return *(i32 *)address; return *(i32 *)address;
@ -70,7 +70,7 @@ get_global_i32(i32 offset)
INLINE i64 INLINE i64
get_global_i64(i32 offset) 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]; void *address = &mem_as_chars[offset];
return *(i64 *)address; return *(i64 *)address;
@ -80,7 +80,7 @@ get_global_i64(i32 offset)
INLINE void INLINE void
set_f32(i32 offset, float v) 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]; void *address = &mem_as_chars[offset];
*(float *)address = v; *(float *)address = v;
@ -89,7 +89,7 @@ set_f32(i32 offset, float v)
INLINE void INLINE void
set_f64(i32 offset, double v) 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]; void *address = &mem_as_chars[offset];
*(double *)address = v; *(double *)address = v;
@ -98,7 +98,7 @@ set_f64(i32 offset, double v)
INLINE void INLINE void
set_i8(i32 offset, i8 v) 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]; void *address = &mem_as_chars[offset];
*(i8 *)address = v; *(i8 *)address = v;
@ -107,7 +107,7 @@ set_i8(i32 offset, i8 v)
INLINE void INLINE void
set_i16(i32 offset, i16 v) 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]; void *address = &mem_as_chars[offset];
*(i16 *)address = v; *(i16 *)address = v;
@ -116,7 +116,7 @@ set_i16(i32 offset, i16 v)
INLINE void INLINE void
set_i32(i32 offset, i32 v) 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]; void *address = &mem_as_chars[offset];
*(i32 *)address = v; *(i32 *)address = v;
@ -125,7 +125,7 @@ set_i32(i32 offset, i32 v)
INLINE void INLINE void
set_i64(i32 offset, i64 v) 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]; void *address = &mem_as_chars[offset];
*(i64 *)address = v; *(i64 *)address = v;
@ -134,7 +134,7 @@ set_i64(i32 offset, i64 v)
INLINE void INLINE void
set_global_i32(i32 offset, i32 v) 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]; void *address = &mem_as_chars[offset];
*(i32 *)address = v; *(i32 *)address = v;
@ -143,7 +143,7 @@ set_global_i32(i32 offset, i32 v)
INLINE void INLINE void
set_global_i64(i32 offset, i64 v) 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]; void *address = &mem_as_chars[offset];
*(i64 *)address = v; *(i64 *)address = v;
@ -155,7 +155,7 @@ get_function_from_table(u32 idx, u32 type_id)
{ {
assert(idx < INDIRECT_TABLE_SIZE); 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.type_id == type_id);
assert(f.func_pointer); assert(f.func_pointer);

@ -73,11 +73,14 @@ struct indirect_table_entry {
void *func_pointer; 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 struct sandbox_member_cache local_sandbox_member_cache;
extern __thread void *sandbox_lmbase;
extern __thread u32 sandbox_lmbound;
/* TODO: LOG_TO_FILE logic is untested */ /* TODO: LOG_TO_FILE logic is untested */
extern i32 runtime_log_file_descriptor; extern i32 runtime_log_file_descriptor;

@ -1,8 +1,15 @@
#include "current_sandbox.h" #include "current_sandbox.h"
#include "types.h"
/* current sandbox that is active.. */ /* current sandbox that is active.. */
static __thread sandbox_t *worker_thread_current_sandbox = NULL; 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 * Getter for the current sandbox executing on this thread
* @returns 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 */ /* Unpack hierarchy to avoid pointer chasing */
if (sandbox == NULL) { 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; worker_thread_current_sandbox = NULL;
sandbox_lmbase = NULL;
sandbox_lmbound = 0;
module_indirect_table = NULL;
} else { } 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; worker_thread_current_sandbox = sandbox;
sandbox_lmbase = sandbox->linear_memory_start;
sandbox_lmbound = sandbox->linear_memory_size;
module_indirect_table = sandbox->module->indirect_table;
} }
} }

@ -1,9 +1,11 @@
#include <runtime.h>
#include <worker_thread.h>
#include <sandbox.h>
#include <uv.h> #include <uv.h>
#include <http_request.h>
#include <current_sandbox.h> #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? // What should we tell the child program its UID and GID are?
#define UID 0xFF #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); 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(); } for (int i = 0; i < len / WASM_PAGE_SIZE; i++) { expand_memory(); }
return result; return result;

@ -1,7 +1,8 @@
/* Code from https://github.com/gwsystems/silverfish/blob/master/runtime/memory/64bit_nix.c */ /* Code from https://github.com/gwsystems/silverfish/blob/master/runtime/memory/64bit_nix.c */
#include <runtime.h> #include "current_sandbox.h"
#include <sandbox.h> #include "runtime.h"
#include <current_sandbox.h> #include "sandbox.h"
#include "types.h"
#ifdef USE_MEM_VM #ifdef USE_MEM_VM
@ -27,10 +28,11 @@ expand_memory(void)
struct sandbox *sandbox = current_sandbox_get(); struct sandbox *sandbox = current_sandbox_get();
// max_pages = 0 => no limit: FIXME // 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 // Remap the relevant wasm page to readable
char *mem_as_chars = sandbox_lmbase; char *mem_as_chars = local_sandbox_member_cache.linear_memory_start;
char *page_address = &mem_as_chars[sandbox_lmbound]; 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, void *map_result = mmap(page_address, WASM_PAGE_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
@ -40,12 +42,13 @@ expand_memory(void)
} }
// TODO: check sandbox->linear_memory_max_size // 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"); printf("expand_memory - Out of Memory!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
sandbox_lmbound += WASM_PAGE_SIZE; local_sandbox_member_cache.linear_memory_size += WASM_PAGE_SIZE;
sandbox->linear_memory_size = sandbox_lmbound; // local_sandbox_member_cache is "forked state", so update authoritative member
sandbox->linear_memory_size = local_sandbox_member_cache.linear_memory_size;
} }
INLINE char * 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 < // Due to how we setup memory for x86, the virtual memory mechanism will catch the error, if bounds <
// WASM_PAGE_SIZE // WASM_PAGE_SIZE
assert(bounds_check < 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]; char *address = &mem_as_chars[offset];
return address; return address;

@ -1,15 +1,12 @@
#include <runtime.h> #include "runtime.h"
#include "types.h"
__thread struct indirect_table_entry *module_indirect_table = NULL;
__thread void * sandbox_lmbase = NULL;
__thread u32 sandbox_lmbound = 0;
/* Region initialization helper function */ /* Region initialization helper function */
EXPORT void EXPORT void
initialize_region(u32 offset, u32 data_count, char *data) initialize_region(u32 offset, u32 data_count, char *data)
{ {
assert(sandbox_lmbound >= data_count); assert(local_sandbox_member_cache.linear_memory_size >= data_count);
assert(offset < sandbox_lmbound - data_count); assert(offset < local_sandbox_member_cache.linear_memory_size - data_count);
/* FIXME: Hack around segmented and unsegmented access */ /* FIXME: Hack around segmented and unsegmented access */
memcpy(get_memory_ptr_for_runtime(offset, data_count), data, data_count); 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) add_function_to_table(u32 idx, u32 type_id, char *pointer)
{ {
assert(idx < INDIRECT_TABLE_SIZE); assert(idx < INDIRECT_TABLE_SIZE);
assert(local_sandbox_member_cache.module_indirect_table != NULL);
/* TODO: atomic for multiple concurrent invocations? */ /* 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 */ /* If we are using runtime globals, we need to populate them */

@ -4,9 +4,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <uv.h> #include <uv.h>
#include <module.h> #include "types.h"
#include <module_database.h> #include "module.h"
#include <runtime.h> #include "module_database.h"
#include "runtime.h"
/************************* /*************************
* Private Static Inline * * 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->max_request_or_response_size = round_up_to_page(response_size);
} }
/* module_indirect_table is a thread-local struct */ /* Table initialization calls a function that runs within the sandbox. Rather than setting the current sandbox,
struct indirect_table_entry *cache_tbl = module_indirect_table; * we partially fake this out by only setting the module_indirect_table and then clearing after table
* initialization is complete.
/* 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 * assumption: This approach depends on module_new only being invoked at program start before preemption is
yet preempting If we want to be able to do this later, we can possibly defer module_initialize_table until * enabled. We are check that local_sandbox_member_cache.module_indirect_table is NULL to gain confidence that
the first invocation */ * we are not invoking this in a way that clobbers a current module.
assert(cache_tbl == NULL); *
* If we want to be able to do this later, we can possibly defer module_initialize_table until the first
/* TODO: determine why we have to set the module_indirect_table state before calling table init and then * invocation
* restore the existing value. What is the relationship between these things? */ */
module_indirect_table = module->indirect_table;
assert(local_sandbox_member_cache.module_indirect_table == NULL);
local_sandbox_member_cache.module_indirect_table = module->indirect_table;
module_initialize_table(module); 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 */ /* Add the module to the in-memory module DB */
module_database_add(module); module_database_add(module);

@ -1,14 +1,16 @@
#include <assert.h> #include <assert.h>
#include <runtime.h>
#include <worker_thread.h>
#include <sandbox.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <pthread.h> #include <pthread.h>
#include <signal.h> #include <signal.h>
#include <uv.h> #include <uv.h>
#include <libuv_callbacks.h>
#include <current_sandbox.h> #include "current_sandbox.h"
#include <http_parser_settings.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 * 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); i32 argument_count = module_get_argument_count(sandbox->module);
/* whatever gregor has, to be able to pass arguments to a module! */ /* whatever gregor has, to be able to pass arguments to a module! */
sandbox->arguments_offset = sandbox_lmbound; sandbox->arguments_offset = local_sandbox_member_cache.linear_memory_size;
assert(sandbox_lmbase == sandbox->linear_memory_start); assert(local_sandbox_member_cache.linear_memory_start == sandbox->linear_memory_start);
expand_memory(); expand_memory();
i32 *array_ptr = worker_thread_get_memory_ptr_void(sandbox->arguments_offset, argument_count * sizeof(i32)); i32 *array_ptr = worker_thread_get_memory_ptr_void(sandbox->arguments_offset, argument_count * sizeof(i32));

Loading…
Cancel
Save