feat: Only dequeue request if actually earlier

main
Sean McBride 4 years ago
parent e3261244ee
commit 587e2ab354

@ -1,15 +1,19 @@
#pragma once #pragma once
#include <stdint.h>
#include "sandbox_request.h" #include "sandbox_request.h"
/* Returns pointer back if successful, null otherwise */ /* Returns pointer back if successful, null otherwise */
typedef struct sandbox_request *(*global_request_scheduler_add_fn_t)(void *); typedef struct sandbox_request *(*global_request_scheduler_add_fn_t)(void *);
typedef int (*global_request_scheduler_remove_fn_t)(struct sandbox_request **); typedef int (*global_request_scheduler_remove_fn_t)(struct sandbox_request **);
typedef int (*global_request_scheduler_remove_if_earlier_fn_t)(struct sandbox_request **, uint64_t);
typedef uint64_t (*global_request_scheduler_peek_fn_t)(void); typedef uint64_t (*global_request_scheduler_peek_fn_t)(void);
struct global_request_scheduler_config { struct global_request_scheduler_config {
global_request_scheduler_add_fn_t add_fn; global_request_scheduler_add_fn_t add_fn;
global_request_scheduler_remove_fn_t remove_fn; global_request_scheduler_remove_fn_t remove_fn;
global_request_scheduler_remove_if_earlier_fn_t remove_if_earlier_fn;
global_request_scheduler_peek_fn_t peek_fn; global_request_scheduler_peek_fn_t peek_fn;
}; };
@ -17,4 +21,5 @@ struct global_request_scheduler_config {
void global_request_scheduler_initialize(struct global_request_scheduler_config *config); void global_request_scheduler_initialize(struct global_request_scheduler_config *config);
struct sandbox_request *global_request_scheduler_add(struct sandbox_request *); struct sandbox_request *global_request_scheduler_add(struct sandbox_request *);
int global_request_scheduler_remove(struct sandbox_request **); int global_request_scheduler_remove(struct sandbox_request **);
int global_request_scheduler_remove_if_earlier(struct sandbox_request **, uint64_t targed_deadline);
uint64_t global_request_scheduler_peek(); uint64_t global_request_scheduler_peek();

@ -40,6 +40,7 @@ priority_queue_is_empty(struct priority_queue *self)
void priority_queue_initialize(struct priority_queue *self, priority_queue_get_priority_fn_t get_priority_fn); void priority_queue_initialize(struct priority_queue *self, priority_queue_get_priority_fn_t get_priority_fn);
int priority_queue_enqueue(struct priority_queue *self, void *value); int priority_queue_enqueue(struct priority_queue *self, void *value);
int priority_queue_dequeue(struct priority_queue *self, void **dequeued_element); int priority_queue_dequeue(struct priority_queue *self, void **dequeued_element);
int priority_queue_dequeue_if_earlier(struct priority_queue *self, void **dequeued_element, uint64_t target_deadline);
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); uint64_t priority_queue_peek(struct priority_queue *self);
int priority_queue_delete(struct priority_queue *self, void *value); int priority_queue_delete(struct priority_queue *self, void *value);

@ -61,6 +61,20 @@ global_request_scheduler_remove(struct sandbox_request **removed_sandbox)
return global_request_scheduler.remove_fn(removed_sandbox); return global_request_scheduler.remove_fn(removed_sandbox);
} }
/**
* Removes a sandbox request according to the scheduling policy of the variant
* @param removed_sandbox where to write the adddress of the removed sandbox
* @param target_deadline the deadline that must be validated before dequeuing
* @returns 0 if successfully returned a sandbox request, -ENOENT if empty or if no element meets target_deadline,
* -EAGAIN if atomic operation unsuccessful
*/
int
global_request_scheduler_remove_if_earlier(struct sandbox_request **removed_sandbox, uint64_t target_deadline)
{
assert(removed_sandbox != NULL);
return global_request_scheduler.remove_if_earlier_fn(removed_sandbox, target_deadline);
}
/** /**
* Peeks at the priority of the highest priority sandbox request * Peeks at the priority of the highest priority sandbox request
* @returns highest priority * @returns highest priority

@ -36,6 +36,14 @@ global_request_scheduler_deque_remove(struct sandbox_request **removed_sandbox_r
return deque_steal_sandbox(global_request_scheduler_deque, removed_sandbox_request); return deque_steal_sandbox(global_request_scheduler_deque, removed_sandbox_request);
} }
static int
global_request_scheduler_deque_remove_if_earlier(struct sandbox_request **removed_sandbox_request,
uint64_t target_deadline)
{
panic("Deque variant does not support this call\n");
return -1;
}
void void
global_request_scheduler_deque_initialize() global_request_scheduler_deque_initialize()
{ {
@ -46,8 +54,11 @@ global_request_scheduler_deque_initialize()
deque_init_sandbox(global_request_scheduler_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 */ /* Register Function Pointers for Abstract Scheduling API */
struct global_request_scheduler_config config = { .add_fn = global_request_scheduler_deque_add, struct global_request_scheduler_config config = {
.remove_fn = global_request_scheduler_deque_remove }; .add_fn = global_request_scheduler_deque_add,
.remove_fn = global_request_scheduler_deque_remove,
.remove_if_earlier_fn = global_request_scheduler_deque_remove_if_earlier
};
global_request_scheduler_initialize(&config); global_request_scheduler_initialize(&config);
} }

@ -37,6 +37,20 @@ global_request_scheduler_minheap_remove(struct sandbox_request **removed_sandbox
return priority_queue_dequeue(&global_request_scheduler_minheap, (void **)removed_sandbox_request); return priority_queue_dequeue(&global_request_scheduler_minheap, (void **)removed_sandbox_request);
} }
/**
* @param removed_sandbox_request pointer to set to removed sandbox request
* @param target_deadline the deadline that the request must be earlier than to dequeue
* @returns 0 if successful, -ENOENT if empty or if request isn't earlier than target_deadline
*/
int
global_request_scheduler_minheap_remove_if_earlier(struct sandbox_request **removed_sandbox_request,
uint64_t target_deadline)
{
assert(!software_interrupt_is_enabled());
return priority_queue_dequeue_if_earlier(&global_request_scheduler_minheap, (void **)removed_sandbox_request,
target_deadline);
}
/** /**
* Peek at the priority of the highest priority task without having to take the lock * Peek at the priority of the highest priority task without having to take the lock
* Because this is a min-heap PQ, the highest priority is the lowest 64-bit integer * Because this is a min-heap PQ, the highest priority is the lowest 64-bit integer
@ -65,9 +79,12 @@ global_request_scheduler_minheap_initialize()
{ {
priority_queue_initialize(&global_request_scheduler_minheap, sandbox_request_get_priority_fn); 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, struct global_request_scheduler_config config = {
.add_fn = global_request_scheduler_minheap_add,
.remove_fn = global_request_scheduler_minheap_remove, .remove_fn = global_request_scheduler_minheap_remove,
.peek_fn = global_request_scheduler_minheap_peek }; .remove_if_earlier_fn = global_request_scheduler_minheap_remove_if_earlier,
.peek_fn = global_request_scheduler_minheap_peek
};
global_request_scheduler_initialize(&config); global_request_scheduler_initialize(&config);
} }

@ -142,10 +142,17 @@ local_runqueue_minheap_preempt(ucontext_t *user_context)
current_sandbox->request_arrival_timestamp, local_deadline, global_deadline); current_sandbox->request_arrival_timestamp, local_deadline, global_deadline);
#endif #endif
int return_code = global_request_scheduler_remove(&sandbox_request); int return_code = global_request_scheduler_remove_if_earlier(&sandbox_request, local_deadline);
/* If we were unable to get a sandbox_request, exit */ /* If we were unable to get a sandbox_request, exit */
if (return_code != 0) goto done; if (return_code != 0) {
#ifdef LOG_PREEMPTION
debuglog("Preemption aborted. Another thread took the request\n");
#endif
goto done;
}
assert(sandbox_request->absolute_deadline < local_deadline);
#ifdef LOG_PREEMPTION #ifdef LOG_PREEMPTION
debuglog("Preempted %lu for %lu\n", local_deadline, sandbox_request->absolute_deadline); debuglog("Preempted %lu for %lu\n", local_deadline, sandbox_request->absolute_deadline);

@ -244,6 +244,18 @@ priority_queue_delete(struct priority_queue *self, void *value)
*/ */
int int
priority_queue_dequeue(struct priority_queue *self, void **dequeued_element) priority_queue_dequeue(struct priority_queue *self, void **dequeued_element)
{
return priority_queue_dequeue_if_earlier(self, dequeued_element, UINT64_MAX);
}
/**
* @param self - the priority queue we want to add to
* @param dequeued_element a pointer to set to the dequeued element
* @param target_deadline the deadline that the request must be earlier than in order to dequeue
* @returns RC 0 if successfully set dequeued_element, -ENOENT if empty or if none meet target_deadline
*/
int
priority_queue_dequeue_if_earlier(struct priority_queue *self, void **dequeued_element, uint64_t target_deadline)
{ {
assert(self != NULL); assert(self != NULL);
assert(dequeued_element != NULL); assert(dequeued_element != NULL);
@ -253,7 +265,8 @@ priority_queue_dequeue(struct priority_queue *self, void **dequeued_element)
LOCK_LOCK(&self->lock); LOCK_LOCK(&self->lock);
if (priority_queue_is_empty_locked(self)) goto err_enoent; /* If the dequeue is not higher priority (earlier timestamp) than targed_deadline, return immediately */
if (priority_queue_is_empty_locked(self) || self->highest_priority >= target_deadline) goto err_enoent;
*dequeued_element = self->items[1]; *dequeued_element = self->items[1];
self->items[1] = self->items[--self->first_free]; self->items[1] = self->items[--self->first_free];

Loading…
Cancel
Save