diff --git a/runtime/include/runtime.h b/runtime/include/runtime.h index ba1e77d..1f14e4a 100644 --- a/runtime/include/runtime.h +++ b/runtime/include/runtime.h @@ -43,6 +43,7 @@ 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]; +extern uint64_t runtime_worker_threads_remaining_slack[RUNTIME_WORKER_THREAD_CORE_COUNT]; extern void runtime_initialize(void); extern void runtime_set_pthread_prio(pthread_t thread, unsigned int nice); diff --git a/runtime/include/sandbox_set_as_running.h b/runtime/include/sandbox_set_as_running.h index af20cf1..3f23bb7 100644 --- a/runtime/include/sandbox_set_as_running.h +++ b/runtime/include/sandbox_set_as_running.h @@ -29,6 +29,7 @@ sandbox_set_as_running(struct sandbox *sandbox, sandbox_state_t last_state) sandbox->runnable_duration += duration_of_last_state; current_sandbox_set(sandbox); runtime_worker_threads_deadline[worker_thread_idx] = sandbox->absolute_deadline; + runtime_worker_threads_remaining_slack[worker_thread_idx] = sandbox->remaining_slack; //mem_log("time %lu sandbox starts running, request id:%d name %s obj=%p remaining slack %lu, last_rs %lu now %lu last %lu \n", start_execution, // sandbox->id, sandbox->module->name, sandbox, sandbox->remaining_slack, last_rs, now, last); /* Does not handle context switch because the caller knows if we need to use fast or slow switched */ diff --git a/runtime/include/scheduler.h b/runtime/include/scheduler.h index fba923a..0c0064a 100644 --- a/runtime/include/scheduler.h +++ b/runtime/include/scheduler.h @@ -357,6 +357,7 @@ scheduler_yield() sandbox_exit(current_sandbox); current_sandbox_set(NULL); runtime_worker_threads_deadline[worker_thread_idx] = UINT64_MAX; + runtime_worker_threads_remaining_slack[worker_thread_idx] = UINT64_MAX; /* Assumption: Base Worker context should never be preempted */ assert(worker_thread_base_context.variant == ARCH_CONTEXT_VARIANT_FAST); diff --git a/runtime/src/main.c b/runtime/src/main.c index c92319c..557c8d4 100644 --- a/runtime/src/main.c +++ b/runtime/src/main.c @@ -197,7 +197,7 @@ runtime_configure() if (strcmp(sigalrm_policy, "BROADCAST") == 0) { runtime_sigalrm_handler = RUNTIME_SIGALRM_HANDLER_BROADCAST; } else if (strcmp(sigalrm_policy, "TRIAGED") == 0) { - if (unlikely(scheduler != SCHEDULER_EDF)) panic("triaged sigalrm handlers are only valid with EDF\n"); + if (unlikely(scheduler != SCHEDULER_EDF && scheduler != SCHEDULER_SRSF)) panic("triaged sigalrm handlers are only valid with EDF and SRSF\n"); runtime_sigalrm_handler = RUNTIME_SIGALRM_HANDLER_TRIAGED; } else { panic("Invalid sigalrm policy: %s. Must be {BROADCAST|TRIAGED}\n", sigalrm_policy); diff --git a/runtime/src/runtime.c b/runtime/src/runtime.c index 7b061fc..cabf351 100644 --- a/runtime/src/runtime.c +++ b/runtime/src/runtime.c @@ -32,6 +32,7 @@ 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 }; +uint64_t runtime_worker_threads_remaining_slack[RUNTIME_WORKER_THREAD_CORE_COUNT] = { UINT64_MAX }; /****************************************** * Shared Process / Listener Thread Logic * diff --git a/runtime/src/software_interrupt.c b/runtime/src/software_interrupt.c index b9a07b7..f3c7243 100644 --- a/runtime/src/software_interrupt.c +++ b/runtime/src/software_interrupt.c @@ -83,11 +83,18 @@ sigalrm_propagate_workers(siginfo_t *signal_info) /* If using EDF, conditionally send signals. If not, broadcast */ switch (runtime_sigalrm_handler) { case RUNTIME_SIGALRM_HANDLER_TRIAGED: { - assert(scheduler == SCHEDULER_EDF); - uint64_t local_deadline = runtime_worker_threads_deadline[i]; - uint64_t global_deadline = global_request_scheduler_peek(); - if (global_deadline < local_deadline) pthread_kill(runtime_worker_threads[i], SIGALRM); - continue; + //assert(scheduler == SCHEDULER_EDF); + if (scheduler == SCHEDULER_EDF) { + uint64_t local_deadline = runtime_worker_threads_deadline[i]; + uint64_t global_deadline = global_request_scheduler_peek(); + if (global_deadline < local_deadline) pthread_kill(runtime_worker_threads[i], SIGALRM); + continue; + } else if (scheduler == SCHEDULER_SRSF) { + uint64_t local_remaining_slack = runtime_worker_threads_remaining_slack[i]; + uint64_t global_slack = global_request_scheduler_peek(); + if (global_slack < local_remaining_slack) pthread_kill(runtime_worker_threads[i], SIGALRM); + continue; + } } case RUNTIME_SIGALRM_HANDLER_BROADCAST: { pthread_kill(runtime_worker_threads[i], SIGALRM); @@ -175,6 +182,9 @@ software_interrupt_handle_signals(int signal_type, siginfo_t *signal_info, void /* record queuelength of the current worker thread */ recording_buffer[software_interrupt_SIGALRM_kernel_count + software_interrupt_SIGALRM_thread_count] = local_workload_count; sigalrm_propagate_workers(signal_info); + /* if disable preemption, then return directly */ + if (!runtime_preemption_enabled) return; + if (current_sandbox == NULL || current_sandbox->ctxt.preemptable == false) { /* Cannot preempt, so defer signal * TODO: First worker gets tons of kernel sigalrms, should these be treated the same? @@ -208,7 +218,7 @@ software_interrupt_handle_signals(int signal_type, siginfo_t *signal_info, void software_interrupt_disarm_timer(); /* Only the thread that receives SIGINT from the kernel or user space will broadcast SIGINT to other worker threads */ sigint_propagate_workers_listener(signal_info); - mem_log("thread id %d test buffer:",worker_thread_idx); + mem_log("thread id %d kernal sig %u thread sig %u test buffer:",worker_thread_idx, software_interrupt_SIGALRM_kernel_count, software_interrupt_SIGALRM_thread_count); for(int i = 0; i < software_interrupt_SIGALRM_kernel_count + software_interrupt_SIGALRM_thread_count; i++) { mem_log("%d ", recording_buffer[i]); } @@ -245,6 +255,10 @@ software_interrupt_arm_timer(void) { if (!runtime_preemption_enabled) return; + /* if preemption disabled, broadcast sig alarm to all other threads to record the queuelength info */ + if (!runtime_preemption_enabled) { + runtime_sigalrm_handler = RUNTIME_SIGALRM_HANDLER_BROADCAST; + } struct itimerval interval_timer; memset(&interval_timer, 0, sizeof(struct itimerval));