1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-15 17:43:51 +01:00
RIOT/sys/include/event/thread.h
Marian Buschsieweke f0540a9000
sys/event: manage event thread size via build system
This adds a mechanism for modules to declare requirements on the thread
stack size in their `Makefile.dep` and let the build system then
override the default stack size, if any requirements are declared.

The motivation is to allow multiple modules to have special requirements
without causing conflicts, as just adding the following to their
`Makefile.include` would do:

```Makefile
CFLAGS += -DEVENT_THREAD_MEDIUM_STACKSIZE=<MAGIC_NUMBER>
```

Instead, the new mechanism would work by having them both declare in
their `Makefile.dep`:

```Makefile
EVENT_THREAD_MEDIUM_STACKSIZE_MIN +=
```

The build system then picks the maximum number in
`EVENT_THREAD_MEDIUM_STACKSIZE_MIN` and exposes this as stack size, if
any module did declare a minimum requirement.

Co-authored-by: benpicco <benpicco@googlemail.com>
2025-12-09 13:50:56 +01:00

153 lines
5.4 KiB
C

/*
* Copyright (C) 2020 Kaspar Schleiser <kaspar@schleiser.de>
* 2020 Freie Universität Berlin
* 2020 Inria
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#pragma once
/**
* @ingroup sys_event
* @brief Provides utility functions for event handler threads
*
* Usage
* =====
*
* By using the module `event_thread`, the event queues
* @ref EVENT_PRIO_HIGHEST, @ref EVENT_PRIO_MEDIUM, and
* @ref EVENT_PRIO_LOWEST are provided and declared in the header
* `event/thread.h`. With default settings, the `auto_init` module will
* automatically start one or more threads to handle these
* queues.
*
* By default, a single thread with priority `EVENT_THREAD_MEDIUM_PRIO`
* will handle all three event queues according to their priority.
* An already started event handler will not be preempted in this case by an
* incoming higher priority event. Still, lower priority event queues will only
* be worked on once the higher priority queues are empty. Hence, the worst case
* latency is increased by the worst case duration of any possible lower
* priority event in this configuration.
*
* By using module `event_thread_highest`, the highest priority queue gets its
* own thread. With this, events of the highest priority can preempt already
* running event handlers of medium and lowest priority.
*
* By using module `event_thread_medium`, the lowest priority events are handled
* in their own thread. With this, events of at least medium priority can
* preempt already running events of the lowest priority.
*
* By using both module `event_thread_highest` and `event_thread_medium`, each
* event queue gets its own thread. So higher priority events will always
* preempt events of lower priority in this case.
*
* Managing Stack Size Requirements
* --------------------------------
*
* A module using the medium priority event queue might require a certain
* minimum stack size, say 1024, to operate correctly. Instead of just adding
* `CFLAGS += -DDEVENT_THREAD_MEDIUM_STACKSIZE=1024`, it can instead add the
* following to its `Makefile.dep`:
*
* ```Makefile
* EVENT_THREAD_MEDIUM_STACKSIZE_MIN += 1024
* ```
*
* In the `Makefile.include` of `sys/event` the highest value of the minimum
* requirements declared by any module will be picked and added to the
* `CFLAGS`.
*
* @note `EVENT_THREAD_MEDIUM_STACKSIZE_MIN` and
* `EVENT_THREAD_HIGHEST_STACKSIZE_MIN` always apply to the thread
* managing the medium priority queue.
* @details E.g. without the module `event_thread_medium` the lowest priority
* and medium priority queues are both handled by the lowest priority
* even thread. In that case, `EVENT_THREAD_MEDIUM_STACKSIZE_MIN` would
* ensure a minimum thread statck size on the lowest priority even
* thread. With `event_thread_medium` in use, it would instead apply
* to the stack of the dedicated medium event queue thread.
*
* @{
*
* @file
* @brief Event Thread API
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/
#include <stddef.h>
#include "event.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Convenience function for initializing an event queue thread
* handling multiple queues
*
* @param[in] queues array of the preallocated queue objects
* @param[in] queues_numof number of elements in @p queues
* @param[in] stack ptr to stack space
* @param[in] stack_size size of stack
* @param[in] priority priority to use
*
* @pre @p queues_numof is at most 4
*/
void event_thread_init_multi(event_queue_t *queues, size_t queues_numof,
char *stack, size_t stack_size,
unsigned priority);
/**
* @brief Convenience function for initializing an event queue thread
*
* @param[in] queue ptr to preallocated queue object
* @param[in] stack ptr to stack space
* @param[in] stack_size size of stack
* @param[in] priority priority to use
*/
static inline void event_thread_init(event_queue_t *queue,
char *stack, size_t stack_size,
unsigned priority)
{
event_thread_init_multi(queue, 1, stack, stack_size, priority);
}
/**
* @brief Event queue priorities
*
* @details The lower the numeric value, the higher the priority. The highest
* priority is 0, so that these priorities can be used as index to
* access arrays.
*/
enum {
EVENT_QUEUE_PRIO_HIGHEST, /**< Highest event queue priority */
EVENT_QUEUE_PRIO_MEDIUM, /**< Medium event queue priority */
EVENT_QUEUE_PRIO_LOWEST, /**< Lowest event queue priority */
EVENT_QUEUE_PRIO_NUMOF /**< Number of event queue priorities */
};
extern event_queue_t event_thread_queues[EVENT_QUEUE_PRIO_NUMOF];
/**
* @brief Pointer to the event queue handling highest priority events
*/
#define EVENT_PRIO_HIGHEST (&event_thread_queues[EVENT_QUEUE_PRIO_HIGHEST])
/**
* @brief Pointer to the event queue handling medium priority events
*/
#define EVENT_PRIO_MEDIUM (&event_thread_queues[EVENT_QUEUE_PRIO_MEDIUM])
/**
* @brief Pointer to the event queue handling lowest priority events
*/
#define EVENT_PRIO_LOWEST (&event_thread_queues[EVENT_QUEUE_PRIO_LOWEST])
#ifdef __cplusplus
}
#endif
/** @} */