event.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2017 Inria
3  * 2017 Kaspar Schleiser <kaspar@schleiser.de>
4  * 2018-2019 Freie Universität Berlin
5  *
6  * This file is subject to the terms and conditions of the GNU Lesser
7  * General Public License v2.1. See the file LICENSE in the top level
8  * directory for more details.
9  */
10 
11 #pragma once
12 
98 #include <stdio.h>
99 #include <stdint.h>
100 #include <stdbool.h>
101 #include <string.h>
102 
103 #include "assert.h"
104 #include "clist.h"
105 #include "irq.h"
106 #include "thread.h"
107 #include "thread_flags.h"
108 #include "ptrtag.h"
109 #include "ztimer.h"
110 
111 #ifdef __cplusplus
112 extern "C" {
113 #endif
114 
115 #ifndef THREAD_FLAG_EVENT
119 # define THREAD_FLAG_EVENT (0x1)
120 #endif
121 
125 #define EVENT_QUEUE_INIT \
126  { \
127  .waiter = thread_get_active() \
128  }
129 
133 #define EVENT_QUEUE_INIT_DETACHED \
134  { \
135  .waiter = NULL \
136  }
137 
141 typedef struct event event_t;
142 
146 typedef void (*event_handler_t)(event_t *);
147 
151 struct event {
154 };
155 
159 typedef struct PTRTAG {
163 
172 static inline void event_queues_init(event_queue_t *queues,
173  size_t n_queues)
174 {
175  assert(queues && n_queues);
176  thread_t *me = thread_get_active();
177  for (size_t i = 0; i < n_queues; i++) {
178  memset(&queues[i], '\0', sizeof(queues[0]));
179  queues[i].waiter = me;
180  }
181 }
182 
190 static inline void event_queue_init(event_queue_t *queue)
191 {
192  event_queues_init(queue, 1);
193 }
194 
201 static inline void event_queues_init_detached(event_queue_t *queues,
202  size_t n_queues)
203 {
204  assert(queues);
205  for (size_t i = 0; i < n_queues; i++) {
206  memset(&queues[i], '\0', sizeof(queues[0]));
207  }
208 }
209 
215 static inline void event_queue_init_detached(event_queue_t *queue)
216 {
217  event_queues_init_detached(queue, 1);
218 }
219 
231 static inline void event_queues_claim(event_queue_t *queues, size_t n_queues)
232 {
233  assert(queues);
234  thread_t *me = thread_get_active();
235  for (size_t i = 0; i < n_queues; i++) {
236  assert(queues[i].waiter == NULL);
237  queues[i].waiter = me;
238  }
239 }
240 
251 static inline void event_queue_claim(event_queue_t *queue)
252 {
253  event_queues_claim(queue, 1);
254 }
255 
270 
282 
292 bool event_is_queued(const event_queue_t *queue, const event_t *event);
293 
306 
338 event_t *event_wait_multi(event_queue_t *queues, size_t n_queues);
339 
357 static inline event_t *event_wait(event_queue_t *queue)
358 {
359  return event_wait_multi(queue, 1);
360 }
361 
362 #if IS_USED(MODULE_XTIMER) || defined(DOXYGEN)
375 event_t *event_wait_timeout(event_queue_t *queue, uint32_t timeout);
376 
389 event_t *event_wait_timeout64(event_queue_t *queue, uint64_t timeout);
390 #endif
391 
392 #if IS_USED(MODULE_ZTIMER) || defined(DOXYGEN)
411  ztimer_clock_t *clock, uint32_t timeout);
412 #endif
413 
423 #ifndef CONFIG_EVENT_LOOP_DEBUG_THRESHOLD_US
424 # define CONFIG_EVENT_LOOP_DEBUG_THRESHOLD_US (0)
425 #endif
426 
455 static inline void event_loop_multi(event_queue_t *queues, size_t n_queues)
456 {
457  while (1) {
458  event_t *event = event_wait_multi(queues, n_queues);
459  if (IS_USED(MODULE_EVENT_LOOP_DEBUG)) {
461 
464  (!IS_USED(MODULE_EVENT_CALLBACK) ||
466  printf("event: executing %p->%p\n",
467  (void *)event, (void *)(uintptr_t)event->handler);
468  }
469  uint32_t now = ztimer_now(ZTIMER_USEC);
470  /* events might modify themself */
471  void *handler_ptr = (void *)(uintptr_t)event->handler;
472 
473  event->handler(event);
474 
475  uint32_t dt = ztimer_now(ZTIMER_USEC) - now;
476 
479  printf("event: %p->%p ran: %" PRIu32 " usec\n",
480  (void *)event, handler_ptr, dt);
481  }
483  }
484  else {
485  event->handler(event);
486  }
487  }
488 }
489 
512 static inline void event_loop(event_queue_t *queue)
513 {
514  event_loop_multi(queue, 1);
515 }
516 
537 
538 #ifdef __cplusplus
539 }
540 #endif
POSIX.1-2008 compliant version of the assert macro.
#define assert(cond)
abort the program if assertion is false
Definition: assert.h:146
void _event_callback_handler(event_t *event)
event callback handler function (used internally)
Circular linked list.
static thread_t * thread_get_active(void)
Returns a pointer to the Thread Control Block of the currently running thread.
Definition: thread.h:413
#define printf(...)
A wrapper for the printf() function that passes arguments through unmodified, but fails to compile if...
Definition: stdio.h:57
#define CONFIG_EVENT_LOOP_DEBUG_THRESHOLD_US
Threshold in microseconds below which event_handler are not printed while debugging.
Definition: event.h:424
static event_t * event_wait(event_queue_t *queue)
Get next event from event queue, blocking.
Definition: event.h:357
static void event_loop_multi(event_queue_t *queues, size_t n_queues)
Simple event loop with multiple queues.
Definition: event.h:455
void event_post(event_queue_t *queue, event_t *event)
Queue an event.
event_t * event_wait_timeout64(event_queue_t *queue, uint64_t timeout)
Get next event from event queue, blocking until timeout expires.
static void event_loop(event_queue_t *queue)
Simple event loop.
Definition: event.h:512
static void event_queue_init(event_queue_t *queue)
Initialize an event queue.
Definition: event.h:190
void(* event_handler_t)(event_t *)
event handler type definition
Definition: event.h:146
void event_cancel(event_queue_t *queue, event_t *event)
Cancel a queued event.
event_t * event_wait_timeout_ztimer(event_queue_t *queue, ztimer_clock_t *clock, uint32_t timeout)
Get next event from event queue, blocking until timeout expires.
struct PTRTAG event_queue_t
event queue structure
static void event_queue_init_detached(event_queue_t *queue)
Initialize an event queue not binding it to a thread.
Definition: event.h:215
static void event_queue_claim(event_queue_t *queue)
Bind an event queue to the calling thread.
Definition: event.h:251
static void event_queues_claim(event_queue_t *queues, size_t n_queues)
Bind an array of event queues to the calling thread.
Definition: event.h:231
void event_sync(event_queue_t *queue)
Synchronize with the last event on the queue.
static void event_queues_init_detached(event_queue_t *queues, size_t n_queues)
Initialize an array of event queues not binding it to a thread.
Definition: event.h:201
static void event_queues_init(event_queue_t *queues, size_t n_queues)
Initialize an array of event queues.
Definition: event.h:172
bool event_is_queued(const event_queue_t *queue, const event_t *event)
Check if an event is already queued.
event_t * event_get(event_queue_t *queue)
Get next event from event queue, non-blocking.
event_t * event_wait_multi(event_queue_t *queues, size_t n_queues)
Get next event from the given event queues, blocking.
event_t * event_wait_timeout(event_queue_t *queue, uint32_t timeout)
Get next event from event queue, blocking until timeout expires.
bool ztimer_release(ztimer_clock_t *clock)
Release a clock.
ztimer_clock_t *const ZTIMER_USEC
Default ztimer microsecond clock.
bool ztimer_acquire(ztimer_clock_t *clock)
Acquire a clock.
static ztimer_now_t ztimer_now(ztimer_clock_t *clock)
Get the current time from a clock.
Definition: ztimer.h:683
IRQ driver interface.
#define IS_USED(module)
Checks whether a module is being used or not.
Definition: modules.h:70
time_point now()
Returns the current time saved in a time point.
Definition: chrono.hpp:104
Pointer Tagging Helpers.
event queue structure
Definition: event.h:159
thread_t * waiter
thread owning event queue
Definition: event.h:161
clist_node_t event_list
list of queued events
Definition: event.h:160
thread_t holds thread's context data.
Definition: thread.h:170
event structure
Definition: event.h:151
event_handler_t handler
pointer to event handler function
Definition: event.h:153
clist_node_t list_node
event queue list entry
Definition: event.h:152
List node structure.
Definition: list.h:39
ztimer device structure
Definition: ztimer.h:370
Thread Flags API.
ztimer API