Function riot_sys::mutex_cancel

source ·
pub unsafe extern "C" fn mutex_cancel(mc: *mut mutex_cancel_t)
Expand description

@brief Cancels a call to @ref mutex_lock_cancelable

@param[in,out] mc Mutex cancellation structure referring to the thread calling @ref mutex_lock_cancelable and to the mutex to cancel the operation on

@note This function is considered internal. Out of tree users should be aware that breaking API changes or removal of this API without an deprecation period might happen.

@pre @p mc is used to cancel at most one call to @ref mutex_lock_cancelable. (You can reinitialize the same memory to safely reuse it.) @warning You MUST NOT call this function once the thread referred to by @p mc reuses the mutex object referred to by @p mc (not counting the call to @ref mutex_lock_cancelable @p mc was used in). @note It is safe to call this function from IRQ context, e.g. from a timer interrupt. @note It is safe to call this function more than once on the same @p mc while it is still valid (see the warning above). The first call will cancel the operation and subsequent calls will have no effect.

@details If @p thread is currently running (or pending), a subsequent call from @p thread to @ref mutex_lock_cancelable will also fail

Canonical use:

static void timeout_cb(void *arg) {
    mutex_cancel(arg);
}

int ztimer_mutex_lock_timeout(ztimer_clock_t *clock, mutex_t *mutex,
                              uint32_t timeout)
{
    mutex_cancel_t mc = mutex_cancel_init(mutex);
    ztimer_t t = { .callback = timeout_cb, .arg = &mc };
    ztimer_set(clock, &t, timeout);
    if (mutex_lock_cancelable(&mc)) {
        return -ECANCELED;
    }
    ztimer_remove(clock, &t);
    return 0;
}

In the above example a simple implementation of how to implement mutex locking with a timeout is given. There are two corner cases:

  1. The call to @ref mutex_cancel could occur before the call to @ref mutex_lock_cancelable. (E.g. for timeout == 0.)
  2. The call to @ref mutex_cancel could occur right after the mutex was successfully obtained, but before ztimer_remove() was executed.

In the first corner case the cancellation is stored in @p mc. Hence, the subsequent call to @ref mutex_lock_cancelable gets indeed canceled. In the second corner case the cancellation is also stored in @p mc but never used - the mutex cancellation structure @p mc is not allowed to be reused without reinitialization.