BeRTOS
Defines | Functions
Event handling module
BeRTOS core functionality

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.

Detailed Description

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);
 }
Author:
Bernie Innocenti <bernie@codewiz.org>

Function Documentation

Event event_createGeneric ( void  ) [inline]

Create a generic sleepable event.

Returns:
the properly initialized generic event structure.

Definition at line 247 of file event.h.

void event_do ( struct Event *  e) [inline]

Trigger an event.

Execute the callback function associated with event e.

This function can be used also in interrupt routines, but only if the event was created as a signal or generic event.

Definition at line 301 of file event.h.

int event_select ( Event **  evs,
int  n,
ticks_t  timeout 
)

Wait for multiple events.

On success return the offset in the evs vector of the Event that happened, -1 if the timeout expires.

NOTE: timeout == 0 means no timeout.

Attention:
The API is work in progress and may change in future versions.

Definition at line 193 of file event.c.

void event_wait ( Event *  e) [inline]

Wait the completion of event e.

This function releases the CPU the application is configured to use the kernel, otherwise it's just a busy wait.

Note:
It's forbidden to use this function inside irq handling functions.

Definition at line 261 of file event.h.

bool event_waitTimeout ( Event *  e,
ticks_t  timeout 
)

Wait the completion of event e or timeout elapses.

Note:
It's forbidden to use this function inside irq handling functions.

Definition at line 178 of file event.c.