Event Queues

An event queue allows a task to serialize incoming events and simplify event processing. Events are stored in a queue and a task removes and processes an event from the queue. An event is processed in the context of this task. Events may be generated by OS callouts, interrupt handlers, and other tasks.

Description

Mynewt’s event queue model uses callback functions to process events. Each event is associated with a callback function that is called to process the event. This model enables a library package, that uses events in its implementation but does not have real-time timing requirements, to use an application event queue instead of creating a dedicated event queue and task to process its events. The callback function executes in the context of the task that the application creates to manage the event queue. This model reduces an application’s memory requirement because memory must be allocated for the task’s stack when a task is created. A package that has real-time timing requirements and must run at a specific task priority should create a dedicated event queue and task to process its events.

In the Mynewt model, a package defines its events and implements the callback functions for the events. A package that does not have real-time timing requirements should use Mynewt’s default event queue for its events. The callback function for an event from the Mynewt default event queue is executed in the context of the application main task. A package can, optionally, export a function that allows an application to specify the event queue for the package to use. The application task handler that manages the event queue simply pulls events from the event queue and executes the event’s callback function in its context.

A common way that Mynewt applications or packages process events from an event queue is to have a task that executes in an infinite loop and calls the os_eventq_get() function to dequeue and return the event from the head of the event queue. The task then calls the event callback function to process the event. The os_eventq_get() function puts the task in to the sleeping state when there are no events on the queue. (See Scheduler for more information on task execution states.) Other tasks (or interrupts) call the os_eventq_put() function to add an event to the queue. The os_eventq_put() function determines whether a task is blocked waiting for an event on the queue and puts the task into the ready-to-run state.

A task can use the os_eventq_run() wrapper function that calls the os_eventq_get() function to dequeue an event from the queue and then calls the event callback function to process the event. Note:

  • Only one task should consume or block waiting for events from an event queue.

  • The OS callout subsystem uses events for timer expiration notification.

Example

Here is an example of using an event from the BLE host:

static void ble_hs_event_tx_notify(struct os_event *ev);

/** OS event - triggers tx of pending notifications and indications. */
static struct os_event ble_hs_ev_tx_notifications = {
    .ev_cb = ble_hs_event_tx_notify,
};

API

typedef void os_event_fn(struct os_event *ev)
void os_eventq_init(struct os_eventq*)

Initialize the event queue.

Parameters
  • evq: The event queue to initialize

int os_eventq_inited(const struct os_eventq *evq)

Check whether the event queue is initialized.

Parameters
  • evq: The event queue to check

void os_eventq_put(struct os_eventq*, struct os_event*)

Put an event on the event queue.

Parameters
  • evq: The event queue to put an event on

  • ev: The event to put on the queue

struct os_event *os_eventq_get_no_wait(struct os_eventq *evq)

Poll an event from the event queue and return it immediately.

If no event is available, don’t block, just return NULL.

Return

Event from the queue, or NULL if none available.

struct os_event *os_eventq_get(struct os_eventq*)

Pull a single item from an event queue.

This function blocks until there is an item on the event queue to read.

Return

The event from the queue

Parameters
  • evq: The event queue to pull an event from

void os_eventq_run(struct os_eventq *evq)

Pull a single item off the event queue and call it’s event callback.

Parameters
  • evq: The event queue to pull the item off.

struct os_event *os_eventq_poll(struct os_eventq**, int, os_time_t)

Poll the list of event queues specified by the evq parameter (size nevqs), and return the “first” event available on any of the queues.

Event queues are searched in the order that they are passed in the array.

Return

An event, or NULL if no events available

Parameters
  • evq: Array of event queues

  • nevqs: Number of event queues in evq

  • timo: Timeout, forever if OS_WAIT_FOREVER is passed to poll.

void os_eventq_remove(struct os_eventq*, struct os_event*)

Remove an event from the queue.

Parameters
  • evq: The event queue to remove the event from

  • ev: The event to remove from the queue

struct os_eventq *os_eventq_dflt_get(void)

Retrieves the default event queue processed by OS main task.

Return

The default event queue.

OS_EVENT_QUEUED(__ev)

Return whether or not the given event is queued.

struct os_event
#include <os_eventq.h>

Structure representing an OS event.

OS events get placed onto the event queues and are consumed by tasks.

Public Members

uint8_t ev_queued

Whether this OS event is queued on an event queue.

os_event_fn *ev_cb

Callback to call when the event is taken off of an event queue.

APIs, except for os_eventq_run(), assume this callback will be called by the user.

void *ev_arg

Argument to pass to the event queue callback.

struct os_eventq
#include <os_eventq.h>

Public Members

struct os_task *evq_owner

Pointer to task that “owns” this event queue.

struct os_task *evq_task

Pointer to the task that is sleeping on this event queue, either NULL, or the owner task.