chore: rename scheduler interfaces and variants

main
Sean McBride 4 years ago
parent 0eb474a8d7
commit 1c2aa448cd

@ -0,0 +1,21 @@
#pragma once
#include <sandbox_request.h>
/* 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();

@ -0,0 +1,5 @@
#pragma once
#include <global_request_scheduler.h>
void global_request_scheduler_deque_initialize();

@ -0,0 +1,5 @@
#pragma once
#include <global_request_scheduler.h>
void global_request_scheduler_minheap_initialize();

@ -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();

@ -0,0 +1,28 @@
#pragma once
#include <stdbool.h>
#include <sandbox.h>
/* 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 *);

@ -0,0 +1,5 @@
#pragma once
#include "sandbox.h"
void local_runqueue_list_initialize();

@ -0,0 +1,5 @@
#pragma once
#include "sandbox.h"
void local_runqueue_minheap_initialize();

@ -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();

@ -1,21 +0,0 @@
#pragma once
#include <sandbox_request.h>
/* 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();

@ -1,5 +0,0 @@
#pragma once
#include <sandbox_request_scheduler.h>
void sandbox_request_scheduler_fifo_initialize();

@ -1,5 +0,0 @@
#pragma once
#include <sandbox_request_scheduler.h>
void sandbox_request_scheduler_ps_initialize();

@ -1,30 +0,0 @@
#pragma once
#include <stdbool.h>
#include <sandbox.h>
/* 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 *);

@ -1,5 +0,0 @@
#pragma once
#include "sandbox.h"
void sandbox_run_queue_fifo_initialize();

@ -1,5 +0,0 @@
#pragma once
#include "sandbox.h"
void sandbox_run_queue_ps_initialize();

@ -0,0 +1,49 @@
#include <global_request_scheduler.h>
/* 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();
};

@ -1,7 +1,7 @@
#include <sandbox_request_scheduler.h>
#include <global_request_scheduler.h>
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);
}

@ -0,0 +1,66 @@
#include <global_request_scheduler.h>
#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);
}

@ -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);
}
}

@ -0,0 +1,66 @@
#include <local_runqueue.h>
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);
};

@ -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);
};

@ -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 <stdint.h>
__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);
}

@ -18,8 +18,8 @@
#include <http_parser_settings.h>
#include <module.h>
#include <sandbox_request.h>
#include <sandbox_request_scheduler_fifo.h>
#include <sandbox_request_scheduler_ps.h>
#include <global_request_scheduler_deque.h>
#include <global_request_scheduler_minheap.h>
#include <software_interrupt.h>
#include <types.h>
@ -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);
}
}

@ -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);
}
}

@ -1,49 +0,0 @@
#include <sandbox_request_scheduler.h>
/* 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();
};

@ -1,66 +0,0 @@
#include <sandbox_request_scheduler.h>
#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);
}

@ -1,66 +0,0 @@
#include <sandbox_run_queue.h>
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);
};

@ -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);
};

@ -13,7 +13,7 @@
#include <arch/context.h>
#include <software_interrupt.h>
#include <current_sandbox.h>
#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;
}

@ -15,11 +15,11 @@ If placed in Local Includes, error is triggered that memset was implicitly decla
* Local Includes *
**************************/
#include <current_sandbox.h>
#include <sandbox_completion_queue.h>
#include <sandbox_request_scheduler.h>
#include <sandbox_run_queue.h>
#include <sandbox_run_queue_fifo.h>
#include <sandbox_run_queue_ps.h>
#include <global_request_scheduler.h>
#include <local_completion_queue.h>
#include <local_runqueue.h>
#include <local_runqueue_list.h>
#include <local_runqueue_minheap.h>
#include <types.h>
#include <worker_thread.h>
@ -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);

Loading…
Cancel
Save