BeRTOS
|
Events handling. More...
Defines | |
#define | event_initNone(e) ((e)->action = event_hook_ignore) |
Initialize the event e as a no-op. | |
#define | event_initSoftint(e, f, u) ((e)->action = event_hook_softint,(e)->Ev.Int.func = (f), (e)->Ev.Int.user_data = (u)) |
Initialize the event e with a software interrupt (call function f, with parameter u) | |
Functions | |
Event | event_createNone (void) |
Same as event_initNone(), but returns the initialized event. | |
Event | event_createSoftint (Hook func, void *user_data) |
Same as event_initSoftint(), but returns the initialized event. | |
Event | event_createGeneric (void) |
Create a generic sleepable event. | |
void | event_wait (Event *e) |
Wait the completion of event e. | |
int | event_select (Event **evs, int n, ticks_t timeout) |
Wait for multiple events. | |
bool | event_waitTimeout (Event *e, ticks_t timeout) |
Wait the completion of event e or timeout elapses. | |
void | event_do (struct Event *e) |
Trigger an event. |
Events handling.
This module implements a common system for executing a user defined action calling a hook function.
Device drivers often need to wait the completion of some event, usually to allow the hardware to accomplish some asynchronous task.
A common approach is to place a busy wait with a cpu_relax() loop that invokes the architecture-specific instructions to say that we're not doing much with the processor.
Although technically correct, the busy loop degrades the overall system performance in presence of multiple processes and power consumption.
With the kernel the natural way to implement such wait/complete mechanism is to use signals via sig_wait() and sig_post()/sig_send().
However, signals in BeRTOS are only available in presence of the kernel (that is just a compile-time option). This means that each device driver must provide two different interfaces to implement the wait/complete semantic: one with the kernel and another without the kernel.
The purpose of the completion events is to provide a generic interface to implement a synchronization mechanism to block the execution of code until a specific event happens.
This interface does not depend on the presence of the kernel and it automatically uses the appropriate event backend to provide the same behaviour with or without the kernel.
Example usage (wait for a generic device driver initialization):
static Event e; static void irq_handler(void) { // Completion event has happened, resume the execution of init() event_do(&e); } static void init(void) { // Declare the generic completion event event_initGeneric(&e); // Submit the hardware initialization request async_hw_init(); // Wait for the completion of the event event_wait(&e); }
Example usage: wait multiple generic events via event_select()
Event ev1; Event ev2; void event_notifier(void) { Event *evs[] = { &ev1, &ev2 }; event_initGeneric(&ev1); event_initGeneric(&ev2); while (1) { int id = event_select(evs, countof(evs), ms_to_ticks(100)); if (id < 0) { kprintf("no IRQ\n"); continue; } kprintf("IRQ %d happened\n", id); } } void irq1_handler(void) { // do something ... // notify the completion of event 1 event_do(&ev1); } void irq2_handler(void) { // do something ... // notify the completion of event 2 event_do(&ev2); }
Event event_createGeneric | ( | void | ) | [inline] |
void event_do | ( | struct Event * | e | ) | [inline] |
int event_select | ( | Event ** | evs, |
int | n, | ||
ticks_t | timeout | ||
) |
void event_wait | ( | Event * | e | ) | [inline] |