mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
134 lines
4.2 KiB
C
134 lines
4.2 KiB
C
/*
|
|
* Copyright (C) 2019 Kaspar Schleiser <kaspar@schleiser.de>
|
|
* 2018 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.
|
|
*/
|
|
|
|
/**
|
|
* @ingroup sys_event
|
|
* @{
|
|
*
|
|
* @file
|
|
* @brief Event Loop Thread implementation
|
|
*
|
|
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
|
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
|
*
|
|
* @}
|
|
*/
|
|
|
|
#include "architecture.h"
|
|
#include "thread.h"
|
|
#include "event.h"
|
|
#include "event/thread.h"
|
|
|
|
struct event_queue_and_size {
|
|
event_queue_t *q;
|
|
size_t q_numof;
|
|
};
|
|
|
|
static void *_handler_thread(void *tagged_ptr)
|
|
{
|
|
event_queue_t *qs = ptrtag_ptr(tagged_ptr);
|
|
/* number of queues is encoded in lower pointer bits */
|
|
size_t n = ptrtag_tag(tagged_ptr) + 1;
|
|
event_queues_claim(qs, n);
|
|
/* start event loop */
|
|
event_loop_multi(qs, n);
|
|
|
|
/* should be never reached */
|
|
return NULL;
|
|
}
|
|
|
|
void event_thread_init_multi(event_queue_t *queues, size_t queues_numof,
|
|
char *stack, size_t stack_size, unsigned priority)
|
|
{
|
|
/* For the auto_init use case, this will be called before main gets
|
|
* started. main might already use the queues, so they need to be
|
|
* initialized at that point.
|
|
*
|
|
* They will be claimed within the handler thread.
|
|
*/
|
|
event_queues_init_detached(queues, queues_numof);
|
|
|
|
void *tagged_ptr = ptrtag(queues, queues_numof - 1);
|
|
|
|
thread_create(stack, stack_size, priority, THREAD_CREATE_STACKTEST,
|
|
_handler_thread, tagged_ptr, "event");
|
|
}
|
|
|
|
#ifndef EVENT_THREAD_STACKSIZE_DEFAULT
|
|
# ifdef ISR_STACKSIZE
|
|
# define EVENT_THREAD_STACKSIZE_DEFAULT ISR_STACKSIZE
|
|
# else
|
|
# define EVENT_THREAD_STACKSIZE_DEFAULT THREAD_STACKSIZE_SMALL
|
|
# endif
|
|
#endif
|
|
|
|
#ifndef EVENT_THREAD_HIGHEST_STACKSIZE
|
|
#define EVENT_THREAD_HIGHEST_STACKSIZE EVENT_THREAD_STACKSIZE_DEFAULT
|
|
#endif
|
|
|
|
#ifndef EVENT_THREAD_HIGHEST_PRIO
|
|
#define EVENT_THREAD_HIGHEST_PRIO (0)
|
|
#endif
|
|
|
|
#ifndef EVENT_THREAD_MEDIUM_STACKSIZE
|
|
#define EVENT_THREAD_MEDIUM_STACKSIZE EVENT_THREAD_STACKSIZE_DEFAULT
|
|
#endif
|
|
#ifndef EVENT_THREAD_MEDIUM_PRIO
|
|
#define EVENT_THREAD_MEDIUM_PRIO (THREAD_PRIORITY_MAIN - 1)
|
|
#endif
|
|
|
|
#ifndef EVENT_THREAD_LOWEST_STACKSIZE
|
|
#define EVENT_THREAD_LOWEST_STACKSIZE EVENT_THREAD_STACKSIZE_DEFAULT
|
|
#endif
|
|
#ifndef EVENT_THREAD_LOWEST_PRIO
|
|
#define EVENT_THREAD_LOWEST_PRIO (THREAD_PRIORITY_IDLE - 1)
|
|
#endif
|
|
|
|
/* rely on compiler / linker to garbage collect unused stacks */
|
|
static char WORD_ALIGNED _evq_highest_stack[EVENT_THREAD_HIGHEST_STACKSIZE];
|
|
static char WORD_ALIGNED _evq_medium_stack[EVENT_THREAD_MEDIUM_STACKSIZE];
|
|
static char WORD_ALIGNED _evq_lowest_stack[EVENT_THREAD_LOWEST_STACKSIZE];
|
|
|
|
event_queue_t event_thread_queues[EVENT_QUEUE_PRIO_NUMOF];
|
|
|
|
void auto_init_event_thread(void)
|
|
{
|
|
if (IS_USED(MODULE_EVENT_THREAD_HIGHEST)) {
|
|
/* In order to allow highest priority events to preempt all others,
|
|
* high priority events must be run in their own thread. This thread
|
|
* can preempt than preempt the other event thread(s). */
|
|
event_thread_init(EVENT_PRIO_HIGHEST,
|
|
_evq_highest_stack, sizeof(_evq_highest_stack),
|
|
EVENT_THREAD_HIGHEST_PRIO);
|
|
}
|
|
if (IS_USED(MODULE_EVENT_THREAD_MEDIUM)) {
|
|
/* In order to allow medium priority events to preempt low priority
|
|
* events, we need to move the low priority events into their own
|
|
* thread. The always existing medium priority event thread can then
|
|
* preempt the lowest priority event thread. */
|
|
event_thread_init(EVENT_PRIO_LOWEST,
|
|
_evq_lowest_stack, sizeof(_evq_lowest_stack),
|
|
EVENT_THREAD_LOWEST_PRIO);
|
|
}
|
|
|
|
event_queue_t *qs = EVENT_PRIO_MEDIUM;
|
|
size_t qs_numof = 1;
|
|
if (!IS_USED(MODULE_EVENT_THREAD_HIGHEST)) {
|
|
qs = EVENT_PRIO_HIGHEST;
|
|
qs_numof = 2;
|
|
}
|
|
if (!IS_USED(MODULE_EVENT_THREAD_MEDIUM)) {
|
|
qs_numof++;
|
|
}
|
|
event_thread_init_multi(qs, qs_numof,
|
|
_evq_medium_stack, sizeof(_evq_medium_stack),
|
|
EVENT_THREAD_MEDIUM_PRIO);
|
|
}
|