mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #15789 from haukepetersen/add_event_timeoutztimer
sys/event: add event_wait_timeout_ztimer()
This commit is contained in:
commit
9a5657a2bc
@ -29,7 +29,7 @@
|
||||
#include "clist.h"
|
||||
#include "thread.h"
|
||||
|
||||
#ifdef MODULE_XTIMER
|
||||
#if IS_USED(MODULE_XTIMER)
|
||||
#include "xtimer.h"
|
||||
#endif
|
||||
|
||||
@ -96,8 +96,8 @@ event_t *event_wait_multi(event_queue_t *queues, size_t n_queues)
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef MODULE_XTIMER
|
||||
static event_t *_wait_timeout(event_queue_t *queue, xtimer_t *timer)
|
||||
#if IS_USED(MODULE_XTIMER) || IS_USED(MODULE_ZTIMER)
|
||||
static event_t *_wait_timeout(event_queue_t *queue)
|
||||
{
|
||||
assert(queue);
|
||||
event_t *result;
|
||||
@ -106,10 +106,19 @@ static event_t *_wait_timeout(event_queue_t *queue, xtimer_t *timer)
|
||||
do {
|
||||
result = event_get(queue);
|
||||
if (result == NULL) {
|
||||
flags = thread_flags_wait_any(THREAD_FLAG_EVENT | THREAD_FLAG_TIMEOUT);
|
||||
flags = thread_flags_wait_any(THREAD_FLAG_EVENT |
|
||||
THREAD_FLAG_TIMEOUT);
|
||||
}
|
||||
} while ((result == NULL) && (flags & THREAD_FLAG_EVENT));
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_USED(MODULE_XTIMER)
|
||||
static event_t *_wait_timeout_xtimer(event_queue_t *queue, xtimer_t *timer)
|
||||
{
|
||||
event_t *result = _wait_timeout(queue);
|
||||
if (result) {
|
||||
xtimer_remove(timer);
|
||||
}
|
||||
@ -121,15 +130,34 @@ event_t *event_wait_timeout(event_queue_t *queue, uint32_t timeout)
|
||||
{
|
||||
xtimer_t timer;
|
||||
|
||||
thread_flags_clear(THREAD_FLAG_TIMEOUT);
|
||||
xtimer_set_timeout_flag(&timer, timeout);
|
||||
return _wait_timeout(queue, &timer);
|
||||
return _wait_timeout_xtimer(queue, &timer);
|
||||
}
|
||||
|
||||
event_t *event_wait_timeout64(event_queue_t *queue, uint64_t timeout)
|
||||
{
|
||||
xtimer_t timer;
|
||||
|
||||
thread_flags_clear(THREAD_FLAG_TIMEOUT);
|
||||
xtimer_set_timeout_flag64(&timer, timeout);
|
||||
return _wait_timeout(queue, &timer);
|
||||
return _wait_timeout_xtimer(queue, &timer);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_USED(MODULE_ZTIMER)
|
||||
event_t *event_wait_timeout_ztimer(event_queue_t *queue,
|
||||
ztimer_clock_t *clock, uint32_t timeout)
|
||||
{
|
||||
ztimer_t timer;
|
||||
event_t *result;
|
||||
|
||||
thread_flags_clear(THREAD_FLAG_TIMEOUT);
|
||||
ztimer_set_timeout_flag(clock, &timer, timeout);
|
||||
result = _wait_timeout(queue);
|
||||
if (result) {
|
||||
ztimer_remove(clock, &timer);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
@ -106,6 +106,10 @@
|
||||
#include "thread_flags.h"
|
||||
#include "ptrtag.h"
|
||||
|
||||
#if IS_USED(MODULE_ZTIMER)
|
||||
#include "ztimer.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -333,7 +337,7 @@ static inline event_t *event_wait(event_queue_t *queue)
|
||||
return event_wait_multi(queue, 1);
|
||||
}
|
||||
|
||||
#if defined(MODULE_XTIMER) || defined(DOXYGEN)
|
||||
#if IS_USED(MODULE_XTIMER) || defined(DOXYGEN)
|
||||
/**
|
||||
* @brief Get next event from event queue, blocking until timeout expires
|
||||
*
|
||||
@ -357,6 +361,25 @@ event_t *event_wait_timeout(event_queue_t *queue, uint32_t timeout);
|
||||
event_t *event_wait_timeout64(event_queue_t *queue, uint64_t timeout);
|
||||
#endif
|
||||
|
||||
#if IS_USED(MODULE_ZTIMER) || defined(DOXYGEN)
|
||||
/**
|
||||
* @brief Get next event from event queue, blocking until timeout expires
|
||||
*
|
||||
* This function is the same as event_wait_timeout() with the difference that it
|
||||
* uses ztimer instead of xtimer as timer backend.
|
||||
*
|
||||
* @param[in] queue queue to query for an event
|
||||
* @param[in] clock ztimer clock to use
|
||||
* @param[in] timeout maximum time to wait for an event, time unit depends
|
||||
* on the used ztimer clock
|
||||
*
|
||||
* @return pointer to next event if event was taken from the queue
|
||||
* @return NULL if timeout expired before an event was posted
|
||||
*/
|
||||
event_t *event_wait_timeout_ztimer(event_queue_t *queue,
|
||||
ztimer_clock_t *clock, uint32_t timeout);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Simple event loop with multiple queues
|
||||
*
|
||||
|
15
tests/event_wait_timeout_ztimer/Makefile
Normal file
15
tests/event_wait_timeout_ztimer/Makefile
Normal file
@ -0,0 +1,15 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
FORCE_ASSERTS = 1
|
||||
USEMODULE += event
|
||||
USEMODULE += ztimer_usec ztimer_msec
|
||||
USEMODULE += core_thread_flags
|
||||
|
||||
# stm32f030f4-demo doesn't have enough RAM to run the test
|
||||
# so we reduce the stack size for every thread
|
||||
ifneq (,$(filter stm32f030f4-demo,$(BOARD)))
|
||||
CFLAGS += -DTHREAD_STACKSIZE_DEFAULT=512
|
||||
endif
|
||||
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
7
tests/event_wait_timeout_ztimer/Makefile.ci
Normal file
7
tests/event_wait_timeout_ztimer/Makefile.ci
Normal file
@ -0,0 +1,7 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-duemilanove \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
nucleo-l011k4 \
|
||||
#
|
137
tests/event_wait_timeout_ztimer/main.c
Normal file
137
tests/event_wait_timeout_ztimer/main.c
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Freie Universität Berlin
|
||||
*
|
||||
* 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 Test application to test event wait timeout
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "event.h"
|
||||
#include "thread.h"
|
||||
#include "timex.h"
|
||||
#include "thread_flags.h"
|
||||
|
||||
#define STATIC_TIMEOUT_MS (10U) /* 10ms */
|
||||
#define STATIC_TIMEOUT_US (STATIC_TIMEOUT_MS * US_PER_MS) /* 10ms */
|
||||
#define TIMEOUT_US (50U * US_PER_MS) /* 50ms */
|
||||
#define PRIO (THREAD_PRIORITY_MAIN - 5)
|
||||
#define STACKSIZE (THREAD_STACKSIZE_DEFAULT)
|
||||
|
||||
#define FLAG_SYNC (0x0040)
|
||||
|
||||
static void _on_evt(event_t *evt);
|
||||
|
||||
static event_queue_t _evtq;
|
||||
static event_t _evt = { .handler = _on_evt };
|
||||
|
||||
static char _stack[STACKSIZE];
|
||||
static thread_t *_thread_main;
|
||||
|
||||
static atomic_uint _wakeup_evt = ATOMIC_VAR_INIT(0);
|
||||
static atomic_uint _wakeup_timeout = ATOMIC_VAR_INIT(0);
|
||||
|
||||
static void _on_evt(event_t *evt)
|
||||
{
|
||||
(void)evt;
|
||||
atomic_fetch_add(&_wakeup_evt, 1);
|
||||
}
|
||||
|
||||
static void *_cnt_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
event_queue_init(&_evtq);
|
||||
|
||||
while (1) {
|
||||
event_t *evt = event_wait_timeout_ztimer(&_evtq, ZTIMER_USEC, TIMEOUT_US);
|
||||
if (evt) {
|
||||
evt->handler(evt);
|
||||
}
|
||||
else {
|
||||
atomic_fetch_add(&_wakeup_timeout, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* setup */
|
||||
_thread_main = thread_get_active();
|
||||
|
||||
puts("[START] event_wait_timeout test application.\n");
|
||||
|
||||
/* test 'instant' return */
|
||||
event_queue_t tmp_eq = EVENT_QUEUE_INIT;
|
||||
event_t *tmp_evt = event_wait_timeout_ztimer(&tmp_eq, ZTIMER_USEC, 0);
|
||||
if (tmp_evt != NULL) {
|
||||
puts("[FAILED");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* test return in a predefined amount of time */
|
||||
puts("waiting for event with 10ms timeout @ ZTIMER_USEC...");
|
||||
ztimer_now_t before = ztimer_now(ZTIMER_USEC);
|
||||
tmp_evt = event_wait_timeout_ztimer(&tmp_eq, ZTIMER_USEC, STATIC_TIMEOUT_US);
|
||||
if (tmp_evt != NULL) {
|
||||
puts("[FAILED]");
|
||||
return 1;
|
||||
}
|
||||
ztimer_now_t diff = ztimer_now(ZTIMER_USEC) - before;
|
||||
printf("event_wait time out after %"PRIu32"us\n", diff);
|
||||
|
||||
puts("waiting for event with 10ms timeout @ ZTIMER_MSEC...");
|
||||
before = ztimer_now(ZTIMER_USEC);
|
||||
tmp_evt = event_wait_timeout_ztimer(&tmp_eq, ZTIMER_MSEC, STATIC_TIMEOUT_MS);
|
||||
if (tmp_evt != NULL) {
|
||||
puts("[FAILED]");
|
||||
return 1;
|
||||
}
|
||||
diff = ztimer_now(ZTIMER_USEC) - before;
|
||||
printf("event_wait time out after %"PRIu32"us\n", diff);
|
||||
|
||||
thread_create(_stack, sizeof(_stack), PRIO, 0, _cnt_thread, NULL, "cnt");
|
||||
/* first, wait 155ms -> should lead to 3 timeout wakeups */
|
||||
ztimer_sleep(ZTIMER_MSEC, 155U);
|
||||
/* post event 3 times -> should lead to 3 event wakeups */
|
||||
for (unsigned i = 0; i < 3; i++) {
|
||||
event_post(&_evtq, &_evt);
|
||||
ztimer_sleep(ZTIMER_MSEC, 5U);
|
||||
}
|
||||
/* wait for 35ms and post another event -> +1 event wakeup */
|
||||
ztimer_sleep(ZTIMER_MSEC, 35U);
|
||||
event_post(&_evtq, &_evt);
|
||||
/* finally, wait 60ms and collect results -> +1 timeout wakeup */
|
||||
ztimer_sleep(ZTIMER_MSEC, 60U);
|
||||
|
||||
unsigned events = atomic_load(&_wakeup_evt);
|
||||
unsigned timeouts = atomic_load(&_wakeup_timeout);
|
||||
|
||||
/* rate results */
|
||||
printf("finished: %u/4 events and %u/4 timeouts recorded\n",
|
||||
events, timeouts);
|
||||
if ((events == 4) && (timeouts == 4)) {
|
||||
puts("[SUCCESS]");
|
||||
}
|
||||
else {
|
||||
puts("[FAILED]");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
19
tests/event_wait_timeout_ztimer/tests/01-run.py
Executable file
19
tests/event_wait_timeout_ztimer/tests/01-run.py
Executable file
@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2016 Kaspar Schleiser <kaspar@schleiser.de>
|
||||
# 2017 Sebastian Meiling <s@mlng.net>
|
||||
#
|
||||
# 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.
|
||||
|
||||
import sys
|
||||
from testrunner import run
|
||||
|
||||
|
||||
def testfunc(child):
|
||||
child.expect_exact(u"[SUCCESS]")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(run(testfunc))
|
Loading…
Reference in New Issue
Block a user