Merge pull request #11487 from haukepetersen/add_event_waituntil

sys/event: add event_wait_until()
This commit is contained in:
Kaspar Schleiser 2019-05-16 12:59:40 +02:00 committed by GitHub
commit 30d89b3f62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 185 additions and 1 deletions

View File

@ -29,6 +29,10 @@
#include "clist.h"
#include "thread.h"
#ifdef MODULE_XTIMER
#include "xtimer.h"
#endif
void event_queue_init_detached(event_queue_t *queue)
{
assert(queue);
@ -110,6 +114,30 @@ event_t *event_wait(event_queue_t *queue)
return result;
}
#ifdef MODULE_XTIMER
event_t *event_wait_timeout(event_queue_t *queue, uint32_t timeout)
{
assert(queue);
event_t *result;
xtimer_t timer;
thread_flags_t flags = 0;
xtimer_set_timeout_flag(&timer, timeout);
do {
result = event_get(queue);
if (result == NULL) {
flags = thread_flags_wait_any(THREAD_FLAG_EVENT | THREAD_FLAG_TIMEOUT);
}
} while ((result == NULL) && (flags & THREAD_FLAG_EVENT));
if (result) {
xtimer_remove(&timer);
}
return result;
}
#endif
void event_loop(event_queue_t *queue)
{
event_t *event;

View File

@ -1,7 +1,7 @@
/*
* Copyright (C) 2017 Inria
* 2017 Kaspar Schleiser <kaspar@schleiser.de>
* 2018 Freie Universität Berlin
* 2018-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
@ -231,6 +231,19 @@ event_t *event_get(event_queue_t *queue);
*/
event_t *event_wait(event_queue_t *queue);
#if defined(MODULE_XTIMER) || defined(DOXYGEN)
/**
* @brief Get next event from event queue, blocking until timeout expires
*
* @param[in] queue queue to query for an event
* @param[in] timeout maximum time to wait for an event to be posted in us
*
* @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(event_queue_t *queue, uint32_t timeout);
#endif
/**
* @brief Simple event loop
*

View File

@ -0,0 +1,12 @@
include ../Makefile.tests_common
BOARD_INSUFFICIENT_MEMORY := arduino-duemilanove arduino-nano arduino-uno
FORCE_ASSERTS = 1
USEMODULE += event
USEMODULE += xtimer
USEMODULE += core_thread_flags
TEST_ON_CI_WHITELIST += all
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,112 @@
/*
* 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 <stdio.h>
#include "event.h"
#include "thread.h"
#include "xtimer.h"
#include "thread_flags.h"
#define TIMEOUT (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 unsigned _wakeup_evt = 0;
static unsigned _wakeup_timeout = 0;
static void _on_evt(event_t *evt)
{
(void)evt;
++_wakeup_evt;
}
static void *_cnt_thread(void *arg)
{
(void)arg;
event_queue_init(&_evtq);
while (1) {
event_t *evt = event_wait_timeout(&_evtq, TIMEOUT);
if (evt) {
evt->handler(evt);
}
else {
++_wakeup_timeout;
}
}
return NULL;
}
int main(void)
{
/* setup */
_thread_main = (thread_t *)thread_get(thread_getpid());
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(&tmp_eq, 0);
if (tmp_evt != NULL) {
puts("[FAILED]");
return 1;
}
thread_create(_stack, sizeof(_stack), PRIO, 0, _cnt_thread, NULL, "cnt");
/* first, wait 155ms -> should lead to 3 timeout wakeups */
xtimer_usleep(155U * US_PER_MS);
/* post event 3 times -> should lead to 3 event wakeups */
for (unsigned i = 0; i < 3; i++) {
event_post(&_evtq, &_evt);
xtimer_usleep(5U * US_PER_MS);
}
/* wait for 35ms and post another event -> +1 event wakeup */
xtimer_usleep(35U * US_PER_MS);
event_post(&_evtq, &_evt);
/* finally, wait 60ms and collect results -> +1 timeout wakeup */
xtimer_usleep(60U * US_PER_MS);
unsigned events = _wakeup_evt;
unsigned timeouts = _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;
}

View 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))