Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,10 @@ ifneq (,$(filter event_%,$(USEMODULE)))
USEMODULE += event
endif

ifneq (,$(filter event_thread_%,$(USEMODULE)))
USEMODULE += event_thread
endif

ifneq (,$(filter event_timeout,$(USEMODULE)))
USEMODULE += xtimer
endif
Expand Down
4 changes: 4 additions & 0 deletions sys/auto_init/auto_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ void auto_init(void)
#ifdef MODULE_SCHEDSTATISTICS
init_schedstatistics();
#endif
#ifdef MODULE_EVENT_THREAD
extern void auto_init_event_thread(void);
auto_init_event_thread();
Comment thread
kaspar030 marked this conversation as resolved.
#endif
#ifdef MODULE_MCI
DEBUG("Auto init mci module.\n");
mci_initialize();
Expand Down
3 changes: 2 additions & 1 deletion sys/event/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
SRC := event.c

SUBMODULES = 1
SUBMODULES := 1
SUBMODULES_NOFORCE := 1

include $(RIOTBASE)/Makefile.base
125 changes: 125 additions & 0 deletions sys/event/thread.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* 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 "thread.h"
#include "event.h"
#include "event/thread.h"

static void *_handler(void *event_queue)
{
event_queue_claim(event_queue);
event_loop(event_queue);

/* should be never reached */
return NULL;
}

void event_thread_init(event_queue_t *queue, 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_queue_init_detached(queue);

thread_create(stack, stack_size, priority, 0, _handler, queue, "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)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would have at most exactly two priorities and two threads, right? Shouldn't the lowest thread priority be (THREAD_PRIORITY_MAIN - 1)? Otherwise drivers would have to use again the high priority thread to ensure that their events are at least handled before the main thread is executed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise drivers would have to use again the high priority thread to ensure that their events are at least handled before the main thread is executed.

Maybe they want to, as in, "do this when there is time". That's why I've made it just one higher than idle.

How about I add a third priority ("medium"), which is just one higher than main? Or does the current very-low one make sense at all?

I mean, this is just the auto configuration, cpus / boards / applications can freely launch more handler threads...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about I add a third priority ("medium"), which is just one higher than main? Or does the current very-low one make sense at all?

What priority should a thread have that is used by a driver to handle an interrupt from the hardware? IMHO, its priority should be at least higher than the priority of the main thread. A medium priority thread seems to be more important than a very low priority thread.

I mean, this is just the auto configuration, cpus / boards / applications can freely launch more handler threads...

Yes of course, but drivers can only use threads that are known from the auto configuration. Otherwise, they would need an additional thread parameter for the initializtion. This in turn would prevent the auto initialization.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What priority should a thread have that is used by a driver to handle an interrupt from the hardware?

I guess that depends... It is easy to add more priorities, so I propose I add one more middle priority (one higher than main) and see how far we go with that.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 The three priorities high (0), medium (main-1) and low (idle-1) probably meet the requirements of most use cases.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added medium priority

#endif

#ifdef MODULE_EVENT_THREAD_HIGHEST
event_queue_t event_queue_highest;
static char _evq_highest_stack[EVENT_THREAD_HIGHEST_STACKSIZE];
#endif

#ifdef MODULE_EVENT_THREAD_MEDIUM
event_queue_t event_queue_medium;
static char _evq_medium_stack[EVENT_THREAD_MEDIUM_STACKSIZE];
#endif

#ifdef MODULE_EVENT_THREAD_LOWEST
event_queue_t event_queue_lowest;
static char _evq_lowest_stack[EVENT_THREAD_LOWEST_STACKSIZE];
#endif

typedef struct {
event_queue_t *queue;
char *stack;
size_t stack_size;
unsigned priority;
} event_threads_t;

const event_threads_t _event_threads[] = {
#ifdef MODULE_EVENT_THREAD_HIGHEST
{ &event_queue_highest, _evq_highest_stack, sizeof(_evq_highest_stack),
EVENT_THREAD_HIGHEST_PRIO },
#endif
#ifdef MODULE_EVENT_THREAD_MEDIUM
{ &event_queue_medium, _evq_medium_stack, sizeof(_evq_medium_stack),
EVENT_THREAD_MEDIUM_PRIO },
#endif
#ifdef MODULE_EVENT_THREAD_LOWEST
{ &event_queue_lowest, _evq_lowest_stack, sizeof(_evq_lowest_stack),
EVENT_THREAD_LOWEST_PRIO },
#endif
};

void auto_init_event_thread(void)
{
for (unsigned i = 0; i < ARRAY_SIZE(_event_threads); i++) {
event_thread_init(_event_threads[i].queue,
_event_threads[i].stack, _event_threads[i].stack_size,
_event_threads[i].priority);
}
}
64 changes: 64 additions & 0 deletions sys/include/event/thread.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* 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.
*/

/**
* @ingroup sys_event
* @brief Provides utility functions for event handler threads
*
* @{
*
* @file
* @brief Event Thread API
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/

#ifndef EVENT_THREAD_H
#define EVENT_THREAD_H

#include <stddef.h>

#include "event.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @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
*/
void event_thread_init(event_queue_t *queue, char *stack, size_t stack_size,
unsigned priority);

#ifdef MODULE_EVENT_THREAD_HIGHEST
extern event_queue_t event_queue_highest;
#define EVENT_PRIO_HIGHEST (&event_queue_highest)
#endif

#ifdef MODULE_EVENT_THREAD_MEDIUM
extern event_queue_t event_queue_medium;
#define EVENT_PRIO_MEDIUM (&event_queue_medium)
#endif

#ifdef MODULE_EVENT_THREAD_LOWEST
extern event_queue_t event_queue_lowest;
#define EVENT_PRIO_LOWEST (&event_queue_lowest)
#endif

#ifdef __cplusplus
}
#endif
#endif /* EVENT_THREAD_H */
/** @} */
8 changes: 8 additions & 0 deletions tests/event_threads/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
include ../Makefile.tests_common

USEMODULE += event_thread_highest event_thread_medium event_thread_lowest

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we define these as configuration values (CFLAGS) that depend on the module "event_thread"? Otherwise it's hard to configure it using Kconfig.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how hard?


# arm7 has an issue with it's ISR_STACKSIZE define
FEATURES_BLACKLIST += arch_arm7

include $(RIOTBASE)/Makefile.include
8 changes: 8 additions & 0 deletions tests/event_threads/Makefile.ci
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-nano \
arduino-uno \
atmega328p \
nucleo-f031k6 \
stm32f030f4-demo \
#
58 changes: 58 additions & 0 deletions tests/event_threads/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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.
*/

/**
* @ingroup tests
* @{
*
* @file
* @brief Event threads test application
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*
* @}
*/

#include <stdio.h>

#include "thread.h"
#include "event/thread.h"

static void _handler_high(event_t *event) {
(void)event;
puts("high");
}

static event_t event_high = { .handler=_handler_high };

static void _handler_medium(event_t *event) {
(void)event;
puts("medium");
}

static event_t event_medium = { .handler=_handler_medium };

static void _handler_low(event_t *event) {
(void)event;
puts("low");
}

static event_t event_low = { .handler=_handler_low };

int main(void)
{
event_post(EVENT_PRIO_LOWEST, &event_low);
event_post(EVENT_PRIO_MEDIUM, &event_medium);
event_post(EVENT_PRIO_HIGHEST, &event_high);

puts("main done");

return 0;
}
15 changes: 15 additions & 0 deletions tests/event_threads/tests/01-run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env python3

import sys
from testrunner import run


def testfunc(child):
child.expect_exact('medium\r\n')
child.expect_exact('high\r\n')
child.expect_exact('main done\r\n')
child.expect_exact('low\r\n')


if __name__ == "__main__":
sys.exit(run(testfunc))