fix: correct runqueue cleanup bug

main
Sean McBride 5 years ago
parent 83ee42e89b
commit 996c147928

@ -13,12 +13,12 @@
* @param element
* @returns priority (a u64)
**/
typedef unsigned long long int (*priority_queue_get_priority_t)(void *element);
typedef uint64_t (*priority_queue_get_priority_t)(void *element);
// We assume that priority is expressed in terms of a 64 bit unsigned integral
struct priority_queue {
ck_spinlock_fas_t lock;
unsigned long long int highest_priority;
uint64_t highest_priority;
void * items[MAX];
int first_free;
priority_queue_get_priority_t get_priority;
@ -26,7 +26,9 @@ struct priority_queue {
void priority_queue_initialize(struct priority_queue *self, priority_queue_get_priority_t get_priority);
int priority_queue_enqueue(struct priority_queue *self, void *value);
void *priority_queue_dequeue(struct priority_queue *self);
void * priority_queue_dequeue(struct priority_queue *self);
int priority_queue_length(struct priority_queue *self);
uint64_t priority_queue_peek(struct priority_queue *self);
int priority_queue_delete(struct priority_queue *self, void *value);
#endif /* PRIORITY_QUEUE_H */

@ -6,10 +6,12 @@
// Returns pointer back if successful, null otherwise
typedef sandbox_request_t *(*sandbox_request_scheduler_add_t)(void *);
typedef sandbox_request_t *(*sandbox_request_scheduler_remove_t)(void);
typedef uint64_t (*sandbox_request_scheduler_peek_t)(void);
typedef struct sandbox_request_scheduler_config_t {
sandbox_request_scheduler_add_t add;
sandbox_request_scheduler_remove_t remove;
sandbox_request_scheduler_peek_t peek;
} sandbox_request_scheduler_config_t;
@ -17,5 +19,6 @@ void sandbox_request_scheduler_initialize(sandbox_request_scheduler_config_t *co
sandbox_request_t *sandbox_request_scheduler_add(sandbox_request_t *);
sandbox_request_t *sandbox_request_scheduler_remove();
uint64_t sandbox_request_scheduler_peek();
#endif /* SFRT_SANDBOX_REQUEST_QUEUE_H */

@ -8,17 +8,20 @@
typedef struct sandbox *(*sandbox_run_queue_add_t)(struct sandbox *);
typedef struct sandbox *(*sandbox_run_queue_remove_t)(void);
typedef bool (*sandbox_run_queue_is_empty_t)(void);
typedef void (*sandbox_run_queue_delete_t)(struct sandbox *sandbox);
typedef struct sandbox_run_queue_config_t {
sandbox_run_queue_add_t add;
sandbox_run_queue_is_empty_t is_empty;
sandbox_run_queue_remove_t remove;
sandbox_run_queue_delete_t delete;
} sandbox_run_queue_config_t;
void sandbox_run_queue_initialize(sandbox_run_queue_config_t *config);
struct sandbox *sandbox_run_queue_add(struct sandbox *);
void sandbox_run_queue_delete(struct sandbox *);
struct sandbox *sandbox_run_queue_remove();
bool sandbox_run_queue_is_empty();

@ -1,8 +1,8 @@
#ifndef SFRT_SANDBOX_RUN_QUEUE_FIFO_H
#define SFRT_SANDBOX_RUN_QUEUE_FIFO_H
#ifndef SFRT_SANDBOX_RUN_QUEUE_PS_H
#define SFRT_SANDBOX_RUN_QUEUE_PS_H
#include "sandbox.h"
void sandbox_run_queue_ps_initialize();
#endif /* SFRT_SANDBOX_RUN_QUEUE_FIFO_H */
#endif /* SFRT_SANDBOX_RUN_QUEUE_PS_H */

@ -82,12 +82,11 @@ priority_queue_find_smallest_child(struct priority_queue *self, int parent_index
* @param self the priority queue
*/
static inline void
priority_queue_percolate_down(struct priority_queue *self)
priority_queue_percolate_down(struct priority_queue *self, int parent_index)
{
assert(self != NULL);
assert(self->get_priority != NULL);
int parent_index = 1;
int left_child_index = 2 * parent_index;
while (left_child_index >= 2 && left_child_index < self->first_free) {
int smallest_child_index = priority_queue_find_smallest_child(self, parent_index);
@ -173,6 +172,31 @@ priority_queue_enqueue(struct priority_queue *self, void *value)
ck_spinlock_fas_unlock(&self->lock);
return rc;
}
/**
* @param self - the priority queue we want to delete from
* @param value - the value we want to delete
* @returns 0 on success. -1 on not found. -2 on unable to take lock
**/
int
priority_queue_delete(struct priority_queue *self, void *value)
{
assert(self != NULL);
if (ck_spinlock_fas_trylock(&self->lock) == false) return -2;
bool did_delete = false;
for (int i = 1; i < self->first_free; i++) {
if (self->items[i] == value) {
self->items[i] = self->items[self->first_free - 1];
self->items[self->first_free - 1] = NULL;
self->first_free--;
priority_queue_percolate_down(self, i);
did_delete = true;
}
}
ck_spinlock_fas_unlock(&self->lock);
if (!did_delete) return -1;
return 0;
}
static bool
priority_queue_is_empty(struct priority_queue *self)
@ -201,7 +225,7 @@ priority_queue_dequeue(struct priority_queue *self)
self->items[self->first_free - 1] = NULL;
self->first_free--;
// Because of 1-based indices, first_free is 2 when there is only one element
if (self->first_free > 2) priority_queue_percolate_down(self);
if (self->first_free > 2) priority_queue_percolate_down(self, 1);
// Update the highest priority
self->highest_priority = !priority_queue_is_empty(self) ? self->get_priority(self->items[1])
@ -211,3 +235,9 @@ priority_queue_dequeue(struct priority_queue *self)
// End of Critical Section
return min;
}
uint64_t
priority_queue_peek(struct priority_queue *self)
{
return self->highest_priority;
}

@ -18,7 +18,7 @@
#include <http_parser_settings.h>
#include <module.h>
#include <sandbox_request.h>
// #include <sandbox_request_scheduler_fifo.h>
#include <sandbox_request_scheduler_fifo.h>
#include <sandbox_request_scheduler_ps.h>
#include <software_interrupt.h>
#include <types.h>

@ -27,7 +27,17 @@ sandbox_request_scheduler_ps_remove(void)
return (sandbox_request_t *)priority_queue_dequeue(&sandbox_request_scheduler_ps);
}
unsigned long long int
/**
*
* @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(void *element)
{
sandbox_request_t *sandbox_request = (sandbox_request_t *)element;
@ -46,7 +56,8 @@ sandbox_request_scheduler_ps_initialize()
// Register Function Pointers for Abstract Scheduling API
sandbox_request_scheduler_config_t config = { .add = sandbox_request_scheduler_ps_add,
.remove = sandbox_request_scheduler_ps_remove };
.remove = sandbox_request_scheduler_ps_remove,
.peek = sandbox_request_scheduler_ps_peek };
sandbox_request_scheduler_initialize(&config);
}

@ -18,6 +18,13 @@ sandbox_run_queue_add(struct sandbox *sandbox)
return sandbox_run_queue.add(sandbox);
}
void
sandbox_run_queue_delete(struct sandbox *sandbox)
{
assert(sandbox_run_queue.delete != NULL);
sandbox_run_queue.delete(sandbox);
}
// Removes a sandbox request
struct sandbox *
sandbox_run_queue_remove()

@ -54,7 +54,8 @@ sandbox_run_queue_fifo_initialize()
// 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,
.remove = sandbox_run_queue_fifo_remove_and_return };
.remove = sandbox_run_queue_fifo_remove_and_return,
.delete = sandbox_run_queue_fifo_remove };
sandbox_run_queue_initialize(&config);
}

@ -34,7 +34,19 @@ sandbox_run_queue_ps_remove(void)
return (struct sandbox *)priority_queue_dequeue(&sandbox_run_queue_ps);
}
unsigned long long int
/**
*
* @returns A Sandbox Request or NULL
**/
static void
sandbox_run_queue_ps_delete(struct sandbox *sandbox)
{
assert(sandbox != NULL);
int rc = priority_queue_delete(&sandbox_run_queue_ps, sandbox);
assert(rc != -2);
}
uint64_t
sandbox_get_priority(void *element)
{
struct sandbox *sandbox = (struct sandbox *)element;
@ -50,7 +62,8 @@ sandbox_run_queue_ps_initialize()
// 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,
.remove = sandbox_run_queue_ps_remove };
.remove = sandbox_run_queue_ps_remove,
.delete = sandbox_run_queue_ps_delete };
sandbox_run_queue_initialize(&config);
}

@ -18,7 +18,7 @@
#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_fifo.h>
#include <sandbox_run_queue_ps.h>
#include <types.h>
#include <worker_thread.h>
@ -102,7 +102,7 @@ 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_remove(previous_sandbox);
sandbox_run_queue_delete(previous_sandbox);
previous_sandbox->state = BLOCKED;
// Switch to the next sandbox
@ -269,14 +269,14 @@ worker_thread_exit_current_sandbox(void)
struct sandbox *previous_sandbox = current_sandbox_get();
assert(previous_sandbox);
software_interrupt_disable();
sandbox_run_queue_remove(previous_sandbox);
sandbox_run_queue_delete(previous_sandbox);
previous_sandbox->state = RETURNED;
struct sandbox *next_sandbox = worker_thread_get_next_sandbox();
assert(next_sandbox != previous_sandbox);
software_interrupt_enable();
// Because the stack is still in use, only unmap linear memory and defer free resources until "main function
// execution"
// Because the stack is still in use, only unmap linear memory and defer free resources until "main
// function execution"
munmap(previous_sandbox->linear_memory_start, SBOX_MAX_MEM + PAGE_SIZE);
worker_thread_switch_to_sandbox(next_sandbox);
}

Loading…
Cancel
Save