Skip to content

Commit

Permalink
sys/ztimer: add ztimer_mbox_get_timeout()
Browse files Browse the repository at this point in the history
  • Loading branch information
maribu committed Nov 13, 2023
1 parent 512c1ae commit 2ff0292
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 2 deletions.
23 changes: 23 additions & 0 deletions sys/include/ztimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,29 @@ int ztimer_mutex_lock_timeout(ztimer_clock_t *clock, mutex_t *mutex,
int ztimer_rmutex_lock_timeout(ztimer_clock_t *clock, rmutex_t *rmutex,
uint32_t timeout);

/**
* @brief Try to get a message from a mbox, but give up after @p timeout
*
* @param[in] clock ztimer clock to operate on
* @param[in,out] mbox message box to get the message out
* @param[out] dest pointer to storage to write retrieve message to
* @param[in] timeout timeout after which to give up
*
* @retval 0 Success, retrieve message written to @p dest
* @retval -ECANCELED Timeout triggered without a message received
*
* @warning This function is ***not stable*** and was rushed into a release
* to fix a nasty bug. Do not start using this API yet.
* @note This function will only be available if both the `core_mbox` and
* the `core_thread_flags` module is used.
* @warning This function will the `thread_flags` flag `THREAD_FLAG_TIMEOUT`
* internally and will clear this flag in the process. If this flag
* gets set on the calling thread by other means, a premature timeout
* will be caused. Avoid using this flag on the thread of the caller.
*/
int ztimer_mbox_get_timeout(ztimer_clock_t *clock, mbox_t *mbox, msg_t *dest,
uint32_t timeout);

/**
* @brief Initialize the board-specific default ztimer configuration
*/
Expand Down
36 changes: 34 additions & 2 deletions sys/ztimer/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ void ztimer_set_wakeup(ztimer_clock_t *clock, ztimer_t *timer, uint32_t offset,
ztimer_set(clock, timer, offset);
}

static void timeout_cb(void *arg)
static void timeout_cb_mutex_cancel(void *arg)
{
mutex_cancel(arg);
}
Expand All @@ -185,7 +185,7 @@ int ztimer_mutex_lock_timeout(ztimer_clock_t *clock, mutex_t *mutex,
}

mutex_cancel_t mc = mutex_cancel_init(mutex);
ztimer_t t = { .callback = timeout_cb, .arg = &mc };
ztimer_t t = { .callback = timeout_cb_mutex_cancel, .arg = &mc };

ztimer_set(clock, &t, timeout);
if (mutex_lock_cancelable(&mc)) {
Expand All @@ -209,3 +209,35 @@ int ztimer_rmutex_lock_timeout(ztimer_clock_t *clock, rmutex_t *rmutex,
}
return -ECANCELED;
}

#if MODULE_CORE_THREAD_FLAGS && MODULE_CORE_MBOX
static void timeout_cb_thread_flags(void *arg)
{
thread_flags_set(arg, THREAD_FLAG_TIMEOUT);
}

int ztimer_mbox_get_timeout(ztimer_clock_t *clock, mbox_t *mbox, msg_t *dest,
uint32_t timeout)
{
/* Optimize for the high load case: Message is already in the mbox, don't
* waste time out setting up a timeout */
if (mbox_try_get(mbox, dest)) {
return 0;
}

/* Clear any timeout flag to avoid short timeout */
thread_flags_clear(THREAD_FLAG_TIMEOUT);
ztimer_t t = {
.callback = timeout_cb_thread_flags, .arg = thread_get_active()
};

ztimer_set(clock, &t, timeout);

if (0 == thread_flags_wait_any_or_mbox(mbox, dest, THREAD_FLAG_TIMEOUT)) {
ztimer_remove(clock, &t);
return 0;
}

return -ECANCELED;
}
#endif /* module core_thread_flags and core_mbox in use */

0 comments on commit 2ff0292

Please sign in to comment.