#include #include #include #include #include #include #include #include #include #include #include #include "admissions_control.h" #include "arch/context.h" #include "client_socket.h" #include "debuglog.h" #include "global_request_scheduler_deque.h" #include "global_request_scheduler_minheap.h" #include "http_parser_settings.h" #include "listener_thread.h" #include "module.h" #include "module_manager.h" #include "runtime.h" #include "sandbox_request.h" #include "scheduler.h" #include "software_interrupt.h" /*************************** * Shared Process State * **************************/ pthread_t runtime_worker_threads[RUNTIME_WORKER_THREAD_CORE_COUNT]; int runtime_worker_threads_argument[RUNTIME_WORKER_THREAD_CORE_COUNT] = { 0 }; /* The active deadline of the sandbox running on each worker thread */ uint64_t runtime_worker_threads_deadline[RUNTIME_WORKER_THREAD_CORE_COUNT] = { UINT64_MAX }; /****************************************** * Shared Process / Listener Thread Logic * *****************************************/ void runtime_cleanup() { if (runtime_sandbox_perf_log != NULL) fflush(runtime_sandbox_perf_log); software_interrupt_deferred_sigalrm_max_print(); 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) { // rlim_cur is soft limit strncpy(lim, "Infinite", uint64_t_max_digits); } else { snprintf(lim, uint64_t_max_digits, "%lu", limit.rlim_cur); } if (limit.rlim_max == RLIM_INFINITY) { // rlim_max is hard limit 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 */ void runtime_initialize(void) { http_total_init(); //initilize http requests/error response counter sandbox_request_count_initialize(); //initilize sandbox requests counter sandbox_count_initialize(); //initilize sandbox state counter /* Setup Scheduler */ scheduler_initialize(); //set function pointers to global_request_scheduler, both EDF and FIFO have a set of functions /* Init global module hash table */ init_module_ht(); /* Configure Signals */ signal(SIGPIPE, SIG_IGN); // ignore SIGPIPE signal(SIGTERM, runtime_cleanup); // call runtime_cleanup when get SIGTERM signal http_parser_settings_initialize(); // set function pointers for http parser lib, when get a http message, some callback // functions will be called admissions_control_initialize(); } static void runtime_call_getrlimit(int id, char *name) { struct rlimit rl; if (getrlimit(id, &rl)) { perror("getrlimit: "); exit(-1); } } static void runtime_call_setrlimit(int id, rlim_t c, rlim_t m) { struct rlimit rl; rl.rlim_cur = c; rl.rlim_max = m; if (setrlimit(id, &rl)) { perror("getrlimit: "); exit(-1); } } void runtime_set_pthread_prio(pthread_t thread, unsigned int nice) { struct sched_param sp; int policy; runtime_call_getrlimit(RLIMIT_CPU, "CPU"); runtime_call_getrlimit(RLIMIT_RTTIME, "RTTIME"); runtime_call_getrlimit(RLIMIT_RTPRIO, "RTPRIO"); runtime_call_setrlimit(RLIMIT_RTPRIO, RLIM_INFINITY, RLIM_INFINITY); runtime_call_getrlimit(RLIMIT_RTPRIO, "RTPRIO"); runtime_call_getrlimit(RLIMIT_NICE, "NICE"); if (pthread_getschedparam(thread, &policy, &sp) < 0) { perror("pth_getparam: "); } sp.sched_priority = sched_get_priority_max(SCHED_RR) - nice; if (pthread_setschedparam(thread, SCHED_RR, &sp) < 0) { perror("pth_setparam: "); exit(-1); } if (pthread_getschedparam(thread, &policy, &sp) < 0) { perror("getparam: "); } assert(sp.sched_priority == sched_get_priority_max(SCHED_RR) - nice); return; } void runtime_set_prio(unsigned int nice) { struct sched_param sp; runtime_call_getrlimit(RLIMIT_CPU, "CPU"); runtime_call_getrlimit(RLIMIT_RTTIME, "RTTIME"); runtime_call_getrlimit(RLIMIT_RTPRIO, "RTPRIO"); runtime_call_setrlimit(RLIMIT_RTPRIO, RLIM_INFINITY, RLIM_INFINITY); runtime_call_getrlimit(RLIMIT_RTPRIO, "RTPRIO"); runtime_call_getrlimit(RLIMIT_NICE, "NICE"); if (sched_getparam(0, &sp) < 0) { perror("getparam: "); } sp.sched_priority = sched_get_priority_max(SCHED_RR) - nice; if (sched_setscheduler(0, SCHED_RR, &sp) < 0) { perror("setscheduler: "); exit(-1); } if (sched_getparam(0, &sp) < 0) { perror("getparam: "); } assert(sp.sched_priority == sched_get_priority_max(SCHED_RR) - nice); return; }