chore: namespace macros and globals in main.c

main
Sean McBride 5 years ago
parent 3cbb7f0748
commit 9dfc740d05

@ -13,7 +13,7 @@ CFLAGS = ${OPTFLAGS} -D${USE_MEM} -I${INC} -pthread
CFLAGS += -DX86_64
#CFLAGS += -DDEBUG
CFLAGS += -D_GNU_SOURCE
#CFLAGS += -DNOSTDIO
#CFLAGS += -DLOG_TO_FILE
CFLAGS += -DUSE_HTTP_UVIO #-DUSE_HTTP_SYNC
#CFLAGS += -DUSE_SYSCALL
#CFLAGS += -DPREEMPT_DISABLE

@ -64,8 +64,8 @@ http_parser_settings__on_header_field(http_parser *parser, const char *at, size_
struct http_request *http_request = &sandbox->http_request;
if (http_request->last_was_value) http_request->header_count++;
assert(http_request->header_count <= HTTP_HEADERS_MAX);
assert(length < HTTP_HEADER_MAXSZ);
assert(http_request->header_count <= HTTP__MAX_HEADER_COUNT);
assert(length < HTTP__MAX_HEADER_LENGTH);
http_request->last_was_value = 0;
http_request->headers[http_request->header_count - 1].key = (char *)
@ -89,8 +89,8 @@ http_parser_settings__on_header_value(http_parser *parser, const char *at, size_
struct http_request *http_request = &sandbox->http_request;
http_request->last_was_value = 1;
assert(http_request->header_count <= HTTP_HEADERS_MAX);
assert(length < HTTP_HEADERVAL_MAXSZ);
assert(http_request->header_count <= HTTP__MAX_HEADER_COUNT);
assert(length < HTTP__MAX_HEADER_VALUE_LENGTH);
http_request->headers[http_request->header_count - 1].value = (char *)
at; // it is from the sandbox's request_response_data, should persist.

@ -10,7 +10,7 @@ struct http_header {
};
struct http_request {
struct http_header headers[HTTP_HEADERS_MAX];
struct http_header headers[HTTP__MAX_HEADER_COUNT];
int header_count;
char * body;
int body_length;

@ -16,16 +16,16 @@ struct http_response_header {
};
struct http_response {
struct http_response_header headers[HTTP_HEADERS_MAX];
struct http_response_header headers[HTTP__MAX_HEADER_COUNT];
int header_count;
char * body;
int body_length;
char * status;
int status_length;
#ifdef USE_HTTP_UVIO
uv_buf_t bufs[HTTP_HEADERS_MAX * 2 + 3]; // max headers, one line for status code, remaining for body!
uv_buf_t bufs[HTTP__MAX_HEADER_COUNT * 2 + 3]; // max headers, one line for status code, remaining for body!
#else
struct iovec bufs[HTTP_HEADERS_MAX * 2 + 3];
struct iovec bufs[HTTP__MAX_HEADER_COUNT * 2 + 3];
#endif
};

@ -6,8 +6,8 @@
#include <types.h>
struct module {
char name[MOD_NAME_MAX];
char path[MOD_PATH_MAX];
char name[MODULE__MAX_NAME_LENGTH];
char path[MODULE__MAX_PATH_LENGTH];
void * dynamic_library_handle; // Handle to the *.so of the serverless function
i32 argument_count;
u32 stack_size; // a specification?
@ -27,15 +27,15 @@ struct module {
// uv_handle_t srvuv;
unsigned long max_request_size;
char request_headers[HTTP_HEADERS_MAX][HTTP_HEADER_MAXSZ];
char request_headers[HTTP__MAX_HEADER_COUNT][HTTP__MAX_HEADER_LENGTH];
int request_header_count;
char request_content_type[HTTP_HEADERVAL_MAXSZ];
char request_content_type[HTTP__MAX_HEADER_VALUE_LENGTH];
// resp size including headers!
unsigned long max_response_size;
int response_header_count;
char response_content_type[HTTP_HEADERVAL_MAXSZ];
char response_headers[HTTP_HEADERS_MAX][HTTP_HEADER_MAXSZ];
char response_content_type[HTTP__MAX_HEADER_VALUE_LENGTH];
char response_headers[HTTP__MAX_HEADER_COUNT][HTTP__MAX_HEADER_LENGTH];
// Equals the largest of either max_request_size or max_response_size
unsigned long max_request_or_response_size;
@ -171,10 +171,10 @@ module__set_http_info(struct module *module, int request_count, char *request_he
{
assert(module);
module->request_header_count = request_count;
memcpy(module->request_headers, request_headers, HTTP_HEADER_MAXSZ * HTTP_HEADERS_MAX);
memcpy(module->request_headers, request_headers, HTTP__MAX_HEADER_LENGTH * HTTP__MAX_HEADER_COUNT);
strcpy(module->request_content_type, request_content_type);
module->response_header_count = response_count;
memcpy(module->response_headers, response_headers, HTTP_HEADER_MAXSZ * HTTP_HEADERS_MAX);
memcpy(module->response_headers, response_headers, HTTP__MAX_HEADER_LENGTH * HTTP__MAX_HEADER_COUNT);
strcpy(module->response_content_type, response_content_type);
}

@ -22,7 +22,7 @@ module_database__add(struct module *module)
// __sync_fetch_and_add is provided by GCC
int f = __sync_fetch_and_add(&module_database_free_offset, 1);
assert(f < MOD_MAX);
assert(f < MODULE__MAX_MODULE_COUNT);
module_database[f] = module;
return 0;

@ -53,7 +53,7 @@ struct sandbox {
void *arguments; // arguments from request, must be of module->argument_count size.
i32 return_value;
struct sandbox__io_handle io_handles[SBOX_MAX_OPEN];
struct sandbox__io_handle io_handles[SANDBOX__MAX_IO_HANDLE_COUNT];
struct sockaddr client_address; // client requesting connection!
int client_socket_descriptor;
uv_tcp_t client_libuv_stream;
@ -136,11 +136,11 @@ sandbox__initialize_io_handle(struct sandbox *sandbox)
{
if (!sandbox) return -1;
int io_handle_index;
for (io_handle_index = 0; io_handle_index < SBOX_MAX_OPEN; io_handle_index++) {
for (io_handle_index = 0; io_handle_index < SANDBOX__MAX_IO_HANDLE_COUNT; io_handle_index++) {
if (sandbox->io_handles[io_handle_index].file_descriptor < 0) break;
}
if (io_handle_index == SBOX_MAX_OPEN) return -1;
sandbox->io_handles[io_handle_index].file_descriptor = SBOX_PREOPEN_MAGIC;
if (io_handle_index == SANDBOX__MAX_IO_HANDLE_COUNT) return -1;
sandbox->io_handles[io_handle_index].file_descriptor = SANDBOX__FILE_DESCRIPTOR_PREOPEN_MAGIC;
memset(&sandbox->io_handles[io_handle_index].libuv_handle, 0, sizeof(union uv_any_handle));
return io_handle_index;
}
@ -176,8 +176,9 @@ static inline int
sandbox__set_file_descriptor(struct sandbox *sandbox, int io_handle_index, int file_descriptor)
{
if (!sandbox) return -1;
if (io_handle_index >= SBOX_MAX_OPEN || io_handle_index < 0) return -1;
if (file_descriptor < 0 || sandbox->io_handles[io_handle_index].file_descriptor != SBOX_PREOPEN_MAGIC)
if (io_handle_index >= SANDBOX__MAX_IO_HANDLE_COUNT || io_handle_index < 0) return -1;
if (file_descriptor < 0
|| sandbox->io_handles[io_handle_index].file_descriptor != SANDBOX__FILE_DESCRIPTOR_PREOPEN_MAGIC)
return -1;
sandbox->io_handles[io_handle_index].file_descriptor = file_descriptor;
return io_handle_index;
@ -193,7 +194,7 @@ static inline int
sandbox__get_file_descriptor(struct sandbox *sandbox, int io_handle_index)
{
if (!sandbox) return -1;
if (io_handle_index >= SBOX_MAX_OPEN || io_handle_index < 0) return -1;
if (io_handle_index >= SANDBOX__MAX_IO_HANDLE_COUNT || io_handle_index < 0) return -1;
return sandbox->io_handles[io_handle_index].file_descriptor;
}
@ -205,7 +206,7 @@ sandbox__get_file_descriptor(struct sandbox *sandbox, int io_handle_index)
static inline void
sandbox__close_file_descriptor(struct sandbox *sandbox, int io_handle_index)
{
if (io_handle_index >= SBOX_MAX_OPEN || io_handle_index < 0) return;
if (io_handle_index >= SANDBOX__MAX_IO_HANDLE_COUNT || io_handle_index < 0) return;
// TODO: Do we actually need to call some sort of close function here?
sandbox->io_handles[io_handle_index].file_descriptor = -1;
}
@ -220,7 +221,7 @@ static inline union uv_any_handle *
sandbox__get_libuv_handle(struct sandbox *sandbox, int io_handle_index)
{
if (!sandbox) return NULL;
if (io_handle_index >= SBOX_MAX_OPEN || io_handle_index < 0) return NULL;
if (io_handle_index >= SANDBOX__MAX_IO_HANDLE_COUNT || io_handle_index < 0) return NULL;
return &sandbox->io_handles[io_handle_index].libuv_handle;
}

@ -81,7 +81,7 @@ extern __thread struct indirect_table_entry *module_indirect_table;
// for sandbox linear memory isolation
extern __thread void *sandbox_lmbase;
extern __thread u32 sandbox_lmbound;
extern i32 log_file_descriptor; // TODO: NOSTDIO logic is untested
extern i32 runtime__log_file_descriptor; // TODO: LOG_TO_FILE logic is untested
// functions in the module to lookup and call per sandbox.
typedef i32 (*mod_main_fn_t)(i32 a, i32 b);
@ -99,67 +99,66 @@ typedef enum
MOD_ARG_MAX,
} mod_argindex_t;
#define MOD_MAIN_FN "wasmf_main"
#define MOD_GLB_FN "populate_globals"
#define MOD_MEM_FN "populate_memory"
#define MOD_TBL_FN "populate_table"
#define MOD_LIBC_FN "wasmf___init_libc"
#define MOD_MAX_ARGS 16 // Max number of arguments
#define MOD_ARG_MAX_SZ 64 // Max size of a single argument
#define MOD_MAX 1024 // Max size of a single module in JSON
#define MOD_NAME_MAX 32 // Max module name length
#define MOD_PATH_MAX 256 // Max module path length
#define JSON_ELE_MAX 16 // Max number of elements defined in JSON
// This is the max number of standboxes that get pulled onto the local runqueue in a single batch
#define SBOX_PULL_MAX 1
#define SBOX_MAX_OPEN 32
#define SBOX_PREOPEN_MAGIC (707707707) // reads lol lol lol upside down
#define SOFTINT_TIMER_START_USEC (10 * 1000) // start timers 10 ms from now.
#define SOFTINT_TIMER_PERIOD_USEC (1000 * 5) // 5ms timer..
/**
* debuglog is a macro that behaves based on the macros DEBUG and LOG_TO_FILE
* If DEBUG is not set, debuglog does nothing
* If DEBUG is set and LOG_TO_FILE is set, debuglog prints to the logfile defined in runtime__log_file_descriptor
* If DEBUG is set adn LOG_TO_FILE is not set, debuglog prints to STDOUT
**/
#ifdef DEBUG
#ifdef NOSTDIO
#define debuglog(fmt, ...) \
dprintf(log_file_descriptor, "(%d,%lu) %s: " fmt, sched_getcpu(), pthread_self(), __func__, ##__VA_ARGS__)
#else
#ifdef LOG_TO_FILE
#define debuglog(fmt, ...) \
dprintf(runtime__log_file_descriptor, "(%d,%lu) %s: " fmt, sched_getcpu(), pthread_self(), __func__, \
##__VA_ARGS__)
#else // !LOG_TO_FILE
#define debuglog(fmt, ...) printf("(%d,%lu) %s: " fmt, sched_getcpu(), pthread_self(), __func__, ##__VA_ARGS__)
#endif
#else
#endif // LOG_TO_FILE
#else // !DEBUG
#define debuglog(fmt, ...)
#endif
#endif // DEBUG
#define HTTP__MAX_HEADER_COUNT 16
#define HTTP__MAX_HEADER_LENGTH 32
#define HTTP__MAX_HEADER_VALUE_LENGTH 64
#define HTTP__RESPONSE_200_OK "HTTP/1.1 200 OK\r\n"
#define HTTP__RESPONSE_CONTENT_LENGTH "Content-length: \r\n\r\n" // content body follows this
#define HTTP__RESPONSE_CONTENT_TYPE "Content-type: \r\n"
#define HTTP__RESPONSE_CONTENT_TYPE_PLAIN "text/plain"
#define JSON__MAX_ELEMENT_COUNT 16 // Max number of elements defined in JSON
#define JSON__MAX_ELEMENT_SIZE 1024 // Max size of a single module in JSON
#define LISTENER_THREAD__CORE_ID 0 // Dedicated Listener Core
#define LISTENER_THREAD__MAX_EPOLL_EVENTS 1024
#define MODULE__DEFAULT_REQUEST_RESPONSE_SIZE (PAGE_SIZE)
#define MODULE__INITIALIZE_GLOBALS "populate_globals" // From Silverfish
#define MODULE__INITIALIZE_MEMORY "populate_memory" // From Silverfish
#define MODULE__INITIALIZE_TABLE "populate_table" // From Silverfish
#define MODULE__INITIALIZE_LIBC "wasmf___init_libc" // From Silverfish
#define MODULE__MAIN "wasmf_main" // From Silverfish
#define MODULE__MAX_ARGUMENT_COUNT 16 // Max number of arguments
#define MODULE__MAX_ARGUMENT_SIZE 64 // Max size of a single argument
#define MODULE__MAX_MODULE_COUNT 128 // Max number of modules
#define MODULE__MAX_NAME_LENGTH 32 // Max module name length
#define MODULE__MAX_PATH_LENGTH 256 // Max length of path string
#define MODULE__MAX_PENDING_CLIENT_REQUESTS 1000
#define RUNTIME__LOG_FILE "awesome.log"
#define RUNTIME__READ_WRITE_VECTOR_LENGTH 16
#define RUNTIME__MAX_SANDBOX_REQUEST_COUNT (1 << 19) // random!
#define SANDBOX__FILE_DESCRIPTOR_PREOPEN_MAGIC (707707707) // reads lol lol lol upside down
#define SANDBOX__MAX_IO_HANDLE_COUNT 32
#define SANDBOX__PULL_BATCH_SIZE 1 // Max # standboxes pulled onto the local runqueue in a single batch
#define SOFTWARE_INTERRUPT__TIME_TO_START_IN_USEC (10 * 1000) // start timers 10 ms from now.
#define SOFTWARE_INTERRUPT__INTERVAL_DURATION_IN_USEC (1000 * 5) // and execute every 5ms
#define GLB_STDOUT "/dev/null"
#define GLB_STDERR "/dev/null"
#define GLB_STDIN "/dev/zero"
#define LOGFILE "awesome.log"
#define RDWR_VEC_MAX 16
#define MOD_REQ_CORE 0 // Dedicated Listener Core
// If multicore, use all but the dedicated listener core
// If there are fewer cores than this, main dynamically overrides this and uses all available
#define SBOX_NCORES (NCORES > 1 ? NCORES - 1 : NCORES)
#define SBOX_MAX_REQS (1 << 19) // random!
#define SBOX_RESP_STRSZ 32
#define MOD_BACKLOG 1000
#define EPOLL_MAX 1024
#define MOD_REQ_RESP_DEFAULT (PAGE_SIZE)
#define HTTP_HEADERS_MAX 16
#define HTTP_HEADER_MAXSZ 32
#define HTTP_HEADERVAL_MAXSZ 64
#define WORKER_THREAD__CORE_COUNT (NCORES > 1 ? NCORES - 1 : NCORES)
#define HTTP_RESP_200OK "HTTP/1.1 200 OK\r\n"
#define HTTP_RESP_CONTTYPE "Content-type: \r\n"
#define HTTP_RESP_CONTLEN "Content-length: \r\n\r\n" // content body follows this
#define HTTP_RESP_CONTTYPE_PLAIN "text/plain"
#endif /* SFRT_TYPES_H */

@ -88,7 +88,7 @@ http_response__set_body(struct http_response *http_response, char *body, int len
int
http_response__set_header(struct http_response *http_response, char *header, int length)
{
assert(http_response->header_count < HTTP_HEADERS_MAX);
assert(http_response->header_count < HTTP__MAX_HEADER_COUNT);
http_response->header_count++;
http_response->headers[http_response->header_count - 1].header = header;
http_response->headers[http_response->header_count - 1].length = length;

@ -183,7 +183,7 @@ i32
wasm_open(i32 path_off, i32 flags, i32 mode)
{
uv_fs_t req = UV_FS_REQ_INIT();
char * path = worker_thread__get_memory_string(path_off, 4096);
char * path = worker_thread__get_memory_string(path_off, MODULE__MAX_PATH_LENGTH);
int iofd = current_sandbox__initialize_io_handle();
if (iofd < 0) return -1;
@ -296,7 +296,7 @@ struct wasm_stat {
i32
wasm_stat(u32 path_str_offset, i32 stat_offset)
{
char * path = worker_thread__get_memory_string(path_str_offset, 4096);
char * path = worker_thread__get_memory_string(path_str_offset, MODULE__MAX_PATH_LENGTH);
struct wasm_stat *stat_ptr = worker_thread__get_memory_ptr_void(stat_offset, sizeof(struct wasm_stat));
struct stat stat;
@ -388,7 +388,7 @@ wasm_fstat(i32 filedes, i32 stat_offset)
i32
wasm_lstat(i32 path_str_offset, i32 stat_offset)
{
char * path = worker_thread__get_memory_string(path_str_offset, 4096);
char * path = worker_thread__get_memory_string(path_str_offset, MODULE__MAX_PATH_LENGTH);
struct wasm_stat *stat_ptr = worker_thread__get_memory_ptr_void(stat_offset, sizeof(struct wasm_stat));
struct stat stat;
@ -521,12 +521,12 @@ wasm_readv(i32 file_descriptor, i32 iov_offset, i32 iovcnt)
int d = current_sandbox__get_file_descriptor(file_descriptor);
struct wasm_iovec *iov = worker_thread__get_memory_ptr_void(iov_offset, iovcnt * sizeof(struct wasm_iovec));
for (int i = 0; i < iovcnt; i += RDWR_VEC_MAX) {
uv_fs_t req = UV_FS_REQ_INIT();
uv_buf_t bufs[RDWR_VEC_MAX] = { 0 }; // avoid mallocs here!
int j = 0;
for (int i = 0; i < iovcnt; i += RUNTIME__READ_WRITE_VECTOR_LENGTH) {
uv_fs_t req = UV_FS_REQ_INIT();
uv_buf_t bufs[RUNTIME__READ_WRITE_VECTOR_LENGTH] = { 0 }; // avoid mallocs here!
int j = 0;
for (j = 0; j < RDWR_VEC_MAX && i + j < iovcnt; j++) {
for (j = 0; j < RUNTIME__READ_WRITE_VECTOR_LENGTH && i + j < iovcnt; j++) {
bufs[j] = uv_buf_init(worker_thread__get_memory_ptr_void(iov[i + j].base_offset,
iov[i + j].len),
iov[i + j].len);
@ -570,12 +570,12 @@ wasm_writev(i32 file_descriptor, i32 iov_offset, i32 iovcnt)
int gret = 0;
struct wasm_iovec *iov = worker_thread__get_memory_ptr_void(iov_offset, iovcnt * sizeof(struct wasm_iovec));
for (int i = 0; i < iovcnt; i += RDWR_VEC_MAX) {
uv_fs_t req = UV_FS_REQ_INIT();
uv_buf_t bufs[RDWR_VEC_MAX] = { 0 }; // avoid mallocs here!
int j = 0;
for (int i = 0; i < iovcnt; i += RUNTIME__READ_WRITE_VECTOR_LENGTH) {
uv_fs_t req = UV_FS_REQ_INIT();
uv_buf_t bufs[RUNTIME__READ_WRITE_VECTOR_LENGTH] = { 0 }; // avoid mallocs here!
int j = 0;
for (j = 0; j < RDWR_VEC_MAX && i + j < iovcnt; j++) {
for (j = 0; j < RUNTIME__READ_WRITE_VECTOR_LENGTH && i + j < iovcnt; j++) {
bufs[j] = uv_buf_init(worker_thread__get_memory_ptr_void(iov[i + j].base_offset,
iov[i + j].len),
iov[i + j].len);
@ -668,10 +668,10 @@ wasm_getcwd(u32 buf_offset, u32 buf_size)
u32
wasm_unlink(u32 path_str_offset)
{
char * str = worker_thread__get_memory_string(path_str_offset, 4096);
uv_fs_t req = UV_FS_REQ_INIT();
debuglog("[%p] start[%s]\n", uv_fs_get_data(&req), str);
uv_fs_unlink(worker_thread__get_thread_libuv_handle(), &req, str, wasm_fs_callback);
char * path = worker_thread__get_memory_string(path_str_offset, MODULE__MAX_PATH_LENGTH);
uv_fs_t req = UV_FS_REQ_INIT();
debuglog("[%p] start[%s]\n", uv_fs_get_data(&req), path);
uv_fs_unlink(worker_thread__get_thread_libuv_handle(), &req, path, wasm_fs_callback);
worker_thread__block_current_sandbox();
int ret = uv_fs_get_result(&req);
@ -881,7 +881,7 @@ wasm_bind(i32 sockfd, i32 sockaddr_offset, i32 addrlen)
debuglog("[%p] tcp\n", c);
int r1 = uv_tcp_bind((uv_tcp_t *)h, worker_thread__get_memory_ptr_void(sockaddr_offset, addrlen),
0 /* TODO: flags */);
if (file_descriptor == SBOX_PREOPEN_MAGIC) {
if (file_descriptor == SANDBOX__FILE_DESCRIPTOR_PREOPEN_MAGIC) {
int r2 = -1, f = -1;
r2 = uv_fileno((uv_handle_t *)h, &f);
debuglog("[%p] [%d,%d]\n", c, f, file_descriptor);
@ -892,7 +892,7 @@ wasm_bind(i32 sockfd, i32 sockaddr_offset, i32 addrlen)
debuglog("[%p] udp\n", c);
int r1 = uv_udp_bind((uv_udp_t *)h, worker_thread__get_memory_ptr_void(sockaddr_offset, addrlen),
0 /* TODO: flags */);
if (file_descriptor == SBOX_PREOPEN_MAGIC) {
if (file_descriptor == SANDBOX__FILE_DESCRIPTOR_PREOPEN_MAGIC) {
int r2 = -1, f = -1;
r2 = uv_fileno((uv_handle_t *)h, &f);
debuglog("[%p] [%d,%d]\n", c, f, file_descriptor);

@ -13,12 +13,18 @@
#include <sandbox.h>
#include <software_interrupt.h>
i32 log_file_descriptor = -1;
u32 total_online_processors = 0;
u32 total_worker_processors = 0;
u32 first_worker_processor = 0;
int worker_threads_argument[SBOX_NCORES] = { 0 }; // The worker sets its argument to -1 on error
pthread_t worker_threads[SBOX_NCORES];
// Conditionally used by debuglog when DEBUG is set
#ifdef DEBUG
i32 runtime__log_file_descriptor = -1;
#endif
u32 runtime__total_online_processors = 0;
u32 runtime__total_worker_processors = 0;
u32 runtime__first_worker_processor = 0;
int runtime__runtime__worker_threads_argument[WORKER_THREAD__CORE_COUNT] = {
0
}; // The worker sets its argument to -1 on error
pthread_t runtime__worker_threads[WORKER_THREAD__CORE_COUNT];
/**
@ -26,7 +32,7 @@ pthread_t worker_threads[SBOX_NCORES];
* @param cmd - The command the user entered
**/
static void
usage(char *cmd)
runtime__usage(char *cmd)
{
printf("%s <modules_file>\n", cmd);
debuglog("%s <modules_file>\n", cmd);
@ -37,7 +43,7 @@ usage(char *cmd)
* (RLIMIT_NOFILE) soft limit to its hard limit (see man getrlimit)
**/
void
set_resource_limits_to_max()
runtime__set_resource_limits_to_max()
{
struct rlimit resource_limit;
if (getrlimit(RLIMIT_DATA, &resource_limit) < 0) {
@ -64,58 +70,63 @@ set_resource_limits_to_max()
* Check the number of cores and the compiler flags and allocate available cores
**/
void
allocate_available_cores()
runtime__allocate_available_cores()
{
// Find the number of processors currently online
total_online_processors = sysconf(_SC_NPROCESSORS_ONLN);
runtime__total_online_processors = sysconf(_SC_NPROCESSORS_ONLN);
// If multicore, we'll pin one core as a listener and run sandbox threads on all others
if (total_online_processors > 1) {
first_worker_processor = 1;
// SBOX_NCORES can be used as a cap on the number of cores to use
// But if there are few cores that SBOX_NCORES, just use what is available
u32 max_possible_workers = total_online_processors - 1;
total_worker_processors = (max_possible_workers >= SBOX_NCORES) ? SBOX_NCORES : max_possible_workers;
if (runtime__total_online_processors > 1) {
runtime__first_worker_processor = 1;
// WORKER_THREAD__CORE_COUNT can be used as a cap on the number of cores to use
// But if there are few cores that WORKER_THREAD__CORE_COUNT, just use what is available
u32 max_possible_workers = runtime__total_online_processors - 1;
runtime__total_worker_processors = (max_possible_workers >= WORKER_THREAD__CORE_COUNT)
? WORKER_THREAD__CORE_COUNT
: max_possible_workers;
} else {
// If single core, we'll do everything on CPUID 0
first_worker_processor = 0;
total_worker_processors = 1;
runtime__first_worker_processor = 0;
runtime__total_worker_processors = 1;
}
debuglog("Number of cores %u, sandboxing cores %u (start: %u) and module reqs %u\n", total_online_processors,
total_worker_processors, first_worker_processor, MOD_REQ_CORE);
debuglog("Number of cores %u, sandboxing cores %u (start: %u) and module reqs %u\n",
runtime__total_online_processors, runtime__total_worker_processors, runtime__first_worker_processor,
LISTENER_THREAD__CORE_ID);
}
#ifdef DEBUG
/**
* If NOSTIO is defined, close stdin, stdout, stderr, and write to logfile named awesome.log.
* Otherwise, log to STDOUT
* NOSTIO = No Standard Input/Output?
* Controls the behavior of the debuglog macro defined in types.h
* If LOG_TO_FILE is defined, close stdin, stdout, stderr, and debuglog writes to a logfile named awesome.log.
* Otherwise, it writes to STDOUT
**/
void
process_nostio()
runtime__process_debug_log_behavior()
{
#ifdef NOSTDIO
#ifdef LOG_TO_FILE
fclose(stdout);
fclose(stderr);
fclose(stdin);
log_file_descriptor = open(LOGFILE, O_CREAT | O_TRUNC | O_WRONLY, S_IRWXU | S_IRWXG);
if (log_file_descriptor < 0) {
runtime__log_file_descriptor = open(RUNTIME__LOG_FILE, O_CREAT | O_TRUNC | O_WRONLY, S_IRWXU | S_IRWXG);
if (runtime__log_file_descriptor < 0) {
perror("open");
exit(-1);
}
#else
log_file_descriptor = 1;
#endif
runtime__log_file_descriptor = 1;
#endif // LOG_TO_FILE
}
#endif // DEBUG
/**
* Starts all worker threads and sleeps forever on pthread_join, which should never return
**/
void
start_worker_threads()
runtime__start_runtime__worker_threads()
{
for (int i = 0; i < total_worker_processors; i++) {
int ret = pthread_create(&worker_threads[i], NULL, worker_thread__main,
(void *)&worker_threads_argument[i]);
for (int i = 0; i < runtime__total_worker_processors; i++) {
int ret = pthread_create(&runtime__worker_threads[i], NULL, worker_thread__main,
(void *)&runtime__runtime__worker_threads_argument[i]);
if (ret) {
errno = ret;
perror("pthread_create");
@ -124,14 +135,14 @@ start_worker_threads()
cpu_set_t cs;
CPU_ZERO(&cs);
CPU_SET(first_worker_processor + i, &cs);
ret = pthread_setaffinity_np(worker_threads[i], sizeof(cs), &cs);
CPU_SET(runtime__first_worker_processor + i, &cs);
ret = pthread_setaffinity_np(runtime__worker_threads[i], sizeof(cs), &cs);
assert(ret == 0);
}
debuglog("Sandboxing environment ready!\n");
for (int i = 0; i < total_worker_processors; i++) {
int ret = pthread_join(worker_threads[i], NULL);
for (int i = 0; i < runtime__total_worker_processors; i++) {
int ret = pthread_join(runtime__worker_threads[i], NULL);
if (ret) {
errno = ret;
perror("pthread_join");
@ -146,17 +157,20 @@ start_worker_threads()
int
main(int argc, char **argv)
{
#ifdef DEBUG
runtime__process_debug_log_behavior();
#endif
printf("Starting Awsm\n");
if (argc != 2) {
usage(argv[0]);
runtime__usage(argv[0]);
exit(-1);
}
memset(worker_threads, 0, sizeof(pthread_t) * SBOX_NCORES);
memset(runtime__worker_threads, 0, sizeof(pthread_t) * WORKER_THREAD__CORE_COUNT);
set_resource_limits_to_max();
allocate_available_cores();
process_nostio();
runtime__set_resource_limits_to_max();
runtime__allocate_available_cores();
runtime__initialize();
debuglog("Parsing modules file [%s]\n", argv[1]);
@ -166,5 +180,5 @@ main(int argc, char **argv)
}
listener_thread__initialize();
start_worker_threads();
runtime__start_runtime__worker_threads();
}

@ -42,7 +42,7 @@ module__initialize_as_server(struct module *module)
}
// Listen to the interface? Check that it is live?
if (listen(socket_descriptor, MOD_BACKLOG) < 0) assert(0);
if (listen(socket_descriptor, MODULE__MAX_PENDING_CLIENT_REQUESTS) < 0) assert(0);
// Set the socket descriptor and register with our global epoll instance to monitor for incoming HTTP requests
@ -112,24 +112,24 @@ module__new(char *name, char *path, i32 argument_count, u32 stack_size, u32 max_
if (module->dynamic_library_handle == NULL) goto dl_open_error;
// Resolve the symbols in the dynamic library *.so file
module->main = (mod_main_fn_t)dlsym(module->dynamic_library_handle, MOD_MAIN_FN);
module->main = (mod_main_fn_t)dlsym(module->dynamic_library_handle, MODULE__MAIN);
if (module->main == NULL) goto dl_error;
module->initialize_globals = (mod_glb_fn_t)dlsym(module->dynamic_library_handle, MOD_GLB_FN);
module->initialize_globals = (mod_glb_fn_t)dlsym(module->dynamic_library_handle, MODULE__INITIALIZE_GLOBALS);
if (module->initialize_globals == NULL) goto dl_error;
module->initialize_memory = (mod_mem_fn_t)dlsym(module->dynamic_library_handle, MOD_MEM_FN);
module->initialize_memory = (mod_mem_fn_t)dlsym(module->dynamic_library_handle, MODULE__INITIALIZE_MEMORY);
if (module->initialize_memory == NULL) goto dl_error;
module->initialize_tables = (mod_tbl_fn_t)dlsym(module->dynamic_library_handle, MOD_TBL_FN);
module->initialize_tables = (mod_tbl_fn_t)dlsym(module->dynamic_library_handle, MODULE__INITIALIZE_TABLE);
if (module->initialize_tables == NULL) goto dl_error;
module->initialize_libc = (mod_libc_fn_t)dlsym(module->dynamic_library_handle, MOD_LIBC_FN);
module->initialize_libc = (mod_libc_fn_t)dlsym(module->dynamic_library_handle, MODULE__INITIALIZE_LIBC);
if (module->initialize_libc == NULL) goto dl_error;
// Set fields in the module struct
strncpy(module->name, name, MOD_NAME_MAX);
strncpy(module->path, path, MOD_PATH_MAX);
strncpy(module->name, name, MODULE__MAX_NAME_LENGTH);
strncpy(module->path, path, MODULE__MAX_PATH_LENGTH);
module->argument_count = argument_count;
module->stack_size = round_up_to_page(stack_size == 0 ? WASM_STACK_SIZE : stack_size);
@ -137,8 +137,8 @@ module__new(char *name, char *path, i32 argument_count, u32 stack_size, u32 max_
module->timeout = timeout;
module->socket_descriptor = -1;
module->port = port;
if (request_size == 0) request_size = MOD_REQ_RESP_DEFAULT;
if (response_size == 0) response_size = MOD_REQ_RESP_DEFAULT;
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 = request_size;
module->max_response_size = response_size;
module->max_request_or_response_size = round_up_to_page(request_size > response_size ? request_size
@ -215,7 +215,7 @@ module__new_from_json(char *file_name)
// Initialize the Jasmine Parser and an array to hold the tokens
jsmn_parser module_parser;
jsmn_init(&module_parser);
jsmntok_t tokens[MOD_MAX * JSON_ELE_MAX];
jsmntok_t tokens[JSON__MAX_ELEMENT_SIZE * JSON__MAX_ELEMENT_COUNT];
// Use Jasmine to parse the JSON
int total_tokens = jsmn_parse(&module_parser, file_buffer, strlen(file_buffer), tokens,
@ -229,23 +229,23 @@ module__new_from_json(char *file_name)
for (int i = 0; i < total_tokens; i++) {
assert(tokens[i].type == JSMN_OBJECT);
char module_name[MOD_NAME_MAX] = { 0 };
char module_path[MOD_PATH_MAX] = { 0 };
char *request_headers = (char *)malloc(HTTP_HEADER_MAXSZ * HTTP_HEADERS_MAX);
memset(request_headers, 0, HTTP_HEADER_MAXSZ * HTTP_HEADERS_MAX);
char *reponse_headers = (char *)malloc(HTTP_HEADER_MAXSZ * HTTP_HEADERS_MAX);
memset(reponse_headers, 0, HTTP_HEADER_MAXSZ * HTTP_HEADERS_MAX);
i32 request_size = 0;
i32 response_size = 0;
i32 argument_count = 0;
u32 port = 0;
i32 is_active = 0;
i32 request_count = 0;
i32 response_count = 0;
int j = 1;
int ntoks = 2 * tokens[i].size;
char request_content_type[HTTP_HEADERVAL_MAXSZ] = { 0 };
char response_content_type[HTTP_HEADERVAL_MAXSZ] = { 0 };
char module_name[MODULE__MAX_NAME_LENGTH] = { 0 };
char module_path[MODULE__MAX_PATH_LENGTH] = { 0 };
char *request_headers = (char *)malloc(HTTP__MAX_HEADER_LENGTH * HTTP__MAX_HEADER_COUNT);
memset(request_headers, 0, HTTP__MAX_HEADER_LENGTH * HTTP__MAX_HEADER_COUNT);
char *reponse_headers = (char *)malloc(HTTP__MAX_HEADER_LENGTH * HTTP__MAX_HEADER_COUNT);
memset(reponse_headers, 0, HTTP__MAX_HEADER_LENGTH * HTTP__MAX_HEADER_COUNT);
i32 request_size = 0;
i32 response_size = 0;
i32 argument_count = 0;
u32 port = 0;
i32 is_active = 0;
i32 request_count = 0;
i32 response_count = 0;
int j = 1;
int ntoks = 2 * tokens[i].size;
char request_content_type[HTTP__MAX_HEADER_VALUE_LENGTH] = { 0 };
char response_content_type[HTTP__MAX_HEADER_VALUE_LENGTH] = { 0 };
for (; j < ntoks;) {
int ntks = 1;
@ -268,28 +268,28 @@ module__new_from_json(char *file_name)
is_active = (strcmp(val, "yes") == 0);
} else if (strcmp(key, "http-req-headers") == 0) {
assert(tokens[i + j + 1].type == JSMN_ARRAY);
assert(tokens[i + j + 1].size <= HTTP_HEADERS_MAX);
assert(tokens[i + j + 1].size <= HTTP__MAX_HEADER_COUNT);
request_count = tokens[i + j + 1].size;
ntks += request_count;
ntoks += request_count;
for (int k = 1; k <= tokens[i + j + 1].size; k++) {
jsmntok_t *g = &tokens[i + j + k + 1];
char * r = request_headers + ((k - 1) * HTTP_HEADER_MAXSZ);
assert(g->end - g->start < HTTP_HEADER_MAXSZ);
char * r = request_headers + ((k - 1) * HTTP__MAX_HEADER_LENGTH);
assert(g->end - g->start < HTTP__MAX_HEADER_LENGTH);
strncpy(r, file_buffer + g->start, g->end - g->start);
}
} else if (strcmp(key, "http-resp-headers") == 0) {
assert(tokens[i + j + 1].type == JSMN_ARRAY);
assert(tokens[i + j + 1].size <= HTTP_HEADERS_MAX);
assert(tokens[i + j + 1].size <= HTTP__MAX_HEADER_COUNT);
response_count = tokens[i + j + 1].size;
ntks += response_count;
ntoks += response_count;
for (int k = 1; k <= tokens[i + j + 1].size; k++) {
jsmntok_t *g = &tokens[i + j + k + 1];
char * r = reponse_headers + ((k - 1) * HTTP_HEADER_MAXSZ);
assert(g->end - g->start < HTTP_HEADER_MAXSZ);
char * r = reponse_headers + ((k - 1) * HTTP__MAX_HEADER_LENGTH);
assert(g->end - g->start < HTTP__MAX_HEADER_LENGTH);
strncpy(r, file_buffer + g->start, g->end - g->start);
}
} else if (strcmp(key, "http-req-size") == 0) {

@ -6,7 +6,7 @@
***************************************/
// In-memory representation of all active modules
struct module *module_database[MOD_MAX] = { NULL };
struct module *module_database[MODULE__MAX_MODULE_COUNT] = { NULL };
// First free in module
int module_database_free_offset = 0;

@ -50,7 +50,7 @@ runtime__initialize(void)
runtime__global_deque = (struct deque_sandbox *)malloc(sizeof(struct deque_sandbox));
assert(runtime__global_deque);
// Note: Below is a Macro
deque_init_sandbox(runtime__global_deque, SBOX_MAX_REQS);
deque_init_sandbox(runtime__global_deque, RUNTIME__MAX_SANDBOX_REQUEST_COUNT);
// Mask Signals
software_interrupt__mask_signal(SIGUSR1);
@ -77,11 +77,13 @@ runtime__initialize(void)
void *
listener_thread__main(void *dummy)
{
struct epoll_event *epoll_events = (struct epoll_event *)malloc(EPOLL_MAX * sizeof(struct epoll_event));
struct epoll_event *epoll_events = (struct epoll_event *)malloc(LISTENER_THREAD__MAX_EPOLL_EVENTS
* sizeof(struct epoll_event));
int total_requests = 0;
while (true) {
int request_count = epoll_wait(runtime__epoll_file_descriptor, epoll_events, EPOLL_MAX, -1);
int request_count = epoll_wait(runtime__epoll_file_descriptor, epoll_events,
LISTENER_THREAD__MAX_EPOLL_EVENTS, -1);
u64 start_time = util__rdtsc();
for (int i = 0; i < request_count; i++) {
if (epoll_events[i].events & EPOLLERR) {
@ -125,7 +127,7 @@ listener_thread__initialize(void)
cpu_set_t cs;
CPU_ZERO(&cs);
CPU_SET(MOD_REQ_CORE, &cs);
CPU_SET(LISTENER_THREAD__CORE_ID, &cs);
pthread_t listener_thread;
int ret = pthread_create(&listener_thread, NULL, listener_thread__main, NULL);
@ -263,7 +265,7 @@ void __attribute__((noinline)) __attribute__((noreturn)) worker_thread__sandbox_
/**
* Pulls up to 1..n sandbox requests, allocates them as sandboxes, sets them as runnable and places them on the local
* runqueue, and then frees the sandbox requests The batch size pulled at once is set by SBOX_PULL_MAX
* runqueue, and then frees the sandbox requests The batch size pulled at once is set by SANDBOX__PULL_BATCH_SIZE
* @return the number of sandbox requests pulled
*/
static inline int
@ -271,7 +273,7 @@ worker_thread__pull_and_process_sandbox_requests(void)
{
int total_sandboxes_pulled = 0;
while (total_sandboxes_pulled < SBOX_PULL_MAX) {
while (total_sandboxes_pulled < SANDBOX__PULL_BATCH_SIZE) {
sandbox_request_t *sandbox_request;
if ((sandbox_request = sandbox_request__steal_from_dequeue()) == NULL) break;
// Actually allocate the sandbox for the requests that we've pulled

@ -29,7 +29,7 @@ current_sandbox__setup_arguments(i32 argument_count)
i32 string_off = curr->arguments_offset + (argument_count * sizeof(i32));
for (int i = 0; i < argument_count; i++) {
char * arg = arguments + (i * MOD_ARG_MAX_SZ);
char * arg = arguments + (i * MODULE__MAX_ARGUMENT_SIZE);
size_t str_sz = strlen(arg) + 1;
array_ptr[i] = string_off;
@ -107,31 +107,34 @@ current_sandbox__receive_and_parse_client_request(void)
static inline int
current_sandbox__build_and_send_client_response(void)
{
int sndsz = 0;
struct sandbox *curr = current_sandbox__get();
int response_header_length = strlen(HTTP_RESP_200OK) + strlen(HTTP_RESP_CONTTYPE) + strlen(HTTP_RESP_CONTLEN);
int body_length = curr->request_response_data_length - response_header_length;
int sndsz = 0;
struct sandbox *curr = current_sandbox__get();
int response_header_length = strlen(HTTP__RESPONSE_200_OK) + strlen(HTTP__RESPONSE_CONTENT_TYPE)
+ strlen(HTTP__RESPONSE_CONTENT_LENGTH);
int body_length = curr->request_response_data_length - response_header_length;
memset(curr->request_response_data, 0,
strlen(HTTP_RESP_200OK) + strlen(HTTP_RESP_CONTTYPE) + strlen(HTTP_RESP_CONTLEN));
strncpy(curr->request_response_data, HTTP_RESP_200OK, strlen(HTTP_RESP_200OK));
sndsz += strlen(HTTP_RESP_200OK);
strlen(HTTP__RESPONSE_200_OK) + strlen(HTTP__RESPONSE_CONTENT_TYPE)
+ strlen(HTTP__RESPONSE_CONTENT_LENGTH));
strncpy(curr->request_response_data, HTTP__RESPONSE_200_OK, strlen(HTTP__RESPONSE_200_OK));
sndsz += strlen(HTTP__RESPONSE_200_OK);
if (body_length == 0) goto done;
strncpy(curr->request_response_data + sndsz, HTTP_RESP_CONTTYPE, strlen(HTTP_RESP_CONTTYPE));
strncpy(curr->request_response_data + sndsz, HTTP__RESPONSE_CONTENT_TYPE, strlen(HTTP__RESPONSE_CONTENT_TYPE));
if (strlen(curr->module->response_content_type) <= 0) {
strncpy(curr->request_response_data + sndsz + strlen("Content-type: "), HTTP_RESP_CONTTYPE_PLAIN,
strlen(HTTP_RESP_CONTTYPE_PLAIN));
strncpy(curr->request_response_data + sndsz + strlen("Content-type: "),
HTTP__RESPONSE_CONTENT_TYPE_PLAIN, strlen(HTTP__RESPONSE_CONTENT_TYPE_PLAIN));
} else {
strncpy(curr->request_response_data + sndsz + strlen("Content-type: "),
curr->module->response_content_type, strlen(curr->module->response_content_type));
}
sndsz += strlen(HTTP_RESP_CONTTYPE);
sndsz += strlen(HTTP__RESPONSE_CONTENT_TYPE);
char len[10] = { 0 };
sprintf(len, "%d", body_length);
strncpy(curr->request_response_data + sndsz, HTTP_RESP_CONTLEN, strlen(HTTP_RESP_CONTLEN));
strncpy(curr->request_response_data + sndsz, HTTP__RESPONSE_CONTENT_LENGTH,
strlen(HTTP__RESPONSE_CONTENT_LENGTH));
strncpy(curr->request_response_data + sndsz + strlen("Content-length: "), len, strlen(len));
sndsz += strlen(HTTP_RESP_CONTLEN);
sndsz += strlen(HTTP__RESPONSE_CONTENT_LENGTH);
sndsz += body_length;
done:
@ -204,7 +207,8 @@ current_sandbox__main(void)
current_sandbox->http_parser.data = current_sandbox;
// NOTE: if more headers, do offset by that!
int response_header_length = strlen(HTTP_RESP_200OK) + strlen(HTTP_RESP_CONTTYPE) + strlen(HTTP_RESP_CONTLEN);
int response_header_length = strlen(HTTP__RESPONSE_200_OK) + strlen(HTTP__RESPONSE_CONTENT_TYPE)
+ strlen(HTTP__RESPONSE_CONTENT_LENGTH);
#ifdef USE_HTTP_UVIO
@ -318,7 +322,7 @@ sandbox__allocate(struct module *module, char *arguments, int socket_descriptor,
}
sandbox->client_socket_descriptor = socket_descriptor;
if (socket_address) memcpy(&sandbox->client_address, socket_address, sizeof(struct sockaddr));
for (int i = 0; i < SBOX_MAX_OPEN; i++) sandbox->io_handles[i].file_descriptor = -1;
for (int i = 0; i < SANDBOX__MAX_IO_HANDLE_COUNT; i++) sandbox->io_handles[i].file_descriptor = -1;
ps_list_init_d(sandbox);
// Setup the sandbox's context, stack, and instruction pointer

@ -32,7 +32,7 @@ __thread volatile sig_atomic_t software_interrupt__is_disabled = 0;
* Externs
***************************************/
extern pthread_t worker_threads[];
extern pthread_t runtime__worker_threads[];
/***************************************
* Private Static Inlines
@ -64,12 +64,12 @@ software_interrupt__handle_signals(int signal_type, siginfo_t *signal_info, void
if (signal_info->si_code == SI_KERNEL) {
int rt = 0;
// deliver signal to all other runtime threads..
for (int i = 0; i < SBOX_NCORES; i++) {
if (pthread_self() == worker_threads[i]) {
for (int i = 0; i < WORKER_THREAD__CORE_COUNT; i++) {
if (pthread_self() == runtime__worker_threads[i]) {
rt = 1;
continue;
}
pthread_kill(worker_threads[i], SIGALRM);
pthread_kill(runtime__worker_threads[i], SIGALRM);
}
assert(rt == 1);
} else {
@ -161,8 +161,8 @@ software_interrupt__arm_timer(void)
struct itimerval interval_timer;
memset(&interval_timer, 0, sizeof(struct itimerval));
interval_timer.it_value.tv_usec = SOFTINT_TIMER_START_USEC;
interval_timer.it_interval.tv_usec = SOFTINT_TIMER_PERIOD_USEC;
interval_timer.it_value.tv_usec = SOFTWARE_INTERRUPT__TIME_TO_START_IN_USEC;
interval_timer.it_interval.tv_usec = SOFTWARE_INTERRUPT__INTERVAL_DURATION_IN_USEC;
int return_code = setitimer(ITIMER_REAL, &interval_timer, NULL);
if (return_code) {

Loading…
Cancel
Save