From 247a13cc02a56e2e81742e81c3d122b7e1a920ab Mon Sep 17 00:00:00 2001 From: anjiahao Date: Thu, 12 May 2022 16:07:01 +0800 Subject: [PATCH] include:add recursive lock Signed-off-by: anjiahao --- include/nuttx/mutex.h | 213 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) diff --git a/include/nuttx/mutex.h b/include/nuttx/mutex.h index f52cd36d04..c15e1ece44 100644 --- a/include/nuttx/mutex.h +++ b/include/nuttx/mutex.h @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include /**************************************************************************** @@ -35,6 +37,7 @@ ****************************************************************************/ #define MUTEX_INITIALIZER SEM_INITIALIZER(1); +#define RMUTEX_INITIALIZER {SEM_INITIALIZER(1), INVALID_PROCESS_ID, 0} /**************************************************************************** * Public Type Definitions @@ -42,6 +45,15 @@ typedef sem_t mutex_t; +struct rmutex_s +{ + mutex_t mutex; + pid_t holder; + uint16_t count; +}; + +typedef struct rmutex_s rmutex_t; + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -205,6 +217,207 @@ static inline int nxmutex_unlock(FAR mutex_t *mutex) return nxsem_post(mutex); } +/**************************************************************************** + * Name: nxrmutex_init + * + * Description: + * This function initializes the UNNAMED recursive mutex. Following a + * successful call to nxrmutex_init(), the recursive mutex may be used in + * subsequent calls to nxrmutex_lock(), nxrmutex_unlock(), + * and nxrmutex_trylock(). The recursive mutex remains usable + * until it is destroyed. + * + * Parameters: + * rmutex - Recursive mutex to be initialized + * + * Return Value: + * This is an internal OS interface and should not be used by applications. + * It follows the NuttX internal error return policy: Zero (OK) is + * returned on success. A negated errno value is returned on failure. + * + ****************************************************************************/ + +static inline int nxrmutex_init(FAR rmutex_t *rmutex) +{ + rmutex->count = 0; + rmutex->holder = INVALID_PROCESS_ID; + return nxmutex_init(&rmutex->mutex); +} + +/**************************************************************************** + * Name: nxrmutex_destroy + * + * Description: + * This function destroy the UNNAMED recursive mutex. + * + * Parameters: + * rmutex - Recursive mutex to be destroyed + * + * Return Value: + * This is an internal OS interface and should not be used by applications. + * It follows the NuttX internal error return policy: Zero (OK) is + * returned on success. A negated errno value is returned on failure. + * + ****************************************************************************/ + +static inline int nxrmutex_destroy(FAR rmutex_t *rmutex) +{ + return nxmutex_destroy(&rmutex->mutex); +} + +/**************************************************************************** + * Name: nrxmutex_lock + * + * Description: + * This function attempts to lock the recursive mutex referenced by + * 'rmutex'.The recursive mutex can be locked multiple times in the same + * thread. + * + * Parameters: + * rmutex - Recursive mutex descriptor. + * + * Return Value: + * This is an internal OS interface and should not be used by applications. + * It follows the NuttX internal error return policy: Zero (OK) is + * returned on success. A negated errno value is returned on failure. + * Possible returned errors: + * + ****************************************************************************/ + +static inline int nxrmutex_lock(FAR rmutex_t *rmutex) +{ + int ret = OK; + pid_t tid = gettid(); + + if (rmutex->holder == tid) + { + DEBUGASSERT(rmutex->count < UINT16_MAX); + rmutex->count++; + } + else + { + ret = nxmutex_lock(&rmutex->mutex); + if (ret == OK) + { + rmutex->holder = tid; + rmutex->count = 1; + } + } + + return ret; +} + +/**************************************************************************** + * Name: nxrmutex_trylock + * + * Description: + * This function locks the recursive mutex if the recursive mutex is + * currently not locked or the same thread call. + * If the recursive mutex is locked and other thread call it, + * the call returns without blocking. + * + * Parameters: + * rmutex - Recursive mutex descriptor. + * + * Return Value: + * This is an internal OS interface and should not be used by applications. + * It follows the NuttX internal error return policy: Zero (OK) is + * returned on success. A negated errno value is returned on failure. + * Possible returned errors: + * + * -EINVAL - Invalid attempt to lock the recursive mutex + * -EAGAIN - The recursive mutex is not available. + * + ****************************************************************************/ + +static inline int nxrmutex_trylock(FAR rmutex_t *rmutex) +{ + int ret = OK; + pid_t tid = gettid(); + + if (rmutex->holder == tid) + { + DEBUGASSERT(rmutex->count < UINT16_MAX); + rmutex->count++; + } + else + { + ret = nxmutex_trylock(&rmutex->mutex); + if (ret == OK) + { + rmutex->holder = tid; + rmutex->count = 1; + } + } + + return ret; +} + +/**************************************************************************** + * Name: nxrmutex_is_locked + * + * Description: + * This function get the lock state the recursive mutex + * referenced by 'rmutex'. + * + * Parameters: + * rmutex - Recursive mutex descriptor. + * + * Return Value: + * + ****************************************************************************/ + +static inline bool nxrmutex_is_locked(FAR rmutex_t *rmutex) +{ + return rmutex->count > 0; +} + +/**************************************************************************** + * Name: nxrmutex_unlock + * + * Description: + * This function attempts to unlock the recursive mutex + * referenced by 'rmutex'. + * + * Parameters: + * rmutex - Recursive mutex descriptor. + * + * Return Value: + * This is an internal OS interface and should not be used by applications. + * It follows the NuttX internal error return policy: Zero (OK) is + * returned on success. A negated errno value is returned on failure. + * Possible returned errors: + * + * Assumptions: + * This function may be called from an interrupt handler. + * + ****************************************************************************/ + +static inline int nxrmutex_unlock(FAR rmutex_t *rmutex) +{ + int ret = OK; + pid_t tid = gettid(); + + if (rmutex->holder != tid) + { + return -EPERM; + } + + DEBUGASSERT(rmutex->count > 0); + if (rmutex->count == 1) + { + rmutex->count = 0; + rmutex->holder = INVALID_PROCESS_ID; + ret = nxmutex_unlock(&rmutex->mutex); + } + else + { + rmutex->count--; + } + + return ret; +} + #undef EXTERN #ifdef __cplusplus }