diff options
Diffstat (limited to 'quantum/deferred_exec.c')
| -rw-r--r-- | quantum/deferred_exec.c | 93 | 
1 files changed, 56 insertions, 37 deletions
| diff --git a/quantum/deferred_exec.c b/quantum/deferred_exec.c index 5b0a5b1425..a0046a9648 100644 --- a/quantum/deferred_exec.c +++ b/quantum/deferred_exec.c @@ -9,32 +9,27 @@  #    define MAX_DEFERRED_EXECUTORS 8  #endif -typedef struct deferred_executor_t { -    deferred_token         token; -    uint32_t               trigger_time; -    deferred_exec_callback callback; -    void *                 cb_arg; -} deferred_executor_t; - -static deferred_token      current_token                     = 0; -static uint32_t            last_deferred_exec_check          = 0; -static deferred_executor_t executors[MAX_DEFERRED_EXECUTORS] = {0}; - -static inline bool token_can_be_used(deferred_token token) { +//------------------------------------ +// Helpers +// + +static deferred_token current_token = 0; + +static inline bool token_can_be_used(deferred_executor_t *table, size_t table_count, deferred_token token) {      if (token == INVALID_DEFERRED_TOKEN) {          return false;      } -    for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) { -        if (executors[i].token == token) { +    for (int i = 0; i < table_count; ++i) { +        if (table[i].token == token) {              return false;          }      }      return true;  } -static inline deferred_token allocate_token(void) { +static inline deferred_token allocate_token(deferred_executor_t *table, size_t table_count) {      deferred_token first = ++current_token; -    while (!token_can_be_used(current_token)) { +    while (!token_can_be_used(table, table_count, current_token)) {          ++current_token;          if (current_token == first) {              // If we've looped back around to the first, everything is already allocated (yikes!). Need to exit with a failure. @@ -44,18 +39,22 @@ static inline deferred_token allocate_token(void) {      return current_token;  } -deferred_token defer_exec(uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg) { -    // Ignore queueing if it's a zero-time delay, or invalid callback -    if (delay_ms == 0 || !callback) { +//------------------------------------ +// Advanced API: used when a custom-allocated table is used, primarily for core code. +// + +deferred_token defer_exec_advanced(deferred_executor_t *table, size_t table_count, uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg) { +    // Ignore queueing if the table isn't valid, it's a zero-time delay, or the token is not valid +    if (!table || table_count == 0 || delay_ms == 0 || !callback) {          return INVALID_DEFERRED_TOKEN;      }      // Find an unused slot and claim it -    for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) { -        deferred_executor_t *entry = &executors[i]; +    for (int i = 0; i < table_count; ++i) { +        deferred_executor_t *entry = &table[i];          if (entry->token == INVALID_DEFERRED_TOKEN) {              // Work out the new token value, dropping out if none were available -            deferred_token token = allocate_token(); +            deferred_token token = allocate_token(table, table_count);              if (token == INVALID_DEFERRED_TOKEN) {                  return false;              } @@ -73,15 +72,15 @@ deferred_token defer_exec(uint32_t delay_ms, deferred_exec_callback callback, vo      return INVALID_DEFERRED_TOKEN;  } -bool extend_deferred_exec(deferred_token token, uint32_t delay_ms) { -    // Ignore queueing if it's a zero-time delay, or the token is not valid -    if (delay_ms == 0 || token == INVALID_DEFERRED_TOKEN) { +bool extend_deferred_exec_advanced(deferred_executor_t *table, size_t table_count, deferred_token token, uint32_t delay_ms) { +    // Ignore queueing if the table isn't valid, it's a zero-time delay, or the token is not valid +    if (!table || table_count == 0 || delay_ms == 0 || token == INVALID_DEFERRED_TOKEN) {          return false;      }      // Find the entry corresponding to the token -    for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) { -        deferred_executor_t *entry = &executors[i]; +    for (int i = 0; i < table_count; ++i) { +        deferred_executor_t *entry = &table[i];          if (entry->token == token) {              // Found it, extend the delay              entry->trigger_time = timer_read32() + delay_ms; @@ -93,15 +92,15 @@ bool extend_deferred_exec(deferred_token token, uint32_t delay_ms) {      return false;  } -bool cancel_deferred_exec(deferred_token token) { -    // Ignore request if the token is not valid -    if (token == INVALID_DEFERRED_TOKEN) { +bool cancel_deferred_exec_advanced(deferred_executor_t *table, size_t table_count, deferred_token token) { +    // Ignore request if the table/token are not valid +    if (!table || table_count == 0 || token == INVALID_DEFERRED_TOKEN) {          return false;      }      // Find the entry corresponding to the token -    for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) { -        deferred_executor_t *entry = &executors[i]; +    for (int i = 0; i < table_count; ++i) { +        deferred_executor_t *entry = &table[i];          if (entry->token == token) {              // Found it, cancel and clear the table entry              entry->token        = INVALID_DEFERRED_TOKEN; @@ -116,16 +115,16 @@ bool cancel_deferred_exec(deferred_token token) {      return false;  } -void deferred_exec_task(void) { +void deferred_exec_advanced_task(deferred_executor_t *table, size_t table_count, uint32_t *last_execution_time) {      uint32_t now = timer_read32();      // Throttle only once per millisecond -    if (((int32_t)TIMER_DIFF_32(now, last_deferred_exec_check)) > 0) { -        last_deferred_exec_check = now; +    if (((int32_t)TIMER_DIFF_32(now, (*last_execution_time))) > 0) { +        *last_execution_time = now;          // Run through each of the executors -        for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) { -            deferred_executor_t *entry = &executors[i]; +        for (int i = 0; i < table_count; ++i) { +            deferred_executor_t *entry = &table[i];              // Check if we're supposed to execute this entry              if (entry->token != INVALID_DEFERRED_TOKEN && ((int32_t)TIMER_DIFF_32(entry->trigger_time, now)) <= 0) { @@ -150,3 +149,23 @@ void deferred_exec_task(void) {          }      }  } + +//------------------------------------ +// Basic API: used by user-mode code, guaranteed to not collide with core deferred execution +// + +static uint32_t            last_deferred_exec_check                = 0; +static deferred_executor_t basic_executors[MAX_DEFERRED_EXECUTORS] = {0}; + +deferred_token defer_exec(uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg) { +    return defer_exec_advanced(basic_executors, MAX_DEFERRED_EXECUTORS, delay_ms, callback, cb_arg); +} +bool extend_deferred_exec(deferred_token token, uint32_t delay_ms) { +    return extend_deferred_exec_advanced(basic_executors, MAX_DEFERRED_EXECUTORS, token, delay_ms); +} +bool cancel_deferred_exec(deferred_token token) { +    return cancel_deferred_exec_advanced(basic_executors, MAX_DEFERRED_EXECUTORS, token); +} +void deferred_exec_task(void) { +    deferred_exec_advanced_task(basic_executors, MAX_DEFERRED_EXECUTORS, &last_deferred_exec_check); +} | 
