refactor: Additional cleanup

master
Sean McBride 4 years ago
parent 0f0d0fcb18
commit 85856148e1

@ -28,12 +28,6 @@
#define RUNTIME_RELATIVE_DEADLINE_US_MAX 3600000000 /* One Hour. Fits in uint32_t */
#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,
@ -44,7 +38,6 @@ extern bool runtime_preemption_enabled;
extern uint32_t runtime_processor_speed_MHz;
extern uint32_t runtime_quantum_us;
extern FILE * runtime_sandbox_perf_log;
extern enum RUNTIME_SCHEDULER runtime_scheduler;
extern enum RUNTIME_SIGALRM_HANDLER runtime_sigalrm_handler;
extern pthread_t runtime_worker_threads[];
extern uint32_t runtime_worker_threads_count;
@ -62,17 +55,6 @@ 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);
extern void stub_init(int32_t offset);
static inline char *
runtime_print_scheduler(enum RUNTIME_SCHEDULER variant)
{
switch (variant) {
case RUNTIME_SCHEDULER_FIFO:
return "FIFO";
case RUNTIME_SCHEDULER_EDF:
return "EDF";
}
}
static inline char *
runtime_print_sigalrm_handler(enum RUNTIME_SIGALRM_HANDLER variant)
{

@ -1,50 +0,0 @@
#pragma once
#include <assert.h>
#include <stdint.h>
#include "arch/getcycles.h"
#include "panic.h"
#include "sandbox_state.h"
#include "sandbox_types.h"
/**
* Transitions a sandbox to the SANDBOX_PREEMPTED state.
*
* This occurs when a sandbox is executing and in a RUNNING state and a SIGALRM software interrupt fires
* and pulls a sandbox with an earlier absolute deadline from the global request scheduler.
*
* @param sandbox the sandbox being preempted
* @param last_state the state the sandbox is transitioning from. This is expressed as a constant to
* enable the compiler to perform constant propagation optimizations.
*/
static inline void
sandbox_set_as_preempted(struct sandbox *sandbox, sandbox_state_t last_state)
{
assert(sandbox);
assert(!software_interrupt_is_enabled());
uint64_t now = __getcycles();
uint64_t duration_of_last_state = now - sandbox->last_state_change_timestamp;
sandbox->state = SANDBOX_SET_AS_PREEMPTED;
switch (last_state) {
case SANDBOX_RUNNING: {
sandbox->running_duration += duration_of_last_state;
break;
}
default: {
panic("Sandbox %lu | Illegal transition from %s to Preempted\n", sandbox->id,
sandbox_state_stringify(last_state));
}
}
sandbox->last_state_change_timestamp = now;
sandbox->state = SANDBOX_PREEMPTED;
/* State Change Bookkeeping */
sandbox_state_log_transition(sandbox->id, last_state, SANDBOX_PREEMPTED);
runtime_sandbox_total_increment(SANDBOX_PREEMPTED);
runtime_sandbox_total_decrement(SANDBOX_RUNNING);
}

@ -4,7 +4,6 @@
#include <stdint.h>
#include "arch/getcycles.h"
#include "local_runqueue.h"
#include "panic.h"
#include "software_interrupt.h"
#include "sandbox_types.h"
@ -40,13 +39,16 @@ sandbox_set_as_runnable(struct sandbox *sandbox, sandbox_state_t last_state)
sandbox->blocked_duration += duration_of_last_state;
break;
}
case SANDBOX_RUNNING: {
sandbox->running_duration += duration_of_last_state;
break;
}
default: {
panic("Sandbox %lu | Illegal transition from %s to Runnable\n", sandbox->id,
sandbox_state_stringify(last_state));
}
}
local_runqueue_add(sandbox);
sandbox->last_state_change_timestamp = now;
sandbox->state = SANDBOX_RUNNABLE;

@ -4,6 +4,8 @@
#include <stdint.h>
#include "arch/getcycles.h"
#include "panic.h"
#include "software_interrupt.h"
#include "sandbox_types.h"
static inline void
@ -22,17 +24,12 @@ sandbox_set_as_running(struct sandbox *sandbox, sandbox_state_t last_state)
sandbox->runnable_duration += duration_of_last_state;
break;
}
case SANDBOX_PREEMPTED: {
sandbox->preempted_duration += duration_of_last_state;
break;
}
default: {
panic("Sandbox %lu | Illegal transition from %s to Running\n", sandbox->id,
sandbox_state_stringify(last_state));
}
}
current_sandbox_set(sandbox);
sandbox->last_state_change_timestamp = now;
sandbox->state = SANDBOX_RUNNING;

@ -16,8 +16,6 @@ typedef enum
SANDBOX_RUNNABLE,
SANDBOX_SET_AS_RUNNING,
SANDBOX_RUNNING,
SANDBOX_SET_AS_PREEMPTED,
SANDBOX_PREEMPTED,
SANDBOX_SET_AS_BLOCKED,
SANDBOX_BLOCKED,
SANDBOX_SET_AS_RETURNED,

@ -56,7 +56,6 @@ struct sandbox {
/* Duration of time (in cycles) that the sandbox is in each state */
uint64_t initializing_duration;
uint64_t runnable_duration;
uint64_t preempted_duration;
uint64_t running_duration;
uint64_t blocked_duration;
uint64_t returned_duration;

@ -5,52 +5,142 @@
#include <stdint.h>
#include "client_socket.h"
#include "current_sandbox.h"
#include "global_request_scheduler.h"
#include "global_request_scheduler_deque.h"
#include "global_request_scheduler_minheap.h"
#include "local_runqueue.h"
#include "local_runqueue_minheap.h"
#include "local_runqueue_list.h"
#include "panic.h"
#include "sandbox_request.h"
#include "sandbox_exit.h"
#include "sandbox_functions.h"
#include "sandbox_types.h"
#include "sandbox_set_as_blocked.h"
#include "sandbox_set_as_preempted.h"
#include "sandbox_set_as_runnable.h"
#include "sandbox_set_as_running.h"
#include "worker_thread_execute_epoll_loop.h"
enum SCHEDULER
{
SCHEDULER_FIFO = 0,
SCHEDULER_EDF = 1
};
extern enum SCHEDULER scheduler;
static inline struct sandbox *
scheduler_get_next()
scheduler_edf_get_next()
{
assert(!software_interrupt_is_enabled());
/* Get the deadline of the sandbox at the head of the local request queue */
struct sandbox *local = local_runqueue_get_next();
uint64_t local_deadline = local == NULL ? UINT64_MAX : local->absolute_deadline;
struct sandbox * local = local_runqueue_get_next();
uint64_t local_deadline = local == NULL ? UINT64_MAX : local->absolute_deadline;
struct sandbox_request *request = NULL;
uint64_t global_deadline = global_request_scheduler_peek();
/* Try to pull and allocate from the global queue if earlier
* This will be placed at the head of the local runqueue */
if (global_deadline < local_deadline) {
struct sandbox_request *request = NULL;
int return_code = global_request_scheduler_remove_if_earlier(&request, local_deadline);
if (return_code == 0) {
if (global_request_scheduler_remove_if_earlier(&request, local_deadline) == 0) {
assert(request != NULL);
assert(request->absolute_deadline < local_deadline);
struct sandbox *global = sandbox_allocate(request);
if (!global) {
client_socket_send(request->socket_descriptor, 503);
client_socket_close(request->socket_descriptor, &request->socket_address);
free(request);
debuglog("scheduler failed to allocate sandbox\n");
} else {
assert(global->state == SANDBOX_INITIALIZED);
sandbox_set_as_runnable(global, SANDBOX_INITIALIZED);
}
if (!global) goto err_allocate;
assert(global->state == SANDBOX_INITIALIZED);
sandbox_set_as_runnable(global, SANDBOX_INITIALIZED);
local_runqueue_add(global);
}
}
/* Return what is at the head of the local runqueue or NULL if empty */
/* Return what is at the head of the local runqueue or NULL if empty */
done:
return local_runqueue_get_next();
err_allocate:
client_socket_send(request->socket_descriptor, 503);
client_socket_close(request->socket_descriptor, &request->socket_address);
free(request);
goto done;
}
static inline struct sandbox *
scheduler_fifo_get_next()
{
assert(!software_interrupt_is_enabled());
struct sandbox * sandbox = local_runqueue_get_next();
struct sandbox_request *sandbox_request = NULL;
/* If the local runqueue is empty, pull from global request scheduler */
if (sandbox == NULL) {
struct sandbox_request *sandbox_request;
if (global_request_scheduler_remove(&sandbox_request) < 0) goto err;
sandbox = sandbox_allocate(sandbox_request);
if (!sandbox) goto err_allocate;
sandbox_set_as_runnable(sandbox, SANDBOX_INITIALIZED);
local_runqueue_add(sandbox);
};
done:
return sandbox;
err_allocate:
client_socket_send(sandbox_request->socket_descriptor, 503);
client_socket_close(sandbox_request->socket_descriptor, &sandbox->client_address);
free(sandbox_request);
err:
sandbox = NULL;
goto done;
}
static inline struct sandbox *
scheduler_get_next()
{
switch (scheduler) {
case SCHEDULER_EDF:
return scheduler_edf_get_next();
case SCHEDULER_FIFO:
return scheduler_fifo_get_next();
default:
panic("Unimplemented\n");
}
}
static inline void
scheduler_initialize()
{
/* Setup Scheduler */
switch (scheduler) {
case SCHEDULER_EDF:
global_request_scheduler_minheap_initialize();
break;
case SCHEDULER_FIFO:
global_request_scheduler_deque_initialize();
break;
default:
panic("Invalid scheduler policy: %u\n", scheduler);
}
}
static inline void
scheduler_runqueue_initialize()
{
/* Setup Scheduler */
switch (scheduler) {
case SCHEDULER_EDF:
local_runqueue_minheap_initialize();
break;
case SCHEDULER_FIFO:
local_runqueue_list_initialize();
break;
default:
panic("Invalid scheduler policy: %u\n", scheduler);
}
}
/**
@ -61,6 +151,10 @@ scheduler_get_next()
static inline void
scheduler_preempt(ucontext_t *user_context)
{
// If FIFO, just return
if (scheduler == SCHEDULER_FIFO) return;
assert(scheduler == SCHEDULER_EDF);
assert(user_context != NULL);
assert(!software_interrupt_is_enabled());
@ -78,12 +172,13 @@ scheduler_preempt(ucontext_t *user_context)
if (current == next) return;
/* Save the context of the currently executing sandbox before switching from it */
sandbox_set_as_preempted(current, SANDBOX_RUNNING);
sandbox_set_as_runnable(current, SANDBOX_RUNNING);
arch_mcontext_save(&current->ctxt, &user_context->uc_mcontext);
/* Update current_sandbox to the next sandbox */
assert(next->state == SANDBOX_RUNNABLE);
sandbox_set_as_running(next, SANDBOX_RUNNABLE);
current_sandbox_set(next);
/* Update the current deadline of the worker thread */
runtime_worker_threads_deadline[worker_thread_idx] = next->absolute_deadline;
@ -92,6 +187,17 @@ scheduler_preempt(ucontext_t *user_context)
arch_context_restore_new(&user_context->uc_mcontext, &next->ctxt);
}
static inline char *
scheduler_print(enum SCHEDULER variant)
{
switch (variant) {
case SCHEDULER_FIFO:
return "FIFO";
case SCHEDULER_EDF:
return "EDF";
}
}
/**
* @brief Switches to the next sandbox, placing the current sandbox on the completion queue if in SANDBOX_RETURNED state
* @param next_sandbox The Sandbox Context to switch to
@ -114,6 +220,9 @@ scheduler_switch_to(struct sandbox *next_sandbox)
assert(next_sandbox != current_sandbox);
/* If not the current sandbox (which would be in running state), should be runnable */
assert(next_sandbox->state == SANDBOX_RUNNABLE);
/* Update the worker's absolute deadline */
runtime_worker_threads_deadline[worker_thread_idx] = next_sandbox->absolute_deadline;
@ -135,6 +244,7 @@ scheduler_switch_to(struct sandbox *next_sandbox)
}
sandbox_set_as_running(next_sandbox, next_sandbox->state);
current_sandbox_set(next_sandbox);
arch_context_switch(current_context, next_context);
}

@ -43,6 +43,7 @@ worker_thread_execute_epoll_loop(void)
if (sandbox->state == SANDBOX_BLOCKED) {
sandbox_set_as_runnable(sandbox, SANDBOX_BLOCKED);
local_runqueue_add(sandbox);
}
} else if (epoll_events[i].events & (EPOLLERR | EPOLLHUP)) {
/* Mystery: This seems to never fire. Why? Issue #130 */

@ -38,39 +38,17 @@ local_runqueue_list_remove_and_return()
}
/**
* Execute the sandbox at the head of the thread local runqueue
* If the runqueue is empty, pull a fresh batch of sandbox requests, instantiate them, and then execute the new head
* Get the next sandbox and then insert at tail to "round robin"
* @return the sandbox to execute or NULL if none are available
*/
struct sandbox *
local_runqueue_list_get_next()
{
struct sandbox_request *sandbox_request;
// If our local runqueue is empty, try to pull and allocate a sandbox request from the global request scheduler
if (local_runqueue_is_empty()) {
if (global_request_scheduler_remove(&sandbox_request) < 0) goto err;
struct sandbox *sandbox = sandbox_allocate(sandbox_request);
if (!sandbox) goto err_allocate;
sandbox->state = SANDBOX_RUNNABLE;
local_runqueue_add(sandbox);
done:
return sandbox;
err_allocate:
client_socket_send(sandbox_request->socket_descriptor, 503);
client_socket_close(sandbox_request->socket_descriptor, &sandbox->client_address);
free(sandbox_request);
err:
sandbox = NULL;
goto done;
}
if (local_runqueue_list_is_empty()) return NULL;
/* Execute Round Robin Scheduling Logic */
struct sandbox *next_sandbox = local_runqueue_list_remove_and_return();
assert(next_sandbox->state != SANDBOX_RETURNED);
assert(next_sandbox == NULL || next_sandbox->state != SANDBOX_RETURNED);
local_runqueue_add(next_sandbox);
return next_sandbox;
@ -84,6 +62,7 @@ local_runqueue_list_get_next()
void
local_runqueue_list_append(struct sandbox *sandbox_to_append)
{
assert(sandbox_to_append != NULL);
assert(ps_list_singleton_d(sandbox_to_append));
ps_list_head_append_d(&local_runqueue_list, sandbox_to_append);
}

@ -10,9 +10,6 @@
#include "panic.h"
#include "priority_queue.h"
#include "sandbox_functions.h"
#include "sandbox_set_as_preempted.h"
#include "sandbox_set_as_runnable.h"
#include "sandbox_set_as_running.h"
#include "software_interrupt.h"
#include "runtime.h"

@ -20,6 +20,7 @@
#include "panic.h"
#include "runtime.h"
#include "sandbox_types.h"
#include "scheduler.h"
#include "software_interrupt.h"
#include "worker_thread.h"
@ -33,7 +34,6 @@ const uint32_t runtime_first_worker_processor = 1;
FILE *runtime_sandbox_perf_log = NULL;
enum RUNTIME_SCHEDULER runtime_scheduler = RUNTIME_SCHEDULER_EDF;
enum RUNTIME_SIGALRM_HANDLER runtime_sigalrm_handler = RUNTIME_SIGALRM_HANDLER_BROADCAST;
int runtime_worker_core_count;
@ -170,13 +170,13 @@ runtime_configure()
char *scheduler_policy = getenv("SLEDGE_SCHEDULER");
if (scheduler_policy == NULL) scheduler_policy = "EDF";
if (strcmp(scheduler_policy, "EDF") == 0) {
runtime_scheduler = RUNTIME_SCHEDULER_EDF;
scheduler = SCHEDULER_EDF;
} else if (strcmp(scheduler_policy, "FIFO") == 0) {
runtime_scheduler = RUNTIME_SCHEDULER_FIFO;
scheduler = SCHEDULER_FIFO;
} else {
panic("Invalid scheduler policy: %s. Must be {EDF|FIFO}\n", scheduler_policy);
}
printf("\tScheduler Policy: %s\n", runtime_print_scheduler(runtime_scheduler));
printf("\tScheduler Policy: %s\n", scheduler_print(scheduler));
/* Sigalrm Handler Technique */
char *sigalrm_policy = getenv("SLEDGE_SIGALRM_HANDLER");
@ -184,8 +184,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(runtime_scheduler != RUNTIME_SCHEDULER_EDF))
panic("triaged sigalrm handlers are only valid with EDF\n");
if (unlikely(scheduler != SCHEDULER_EDF)) panic("triaged sigalrm handlers are only valid with EDF\n");
runtime_sigalrm_handler = RUNTIME_SIGALRM_HANDLER_TRIAGED;
} else {
panic("Invalid sigalrm policy: %s. Must be {BROADCAST|TRIAGED}\n", sigalrm_policy);

@ -15,6 +15,7 @@
#include "module_database.h"
#include "panic.h"
#include "runtime.h"
#include "scheduler.h"
const int JSON_MAX_ELEMENT_COUNT = 16;
const int JSON_MAX_ELEMENT_SIZE = 1024;
@ -540,7 +541,7 @@ module_new_from_json(char *file_name)
ADMISSIONS_CONTROL_GRANULARITY);
#else
/* relative-deadline-us is required if scheduler is EDF */
if (runtime_scheduler == RUNTIME_SCHEDULER_EDF && relative_deadline_us == 0)
if (scheduler == SCHEDULER_EDF && relative_deadline_us == 0)
panic("relative_deadline_us is required\n");
#endif

@ -21,6 +21,7 @@
#include "module.h"
#include "runtime.h"
#include "sandbox_request.h"
#include "scheduler.h"
#include "software_interrupt.h"
/***************************
@ -95,16 +96,7 @@ runtime_initialize(void)
sandbox_count_initialize();
/* Setup Scheduler */
switch (runtime_scheduler) {
case RUNTIME_SCHEDULER_EDF:
global_request_scheduler_minheap_initialize();
break;
case RUNTIME_SCHEDULER_FIFO:
global_request_scheduler_deque_initialize();
break;
default:
panic("Invalid scheduler policy set: %u\n", runtime_scheduler);
}
scheduler_initialize();
/* Configure Signals */
signal(SIGPIPE, SIG_IGN);

@ -7,17 +7,14 @@
#include "debuglog.h"
#include "sandbox_state.h"
// TODO: Double check this
const bool sandbox_state_is_terminal[SANDBOX_STATE_COUNT] = {
[SANDBOX_UNINITIALIZED] = false, [SANDBOX_ALLOCATED] = false,
[SANDBOX_INITIALIZED] = true, [SANDBOX_SET_AS_RUNNABLE] = false,
[SANDBOX_RUNNABLE] = true, [SANDBOX_SET_AS_RUNNING] = false,
[SANDBOX_RUNNING] = true, [SANDBOX_SET_AS_PREEMPTED] = false,
[SANDBOX_PREEMPTED] = true, [SANDBOX_SET_AS_BLOCKED] = false,
[SANDBOX_BLOCKED] = true, [SANDBOX_SET_AS_RETURNED] = false,
[SANDBOX_RETURNED] = true, [SANDBOX_SET_AS_COMPLETE] = false,
[SANDBOX_COMPLETE] = true, [SANDBOX_SET_AS_ERROR] = false,
[SANDBOX_ERROR] = true
[SANDBOX_UNINITIALIZED] = false, [SANDBOX_ALLOCATED] = false, [SANDBOX_INITIALIZED] = true,
[SANDBOX_SET_AS_RUNNABLE] = false, [SANDBOX_RUNNABLE] = true, [SANDBOX_SET_AS_RUNNING] = false,
[SANDBOX_RUNNING] = true, [SANDBOX_SET_AS_BLOCKED] = false, [SANDBOX_BLOCKED] = true,
[SANDBOX_SET_AS_RETURNED] = false, [SANDBOX_RETURNED] = true, [SANDBOX_SET_AS_COMPLETE] = false,
[SANDBOX_COMPLETE] = true, [SANDBOX_SET_AS_ERROR] = false, [SANDBOX_ERROR] = true
};
const char *sandbox_state_labels[SANDBOX_STATE_COUNT] = {
@ -30,8 +27,6 @@ const char *sandbox_state_labels[SANDBOX_STATE_COUNT] = {
[SANDBOX_RUNNABLE] = "Runnable",
[SANDBOX_SET_AS_RUNNING] = "Transitioning to Running",
[SANDBOX_RUNNING] = "Running",
[SANDBOX_SET_AS_PREEMPTED] = "Transitioning to Preempted",
[SANDBOX_PREEMPTED] = "Preempted",
[SANDBOX_SET_AS_BLOCKED] = "Transitioning to Blocked",
[SANDBOX_BLOCKED] = "Blocked",
[SANDBOX_SET_AS_RETURNED] = "Transitioning to Returned",

@ -0,0 +1,3 @@
#include "scheduler.h"
enum SCHEDULER scheduler = SCHEDULER_EDF;

@ -52,17 +52,7 @@ worker_thread_main(void *argument)
/* Set my priority */
// runtime_set_pthread_prio(pthread_self(), 0);
/* Initialize Runqueue Variant */
switch (runtime_scheduler) {
case RUNTIME_SCHEDULER_EDF:
local_runqueue_minheap_initialize();
break;
case RUNTIME_SCHEDULER_FIFO:
local_runqueue_list_initialize();
break;
default:
panic("Invalid scheduler policy set: %u\n", runtime_scheduler);
}
scheduler_runqueue_initialize();
/* Initialize Completion Queue */
local_completion_queue_initialize();
@ -78,7 +68,7 @@ worker_thread_main(void *argument)
}
/* Begin Worker Execution Loop */
struct sandbox *next_sandbox;
struct sandbox *next_sandbox = NULL;
while (true) {
assert(!software_interrupt_is_enabled());

Loading…
Cancel
Save