1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

sys/sema: allow to use ztimer and/or xtimer

This commit is contained in:
Hauke Petersen 2021-01-15 15:57:46 +01:00
parent a4c479ca53
commit b339e91e18
3 changed files with 148 additions and 27 deletions

View File

@ -626,10 +626,6 @@ ifneq (,$(filter posix_inet,$(USEMODULE)))
USEMODULE += posix_headers
endif
ifneq (,$(filter sema,$(USEMODULE)))
USEMODULE += xtimer
endif
ifneq (,$(filter sema_inv,$(USEMODULE)))
USEMODULE += atomic_utils
endif

View File

@ -29,6 +29,10 @@
#include "mutex.h"
#if IS_USED(MODULE_ZTIMER)
#include "ztimer.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -109,6 +113,7 @@ static inline unsigned sema_get_value(const sema_t *sema)
return sema->value;
}
#if IS_USED(MODULE_XTIMER) || !IS_USED(MODULE_ZTIMER)
/**
* @brief Wait for a semaphore, blocking or non-blocking.
*
@ -127,8 +132,73 @@ static inline unsigned sema_get_value(const sema_t *sema)
* @return -ECANCELED, if the semaphore was destroyed.
* @return -EAGAIN, if the semaphore is not posted (only if block = 0)
*/
int _sema_wait(sema_t *sema, int block, uint64_t timeout);
int _sema_wait_xtimer(sema_t *sema, int block, uint64_t timeout);
#endif
#if IS_USED(MODULE_ZTIMER)
/**
* @brief Wait for a semaphore, blocking or non-blocking.
*
* @details For commit purposes you should probably use sema_wait(),
* sema_wait_timed_ztimer() and sema_try_wait() instead.
*
* @pre `(sema != NULL)`
*
* @param[in] sema A semaphore.
* @param[in] block if true, block until semaphore is available.
* @param[in] clock ztimer clock
* @param[in] timeout if blocking, ticks of @p clock until the semaphore
* times out. 0 waits forever.
*
* @return 0 on success
* @return -ETIMEDOUT, if the semaphore times out.
* @return -ECANCELED, if the semaphore was destroyed.
* @return -EAGAIN, if the semaphore is not posted (only if block = 0)
*/
int _sema_wait_ztimer(sema_t *sema, int block,
ztimer_clock_t *clock, uint32_t timeout);
#endif
/**
* @brief Wait for a semaphore being posted (without timeout).
*
* @pre `(sema != NULL)`
*
* @param[in] sema A semaphore.
*
* @return 0 on success
* @return -ECANCELED, if the semaphore was destroyed.
*/
static inline int sema_wait(sema_t *sema)
{
#if IS_USED(MODULE_ZTIMER)
return _sema_wait_ztimer(sema, 1, NULL, 0);
#else
return _sema_wait_xtimer(sema, 1, 0);
#endif
}
/**
* @brief Test if the semaphore is posted
*
* @pre `(sema != NULL)`
*
* This is a non-blocking alternative to @ref sema_wait.
*
* @return 0 on success
* @return -EAGAIN, if the semaphore is not posted.
* @return -ECANCELED, if the semaphore was destroyed.
*/
static inline int sema_try_wait(sema_t *sema)
{
#if IS_USED(MODULE_ZTIMER)
return _sema_wait_ztimer(sema, 0, NULL, 0);
#else
return _sema_wait_xtimer(sema, 0, 0);
#endif
}
#if IS_USED(MODULE_XTIMER) || defined(DOXYGEN)
/**
* @brief Wait for a semaphore being posted.
*
@ -145,39 +215,34 @@ int _sema_wait(sema_t *sema, int block, uint64_t timeout);
*/
static inline int sema_wait_timed(sema_t *sema, uint64_t timeout)
{
return _sema_wait(sema, (timeout != 0), timeout);
return _sema_wait_xtimer(sema, (timeout != 0), timeout);
}
#endif
#if IS_USED(MODULE_ZTIMER) || defined(DOXYGEN)
/**
* @brief Wait for a semaphore being posted (without timeout).
* @brief Wait for a semaphore being posted, using ztimer as backend
*
* @pre `(sema != NULL)`
* @pre `(clock != NULL)`
*
* @param[in] sema A semaphore.
* @param[in] sema A semaphore.
* @param[in] clock ztimer clock to use
* @param[in] timeout Time in microseconds until the semaphore times out.
* 0 does not wait.
*
* @return 0 on success
* @return -ETIMEDOUT, if the semaphore times out.
* @return -ECANCELED, if the semaphore was destroyed.
* @return -EAGAIN, if the semaphore is not posted (only if timeout = 0)
*/
static inline int sema_wait(sema_t *sema)
static inline int sema_wait_timed_ztimer(sema_t *sema,
ztimer_clock_t *clock,
uint32_t timeout)
{
return _sema_wait(sema, 1, 0);
}
/**
* @brief Test if the semaphore is posted
*
* @pre `(sema != NULL)`
*
* This is a non-blocking alternative to @ref sema_wait.
*
* @return 0 on success
* @return -EAGAIN, if the semaphore is not posted.
* @return -ECANCELED, if the semaphore was destroyed.
*/
static inline int sema_try_wait(sema_t *sema)
{
return _sema_wait(sema, 0, 0);
return _sema_wait_ztimer(sema, (timeout != 0), clock, timeout);
}
#endif
/**
* @brief Signal semaphore.

View File

@ -21,7 +21,10 @@
#include "irq.h"
#include "assert.h"
#include "sema.h"
#if IS_USED(MODULE_XTIMER)
#include "xtimer.h"
#endif
#define ENABLE_DEBUG 0
#include "debug.h"
@ -46,7 +49,8 @@ void sema_destroy(sema_t *sema)
mutex_unlock(&sema->mutex);
}
int _sema_wait(sema_t *sema, int block, uint64_t us)
#if IS_USED(MODULE_XTIMER)
int _sema_wait_xtimer(sema_t *sema, int block, uint64_t us)
{
assert(sema != NULL);
@ -97,6 +101,62 @@ int _sema_wait(sema_t *sema, int block, uint64_t us)
return 0;
}
#endif
#if IS_USED(MODULE_ZTIMER)
int _sema_wait_ztimer(sema_t *sema, int block,
ztimer_clock_t *clock, uint32_t timeout)
{
assert(sema != NULL);
if (sema->state != SEMA_OK) {
return -ECANCELED;
}
int did_block = block;
unsigned old = irq_disable();
while ((sema->value == 0) && block) {
irq_restore(old);
if (timeout == 0) {
mutex_lock(&sema->mutex);
}
else {
ztimer_now_t start = ztimer_now(clock);
block = !ztimer_mutex_lock_timeout(clock, &sema->mutex, timeout);
uint32_t elapsed = (uint32_t)(ztimer_now(clock) - start);
if (elapsed < timeout) {
timeout -= elapsed;
}
else {
block = 0;
}
}
if (sema->state != SEMA_OK) {
mutex_unlock(&sema->mutex);
return -ECANCELED;
}
old = irq_disable();
}
if (sema->value == 0) {
irq_restore(old);
return (did_block) ? -ETIMEDOUT : -EAGAIN;
}
unsigned int value = --sema->value;
irq_restore(old);
/* only unlock mutex if it was a blocking operation */
if (did_block && value > 0) {
mutex_unlock(&sema->mutex);
}
return 0;
}
#endif
int sema_post(sema_t *sema)
{