Initial Release
This commit is contained in:
136
src/common/pico_sync/include/pico/mutex.h
Normal file
136
src/common/pico_sync/include/pico/mutex.h
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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;
|
||||
bool owned;
|
||||
int8_t owner;
|
||||
} 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
|
Reference in New Issue
Block a user