136 lines
4.1 KiB
C
136 lines
4.1 KiB
C
/*
|
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#ifndef _PLATFORM_MUTEX_H
|
|
#define _PLATFORM_MUTEX_H
|
|
|
|
#include "pico/lock_core.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/** \file mutex.h
|
|
* \defgroup mutex mutex
|
|
* \ingroup pico_sync
|
|
* \brief Mutex API for non IRQ mutual exclusion between cores
|
|
*
|
|
* Mutexes are application level locks usually used protecting data structures that might be used by
|
|
* multiple cores. Unlike critical sections, the mutex protected code is not necessarily
|
|
* required/expected to complete quickly, as no other sytemwide locks are held on account of a locked mutex.
|
|
*
|
|
* Because they are not re-entrant on the same core, blocking on a mutex should never be done in an IRQ
|
|
* handler. It is valid to call \ref mutex_try_enter from within an IRQ handler, if the operation
|
|
* that would be conducted under lock can be skipped if the mutex is locked (at least by the same core).
|
|
*
|
|
* See \ref critical_section.h for protecting access between multiple cores AND IRQ handlers
|
|
*/
|
|
|
|
typedef struct __packed_aligned mutex {
|
|
lock_core_t core;
|
|
int8_t owner; //! core number or -1 for unowned
|
|
} mutex_t;
|
|
|
|
/*! \brief Initialise a mutex structure
|
|
* \ingroup mutex
|
|
*
|
|
* \param mtx Pointer to mutex structure
|
|
*/
|
|
void mutex_init(mutex_t *mtx);
|
|
|
|
/*! \brief Take ownership of a mutex
|
|
* \ingroup mutex
|
|
*
|
|
* This function will block until the calling core can claim ownership of the mutex.
|
|
* On return the caller core owns the mutex
|
|
*
|
|
* \param mtx Pointer to mutex structure
|
|
*/
|
|
void mutex_enter_blocking(mutex_t *mtx);
|
|
|
|
/*! \brief Check to see if a mutex is available
|
|
* \ingroup mutex
|
|
*
|
|
* Will return true if the mutex is unowned, false otherwise
|
|
*
|
|
* \param mtx Pointer to mutex structure
|
|
* \param owner_out If mutex is owned, and this pointer is non-zero, it will be filled in with the core number of the current owner of the mutex
|
|
*/
|
|
bool mutex_try_enter(mutex_t *mtx, uint32_t *owner_out);
|
|
|
|
/*! \brief Wait for mutex with timeout
|
|
* \ingroup mutex
|
|
*
|
|
* Wait for up to the specific time to take ownership of the mutex. If the calling
|
|
* core can take ownership of the mutex before the timeout expires, then true will be returned
|
|
* and the calling core will own the mutex, otherwise false will be returned and the calling
|
|
* core will *NOT* own the mutex.
|
|
*
|
|
* \param mtx Pointer to mutex structure
|
|
* \param timeout_ms The timeout in milliseconds.
|
|
* \return true if mutex now owned, false if timeout occurred before mutex became available
|
|
*/
|
|
bool mutex_enter_timeout_ms(mutex_t *mtx, uint32_t timeout_ms);
|
|
|
|
/*! \brief Wait for mutex until a specific time
|
|
* \ingroup mutex
|
|
*
|
|
* Wait until the specific time to take ownership of the mutex. If the calling
|
|
* core can take ownership of the mutex before the timeout expires, then true will be returned
|
|
* and the calling core will own the mutex, otherwise false will be returned and the calling
|
|
* core will *NOT* own the mutex.
|
|
*
|
|
* \param mtx Pointer to mutex structure
|
|
* \param until The time after which to return if the core cannot take owner ship of the mutex
|
|
* \return true if mutex now owned, false if timeout occurred before mutex became available
|
|
*/
|
|
bool mutex_enter_block_until(mutex_t *mtx, absolute_time_t until);
|
|
|
|
/*! \brief Release ownership of a mutex
|
|
* \ingroup mutex
|
|
*
|
|
* \param mtx Pointer to mutex structure
|
|
*/
|
|
void mutex_exit(mutex_t *mtx);
|
|
|
|
/*! \brief Test for mutex initialised state
|
|
* \ingroup mutex
|
|
*
|
|
* \param mtx Pointer to mutex structure
|
|
* \return true if the mutex is initialised, false otherwise
|
|
*/
|
|
static inline bool mutex_is_initialzed(mutex_t *mtx) {
|
|
return mtx->core.spin_lock != 0;
|
|
}
|
|
|
|
/*! \brief Helper macro for static definition of mutexes
|
|
* \ingroup mutex
|
|
*
|
|
* A mutex defined as follows:
|
|
*
|
|
* ```c
|
|
* auto_init_mutex(my_mutex);
|
|
* ```
|
|
*
|
|
* Is equivalent to doing
|
|
*
|
|
* ```c
|
|
* static mutex_t my_mutex;
|
|
*
|
|
* void my_init_function() {
|
|
* mutex_init(&my_mutex);
|
|
* }
|
|
* ```
|
|
*
|
|
* But the initialization of the mutex is performed automatically during runtime initialization
|
|
*/
|
|
#define auto_init_mutex(name) static __attribute__((section(".mutex_array"))) mutex_t name
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif
|