diff --git a/runtime/include/global_request_scheduler.h b/runtime/include/global_request_scheduler.h new file mode 100644 index 0000000..d9f1a31 --- /dev/null +++ b/runtime/include/global_request_scheduler.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +/* Returns pointer back if successful, null otherwise */ +typedef sandbox_request_t *(*global_request_scheduler_add_fn_t)(void *); +typedef sandbox_request_t *(*global_request_scheduler_remove_fn_t)(void); +typedef uint64_t (*global_request_scheduler_peek_fn_t)(void); + +struct global_request_scheduler_config { + global_request_scheduler_add_fn_t add_fn; + global_request_scheduler_remove_fn_t remove_fn; + global_request_scheduler_peek_fn_t peek_fn; +}; + + +void global_request_scheduler_initialize(struct global_request_scheduler_config *config); + +sandbox_request_t *global_request_scheduler_add(sandbox_request_t *); +sandbox_request_t *global_request_scheduler_remove(); +uint64_t global_request_scheduler_peek(); diff --git a/runtime/include/global_request_scheduler_deque.h b/runtime/include/global_request_scheduler_deque.h new file mode 100644 index 0000000..1e1757e --- /dev/null +++ b/runtime/include/global_request_scheduler_deque.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +void global_request_scheduler_deque_initialize(); diff --git a/runtime/include/global_request_scheduler_minheap.h b/runtime/include/global_request_scheduler_minheap.h new file mode 100644 index 0000000..5c39170 --- /dev/null +++ b/runtime/include/global_request_scheduler_minheap.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +void global_request_scheduler_minheap_initialize(); diff --git a/runtime/include/local_completion_queue.h b/runtime/include/local_completion_queue.h new file mode 100644 index 0000000..20bd9f9 --- /dev/null +++ b/runtime/include/local_completion_queue.h @@ -0,0 +1,7 @@ +#pragma once + +#include "sandbox.h" + +void local_completion_queue_add(struct sandbox *sandbox); +void local_completion_queue_free(); +void local_completion_queue_initialize(); diff --git a/runtime/include/local_runqueue.h b/runtime/include/local_runqueue.h new file mode 100644 index 0000000..c7ab3d7 --- /dev/null +++ b/runtime/include/local_runqueue.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +/* Returns pointer back if successful, null otherwise */ +typedef struct sandbox *(*local_runqueue_add_fn_t)(struct sandbox *); +typedef bool (*local_runqueue_is_empty_fn_t)(void); +typedef void (*local_runqueue_delete_fn_t)(struct sandbox *sandbox); +typedef struct sandbox *(*local_runqueue_get_next_fn_t)(); +typedef void (*local_runqueue_preempt_fn_t)(ucontext_t *); + +struct local_runqueue_config { + local_runqueue_add_fn_t add_fn; + local_runqueue_is_empty_fn_t is_empty_fn; + local_runqueue_delete_fn_t delete_fn; + local_runqueue_get_next_fn_t get_next_fn; + local_runqueue_preempt_fn_t preempt_fn; +}; + +void local_runqueue_initialize(struct local_runqueue_config *config); + +/* This is currently only used by worker_thread_wakeup_sandbox */ +struct sandbox *local_runqueue_add(struct sandbox *); +void local_runqueue_delete(struct sandbox *); +bool local_runqueue_is_empty(); +struct sandbox *local_runqueue_get_next(); +void local_runqueue_preempt(ucontext_t *); diff --git a/runtime/include/local_runqueue_list.h b/runtime/include/local_runqueue_list.h new file mode 100644 index 0000000..3e35443 --- /dev/null +++ b/runtime/include/local_runqueue_list.h @@ -0,0 +1,5 @@ +#pragma once + +#include "sandbox.h" + +void local_runqueue_list_initialize(); diff --git a/runtime/include/local_runqueue_minheap.h b/runtime/include/local_runqueue_minheap.h new file mode 100644 index 0000000..adad36b --- /dev/null +++ b/runtime/include/local_runqueue_minheap.h @@ -0,0 +1,5 @@ +#pragma once + +#include "sandbox.h" + +void local_runqueue_minheap_initialize(); diff --git a/runtime/include/sandbox_completion_queue.h b/runtime/include/sandbox_completion_queue.h deleted file mode 100644 index 61aa8a8..0000000 --- a/runtime/include/sandbox_completion_queue.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "sandbox.h" - -void sandbox_completion_queue_add(struct sandbox *sandbox); -void sandbox_completion_queue_free(); -void sandbox_completion_queue_initialize(); diff --git a/runtime/include/sandbox_request_scheduler.h b/runtime/include/sandbox_request_scheduler.h deleted file mode 100644 index c179776..0000000 --- a/runtime/include/sandbox_request_scheduler.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include - -/* Returns pointer back if successful, null otherwise */ -typedef sandbox_request_t *(*sandbox_request_scheduler_add_fn_t)(void *); -typedef sandbox_request_t *(*sandbox_request_scheduler_remove_fn_t)(void); -typedef uint64_t (*sandbox_request_scheduler_peek_fn_t)(void); - -typedef struct sandbox_request_scheduler_config { - sandbox_request_scheduler_add_fn_t add; - sandbox_request_scheduler_remove_fn_t remove; - sandbox_request_scheduler_peek_fn_t peek; -} sandbox_request_scheduler_config_t; - - -void sandbox_request_scheduler_initialize(sandbox_request_scheduler_config_t *config); - -sandbox_request_t *sandbox_request_scheduler_add(sandbox_request_t *); -sandbox_request_t *sandbox_request_scheduler_remove(); -uint64_t sandbox_request_scheduler_peek(); diff --git a/runtime/include/sandbox_request_scheduler_fifo.h b/runtime/include/sandbox_request_scheduler_fifo.h deleted file mode 100644 index 691fd92..0000000 --- a/runtime/include/sandbox_request_scheduler_fifo.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include - -void sandbox_request_scheduler_fifo_initialize(); diff --git a/runtime/include/sandbox_request_scheduler_ps.h b/runtime/include/sandbox_request_scheduler_ps.h deleted file mode 100644 index 4189931..0000000 --- a/runtime/include/sandbox_request_scheduler_ps.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include - -void sandbox_request_scheduler_ps_initialize(); diff --git a/runtime/include/sandbox_run_queue.h b/runtime/include/sandbox_run_queue.h deleted file mode 100644 index 7d72582..0000000 --- a/runtime/include/sandbox_run_queue.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include -#include - -/* Returns pointer back if successful, null otherwise */ -typedef struct sandbox *(*sandbox_run_queue_add_fn_t)(struct sandbox *); -typedef bool (*sandbox_run_queue_is_empty_fn_t)(void); -typedef void (*sandbox_run_queue_delete_fn_t)(struct sandbox *sandbox); -typedef struct sandbox *(*sandbox_run_queue_get_next_fn_t)(); -typedef void (*sandbox_run_queue_preempt_fn_t)(ucontext_t *); - -typedef struct sandbox_run_queue_config { - sandbox_run_queue_add_fn_t add; - sandbox_run_queue_is_empty_fn_t is_empty; - sandbox_run_queue_delete_fn_t delete; - sandbox_run_queue_get_next_fn_t get_next; - sandbox_run_queue_preempt_fn_t preempt; -} sandbox_run_queue_config_t; - - -void sandbox_run_queue_initialize(sandbox_run_queue_config_t *config); - - -/* This is currently only used by worker_thread_wakeup_sandbox */ -struct sandbox *sandbox_run_queue_add(struct sandbox *); -void sandbox_run_queue_delete(struct sandbox *); -bool sandbox_run_queue_is_empty(); -struct sandbox *sandbox_run_queue_get_next(); -void sandbox_run_queue_preempt(ucontext_t *); diff --git a/runtime/include/sandbox_run_queue_fifo.h b/runtime/include/sandbox_run_queue_fifo.h deleted file mode 100644 index 7c7d39f..0000000 --- a/runtime/include/sandbox_run_queue_fifo.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "sandbox.h" - -void sandbox_run_queue_fifo_initialize(); diff --git a/runtime/include/sandbox_run_queue_ps.h b/runtime/include/sandbox_run_queue_ps.h deleted file mode 100644 index 95ea0e9..0000000 --- a/runtime/include/sandbox_run_queue_ps.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "sandbox.h" - -void sandbox_run_queue_ps_initialize(); diff --git a/runtime/src/global_request_scheduler.c b/runtime/src/global_request_scheduler.c new file mode 100644 index 0000000..4b456c5 --- /dev/null +++ b/runtime/src/global_request_scheduler.c @@ -0,0 +1,49 @@ +#include + + +/* The global of our polymorphic interface */ +static struct global_request_scheduler_config global_request_scheduler; + +/** + * Initializes the polymorphic interface with a concrete implementation + * @param config + */ +void +global_request_scheduler_initialize(struct global_request_scheduler_config *config) +{ + memcpy(&global_request_scheduler, config, sizeof(struct global_request_scheduler_config)); +} + + +/** + * Adds a sandbox request to the request scheduler + * @param sandbox_request + */ +sandbox_request_t * +global_request_scheduler_add(sandbox_request_t *sandbox_request) +{ + assert(global_request_scheduler.add_fn != NULL); + return global_request_scheduler.add_fn(sandbox_request); +} + +/** + * Removes a sandbox request according to the scheduling policy of the variant + * @returns pointer to a sandbox request + */ +sandbox_request_t * +global_request_scheduler_remove() +{ + assert(global_request_scheduler.remove_fn != NULL); + return global_request_scheduler.remove_fn(); +} + +/** + * Peeks at the priority of the highest priority sandbox request + * @returns highest priority + */ +uint64_t +global_request_scheduler_peek() +{ + assert(global_request_scheduler.peek_fn != NULL); + return global_request_scheduler.peek_fn(); +}; \ No newline at end of file diff --git a/runtime/src/sandbox_request_scheduler_fifo.c b/runtime/src/global_request_scheduler_deque.c similarity index 57% rename from runtime/src/sandbox_request_scheduler_fifo.c rename to runtime/src/global_request_scheduler_deque.c index c1f0867..4577b9b 100644 --- a/runtime/src/sandbox_request_scheduler_fifo.c +++ b/runtime/src/global_request_scheduler_deque.c @@ -1,7 +1,7 @@ -#include +#include -static struct deque_sandbox *runtime_global_deque; -static pthread_mutex_t runtime_global_deque_mutex = PTHREAD_MUTEX_INITIALIZER; +static struct deque_sandbox *global_request_scheduler_deque; +static pthread_mutex_t global_request_scheduler_deque_mutex = PTHREAD_MUTEX_INITIALIZER; /** * Pushes a sandbox request to the global deque @@ -9,7 +9,7 @@ static pthread_mutex_t runtime_global_deque_mutex = PTHREAD_MUTEX_INITIALI * @returns pointer to request if added. NULL otherwise */ static sandbox_request_t * -sandbox_request_scheduler_fifo_add(void *sandbox_request_raw) +global_request_scheduler_deque_add(void *sandbox_request_raw) { sandbox_request_t *sandbox_request = (sandbox_request_t *)sandbox_request_raw; int return_code = 1; @@ -17,11 +17,11 @@ sandbox_request_scheduler_fifo_add(void *sandbox_request_raw) /* TODO: Running the runtime and listener cores on a single shared core is untested We are unsure if the locking behavior is correct, so there may be deadlocks */ #if NCORES == 1 - pthread_mutex_lock(&runtime_global_deque_mutex); + pthread_mutex_lock(&global_request_scheduler_deque_mutex); #endif - return_code = deque_push_sandbox(runtime_global_deque, &sandbox_request); + return_code = deque_push_sandbox(global_request_scheduler_deque, &sandbox_request); #if NCORES == 1 - pthread_mutex_unlock(&runtime_global_deque_mutex); + pthread_mutex_unlock(&global_request_scheduler_deque_mutex); #endif if (return_code != 0) return NULL; return sandbox_request_raw; @@ -42,33 +42,33 @@ We are unsure if the locking behavior is correct, so there may be deadlocks */ * @returns A Sandbox Request or NULL */ static sandbox_request_t * -sandbox_request_scheduler_fifo_remove(void) +global_request_scheduler_deque_remove(void) { sandbox_request_t *sandbox_request; #if NCORES == 1 - pthread_mutex_lock(&runtime_global_deque_mutex); - return_code = deque_pop_sandbox(runtime_global_deque, sandbox_request); - pthread_mutex_unlock(&runtime_global_deque_mutex); + pthread_mutex_lock(&global_request_scheduler_deque_mutex); + return_code = deque_pop_sandbox(global_request_scheduler_deque, sandbox_request); + pthread_mutex_unlock(&global_request_scheduler_deque_mutex); #else - int return_code = deque_steal_sandbox(runtime_global_deque, &sandbox_request); + int return_code = deque_steal_sandbox(global_request_scheduler_deque, &sandbox_request); #endif if (return_code) sandbox_request = NULL; return sandbox_request; } void -sandbox_request_scheduler_fifo_initialize() +global_request_scheduler_deque_initialize() { /* Allocate and Initialize the global deque */ - runtime_global_deque = (struct deque_sandbox *)malloc(sizeof(struct deque_sandbox)); - assert(runtime_global_deque); + global_request_scheduler_deque = (struct deque_sandbox *)malloc(sizeof(struct deque_sandbox)); + assert(global_request_scheduler_deque); /* Note: Below is a Macro */ - deque_init_sandbox(runtime_global_deque, RUNTIME_MAX_SANDBOX_REQUEST_COUNT); + deque_init_sandbox(global_request_scheduler_deque, RUNTIME_MAX_SANDBOX_REQUEST_COUNT); /* Register Function Pointers for Abstract Scheduling API */ - sandbox_request_scheduler_config_t config = { .add = sandbox_request_scheduler_fifo_add, - .remove = sandbox_request_scheduler_fifo_remove }; + struct global_request_scheduler_config config = { .add_fn = global_request_scheduler_deque_add, + .remove_fn = global_request_scheduler_deque_remove }; - sandbox_request_scheduler_initialize(&config); + global_request_scheduler_initialize(&config); } \ No newline at end of file diff --git a/runtime/src/global_request_scheduler_minheap.c b/runtime/src/global_request_scheduler_minheap.c new file mode 100644 index 0000000..d2fad90 --- /dev/null +++ b/runtime/src/global_request_scheduler_minheap.c @@ -0,0 +1,66 @@ +#include +#include "priority_queue.h" + +static struct priority_queue global_request_scheduler_minheap; + +/** + * Pushes a sandbox request to the global deque + * @param sandbox_request + * @returns pointer to request if added. NULL otherwise + */ +static sandbox_request_t * +global_request_scheduler_minheap_add(void *sandbox_request) +{ + int return_code = priority_queue_enqueue(&global_request_scheduler_minheap, sandbox_request, "Request"); + + if (return_code == -1) { + printf("Request Queue is full\n"); + exit(EXIT_FAILURE); + } + + if (return_code != 0) return NULL; + return sandbox_request; +} + +/** + * + * @returns A Sandbox Request or NULL + */ +static sandbox_request_t * +global_request_scheduler_minheap_remove(void) +{ + return (sandbox_request_t *)priority_queue_dequeue(&global_request_scheduler_minheap, "Request"); +} + +/** + * + * @returns A Sandbox Request or NULL + */ +static uint64_t +global_request_scheduler_minheap_peek(void) +{ + return priority_queue_peek(&global_request_scheduler_minheap); +} + +uint64_t +sandbox_request_get_priority_fn(void *element) +{ + sandbox_request_t *sandbox_request = (sandbox_request_t *)element; + return sandbox_request->absolute_deadline; +}; + + +/** + * Initializes the variant and registers against the polymorphic interface + */ +void +global_request_scheduler_minheap_initialize() +{ + priority_queue_initialize(&global_request_scheduler_minheap, sandbox_request_get_priority_fn); + + struct global_request_scheduler_config config = { .add_fn = global_request_scheduler_minheap_add, + .remove_fn = global_request_scheduler_minheap_remove, + .peek_fn = global_request_scheduler_minheap_peek }; + + global_request_scheduler_initialize(&config); +} \ No newline at end of file diff --git a/runtime/src/local_completion_queue.c b/runtime/src/local_completion_queue.c new file mode 100644 index 0000000..359e818 --- /dev/null +++ b/runtime/src/local_completion_queue.c @@ -0,0 +1,47 @@ +#include "local_completion_queue.h" + +__thread static struct ps_list_head local_completion_queue; + + +void +local_completion_queue_initialize() +{ + ps_list_head_init(&local_completion_queue); +} + +static inline bool +local_completion_queue_is_empty() +{ + return ps_list_head_empty(&local_completion_queue); +} + +/** + * Adds sandbox to the completion queue + * @param sandbox to add to completion queue + */ +void +local_completion_queue_add(struct sandbox *sandbox) +{ + assert(sandbox); + assert(ps_list_singleton_d(sandbox)); + ps_list_head_append_d(&local_completion_queue, sandbox); + assert(!local_completion_queue_is_empty()); +} + + +/** + * @brief Frees all sandboxes in the thread local completion queue + * @return void + */ +void +local_completion_queue_free() +{ + struct sandbox *sandbox_iterator; + struct sandbox *buffer; + + ps_list_foreach_del_d(&local_completion_queue, sandbox_iterator, buffer) + { + ps_list_rem_d(sandbox_iterator); + sandbox_free(sandbox_iterator); + } +} \ No newline at end of file diff --git a/runtime/src/local_runqueue.c b/runtime/src/local_runqueue.c new file mode 100644 index 0000000..183bd8b --- /dev/null +++ b/runtime/src/local_runqueue.c @@ -0,0 +1,66 @@ +#include + +static struct local_runqueue_config local_runqueue; + +/* Initializes a concrete implementation of the sandbox request scheduler interface */ +void +local_runqueue_initialize(struct local_runqueue_config *config) +{ + memcpy(&local_runqueue, config, sizeof(struct local_runqueue_config)); +} + +/** + * Adds a sandbox request to the run queue + * @param sandbox to add + * @returns sandbox that was added (or NULL?) + */ +struct sandbox * +local_runqueue_add(struct sandbox *sandbox) +{ + assert(local_runqueue.add_fn != NULL); + return local_runqueue.add_fn(sandbox); +} + +/** + * Delete a sandbox from the run queue + * @param sandbox to delete + */ +void +local_runqueue_delete(struct sandbox *sandbox) +{ + assert(local_runqueue.delete_fn != NULL); + local_runqueue.delete_fn(sandbox); +} + +/** + * Checks if run queue is empty + * @returns true if empty + */ +bool +local_runqueue_is_empty() +{ + assert(local_runqueue.is_empty_fn != NULL); + return local_runqueue.is_empty_fn(); +} + +/** + * Get next sandbox from run queue, where next is defined by + * @returns sandbox (or NULL?) + */ +struct sandbox * +local_runqueue_get_next() +{ + assert(local_runqueue.get_next_fn != NULL); + return local_runqueue.get_next_fn(); +}; + +/** + * Preempt the current sandbox according to the scheduler variant + * @param context + */ +void +local_runqueue_preempt(ucontext_t *context) +{ + assert(local_runqueue.preempt_fn != NULL); + return local_runqueue.preempt_fn(context); +}; \ No newline at end of file diff --git a/runtime/src/local_runqueue_list.c b/runtime/src/local_runqueue_list.c new file mode 100644 index 0000000..0fc6dcf --- /dev/null +++ b/runtime/src/local_runqueue_list.c @@ -0,0 +1,103 @@ +#include "local_runqueue_list.h" +#include "local_runqueue.h" +#include "global_request_scheduler.h" + +__thread static struct ps_list_head local_runqueue_list; + +bool +local_runqueue_list_is_empty() +{ + return ps_list_head_empty(&local_runqueue_list); +} + +/* Get the sandbox at the head of the thread local runqueue */ +struct sandbox * +local_runqueue_list_get_head() +{ + return ps_list_head_first_d(&local_runqueue_list, struct sandbox); +} + +/** + * Removes the thread from the thread-local runqueue + * @param sandbox sandbox + */ +void +local_runqueue_list_remove(struct sandbox *sandbox_to_remove) +{ + ps_list_rem_d(sandbox_to_remove); +} + +struct sandbox * +local_runqueue_list_remove_and_return() +{ + struct sandbox *sandbox_to_remove = ps_list_head_first_d(&local_runqueue_list, struct sandbox); + ps_list_rem_d(sandbox_to_remove); + return sandbox_to_remove; +} + +/** + * 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 + * @return the sandbox to execute or NULL if none are available + */ +struct sandbox * +local_runqueue_list_get_next() +{ + if (local_runqueue_is_empty()) { + sandbox_request_t *sandbox_request = global_request_scheduler_remove(); + if (sandbox_request == NULL) return NULL; + struct sandbox *sandbox = sandbox_allocate(sandbox_request); + assert(sandbox); + free(sandbox_request); + sandbox->state = RUNNABLE; + local_runqueue_add(sandbox); + return sandbox; + } + + /* Execute Round Robin Scheduling Logic */ + struct sandbox *next_sandbox = local_runqueue_list_remove_and_return(); + assert(next_sandbox->state != RETURNED); + local_runqueue_add(next_sandbox); + + debuglog("[%p: %s]\n", next_sandbox, next_sandbox->module->name); + return next_sandbox; +} + + +/** + * Append a sandbox to the runqueue + * @returns the appended sandbox + */ +struct sandbox * +local_runqueue_list_append(struct sandbox *sandbox_to_append) +{ + assert(ps_list_singleton_d(sandbox_to_append)); + // fprintf(stderr, "(%d,%lu) %s: run %p, %s\n", sched_getcpu(), pthread_self(), __func__, s, + // s->module->name); + ps_list_head_append_d(&local_runqueue_list, sandbox_to_append); + return sandbox_to_append; +} + +/** + * Conditionally checks to see if current sandbox should be preempted FIFO doesn't preempt, so just return. + */ +void +local_runqueue_list_preempt(ucontext_t *user_context) +{ + return; +} + + +void +local_runqueue_list_initialize() +{ + ps_list_head_init(&local_runqueue_list); + + /* Register Function Pointers for Abstract Scheduling API */ + struct local_runqueue_config config = { .add_fn = local_runqueue_list_append, + .is_empty_fn = local_runqueue_list_is_empty, + .delete_fn = local_runqueue_list_remove, + .get_next_fn = local_runqueue_list_get_next, + .preempt_fn = local_runqueue_list_preempt }; + local_runqueue_initialize(&config); +}; diff --git a/runtime/src/sandbox_run_queue_ps.c b/runtime/src/local_runqueue_minheap.c similarity index 64% rename from runtime/src/sandbox_run_queue_ps.c rename to runtime/src/local_runqueue_minheap.c index 3ec26f6..7f4a616 100644 --- a/runtime/src/sandbox_run_queue_ps.c +++ b/runtime/src/local_runqueue_minheap.c @@ -1,23 +1,23 @@ -#include "sandbox_run_queue_ps.h" -#include "sandbox_run_queue.h" -#include "priority_queue.h" -#include "sandbox_request_scheduler.h" +#include "local_runqueue.h" +#include "local_runqueue_minheap.h" +#include "global_request_scheduler.h" #include "current_sandbox.h" +#include "priority_queue.h" #include -__thread static struct priority_queue sandbox_run_queue_ps; +__thread static struct priority_queue local_runqueue_minheap; /** * Checks if the run queue is empty * @returns true if empty. false otherwise */ bool -sandbox_run_queue_ps_is_empty() +local_runqueue_minheap_is_empty() { - int length = priority_queue_length(&sandbox_run_queue_ps); + int length = priority_queue_length(&local_runqueue_minheap); assert(length < 5); - return priority_queue_length(&sandbox_run_queue_ps) == 0; + return priority_queue_length(&local_runqueue_minheap) == 0; } /** @@ -26,17 +26,17 @@ sandbox_run_queue_ps_is_empty() * @returns pointer to request if added. NULL otherwise */ static struct sandbox * -sandbox_run_queue_ps_add(struct sandbox *sandbox) +local_runqueue_minheap_add(struct sandbox *sandbox) { - int original_length = priority_queue_length(&sandbox_run_queue_ps); + int original_length = priority_queue_length(&local_runqueue_minheap); - int return_code = priority_queue_enqueue(&sandbox_run_queue_ps, sandbox, "Runqueue"); + int return_code = priority_queue_enqueue(&local_runqueue_minheap, sandbox, "Runqueue"); if (return_code == -1) { printf("Thread Runqueue is full!\n"); exit(EXIT_FAILURE); } - int final_length = priority_queue_length(&sandbox_run_queue_ps); + int final_length = priority_queue_length(&local_runqueue_minheap); assert(final_length == original_length + 1); @@ -49,9 +49,9 @@ sandbox_run_queue_ps_add(struct sandbox *sandbox) * @returns A Sandbox or NULL if empty */ static struct sandbox * -sandbox_run_queue_ps_remove() +local_runqueue_minheap_remove() { - return (struct sandbox *)priority_queue_dequeue(&sandbox_run_queue_ps, "Runqueue"); + return (struct sandbox *)priority_queue_dequeue(&local_runqueue_minheap, "Runqueue"); } /** @@ -59,10 +59,10 @@ sandbox_run_queue_ps_remove() * @param sandbox to delete */ static void -sandbox_run_queue_ps_delete(struct sandbox *sandbox) +local_runqueue_minheap_delete(struct sandbox *sandbox) { assert(sandbox != NULL); - int rc = priority_queue_delete(&sandbox_run_queue_ps, sandbox, "Runqueue"); + int rc = priority_queue_delete(&local_runqueue_minheap, sandbox, "Runqueue"); assert(rc == 0); } @@ -75,12 +75,12 @@ sandbox_run_queue_ps_delete(struct sandbox *sandbox) * @return the sandbox to execute or NULL if none are available */ struct sandbox * -sandbox_run_queue_ps_get_next() +local_runqueue_minheap_get_next() { - if (sandbox_run_queue_is_empty()) { + if (local_runqueue_is_empty()) { /* Try to pull a sandbox request and return NULL if we're unable to get one */ sandbox_request_t *sandbox_request; - if ((sandbox_request = sandbox_request_scheduler_remove()) == NULL) { return NULL; }; + if ((sandbox_request = global_request_scheduler_remove()) == NULL) { return NULL; }; /* Otherwise, allocate the sandbox request as a runnable sandbox and place on the runqueue */ struct sandbox *sandbox = sandbox_allocate(sandbox_request); @@ -88,13 +88,13 @@ sandbox_run_queue_ps_get_next() assert(sandbox); free(sandbox_request); sandbox->state = RUNNABLE; - sandbox_run_queue_ps_add(sandbox); + local_runqueue_minheap_add(sandbox); return sandbox; } /* Resume the sandbox at the top of the runqueue */ - struct sandbox *sandbox = sandbox_run_queue_ps_remove(); - sandbox_run_queue_ps_add(sandbox); + struct sandbox *sandbox = local_runqueue_minheap_remove(); + local_runqueue_minheap_add(sandbox); return sandbox; } @@ -103,7 +103,7 @@ sandbox_run_queue_ps_get_next() * Conditionally checks to see if current sandbox should be preempted */ void -sandbox_run_queue_ps_preempt(ucontext_t *user_context) +local_runqueue_minheap_preempt(ucontext_t *user_context) { software_interrupt_disable(); /* no nesting! */ @@ -115,22 +115,22 @@ sandbox_run_queue_ps_preempt(ucontext_t *user_context) }; /* The current sandbox should be the head of the runqueue */ - assert(sandbox_run_queue_ps_is_empty() == false); + assert(local_runqueue_minheap_is_empty() == false); // TODO: Factor quantum and/or sandbox allocation time into decision - // uint64_t global_deadline = sandbox_request_scheduler_peek() - + // uint64_t global_deadline = global_request_scheduler_peek() - // SOFTWARE_INTERRUPT_INTERVAL_DURATION_IN_CYCLES; bool should_enable_software_interrupt = true; - uint64_t local_deadline = priority_queue_peek(&sandbox_run_queue_ps); - uint64_t global_deadline = sandbox_request_scheduler_peek(); + uint64_t local_deadline = priority_queue_peek(&local_runqueue_minheap); + uint64_t global_deadline = global_request_scheduler_peek(); /* Our local deadline should only be ULONG_MAX if our local runqueue is empty */ - if (local_deadline == ULONG_MAX) { assert(sandbox_run_queue_ps.first_free == 1); }; + if (local_deadline == ULONG_MAX) { assert(local_runqueue_minheap.first_free == 1); }; /* If we're able to get a sandbox request with a tighter deadline, preempt the current context and run it */ sandbox_request_t *sandbox_request; - if (global_deadline < local_deadline && (sandbox_request = sandbox_request_scheduler_remove()) != NULL) { + if (global_deadline < local_deadline && (sandbox_request = global_request_scheduler_remove()) != NULL) { printf("Thread %lu Preempted %lu for %lu\n", pthread_self(), local_deadline, sandbox_request->absolute_deadline); @@ -142,7 +142,7 @@ sandbox_run_queue_ps_preempt(ucontext_t *user_context) /* Add it to the runqueue */ printf("adding new sandbox to runqueue\n"); - sandbox_run_queue_add(next_sandbox); + local_runqueue_add(next_sandbox); debuglog("[%p: %s]\n", sandbox, sandbox->module->name); /* Save the context of the currently executing sandbox before switching from it */ @@ -172,17 +172,17 @@ sandbox_get_priority(void *element) * Registers the PS variant with the polymorphic interface **/ void -sandbox_run_queue_ps_initialize() +local_runqueue_minheap_initialize() { /* Initialize local state */ - priority_queue_initialize(&sandbox_run_queue_ps, sandbox_get_priority); + priority_queue_initialize(&local_runqueue_minheap, sandbox_get_priority); /* Register Function Pointers for Abstract Scheduling API */ - sandbox_run_queue_config_t config = { .add = sandbox_run_queue_ps_add, - .is_empty = sandbox_run_queue_ps_is_empty, - .delete = sandbox_run_queue_ps_delete, - .get_next = sandbox_run_queue_ps_get_next, - .preempt = sandbox_run_queue_ps_preempt }; + struct local_runqueue_config config = { .add_fn = local_runqueue_minheap_add, + .is_empty_fn = local_runqueue_minheap_is_empty, + .delete_fn = local_runqueue_minheap_delete, + .get_next_fn = local_runqueue_minheap_get_next, + .preempt_fn = local_runqueue_minheap_preempt }; - sandbox_run_queue_initialize(&config); + local_runqueue_initialize(&config); } diff --git a/runtime/src/runtime.c b/runtime/src/runtime.c index 10b72e3..58efc3d 100644 --- a/runtime/src/runtime.c +++ b/runtime/src/runtime.c @@ -18,8 +18,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -46,8 +46,8 @@ runtime_initialize(void) /* Allocate and Initialize the global deque TODO: Improve to expose variant as a config */ - // sandbox_request_scheduler_fifo_initialize(); - sandbox_request_scheduler_ps_initialize(); + // global_request_scheduler_deque_initialize(); + global_request_scheduler_minheap_initialize(); /* Mask Signals */ software_interrupt_mask_signal(SIGUSR1); @@ -110,7 +110,7 @@ listener_thread_main(void *dummy) assert(sandbox_request); /* Add to the Global Sandbox Request Scheduler */ - sandbox_request_scheduler_add(sandbox_request); + global_request_scheduler_add(sandbox_request); } } diff --git a/runtime/src/sandbox_completion_queue.c b/runtime/src/sandbox_completion_queue.c deleted file mode 100644 index ae23102..0000000 --- a/runtime/src/sandbox_completion_queue.c +++ /dev/null @@ -1,47 +0,0 @@ -#include "sandbox_completion_queue.h" - -__thread static struct ps_list_head sandbox_completion_queue; - - -void -sandbox_completion_queue_initialize() -{ - ps_list_head_init(&sandbox_completion_queue); -} - -static inline bool -sandbox_completion_queue_is_empty() -{ - return ps_list_head_empty(&sandbox_completion_queue); -} - -/** - * Adds sandbox to the completion queue - * @param sandbox to add to completion queue - */ -void -sandbox_completion_queue_add(struct sandbox *sandbox) -{ - assert(sandbox); - assert(ps_list_singleton_d(sandbox)); - ps_list_head_append_d(&sandbox_completion_queue, sandbox); - assert(!sandbox_completion_queue_is_empty()); -} - - -/** - * @brief Frees all sandboxes in the thread local completion queue - * @return void - */ -void -sandbox_completion_queue_free() -{ - struct sandbox *sandbox_iterator; - struct sandbox *buffer; - - ps_list_foreach_del_d(&sandbox_completion_queue, sandbox_iterator, buffer) - { - ps_list_rem_d(sandbox_iterator); - sandbox_free(sandbox_iterator); - } -} \ No newline at end of file diff --git a/runtime/src/sandbox_request_scheduler.c b/runtime/src/sandbox_request_scheduler.c deleted file mode 100644 index 74154b0..0000000 --- a/runtime/src/sandbox_request_scheduler.c +++ /dev/null @@ -1,49 +0,0 @@ -#include - - -/* The global of our polymorphic interface */ -static sandbox_request_scheduler_config_t sandbox_request_scheduler; - -/** - * Initializes the polymorphic interface with a concrete implementation - * @param config - */ -void -sandbox_request_scheduler_initialize(sandbox_request_scheduler_config_t *config) -{ - memcpy(&sandbox_request_scheduler, config, sizeof(sandbox_request_scheduler_config_t)); -} - - -/** - * Adds a sandbox request to the request scheduler - * @param sandbox_request - */ -sandbox_request_t * -sandbox_request_scheduler_add(sandbox_request_t *sandbox_request) -{ - assert(sandbox_request_scheduler.add != NULL); - return sandbox_request_scheduler.add(sandbox_request); -} - -/** - * Removes a sandbox request according to the scheduling policy of the variant - * @returns pointer to a sandbox request - */ -sandbox_request_t * -sandbox_request_scheduler_remove() -{ - assert(sandbox_request_scheduler.remove != NULL); - return sandbox_request_scheduler.remove(); -} - -/** - * Peeks at the priority of the highest priority sandbox request - * @returns highest priority - */ -uint64_t -sandbox_request_scheduler_peek() -{ - assert(sandbox_request_scheduler.peek != NULL); - return sandbox_request_scheduler.peek(); -}; \ No newline at end of file diff --git a/runtime/src/sandbox_request_scheduler_ps.c b/runtime/src/sandbox_request_scheduler_ps.c deleted file mode 100644 index e324639..0000000 --- a/runtime/src/sandbox_request_scheduler_ps.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include "priority_queue.h" - -static struct priority_queue sandbox_request_scheduler_ps; - -/** - * Pushes a sandbox request to the global deque - * @param sandbox_request - * @returns pointer to request if added. NULL otherwise - */ -static sandbox_request_t * -sandbox_request_scheduler_ps_add(void *sandbox_request) -{ - int return_code = priority_queue_enqueue(&sandbox_request_scheduler_ps, sandbox_request, "Request"); - - if (return_code == -1) { - printf("Request Queue is full\n"); - exit(EXIT_FAILURE); - } - - if (return_code != 0) return NULL; - return sandbox_request; -} - -/** - * - * @returns A Sandbox Request or NULL - */ -static sandbox_request_t * -sandbox_request_scheduler_ps_remove(void) -{ - return (sandbox_request_t *)priority_queue_dequeue(&sandbox_request_scheduler_ps, "Request"); -} - -/** - * - * @returns A Sandbox Request or NULL - */ -static uint64_t -sandbox_request_scheduler_ps_peek(void) -{ - return priority_queue_peek(&sandbox_request_scheduler_ps); -} - -uint64_t -sandbox_request_get_priority_fn(void *element) -{ - sandbox_request_t *sandbox_request = (sandbox_request_t *)element; - return sandbox_request->absolute_deadline; -}; - - -/** - * Initializes the variant and registers against the polymorphic interface - */ -void -sandbox_request_scheduler_ps_initialize() -{ - priority_queue_initialize(&sandbox_request_scheduler_ps, sandbox_request_get_priority_fn); - - sandbox_request_scheduler_config_t config = { .add = sandbox_request_scheduler_ps_add, - .remove = sandbox_request_scheduler_ps_remove, - .peek = sandbox_request_scheduler_ps_peek }; - - sandbox_request_scheduler_initialize(&config); -} \ No newline at end of file diff --git a/runtime/src/sandbox_run_queue.c b/runtime/src/sandbox_run_queue.c deleted file mode 100644 index 2ef8bdd..0000000 --- a/runtime/src/sandbox_run_queue.c +++ /dev/null @@ -1,66 +0,0 @@ -#include - -static sandbox_run_queue_config_t sandbox_run_queue; - -/* Initializes a concrete implementation of the sandbox request scheduler interface */ -void -sandbox_run_queue_initialize(sandbox_run_queue_config_t *config) -{ - memcpy(&sandbox_run_queue, config, sizeof(sandbox_run_queue_config_t)); -} - -/** - * Adds a sandbox request to the run queue - * @param sandbox to add - * @returns sandbox that was added (or NULL?) - */ -struct sandbox * -sandbox_run_queue_add(struct sandbox *sandbox) -{ - assert(sandbox_run_queue.add != NULL); - return sandbox_run_queue.add(sandbox); -} - -/** - * Delete a sandbox from the run queue - * @param sandbox to delete - */ -void -sandbox_run_queue_delete(struct sandbox *sandbox) -{ - assert(sandbox_run_queue.delete != NULL); - sandbox_run_queue.delete(sandbox); -} - -/** - * Checks if run queue is empty - * @returns true if empty - */ -bool -sandbox_run_queue_is_empty() -{ - assert(sandbox_run_queue.is_empty != NULL); - return sandbox_run_queue.is_empty(); -} - -/** - * Get next sandbox from run queue, where next is defined by - * @returns sandbox (or NULL?) - */ -struct sandbox * -sandbox_run_queue_get_next() -{ - assert(sandbox_run_queue.get_next != NULL); - return sandbox_run_queue.get_next(); -}; - -/** - * Preempt the current sandbox according to the scheduler variant - * @param context - */ -void -sandbox_run_queue_preempt(ucontext_t *context) -{ - assert(sandbox_run_queue.preempt != NULL); - return sandbox_run_queue.preempt(context); -}; \ No newline at end of file diff --git a/runtime/src/sandbox_run_queue_fifo.c b/runtime/src/sandbox_run_queue_fifo.c deleted file mode 100644 index 1f0792e..0000000 --- a/runtime/src/sandbox_run_queue_fifo.c +++ /dev/null @@ -1,103 +0,0 @@ -#include "sandbox_run_queue_fifo.h" -#include "sandbox_run_queue.h" -#include "sandbox_request_scheduler.h" - -__thread static struct ps_list_head sandbox_run_queue_fifo; - -bool -sandbox_run_queue_fifo_is_empty() -{ - return ps_list_head_empty(&sandbox_run_queue_fifo); -} - -/* Get the sandbox at the head of the thread local runqueue */ -struct sandbox * -sandbox_run_queue_fifo_get_head() -{ - return ps_list_head_first_d(&sandbox_run_queue_fifo, struct sandbox); -} - -/** - * Removes the thread from the thread-local runqueue - * @param sandbox sandbox - */ -void -sandbox_run_queue_fifo_remove(struct sandbox *sandbox_to_remove) -{ - ps_list_rem_d(sandbox_to_remove); -} - -struct sandbox * -sandbox_run_queue_fifo_remove_and_return() -{ - struct sandbox *sandbox_to_remove = ps_list_head_first_d(&sandbox_run_queue_fifo, struct sandbox); - ps_list_rem_d(sandbox_to_remove); - return sandbox_to_remove; -} - -/** - * 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 - * @return the sandbox to execute or NULL if none are available - */ -struct sandbox * -sandbox_run_queue_fifo_get_next() -{ - if (sandbox_run_queue_is_empty()) { - sandbox_request_t *sandbox_request = sandbox_request_scheduler_remove(); - if (sandbox_request == NULL) return NULL; - struct sandbox *sandbox = sandbox_allocate(sandbox_request); - assert(sandbox); - free(sandbox_request); - sandbox->state = RUNNABLE; - sandbox_run_queue_add(sandbox); - return sandbox; - } - - /* Execute Round Robin Scheduling Logic */ - struct sandbox *next_sandbox = sandbox_run_queue_fifo_remove_and_return(); - assert(next_sandbox->state != RETURNED); - sandbox_run_queue_add(next_sandbox); - - debuglog("[%p: %s]\n", next_sandbox, next_sandbox->module->name); - return next_sandbox; -} - - -/** - * Append a sandbox to the runqueue - * @returns the appended sandbox - */ -struct sandbox * -sandbox_run_queue_fifo_append(struct sandbox *sandbox_to_append) -{ - assert(ps_list_singleton_d(sandbox_to_append)); - // fprintf(stderr, "(%d,%lu) %s: run %p, %s\n", sched_getcpu(), pthread_self(), __func__, s, - // s->module->name); - ps_list_head_append_d(&sandbox_run_queue_fifo, sandbox_to_append); - return sandbox_to_append; -} - -/** - * Conditionally checks to see if current sandbox should be preempted FIFO doesn't preempt, so just return. - */ -void -sandbox_run_queue_fifo_preempt(ucontext_t *user_context) -{ - return; -} - - -void -sandbox_run_queue_fifo_initialize() -{ - ps_list_head_init(&sandbox_run_queue_fifo); - - /* Register Function Pointers for Abstract Scheduling API */ - sandbox_run_queue_config_t config = { .add = sandbox_run_queue_fifo_append, - .is_empty = sandbox_run_queue_fifo_is_empty, - .delete = sandbox_run_queue_fifo_remove, - .get_next = sandbox_run_queue_fifo_get_next, - .preempt = sandbox_run_queue_fifo_preempt }; - sandbox_run_queue_initialize(&config); -}; diff --git a/runtime/src/software_interrupt.c b/runtime/src/software_interrupt.c index 63229bd..464ea8c 100644 --- a/runtime/src/software_interrupt.c +++ b/runtime/src/software_interrupt.c @@ -13,7 +13,7 @@ #include #include #include -#include "sandbox_run_queue.h" +#include "local_runqueue.h" /******************* * Process Globals * @@ -85,7 +85,7 @@ software_interrupt_handle_signals(int signal_type, siginfo_t *signal_info, void /* and software interrupts are not disabled */ if (!software_interrupt_is_enabled()) return; /* Preempt */ - sandbox_run_queue_preempt(user_context); + local_runqueue_preempt(user_context); return; } diff --git a/runtime/src/worker_thread.c b/runtime/src/worker_thread.c index 1b695a9..d74a5f8 100644 --- a/runtime/src/worker_thread.c +++ b/runtime/src/worker_thread.c @@ -15,11 +15,11 @@ If placed in Local Includes, error is triggered that memset was implicitly decla * Local Includes * **************************/ #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include @@ -74,7 +74,7 @@ worker_thread_switch_to_sandbox(struct sandbox *next_sandbox) /* If the current sandbox we're switching from is in a RETURNED state, add to completion queue */ if (previous_sandbox != NULL && previous_sandbox->state == RETURNED) { - sandbox_completion_queue_add(previous_sandbox); + local_completion_queue_add(previous_sandbox); } else if (previous_sandbox != NULL) { printf("Switched away from sandbox is state %d\n", previous_sandbox->state); } @@ -94,7 +94,7 @@ worker_thread_wakeup_sandbox(sandbox_t *sandbox) if (sandbox->state == BLOCKED) { sandbox->state = RUNNABLE; printf("Marking blocked sandbox as runnable\n"); - sandbox_run_queue_add(sandbox); + local_runqueue_add(sandbox); } software_interrupt_enable(); } @@ -112,11 +112,11 @@ worker_thread_block_current_sandbox(void) /* Remove the sandbox we were just executing from the runqueue and mark as blocked */ struct sandbox *previous_sandbox = current_sandbox_get(); - sandbox_run_queue_delete(previous_sandbox); + local_runqueue_delete(previous_sandbox); previous_sandbox->state = BLOCKED; /* Switch to the next sandbox */ - struct sandbox *next_sandbox = sandbox_run_queue_get_next(); + struct sandbox *next_sandbox = local_runqueue_get_next(); debuglog("[%p: %next_sandbox, %p: %next_sandbox]\n", previous_sandbox, previous_sandbox->module->name, next_sandbox, next_sandbox ? next_sandbox->module->name : ""); software_interrupt_enable(); @@ -184,9 +184,9 @@ worker_thread_main(void *return_code) { /* Initialize Worker Infrastructure */ arch_context_init(&worker_thread_base_context, 0, 0); - // sandbox_run_queue_fifo_initialize(); - sandbox_run_queue_ps_initialize(); - sandbox_completion_queue_initialize(); + // local_runqueue_list_initialize(); + local_runqueue_minheap_initialize(); + local_completion_queue_initialize(); software_interrupt_is_disabled = false; worker_thread_next_context = NULL; #ifndef PREEMPT_DISABLE @@ -204,12 +204,12 @@ worker_thread_main(void *return_code) if (!worker_thread_is_in_callback) worker_thread_execute_libuv_event_loop(); software_interrupt_disable(); - next_sandbox = sandbox_run_queue_get_next(); + next_sandbox = local_runqueue_get_next(); software_interrupt_enable(); if (next_sandbox != NULL) worker_thread_switch_to_sandbox(next_sandbox); - sandbox_completion_queue_free(); + local_completion_queue_free(); } *(int *)return_code = -1; @@ -229,7 +229,7 @@ worker_thread_on_sandbox_exit(sandbox_t *exiting_sandbox) /* TODO: I do not understand when software interrupts must be disabled? */ software_interrupt_disable(); - sandbox_run_queue_delete(exiting_sandbox); + local_runqueue_delete(exiting_sandbox); exiting_sandbox->state = RETURNED; software_interrupt_enable(); @@ -241,7 +241,7 @@ worker_thread_on_sandbox_exit(sandbox_t *exiting_sandbox) assert(0); } - sandbox_completion_queue_add(exiting_sandbox); + local_completion_queue_add(exiting_sandbox); /* This should force return to main event loop */ worker_thread_switch_to_sandbox(NULL);