fix: correct runqueue cleanup bug

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

@ -13,20 +13,22 @@
* @param element * @param element
* @returns priority (a u64) * @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 // We assume that priority is expressed in terms of a 64 bit unsigned integral
struct priority_queue { struct priority_queue {
ck_spinlock_fas_t lock; ck_spinlock_fas_t lock;
unsigned long long int highest_priority; uint64_t highest_priority;
void * items[MAX]; void * items[MAX];
int first_free; int first_free;
priority_queue_get_priority_t get_priority; priority_queue_get_priority_t get_priority;
}; };
void priority_queue_initialize(struct priority_queue *self, priority_queue_get_priority_t get_priority); 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); 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); 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 */ #endif /* PRIORITY_QUEUE_H */

@ -6,10 +6,12 @@
// Returns pointer back if successful, null otherwise // Returns pointer back if successful, null otherwise
typedef sandbox_request_t *(*sandbox_request_scheduler_add_t)(void *); typedef sandbox_request_t *(*sandbox_request_scheduler_add_t)(void *);
typedef sandbox_request_t *(*sandbox_request_scheduler_remove_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 { typedef struct sandbox_request_scheduler_config_t {
sandbox_request_scheduler_add_t add; sandbox_request_scheduler_add_t add;
sandbox_request_scheduler_remove_t remove; sandbox_request_scheduler_remove_t remove;
sandbox_request_scheduler_peek_t peek;
} sandbox_request_scheduler_config_t; } 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_add(sandbox_request_t *);
sandbox_request_t *sandbox_request_scheduler_remove(); sandbox_request_t *sandbox_request_scheduler_remove();
uint64_t sandbox_request_scheduler_peek();
#endif /* SFRT_SANDBOX_REQUEST_QUEUE_H */ #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_add_t)(struct sandbox *);
typedef struct sandbox *(*sandbox_run_queue_remove_t)(void); typedef struct sandbox *(*sandbox_run_queue_remove_t)(void);
typedef bool (*sandbox_run_queue_is_empty_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 { typedef struct sandbox_run_queue_config_t {
sandbox_run_queue_add_t add; sandbox_run_queue_add_t add;
sandbox_run_queue_is_empty_t is_empty; sandbox_run_queue_is_empty_t is_empty;
sandbox_run_queue_remove_t remove; sandbox_run_queue_remove_t remove;
sandbox_run_queue_delete_t delete;
} sandbox_run_queue_config_t; } sandbox_run_queue_config_t;
void sandbox_run_queue_initialize(sandbox_run_queue_config_t *config); void sandbox_run_queue_initialize(sandbox_run_queue_config_t *config);
struct sandbox *sandbox_run_queue_add(struct sandbox *); struct sandbox *sandbox_run_queue_add(struct sandbox *);
void sandbox_run_queue_delete(struct sandbox *);
struct sandbox *sandbox_run_queue_remove(); struct sandbox *sandbox_run_queue_remove();
bool sandbox_run_queue_is_empty(); bool sandbox_run_queue_is_empty();

@ -1,8 +1,8 @@
#ifndef SFRT_SANDBOX_RUN_QUEUE_FIFO_H #ifndef SFRT_SANDBOX_RUN_QUEUE_PS_H
#define SFRT_SANDBOX_RUN_QUEUE_FIFO_H #define SFRT_SANDBOX_RUN_QUEUE_PS_H
#include "sandbox.h" #include "sandbox.h"
void sandbox_run_queue_ps_initialize(); 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 * @param self the priority queue
*/ */
static inline void 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 != NULL);
assert(self->get_priority != NULL); assert(self->get_priority != NULL);
int parent_index = 1;
int left_child_index = 2 * parent_index; int left_child_index = 2 * parent_index;
while (left_child_index >= 2 && left_child_index < self->first_free) { while (left_child_index >= 2 && left_child_index < self->first_free) {
int smallest_child_index = priority_queue_find_smallest_child(self, parent_index); 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); ck_spinlock_fas_unlock(&self->lock);
return rc; 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 static bool
priority_queue_is_empty(struct priority_queue *self) 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->items[self->first_free - 1] = NULL;
self->first_free--; self->first_free--;
// Because of 1-based indices, first_free is 2 when there is only one element // 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 // Update the highest priority
self->highest_priority = !priority_queue_is_empty(self) ? self->get_priority(self->items[1]) 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 // End of Critical Section
return min; 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 <http_parser_settings.h>
#include <module.h> #include <module.h>
#include <sandbox_request.h> #include <sandbox_request.h>
// #include <sandbox_request_scheduler_fifo.h> #include <sandbox_request_scheduler_fifo.h>
#include <sandbox_request_scheduler_ps.h> #include <sandbox_request_scheduler_ps.h>
#include <software_interrupt.h> #include <software_interrupt.h>
#include <types.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); 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_get_priority(void *element)
{ {
sandbox_request_t *sandbox_request = (sandbox_request_t *)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 // Register Function Pointers for Abstract Scheduling API
sandbox_request_scheduler_config_t config = { .add = sandbox_request_scheduler_ps_add, 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); sandbox_request_scheduler_initialize(&config);
} }

@ -18,6 +18,13 @@ sandbox_run_queue_add(struct sandbox *sandbox)
return sandbox_run_queue.add(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 // Removes a sandbox request
struct sandbox * struct sandbox *
sandbox_run_queue_remove() sandbox_run_queue_remove()

@ -54,7 +54,8 @@ sandbox_run_queue_fifo_initialize()
// Register Function Pointers for Abstract Scheduling API // Register Function Pointers for Abstract Scheduling API
sandbox_run_queue_config_t config = { .add = sandbox_run_queue_fifo_append, sandbox_run_queue_config_t config = { .add = sandbox_run_queue_fifo_append,
.is_empty = sandbox_run_queue_fifo_is_empty, .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); 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); 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) sandbox_get_priority(void *element)
{ {
struct sandbox *sandbox = (struct sandbox *)element; struct sandbox *sandbox = (struct sandbox *)element;
@ -50,7 +62,8 @@ sandbox_run_queue_ps_initialize()
// Register Function Pointers for Abstract Scheduling API // Register Function Pointers for Abstract Scheduling API
sandbox_run_queue_config_t config = { .add = sandbox_run_queue_ps_add, sandbox_run_queue_config_t config = { .add = sandbox_run_queue_ps_add,
.is_empty = sandbox_run_queue_ps_is_empty, .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); sandbox_run_queue_initialize(&config);
} }

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

Loading…
Cancel
Save