0c402157fc8f586e443468e61ca94ce01a9a0ea4

Author
Nick Brassel <nick@tzarc.org>
Committer
GitHub <noreply@github.com>
Date

Message

Advanced deferred_exec for core-side code. (#15579)

Diff

This diff is truncated to protect this page.

  1diff --git a/quantum/deferred_exec.c b/quantum/deferred_exec.c
  2index 5b0a5b14258b0129d17be9599f49c748cde906ff..a64b451df2d2c691d490c7d0a7d398430daaa83e 100644
  3--- a/quantum/deferred_exec.c
  4+++ b/quantum/deferred_exec.c
  5@@ -9,32 +9,27 @@
  6 #    define MAX_DEFERRED_EXECUTORS 8
  7 #endif
  8 
  9-typedef struct deferred_executor_t {
 10-    deferred_token         token;
 11-    uint32_t               trigger_time;
 12-    deferred_exec_callback callback;
 13-    void *                 cb_arg;
 14-} deferred_executor_t;
 15-
 16-static deferred_token      current_token                     = 0;
 17-static uint32_t            last_deferred_exec_check          = 0;
 18-static deferred_executor_t executors[MAX_DEFERRED_EXECUTORS] = {0};
 19-
 20-static inline bool token_can_be_used(deferred_token token) {
 21+//------------------------------------
 22+// Helpers
 23+//
 24+
 25+static deferred_token current_token = 0;
 26+
 27+static inline bool token_can_be_used(deferred_executor_t *table, size_t table_count, deferred_token token) {
 28     if (token == INVALID_DEFERRED_TOKEN) {
 29         return false;
 30     }
 31-    for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) {
 32-        if (executors[i].token == token) {
 33+    for (int i = 0; i < table_count; ++i) {
 34+        if (table[i].token == token) {
 35             return false;
 36         }
 37     }
 38     return true;
 39 }
 40 
 41-static inline deferred_token allocate_token(void) {
 42+static inline deferred_token allocate_token(deferred_executor_t *table, size_t table_count) {
 43     deferred_token first = ++current_token;
 44-    while (!token_can_be_used(current_token)) {
 45+    while (!token_can_be_used(table, table_count, current_token)) {
 46         ++current_token;
 47         if (current_token == first) {
 48             // If we've looped back around to the first, everything is already allocated (yikes!). Need to exit with a failure.
 49@@ -44,18 +39,22 @@ static inline deferred_token allocate_token(void) {
 50     return current_token;
 51 }
 52 
 53-deferred_token defer_exec(uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg) {
 54-    // Ignore queueing if it's a zero-time delay, or invalid callback
 55-    if (delay_ms == 0 || !callback) {
 56+//------------------------------------
 57+// Advanced API: used when a custom-allocated table is used, primarily for core code.
 58+//
 59+
 60+deferred_token defer_exec_advanced(deferred_executor_t *table, size_t table_count, uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg) {
 61+    // Ignore queueing if the table isn't valid, it's a zero-time delay, or the token is not valid
 62+    if (!table || table_count == 0 || delay_ms == 0 || !callback) {
 63         return INVALID_DEFERRED_TOKEN;
 64     }
 65 
 66     // Find an unused slot and claim it
 67-    for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) {
 68-        deferred_executor_t *entry = &executors[i];
 69+    for (int i = 0; i < table_count; ++i) {
 70+        deferred_executor_t *entry = &table[i];
 71         if (entry->token == INVALID_DEFERRED_TOKEN) {
 72             // Work out the new token value, dropping out if none were available
 73-            deferred_token token = allocate_token();
 74+            deferred_token token = allocate_token(table, table_count);
 75             if (token == INVALID_DEFERRED_TOKEN) {
 76                 return false;
 77             }
 78@@ -73,15 +72,15 @@ deferred_token defer_exec(uint32_t delay_ms, deferred_exec_callback callback, vo
 79     return INVALID_DEFERRED_TOKEN;
 80 }
 81 
 82-bool extend_deferred_exec(deferred_token token, uint32_t delay_ms) {
 83-    // Ignore queueing if it's a zero-time delay, or the token is not valid
 84-    if (delay_ms == 0 || token == INVALID_DEFERRED_TOKEN) {
 85+bool extend_deferred_exec_advanced(deferred_executor_t *table, size_t table_count, deferred_token token, uint32_t delay_ms) {
 86+    // Ignore queueing if the table isn't valid, it's a zero-time delay, or the token is not valid
 87+    if (!table || table_count == 0 || delay_ms == 0 || token == INVALID_DEFERRED_TOKEN) {
 88         return false;
 89     }
 90 
 91     // Find the entry corresponding to the token
 92-    for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) {
 93-        deferred_executor_t *entry = &executors[i];
 94+    for (int i = 0; i < table_count; ++i) {
 95+        deferred_executor_t *entry = &table[i];
 96         if (entry->token == token) {
 97             // Found it, extend the delay
 98             entry->trigger_time = timer_read32() + delay_ms;
 99@@ -93,15 +92,15 @@ bool extend_deferred_exec(deferred_token token, uint32_t delay_ms) {
100     return false;
101 }
102 
103-bool cancel_deferred_exec(deferred_token token) {
104-    // Ignore request if the token is not valid
105diff --git a/quantum/deferred_exec.h b/quantum/deferred_exec.h
106index f80d353169bf22d86a6c3d2dd7040a32202415db..97ef0f6c0e2b40e1e7a564b0dec534cd79a575df 100644
107--- a/quantum/deferred_exec.h
108+++ b/quantum/deferred_exec.h
109@@ -5,34 +5,117 @@
110 
111 #include <stdbool.h>
112 #include <stdint.h>
113+#include <stdlib.h>
114 
115-// A token that can be used to cancel an existing deferred execution.
116+//------------------------------------
117+// Common
118+//------------------------------------
119+
120+/**
121+ * @typedef A token that can be used to cancel or extend an existing deferred execution.
122+ */
123 typedef uint8_t deferred_token;
124+
125+/**
126+ * @def The constant used to denote an invalid deferred execution token.
127+ */
128 #define INVALID_DEFERRED_TOKEN 0
129 
130-// Callback to execute.
131-//  -- Parameter trigger_time: the intended trigger time to execute the callback -- equivalent time-space as timer_read32()
132-//               cb_arg: the callback argument specified when enqueueing the deferred executor
133-//  -- Return value: Non-zero re-queues the callback to execute after the returned number of milliseconds. Zero cancels repeated execution.
134+/**
135+ * @typedef Callback to execute.
136+ * @param trigger_time[in] the intended trigger time to execute the callback -- equivalent time-space as timer_read32()
137+ * @param cb_arg[in] the callback argument specified when enqueueing the deferred executor
138+ * @return non-zero re-queues the callback to execute after the returned number of milliseconds. Zero cancels repeated execution.
139+ */
140 typedef uint32_t (*deferred_exec_callback)(uint32_t trigger_time, void *cb_arg);
141 
142-// Configures the supplied deferred executor to be executed after the required number of milliseconds.
143-//  -- Parameter delay_ms: the number of milliseconds before executing the callback
144-//  --           callback: the executor to invoke
145-//  --           cb_arg: the argument to pass to the executor, may be NULL if unused by the executor
146-//  -- Return value: a token usable for cancellation, or INVALID_DEFERRED_TOKEN if an error occurred
147+//------------------------------------
148+// Basic API: used by user-mode code, guaranteed to not collide with core deferred execution
149+//------------------------------------
150+
151+/**
152+ * Configures the supplied deferred executor to be executed after the required number of milliseconds.
153+ *
154+ * @param delay_ms[in] the number of milliseconds before executing the callback
155+ * @param callback[in] the executor to invoke
156+ * @param cb_arg[in] the argument to pass to the executor, may be NULL if unused by the executor
157+ * @return a token usable for extension/cancellation, or INVALID_DEFERRED_TOKEN if an error occurred
158+ */
159 deferred_token defer_exec(uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg);
160 
161-// Allows for extending the timeframe before an existing deferred execution is invoked.
162-//  -- Parameter token: the returned value from defer_exec for the deferred execution you wish to extend.
163-//  --           delay_ms: the new delay (with respect to the current time)
164-//  -- Return value: if the token was found, and the delay was extended
165+/**
166+ * Allows for extending the timeframe before an existing deferred execution is invoked.
167+ *
168+ * @param token[in] the returned value from defer_exec for the deferred execution you wish to extend
169+ * @param delay_ms[in] the number of milliseconds before executing the callback
170+ * @return true if the token was extended successfully, otherwise false
171+ */
172 bool extend_deferred_exec(deferred_token token, uint32_t delay_ms);
173 
174-// Allows for cancellation of an existing deferred execution.
175-//  -- Parameter token: the returned value from defer_exec for the deferred execution you wish to cancel.
176-//  -- Return value: if the token was found, and the executor was cancelled
177+/**
178+ * Allows for cancellation of an existing deferred execution.
179+ *
180+ * @param token[in] the returned value from defer_exec for the deferred execution you wish to cancel
181+ * @return true if the token was cancelled successfully, otherwise false
182+ */
183 bool cancel_deferred_exec(deferred_token token);
184 
185-// Forward declaration for the main loop in order to execute any deferred executors. Should not be invoked by keyboard/user code.
186+/**
187+ * Forward declaration for the main loop in order to execute any deferred executors. Should not be invoked by keyboard/user code.
188+ */
189 void deferred_exec_task(void);
190+
191+//------------------------------------
192+// Advanced API: used when a custom-allocated table is used, primarily for core code.
193+//------------------------------------
194+
195+/**
196+ * @struct Structure for containing self-hosted deferred executor tables.
197+ * @brief Core-side code can use this to create their own tables without impacting on the use of users' ability to add deferred execution.
198+ *        Code outside deferred_exec.c should not worry about internals of this struct, and should just allocate the required number in an array.
199+ */
200+typedef struct deferred_executor_t {
201+    deferred_token         token;
202+    uint32_t               trigger_time;
203+    deferred_exec_callback callback;
204+    void *                 cb_arg;
205+} deferred_executor_t;
206+
207+/**
208+ * Configures the supplied deferred executor to be executed after the required number of milliseconds.