diff --git a/doc/reference/kernel/index.rst b/doc/reference/kernel/index.rst index e9f95d23ff3..032ae2cef25 100644 --- a/doc/reference/kernel/index.rst +++ b/doc/reference/kernel/index.rst @@ -40,6 +40,7 @@ synchronization. synchronization/semaphores.rst synchronization/mutexes.rst synchronization/condvar.rst + synchronization/events.rst smp/smp.rst .. _kernel_data_passing_api: diff --git a/doc/reference/kernel/synchronization/events.rst b/doc/reference/kernel/synchronization/events.rst new file mode 100644 index 00000000000..4e232a71eb3 --- /dev/null +++ b/doc/reference/kernel/synchronization/events.rst @@ -0,0 +1,172 @@ +.. _events: + +Events +###### + +An :dfn:`event object` is a kernel object that implements traditional events. + +.. contents:: + :local: + :depth: 2 + +Concepts +******** + +Any number of event objects can be defined (limited only by available RAM). Each +event object is referenced by its memory address. One or more threads may wait +on an event object until the desired set of events has been delivered to the +event object. When new events are delivered to the event object, all threads +whose wait conditions have been satisfied become ready simultaneously. + +An event object has the following key properties: + +* A 32-bit value that tracks which events have been delivered to it. + +An event object must be initialized before it can be used. + +Events may be **delivered** by a thread or an ISR. When delivering events, the +events may either overwrite the existing set of events or add to them in +a bitwise fashion. When overwriting the existing set of events, this is referred +to as setting. When adding to them in a bitwise fashion, this is referred to as +posting. Both posting and setting events have the potential to fulfill match +conditions of multiple threads waiting on the event object. All threads whose +match conditions have been met are made active at the same time. + +Threads may wait on one or more events. They may either wait for all of the +the requested events, or for any of them. Furthermore, threads making a wait +request have the option of resetting the current set of events tracked by the +event object prior to waiting. Care must be taken with this option when +multiple threads wait on the same event object. + +.. note:: + The kernel does allow an ISR to query an event object, however the ISR must + not attempt to wait for the events. + +Implementation +************** + +Defining an Event Object +======================== + +An event object is defined using a variable of type :c:struct:`k_event`. +It must then be initialized by calling :c:func:`k_event_init`. + +The following code defines an event object. + +.. code-block:: c + + struct k_event my_event; + + k_event_init(&my_event); + +Alternatively, an event object can be defined and initialized at compile time +by calling :c:macro:`K_EVENT_DEFINE`. + +The following code has the same effect as the code segment above. + +.. code-block:: c + + K_EVENT_DEFINE(my_event, 0, 1); + +Setting Events +============== + +Events in an event object are set by calling :c:func:`k_event_set`. + +The following code builds on the example above, and sets the events tracked by +the event object to 0x001. + +.. code-block:: c + + void input_available_interrupt_handler(void *arg) + { + /* notify threads that data is available */ + + k_event_set(&my_event, 0x001); + + ... + } + +Posting Events +============== + +Events are posted to an event object by calling :c:func:`k_event_post`. + +The following code builds on the example above, and posts a set of events to +the event object. + +.. code-block:: c + + void input_available_interrupt_handler(void *arg) + { + ... + + /* notify threads that more data is available */ + + k_event_post(&my_event, 0x120); + + ... + } + +Waiting for Events +================== + +Threads wait for events by calling :c:func:`k_event_wait`. + +The following code builds on the example above, and waits up to 50 milliseconds +for any of the specified events to be posted. A warning is issued if none +of the events are posted in time. + +.. code-block:: c + + void consumer_thread(void) + { + uint32_t events; + + events = k_event_wait(&my_event, 0xFFF, false, K_MSEC(50)); + if (events == 0) { + printk("No input devices are available!"); + } else { + /* Access the desired input device(s) */ + ... + } + ... + } + +Alternatively, the consumer thread may desire to wait for all the events +before continuing. + +.. code-block:: c + + void consumer_thread(void) + { + uint32_t events; + + events = k_event_wait_all(&my_event, 0x121, false, K_MSEC(50)); + if (events == 0) { + printk("At least one input device is not available!"); + } else { + /* Access the desired input devices */ + ... + } + ... + } + +Suggested Uses +************** + +Use events to indicate that a set of conditions have occurred. + +Use events to pass small amounts of data to multiple threads at once. + +Configuration Options +********************* + +Related configuration options: + +* :kconfig:`CONFIG_EVENTS` + +API Reference +************** + +.. doxygengroup:: event_apis