1 /*
2 * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <string.h>
8 #include "pico/async_context_poll.h"
9 #include "pico/async_context_base.h"
10 #include "pico/sync.h"
11
noop(__unused async_context_t * context)12 static void noop(__unused async_context_t *context) { }
13
14 static const async_context_type_t template;
15
async_context_poll_init_with_defaults(async_context_poll_t * self)16 bool async_context_poll_init_with_defaults(async_context_poll_t *self) {
17 memset(self, 0, sizeof(*self));
18 self->core.core_num = get_core_num();
19 self->core.type = &template;
20 self->core.flags = ASYNC_CONTEXT_FLAG_POLLED | ASYNC_CONTEXT_FLAG_CALLBACK_FROM_NON_IRQ;
21 sem_init(&self->sem, 1, 1);
22 return true;
23 }
24
async_context_poll_wake_up(async_context_t * self_base)25 static void async_context_poll_wake_up(async_context_t *self_base) {
26 sem_release(&((async_context_poll_t *)self_base)->sem);
27 }
28
async_context_poll_requires_update(async_context_t * self_base,async_when_pending_worker_t * worker)29 static void async_context_poll_requires_update(async_context_t *self_base, async_when_pending_worker_t *worker) {
30 worker->work_pending = true;
31 async_context_poll_wake_up(self_base);
32 }
33
async_context_poll_poll(async_context_t * self_base)34 static void async_context_poll_poll(async_context_t *self_base) {
35 async_context_base_execute_once(self_base);
36 }
37
async_context_poll_wait_until(__unused async_context_t * self_base,absolute_time_t until)38 static void async_context_poll_wait_until(__unused async_context_t *self_base, absolute_time_t until) {
39 sleep_until(until);
40 }
41
async_context_poll_wait_for_work_until(async_context_t * self_base,absolute_time_t until)42 static void async_context_poll_wait_for_work_until(async_context_t *self_base, absolute_time_t until) {
43 absolute_time_t next_time = self_base->next_time;
44 async_context_poll_t *self = (async_context_poll_t *)self_base;
45 sem_acquire_block_until(&self->sem, absolute_time_min(next_time, until));
46 }
47
async_context_poll_lock_check(async_context_t * self_base)48 static void async_context_poll_lock_check(async_context_t *self_base) {
49 if (__get_current_exception() || get_core_num() != self_base->core_num) {
50 panic("async_context_poll context check failed (IRQ or wrong core)");
51 }
52 }
53
async_context_poll_execute_sync(__unused async_context_t * context,uint32_t (* func)(void * param),void * param)54 uint32_t async_context_poll_execute_sync(__unused async_context_t *context, uint32_t (*func)(void *param), void *param) {
55 return func(param);
56 }
57
58 static const async_context_type_t template = {
59 .type = ASYNC_CONTEXT_POLL,
60 .acquire_lock_blocking = noop,
61 .release_lock = noop,
62 .lock_check = async_context_poll_lock_check,
63 .execute_sync = async_context_poll_execute_sync,
64 .add_at_time_worker = async_context_base_add_at_time_worker,
65 .remove_at_time_worker = async_context_base_remove_at_time_worker,
66 .add_when_pending_worker = async_context_base_add_when_pending_worker,
67 .remove_when_pending_worker = async_context_base_remove_when_pending_worker,
68 .set_work_pending = async_context_poll_requires_update,
69 .poll = async_context_poll_poll,
70 .wait_until = async_context_poll_wait_until,
71 .wait_for_work_until = async_context_poll_wait_for_work_until,
72 .deinit = noop,
73 };
74