summaryrefslogtreecommitdiff
path: root/zephyr/shim/src/hooks.c
diff options
context:
space:
mode:
Diffstat (limited to 'zephyr/shim/src/hooks.c')
-rw-r--r--zephyr/shim/src/hooks.c148
1 files changed, 79 insertions, 69 deletions
diff --git a/zephyr/shim/src/hooks.c b/zephyr/shim/src/hooks.c
index 79a611812f..57a0b7965b 100644
--- a/zephyr/shim/src/hooks.c
+++ b/zephyr/shim/src/hooks.c
@@ -13,37 +13,68 @@
#include "task.h"
#include "timer.h"
-int hook_call_deferred(const struct deferred_data *data, int us)
+static void hook_second_work(struct k_work *work);
+static void hook_tick_work(struct k_work *work);
+
+static struct zephyr_shim_hook_list *hook_registry[HOOK_TYPE_COUNT];
+
+static K_WORK_DELAYABLE_DEFINE(hook_seconds_work_data, hook_second_work);
+static K_WORK_DELAYABLE_DEFINE(hook_ticks_work_data, hook_tick_work);
+
+static void work_queue_error(const void *data, int rv)
{
- struct k_work_delayable *work = data->work;
- int rv = 0;
+ cprints(CC_HOOK,
+ "Warning: deferred call not submitted, "
+ "deferred_data=0x%pP, err=%d",
+ data, rv);
+}
- if (us == -1) {
- k_work_cancel_delayable(work);
- } else if (us >= 0) {
- rv = k_work_reschedule(work, K_USEC(us));
- if (rv == -EINVAL) {
- /* Already processing or completed. */
- return 0;
- } else if (rv < 0) {
- cprints(CC_HOOK,
- "Warning: deferred call not submitted, "
- "deferred_data=0x%pP, err=%d",
- data, rv);
- }
- } else {
- return EC_ERROR_PARAM2;
- }
+static void hook_second_work(struct k_work *work)
+{
+ int rv;
- return rv;
+ hook_notify(HOOK_SECOND);
+
+ rv = k_work_reschedule(&hook_seconds_work_data, K_SECONDS(1));
+ if (rv < 0)
+ work_queue_error(&hook_seconds_work_data, rv);
}
-static struct zephyr_shim_hook_list *hook_registry[HOOK_TYPE_COUNT];
+static void hook_tick_work(struct k_work *work)
+{
+ int rv;
+
+ hook_notify(HOOK_TICK);
+
+ rv = k_work_reschedule(&hook_ticks_work_data,
+ K_USEC(HOOK_TICK_INTERVAL));
+ if (rv < 0)
+ work_queue_error(&hook_ticks_work_data, rv);
+}
+
+static void check_hook_task_priority(void)
+{
+ k_tid_t thread = &k_sys_work_q.thread;
+
+ /*
+ * Numerically lower priorities take precedence, so verify the hook
+ * related threads cannot preempt any of the shimmed tasks.
+ */
+ if (k_thread_priority_get(thread) < (TASK_ID_COUNT - 1))
+ cprintf(CC_HOOK,
+ "ERROR: %s has priority %d but must be >= %d\n",
+ k_thread_name_get(thread),
+ k_thread_priority_get(thread), (TASK_ID_COUNT - 1));
+}
+DECLARE_HOOK(HOOK_INIT, check_hook_task_priority, HOOK_PRIO_FIRST);
static int zephyr_shim_setup_hooks(const struct device *unused)
{
+ int rv;
+
STRUCT_SECTION_FOREACH(zephyr_shim_hook_list, entry) {
- struct zephyr_shim_hook_list **loc = &hook_registry[entry->type];
+ struct zephyr_shim_hook_list **loc =
+ &hook_registry[entry->type];
/* Find the correct place to put the entry in the registry. */
while (*loc && (*loc)->priority < entry->priority)
@@ -55,6 +86,16 @@ static int zephyr_shim_setup_hooks(const struct device *unused)
*loc = entry;
}
+ /* Startup the HOOK_TICK and HOOK_SECOND recurring work */
+ rv = k_work_reschedule(&hook_seconds_work_data, K_SECONDS(1));
+ if (rv < 0)
+ work_queue_error(&hook_seconds_work_data, rv);
+
+ rv = k_work_reschedule(&hook_ticks_work_data,
+ K_USEC(HOOK_TICK_INTERVAL));
+ if (rv < 0)
+ work_queue_error(&hook_ticks_work_data, rv);
+
return 0;
}
@@ -68,55 +109,24 @@ void hook_notify(enum hook_type type)
p->routine();
}
-static void check_hook_task_priority(k_tid_t thread)
-{
- /*
- * Numerically lower priorities take precedence, so verify the hook
- * related threads cannot preempt any of the shimmed tasks.
- */
- if (k_thread_priority_get(thread) < (TASK_ID_COUNT - 1))
- cprintf(CC_HOOK,
- "ERROR: %s has priority %d but must be >= %d\n",
- k_thread_name_get(thread),
- k_thread_priority_get(thread), (TASK_ID_COUNT - 1));
-}
-
-void hook_task(void *u)
+int hook_call_deferred(const struct deferred_data *data, int us)
{
- /* Periodic hooks will be called first time through the loop */
- static uint64_t last_second = -SECOND;
- static uint64_t last_tick = -HOOK_TICK_INTERVAL;
-
- /*
- * Verify deferred routines are run at the lowest priority.
- */
- check_hook_task_priority(&k_sys_work_q.thread);
- check_hook_task_priority(k_current_get());
-
- while (1) {
- uint64_t t = get_time().val;
- int next = 0;
-
- if (t - last_tick >= HOOK_TICK_INTERVAL) {
- hook_notify(HOOK_TICK);
- last_tick = t;
- }
+ struct k_work_delayable *work = data->work;
+ int rv = 0;
- if (t - last_second >= SECOND) {
- hook_notify(HOOK_SECOND);
- last_second = t;
+ if (us == -1) {
+ k_work_cancel_delayable(work);
+ } else if (us >= 0) {
+ rv = k_work_reschedule(work, K_USEC(us));
+ if (rv == -EINVAL) {
+ /* Already processing or completed. */
+ return 0;
+ } else if (rv < 0) {
+ work_queue_error(data, rv);
}
-
- /* Calculate when next tick needs to occur */
- t = get_time().val;
- if (last_tick + HOOK_TICK_INTERVAL > t)
- next = last_tick + HOOK_TICK_INTERVAL - t;
-
- /*
- * Sleep until next tick, unless we've already exceeded
- * HOOK_TICK_INTERVAL.
- */
- if (next > 0)
- task_wait_event(next);
+ } else {
+ return EC_ERROR_PARAM2;
}
+
+ return rv;
}