diff --git a/runtime/include/admissions_control.h b/runtime/include/admissions_control.h index b33e896..b71f13a 100644 --- a/runtime/include/admissions_control.h +++ b/runtime/include/admissions_control.h @@ -1,125 +1,14 @@ #pragma once -#include #include #include -#include - -#include "debuglog.h" -#include "client_socket.h" #define ADMISSIONS_CONTROL_GRANULARITY 1000000 -/* - * Unitless estimate of the instantaneous fraction of system capacity required to complete all previously - * admitted work. This is used to calculate free capacity as part of admissions control - * - * The estimated requirements of a single admitted request is calculated as - * estimated execution time (cycles) / relative deadline (cycles) - * - * These estimates are incremented on request acceptance and decremented on request completion (either - * success or failure) - */ -extern _Atomic uint64_t admissions_control_admitted; -extern uint64_t admissions_control_capacity; -extern const double admissions_control_overhead; - -static inline void -admissions_control_initialize() -{ -#ifdef ADMISSIONS_CONTROL - atomic_init(&admissions_control_admitted, 0); - admissions_control_capacity = runtime_worker_threads_count * ADMISSIONS_CONTROL_GRANULARITY - * ((double)1.0 - admissions_control_overhead); -#endif -} - -static inline void -admissions_control_add(uint64_t admissions_estimate) -{ -#ifdef ADMISSIONS_CONTROL - assert(admissions_estimate > 0); - atomic_fetch_add(&admissions_control_admitted, admissions_estimate); - -#ifdef LOG_ADMISSIONS_CONTROL - debuglog("Runtime Admitted: %lu / %lu\n", admissions_control_admitted, admissions_control_capacity); -#endif - -#endif /* ADMISSIONS_CONTROL */ -} - -static inline void -admissions_control_subtract(uint64_t admissions_estimate) -{ -#ifdef ADMISSIONS_CONTROL - /* Assumption: Should never underflow */ - if (unlikely(admissions_estimate > admissions_control_admitted)) panic("Admissions Estimate underflow\n"); - - atomic_fetch_sub(&admissions_control_admitted, admissions_estimate); - -#ifdef LOG_ADMISSIONS_CONTROL - debuglog("Runtime Admitted: %lu / %lu\n", admissions_control_admitted, admissions_control_capacity); -#endif - -#endif /* ADMISSIONS_CONTROL */ -} - - -static inline uint64_t -admissions_control_calculate_estimate(uint64_t estimated_execution, uint64_t relative_deadline) -{ -#ifdef ADMISSIONS_CONTROL - assert(relative_deadline != 0); - uint64_t admissions_estimate = (estimated_execution * (uint64_t)ADMISSIONS_CONTROL_GRANULARITY) - / relative_deadline; - if (admissions_estimate == 0) - panic("Ratio of Deadline to Execution time cannot exceed %d\n", ADMISSIONS_CONTROL_GRANULARITY); - - return admissions_estimate; -#else - return 0; -#endif -} - -static inline uint64_t -admissions_control_calculate_estimate_us(uint32_t estimated_execution_us, uint32_t relative_deadline_us) -{ -#ifdef ADMISSIONS_CONTROL - assert(relative_deadline_us != 0); - return (uint64_t)((uint64_t)(estimated_execution_us * ADMISSIONS_CONTROL_GRANULARITY)) / relative_deadline_us; -#else - return 0; -#endif -} - -static inline void -admissions_control_log_decision(uint64_t admissions_estimate, bool admitted) -{ -#ifdef LOG_ADMISSIONS_CONTROL - debuglog("Admitted: %lu, Capacity: %lu, Estimate: %lu, Admitted? %s\n", admissions_control_admitted, - admissions_control_capacity, admissions_estimate, admitted ? "yes" : "no"); -#endif /* LOG_ADMISSIONS_CONTROL */ -} - -static inline uint64_t -admissions_control_decide(uint64_t admissions_estimate) -{ - uint64_t work_admitted = 1; /* Nominal non-zero value in case admissions control is disabled */ - -#ifdef ADMISSIONS_CONTROL - if (unlikely(admissions_estimate == 0)) panic("Admissions estimate should never be zero"); - - uint64_t total_admitted = atomic_load(&admissions_control_admitted); - - if (total_admitted + admissions_estimate >= admissions_control_capacity) { - admissions_control_log_decision(admissions_estimate, false); - work_admitted = 0; - } else { - admissions_control_log_decision(admissions_estimate, true); - admissions_control_add(admissions_estimate); - work_admitted = admissions_estimate; - } -#endif /* ADMISSIONS_CONTROL */ - - return work_admitted; -} +void admissions_control_initialize(); +void admissions_control_add(uint64_t admissions_estimate); +void admissions_control_subtract(uint64_t admissions_estimate); +uint64_t admissions_control_calculate_estimate(uint64_t estimated_execution, uint64_t relative_deadline); +uint64_t admissions_control_calculate_estimate_us(uint32_t estimated_execution_us, uint32_t relative_deadline_us); +void admissions_control_log_decision(uint64_t admissions_estimate, bool admitted); +uint64_t admissions_control_decide(uint64_t admissions_estimate); diff --git a/runtime/src/admissions_control.c b/runtime/src/admissions_control.c index 275bee3..90f9705 100644 --- a/runtime/src/admissions_control.c +++ b/runtime/src/admissions_control.c @@ -1,6 +1,120 @@ +#include +#include + #include "admissions_control.h" +#include "debuglog.h" +#include "client_socket.h" +/* + * Unitless estimate of the instantaneous fraction of system capacity required to complete all previously + * admitted work. This is used to calculate free capacity as part of admissions control + * + * The estimated requirements of a single admitted request is calculated as + * estimated execution time (cycles) / relative deadline (cycles) + * + * These estimates are incremented on request acceptance and decremented on request completion (either + * success or failure) + */ _Atomic uint64_t admissions_control_admitted; uint64_t admissions_control_capacity; const double admissions_control_overhead = 0.2; + +void +admissions_control_initialize() +{ +#ifdef ADMISSIONS_CONTROL + atomic_init(&admissions_control_admitted, 0); + admissions_control_capacity = runtime_worker_threads_count * ADMISSIONS_CONTROL_GRANULARITY + * ((double)1.0 - admissions_control_overhead); +#endif +} + +void +admissions_control_add(uint64_t admissions_estimate) +{ +#ifdef ADMISSIONS_CONTROL + assert(admissions_estimate > 0); + atomic_fetch_add(&admissions_control_admitted, admissions_estimate); + +#ifdef LOG_ADMISSIONS_CONTROL + debuglog("Runtime Admitted: %lu / %lu\n", admissions_control_admitted, admissions_control_capacity); +#endif + +#endif /* ADMISSIONS_CONTROL */ +} + +void +admissions_control_subtract(uint64_t admissions_estimate) +{ +#ifdef ADMISSIONS_CONTROL + /* Assumption: Should never underflow */ + if (unlikely(admissions_estimate > admissions_control_admitted)) panic("Admissions Estimate underflow\n"); + + atomic_fetch_sub(&admissions_control_admitted, admissions_estimate); + +#ifdef LOG_ADMISSIONS_CONTROL + debuglog("Runtime Admitted: %lu / %lu\n", admissions_control_admitted, admissions_control_capacity); +#endif + +#endif /* ADMISSIONS_CONTROL */ +} + +uint64_t +admissions_control_calculate_estimate(uint64_t estimated_execution, uint64_t relative_deadline) +{ +#ifdef ADMISSIONS_CONTROL + assert(relative_deadline != 0); + uint64_t admissions_estimate = (estimated_execution * (uint64_t)ADMISSIONS_CONTROL_GRANULARITY) + / relative_deadline; + if (admissions_estimate == 0) + panic("Ratio of Deadline to Execution time cannot exceed %d\n", ADMISSIONS_CONTROL_GRANULARITY); + + return admissions_estimate; +#else + return 0; +#endif +} + +uint64_t +admissions_control_calculate_estimate_us(uint32_t estimated_execution_us, uint32_t relative_deadline_us) +{ +#ifdef ADMISSIONS_CONTROL + assert(relative_deadline_us != 0); + return (uint64_t)((uint64_t)(estimated_execution_us * ADMISSIONS_CONTROL_GRANULARITY)) / relative_deadline_us; +#else + return 0; +#endif +} + +void +admissions_control_log_decision(uint64_t admissions_estimate, bool admitted) +{ +#ifdef LOG_ADMISSIONS_CONTROL + debuglog("Admitted: %lu, Capacity: %lu, Estimate: %lu, Admitted? %s\n", admissions_control_admitted, + admissions_control_capacity, admissions_estimate, admitted ? "yes" : "no"); +#endif /* LOG_ADMISSIONS_CONTROL */ +} + +uint64_t +admissions_control_decide(uint64_t admissions_estimate) +{ + uint64_t work_admitted = 1; /* Nominal non-zero value in case admissions control is disabled */ + +#ifdef ADMISSIONS_CONTROL + if (unlikely(admissions_estimate == 0)) panic("Admissions estimate should never be zero"); + + uint64_t total_admitted = atomic_load(&admissions_control_admitted); + + if (total_admitted + admissions_estimate >= admissions_control_capacity) { + admissions_control_log_decision(admissions_estimate, false); + work_admitted = 0; + } else { + admissions_control_log_decision(admissions_estimate, true); + admissions_control_add(admissions_estimate); + work_admitted = admissions_estimate; + } +#endif /* ADMISSIONS_CONTROL */ + + return work_admitted; +} diff --git a/runtime/src/listener_thread.c b/runtime/src/listener_thread.c index b9bc198..450ec4d 100644 --- a/runtime/src/listener_thread.c +++ b/runtime/src/listener_thread.c @@ -1,6 +1,8 @@ #include +#include #include "arch/getcycles.h" +#include "client_socket.h" #include "global_request_scheduler.h" #include "generic_thread.h" #include "listener_thread.h"