diff --git a/runtime/Makefile b/runtime/Makefile index bf8e731..c9dd3ed 100644 --- a/runtime/Makefile +++ b/runtime/Makefile @@ -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 diff --git a/runtime/include/http_parser_settings.h b/runtime/include/http_parser_settings.h index 185fb85..ed1fad4 100644 --- a/runtime/include/http_parser_settings.h +++ b/runtime/include/http_parser_settings.h @@ -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. diff --git a/runtime/include/http_request.h b/runtime/include/http_request.h index 3483252..2d0c7d2 100644 --- a/runtime/include/http_request.h +++ b/runtime/include/http_request.h @@ -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; diff --git a/runtime/include/http_response.h b/runtime/include/http_response.h index 72e8ddb..510b318 100644 --- a/runtime/include/http_response.h +++ b/runtime/include/http_response.h @@ -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 }; diff --git a/runtime/include/module.h b/runtime/include/module.h index 8e6b745..4f43821 100644 --- a/runtime/include/module.h +++ b/runtime/include/module.h @@ -6,8 +6,8 @@ #include 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); } diff --git a/runtime/include/module_database.h b/runtime/include/module_database.h index f38736a..62a0fb9 100644 --- a/runtime/include/module_database.h +++ b/runtime/include/module_database.h @@ -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; diff --git a/runtime/include/sandbox.h b/runtime/include/sandbox.h index 6aa202a..584c30d 100644 --- a/runtime/include/sandbox.h +++ b/runtime/include/sandbox.h @@ -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; } diff --git a/runtime/include/types.h b/runtime/include/types.h index d33496a..a78b6e6 100644 --- a/runtime/include/types.h +++ b/runtime/include/types.h @@ -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 */ diff --git a/runtime/src/http_response.c b/runtime/src/http_response.c index ab2cad0..d9c87da 100644 --- a/runtime/src/http_response.c +++ b/runtime/src/http_response.c @@ -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; diff --git a/runtime/src/libc/uvio.c b/runtime/src/libc/uvio.c index ab11c6c..244a71e 100644 --- a/runtime/src/libc/uvio.c +++ b/runtime/src/libc/uvio.c @@ -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); diff --git a/runtime/src/main.c b/runtime/src/main.c index f00d13c..9a45509 100644 --- a/runtime/src/main.c +++ b/runtime/src/main.c @@ -13,12 +13,18 @@ #include #include -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 \n", cmd); debuglog("%s \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(); } diff --git a/runtime/src/module.c b/runtime/src/module.c index f02faa4..04b278a 100644 --- a/runtime/src/module.c +++ b/runtime/src/module.c @@ -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) { diff --git a/runtime/src/module_database.c b/runtime/src/module_database.c index 5a0b157..3d0ae7b 100644 --- a/runtime/src/module_database.c +++ b/runtime/src/module_database.c @@ -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; diff --git a/runtime/src/runtime.c b/runtime/src/runtime.c index 3508f35..3b87f44 100644 --- a/runtime/src/runtime.c +++ b/runtime/src/runtime.c @@ -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 diff --git a/runtime/src/sandbox.c b/runtime/src/sandbox.c index 9033486..2bce4e7 100644 --- a/runtime/src/sandbox.c +++ b/runtime/src/sandbox.c @@ -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 diff --git a/runtime/src/software_interrupt.c b/runtime/src/software_interrupt.c index b20d9dc..d010d60 100644 --- a/runtime/src/software_interrupt.c +++ b/runtime/src/software_interrupt.c @@ -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) {