Skip to content

Commit

Permalink
sys/ztimer: implement ztimer_mbox_get_timeout()
Browse files Browse the repository at this point in the history
This function fetches a message from an mbox, possibly blocking if the
mbox has no message - but with a specified timeout.
  • Loading branch information
maribu committed Dec 30, 2024
1 parent 95fe972 commit eab7588
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 1 deletion.
19 changes: 18 additions & 1 deletion sys/include/ztimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,11 @@

#include <stdint.h>

#include "sched.h"
#include "mbox.h"
#include "msg.h"
#include "mutex.h"
#include "rmutex.h"
#include "sched.h"

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -530,6 +531,22 @@ int ztimer_msg_receive_timeout(ztimer_clock_t *clock, msg_t *msg,
/* created with dist/tools/define2u16.py */
#define MSG_ZTIMER 0xc83e /**< msg type used by ztimer_msg_receive_timeout */

/**
* @brief Get message from mailbox, blocking with a timeout
*
* If the mailbox is empty, this function will block until a message becomes
* available or the timeout triggers
*
* @param[in] clock ztimer clock to operate on
* @param[in] mbox ptr to mailbox to operate on
* @param[in] msg ptr to storage for retrieved message
* @param[in] timeout relative timeout, in @p clock time units
*
* @retval 0 Got a message
* @retval -ETIMEDOUT Timeout triggered before a message was obtained
*/
int ztimer_mbox_get_timeout(ztimer_clock_t *clock, mbox_t *mbox, msg_t *msg, uint32_t timeout);

/**
* @brief ztimer_now() for extending timers
*
Expand Down
46 changes: 46 additions & 0 deletions sys/ztimer/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
#include "thread.h"
#include "ztimer.h"

#define ENABLE_DEBUG 0
#include "debug.h"

static void _callback_unlock_mutex(void *arg)
{
mutex_t *mutex = (mutex_t *)arg;
Expand Down Expand Up @@ -128,6 +131,49 @@ int ztimer_msg_receive_timeout(ztimer_clock_t *clock, msg_t *msg,

#endif /* MODULE_CORE_MSG */

#ifdef MODULE_CORE_MBOX
struct ztimer_mbox_thread_status {
ztimer_t timer;
mbox_t *mbox;
thread_t *thread;
int status;
};

static void _ztimer_mbox_get_timeout(void *arg)
{
struct ztimer_mbox_thread_status *data = arg;
if (!list_remove(&data->mbox->readers, &data->thread->rq_entry)) {
/* timeout triggered just after the message was received but before the
* timer was canceled. --> ignore the timeout */
DEBUG_PUTS("ztimer_mbox_get_timeout: timeout triggered, but message already received");
return;
}

sched_set_status(data->thread, STATUS_PENDING);
data->status = -ETIMEDOUT;
thread_yield_higher();
DEBUG_PUTS("ztimer_mbox_get_timeout: timeout triggered");
}

int ztimer_mbox_get_timeout(ztimer_clock_t *clock, mbox_t *mbox, msg_t *msg, uint32_t timeout)
{
struct ztimer_mbox_thread_status data = {
.timer = {
.arg = &data,
.callback = _ztimer_mbox_get_timeout,
},
.mbox = mbox,
.thread = thread_get_active(),
.status = 0,
};

ztimer_set(clock, &data.timer, timeout);
mbox_get(mbox, msg);
ztimer_remove(clock, &data.timer);
return data.status;
}
#endif

#ifdef MODULE_CORE_THREAD_FLAGS
static void _set_timeout_flag_callback(void *arg)
{
Expand Down

0 comments on commit eab7588

Please sign in to comment.