diff --git a/.vscode/settings.json b/.vscode/settings.json index ae42f49..fe28c43 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -56,7 +56,8 @@ "features.h": "c", "time.h": "c", "local_runqueue_minheap.h": "c", - "global_request_scheduler.h": "c" + "global_request_scheduler.h": "c", + "dlfcn.h": "c" }, "files.exclude": { "**/.git": true, diff --git a/runtime/include/runtime.h b/runtime/include/runtime.h index 97b4113..f1fbdbd 100644 --- a/runtime/include/runtime.h +++ b/runtime/include/runtime.h @@ -42,18 +42,25 @@ #define RUNTIME_WORKER_THREAD_CORE_COUNT (NCORES > 1 ? NCORES - 1 : NCORES) +enum RUNTIME_SCHEDULER +{ + RUNTIME_SCHEDULER_FIFO = 0, + RUNTIME_SCHEDULER_EDF = 1 +}; + +enum RUNTIME_SIGALRM_HANDLER +{ + RUNTIME_SIGALRM_HANDLER_BROADCAST = 0, + RUNTIME_SIGALRM_HANDLER_TRIAGED = 1 +}; + /* * Descriptor of the epoll instance used to monitor the socket descriptors of registered * serverless modules. The listener cores listens for incoming client requests through this. */ extern int runtime_epoll_file_descriptor; -extern int runtime_worker_threads_argument[RUNTIME_WORKER_THREAD_CORE_COUNT]; - -extern uint64_t runtime_worker_threads_deadline[RUNTIME_WORKER_THREAD_CORE_COUNT]; - -/* Optional path to a file to log sandbox perf metrics */ -extern FILE *runtime_sandbox_perf_log; +extern bool runtime_preemption_enabled; /* * Assumption: All cores are the same speed @@ -61,17 +68,29 @@ extern FILE *runtime_sandbox_perf_log; */ extern uint32_t runtime_processor_speed_MHz; +extern uint32_t runtime_quantum_us; + +/* Optional path to a file to log sandbox perf metrics */ +extern FILE *runtime_sandbox_perf_log; + +extern enum RUNTIME_SCHEDULER runtime_scheduler; +extern enum RUNTIME_SIGALRM_HANDLER runtime_sigalrm_handler; + /* Count of worker threads and array of their pthread identifiers */ extern pthread_t runtime_worker_threads[]; extern uint32_t runtime_worker_threads_count; +extern int runtime_worker_threads_argument[RUNTIME_WORKER_THREAD_CORE_COUNT]; +extern uint64_t runtime_worker_threads_deadline[RUNTIME_WORKER_THREAD_CORE_COUNT]; -void alloc_linear_memory(void); -void expand_memory(void); + +extern void alloc_linear_memory(void); +extern void expand_memory(void); INLINE char *get_function_from_table(uint32_t idx, uint32_t type_id); INLINE char *get_memory_ptr_for_runtime(uint32_t offset, uint32_t bounds_check); -void runtime_initialize(void); -void listener_thread_initialize(void); -void stub_init(int32_t offset); +extern void listener_thread_initialize(void); +extern void runtime_initialize(void); +extern void runtime_set_resource_limits_to_max(); +extern void stub_init(int32_t offset); unsigned long long __getcycles(void); @@ -90,12 +109,6 @@ runtime_is_worker() return false; } -enum RUNTIME_SCHEDULER -{ - RUNTIME_SCHEDULER_FIFO = 0, - RUNTIME_SCHEDULER_EDF = 1 -}; - static inline char * print_runtime_scheduler(enum RUNTIME_SCHEDULER variant) { @@ -107,13 +120,6 @@ print_runtime_scheduler(enum RUNTIME_SCHEDULER variant) } }; -enum RUNTIME_SIGALRM_HANDLER -{ - RUNTIME_SIGALRM_HANDLER_BROADCAST = 0, - RUNTIME_SIGALRM_HANDLER_TRIAGED = 1 -}; - - static inline char * print_runtime_sigalrm_handler(enum RUNTIME_SIGALRM_HANDLER variant) { @@ -124,8 +130,3 @@ print_runtime_sigalrm_handler(enum RUNTIME_SIGALRM_HANDLER variant) return "TRIAGED"; } }; - -extern enum RUNTIME_SCHEDULER runtime_scheduler; -extern enum RUNTIME_SIGALRM_HANDLER runtime_sigalrm_handler; -extern bool runtime_preemption_enabled; -extern uint32_t runtime_quantum_us; diff --git a/runtime/src/main.c b/runtime/src/main.c index 4c13aed..adf76b3 100644 --- a/runtime/src/main.c +++ b/runtime/src/main.c @@ -5,7 +5,6 @@ #include #include #include -#include #include #include @@ -24,8 +23,7 @@ #include "worker_thread.h" /* Conditionally used by debuglog when NDEBUG is not set */ -int32_t debuglog_file_descriptor = -1; - +int32_t debuglog_file_descriptor = -1; uint32_t runtime_processor_speed_MHz = 0; uint32_t runtime_total_online_processors = 0; uint32_t runtime_worker_threads_count = 0; @@ -52,34 +50,6 @@ runtime_usage(char *cmd) printf("%s \n", cmd); } -/** - * Sets the process data segment (RLIMIT_DATA) and # file descriptors - * (RLIMIT_NOFILE) soft limit to its hard limit (see man getrlimit) - */ -void -runtime_set_resource_limits_to_max() -{ - struct rlimit resource_limit; - if (getrlimit(RLIMIT_DATA, &resource_limit) < 0) { - perror("getrlimit RLIMIT_DATA"); - exit(-1); - } - resource_limit.rlim_cur = resource_limit.rlim_max; - if (setrlimit(RLIMIT_DATA, &resource_limit) < 0) { - perror("setrlimit RLIMIT_DATA"); - exit(-1); - } - if (getrlimit(RLIMIT_NOFILE, &resource_limit) < 0) { - perror("getrlimit RLIMIT_NOFILE"); - exit(-1); - } - resource_limit.rlim_cur = resource_limit.rlim_max; - if (setrlimit(RLIMIT_NOFILE, &resource_limit) < 0) { - perror("setrlimit RLIMIT_NOFILE"); - exit(-1); - } -} - /** * Check the number of cores and the compiler flags and allocate available cores */ diff --git a/runtime/src/runtime.c b/runtime/src/runtime.c index 17742b6..ff26073 100644 --- a/runtime/src/runtime.c +++ b/runtime/src/runtime.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include "admissions_control.h" @@ -38,6 +39,45 @@ runtime_cleanup() exit(EXIT_SUCCESS); } +/** + * Sets the process data segment (RLIMIT_DATA) and # file descriptors + * (RLIMIT_NOFILE) soft limit to its hard limit (see man getrlimit) + */ +void +runtime_set_resource_limits_to_max() +{ + struct rlimit limit; + const size_t uint64_t_max_digits = 20; + char lim[uint64_t_max_digits + 1]; + char max[uint64_t_max_digits + 1]; + + uint64_t resources[] = { RLIMIT_DATA, RLIMIT_NOFILE }; + char * resource_names[] = { "RLIMIT_DATA", "RLIMIT_NOFILE" }; + + for (int i = 0; i < sizeof(resources) / sizeof(resources[0]); i++) { + int resource = resources[i]; + if (getrlimit(resource, &limit) < 0) panic_err(); + + if (limit.rlim_cur == RLIM_INFINITY) { + strncpy(lim, "Infinite", uint64_t_max_digits); + } else { + snprintf(lim, uint64_t_max_digits, "%lu", limit.rlim_cur); + } + if (limit.rlim_max == RLIM_INFINITY) { + strncpy(max, "Infinite", uint64_t_max_digits); + } else { + snprintf(max, uint64_t_max_digits, "%lu", limit.rlim_max); + } + if (limit.rlim_cur == limit.rlim_max) { + printf("\t%s: %s\n", resource_names[i], max); + } else { + limit.rlim_cur = limit.rlim_max; + if (setrlimit(resource, &limit) < 0) panic_err(); + printf("\t%s: %s (Increased from %s)\n", resource_names[i], max, lim); + } + } +} + /** * Initialize runtime global state, mask signals, and init http parser */ @@ -99,8 +139,8 @@ listener_thread_stop_lock_overhead_measurement() } /** - * @brief Execution Loop of the listener core, io_handles HTTP requests, allocates sandbox request objects, and pushes - * the sandbox object to the global dequeue + * @brief Execution Loop of the listener core, io_handles HTTP requests, allocates sandbox request objects, and + * pushes the sandbox object to the global dequeue * @param dummy data pointer provided by pthreads API. Unused in this function * @return NULL * @@ -125,7 +165,8 @@ listener_thread_main(void *dummy) panic("epoll_wait: %s", strerror(errno)); } - /* Assumption: Because epoll_wait is set to not timeout, we should always have descriptors here */ + /* Assumption: Because epoll_wait is set to not timeout, we should always have descriptors here + */ assert(descriptor_count > 0); uint64_t request_arrival_timestamp = __getcycles(); @@ -142,7 +183,8 @@ listener_thread_main(void *dummy) panic("epoll_wait"); }; - /* Assumption: We have only registered EPOLLIN events, so we should see no others here */ + /* Assumption: We have only registered EPOLLIN events, so we should see no others here + */ assert((epoll_events[i].events & EPOLLIN) == EPOLLIN); /* Unpack module from epoll event */ @@ -161,7 +203,8 @@ listener_thread_main(void *dummy) /* * Accept as many requests as possible, terminating when we would have blocked - * This inner loop is used in case there are more datagrams than epoll events for some reason + * This inner loop is used in case there are more datagrams than epoll events for some + * reason */ while (true) { int client_socket = accept4(module->socket_descriptor, @@ -179,13 +222,12 @@ listener_thread_main(void *dummy) assert(client_socket != STDERR_FILENO); /* - * According to accept(2), it is possible that the the sockaddr structure client_address - * may be too small, resulting in data being truncated to fit. The accept call mutates - * the size value to indicate that this is the case. + * According to accept(2), it is possible that the the sockaddr structure + * client_address may be too small, resulting in data being truncated to fit. + * The accept call mutates the size value to indicate that this is the case. */ if (address_length > sizeof(client_address)) { - debuglog("A client address to %s has been truncated because buffer was too " - "small\n", + debuglog("Client address %s truncated because buffer was too small\n", module->name); }