From 156469f158753db41d39d08008aa1ae978af1a47 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Wed, 23 Apr 2025 19:23:22 +0300 Subject: [PATCH] Clean up the nxmutex library - Remove the redundant holder, as nxsem now manages hoder TID - Remove DEBUGASSERTIONS which are managed in nxsem - Remove the "reset" handling logic, as it is now managed in nxsem - Inline the simplest functions Signed-off-by: Jukka Laitinen --- include/nuttx/mutex.h | 852 +++++++++++++++++------------- include/pthread.h | 3 +- libs/libc/misc/lib_mutex.c | 558 +------------------ sched/misc/deadlock.c | 4 +- sched/sched/sched_get_stateinfo.c | 2 +- 5 files changed, 501 insertions(+), 918 deletions(-) diff --git a/include/nuttx/mutex.h b/include/nuttx/mutex.h index e0e75a78787..f2727f8395b 100644 --- a/include/nuttx/mutex.h +++ b/include/nuttx/mutex.h @@ -36,10 +36,8 @@ * Pre-processor Definitions ****************************************************************************/ -#define NXMUTEX_NO_HOLDER ((pid_t)-1) -#define NXMUTEX_INITIALIZER { \ - NXSEM_INITIALIZER(NXSEM_NO_MHOLDER, SEM_TYPE_MUTEX | SEM_PRIO_INHERIT), \ - NXMUTEX_NO_HOLDER} +#define NXMUTEX_INITIALIZER \ + {NXSEM_INITIALIZER(NXSEM_NO_MHOLDER, SEM_TYPE_MUTEX | SEM_PRIO_INHERIT)} #define NXRMUTEX_INITIALIZER {NXMUTEX_INITIALIZER, 0} @@ -50,7 +48,6 @@ struct mutex_s { sem_t sem; - pid_t holder; #if CONFIG_LIBC_MUTEX_BACKTRACE > 0 FAR void *backtrace[CONFIG_LIBC_MUTEX_BACKTRACE]; #endif @@ -80,6 +77,25 @@ extern "C" #define EXTERN extern #endif +/**************************************************************************** + * Name: nxmutex_add_backtrace + * + * Description: + * This function add the backtrace of the holder of the mutex. + * + * Parameters: + * mutex - mutex descriptor. + * + * Return Value: + * + ****************************************************************************/ + +#if CONFIG_LIBC_MUTEX_BACKTRACE > 0 +void nxmutex_add_backtrace(FAR mutex_t *mutex); +#else +# define nxmutex_add_backtrace(mutex) +#endif + /**************************************************************************** * Name: nxmutex_init * @@ -101,27 +117,6 @@ extern "C" int nxmutex_init(FAR mutex_t *mutex); -/**************************************************************************** - * Name: nxmutex_destroy - * - * Description: - * This function initializes the UNNAMED mutex. Following a - * successful call to nxmutex_init(), the mutex may be used in subsequent - * calls to nxmutex_lock(), nxmutex_unlock(), and nxmutex_trylock(). The - * mutex remains usable until it is destroyed. - * - * Parameters: - * mutex - Semaphore 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. - * - ****************************************************************************/ - -int nxmutex_destroy(FAR mutex_t *mutex); - /**************************************************************************** * Name: nxmutex_is_hold * @@ -138,85 +133,6 @@ int nxmutex_destroy(FAR mutex_t *mutex); bool nxmutex_is_hold(FAR mutex_t *mutex); -/**************************************************************************** - * Name: nxmutex_get_holder - * - * Description: - * This function get the holder of the mutex referenced by 'mutex'. - * Note that this is inherently racy unless the calling thread is - * holding the mutex. - * - * Parameters: - * mutex - mutex descriptor. - * - * Return Value: - * - ****************************************************************************/ - -int nxmutex_get_holder(FAR mutex_t *mutex); - -/**************************************************************************** - * Name: nxmutex_is_locked - * - * Description: - * This function get the lock state the mutex referenced by 'mutex'. - * Note that this is inherently racy unless the calling thread is - * holding the mutex. - * - * Parameters: - * mutex - mutex descriptor. - * - * Return Value: - * - ****************************************************************************/ - -bool nxmutex_is_locked(FAR mutex_t *mutex); - -/**************************************************************************** - * Name: nxmutex_lock - * - * Description: - * This function attempts to lock the mutex referenced by 'mutex'. The - * mutex is implemented with a semaphore, so if the semaphore value is - * (<=) zero, then the calling task will not return until it successfully - * acquires the lock. - * - * Parameters: - * mutex - 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: - * - ****************************************************************************/ - -int nxmutex_lock(FAR mutex_t *mutex); - -/**************************************************************************** - * Name: nxmutex_trylock - * - * Description: - * This function locks the mutex only if the mutex is currently not locked. - * If the mutex has been locked already, the call returns without blocking. - * - * Parameters: - * mutex - 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 mutex - * -EAGAIN - The mutex is not available. - * - ****************************************************************************/ - -int nxmutex_trylock(FAR mutex_t *mutex); - /**************************************************************************** * Name: nxmutex_ticklock * @@ -299,252 +215,6 @@ int nxmutex_clocklock(FAR mutex_t *mutex, clockid_t clockid, int nxmutex_timedlock(FAR mutex_t *mutex, unsigned int timeout); -/**************************************************************************** - * Name: nxmutex_unlock - * - * Description: - * This function attempts to unlock the mutex referenced by 'mutex'. - * - * Parameters: - * mutex - 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. - * - ****************************************************************************/ - -int nxmutex_unlock(FAR mutex_t *mutex); - -/**************************************************************************** - * Name: nxmutex_reset - * - * Description: - * This function reset lock state. - * - * Parameters: - * mutex - mutex descriptor. - * - ****************************************************************************/ - -#if defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__) -void nxmutex_reset(FAR mutex_t *mutex); -#endif - -/**************************************************************************** - * Name: nxmutex_breaklock - * - * Description: - * This function attempts to break the mutex - * - * Parameters: - * mutex - Mutex descriptor. - * locked - Is the mutex break success - * - * 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: - * - ****************************************************************************/ - -int nxmutex_breaklock(FAR mutex_t *mutex, FAR unsigned int *locked); - -/**************************************************************************** - * Name: nxmutex_restorelock - * - * Description: - * This function attempts to restore the mutex. - * - * Parameters: - * mutex - mutex descriptor. - * locked - true: it's mean that the mutex is broke success - * - * 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 - * - ****************************************************************************/ - -int nxmutex_restorelock(FAR mutex_t *mutex, unsigned int locked); - -/**************************************************************************** - * Name: nxmutex_set_protocol - * - * Description: - * This function attempts to set the priority protocol of a mutex. - * - * Parameters: - * mutex - mutex descriptor. - * protocol - mutex protocol value to set. - * - * 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 - * - ****************************************************************************/ - -int nxmutex_set_protocol(FAR mutex_t *mutex, int protocol); - -/**************************************************************************** - * Name: nxmutex_getprioceiling - * - * Description: - * This function attempts to get the priority ceiling of a mutex. - * - * Parameters: - * mutex - mutex descriptor. - * prioceiling - location to return the mutex priority ceiling. - * - * 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 - * - ****************************************************************************/ - -int nxmutex_getprioceiling(FAR const mutex_t *mutex, FAR int *prioceiling); - -/**************************************************************************** - * Name: nxmutex_setprioceiling - * - * Description: - * This function attempts to set the priority ceiling of a mutex. - * - * Parameters: - * mutex - mutex descriptor. - * prioceiling - mutex priority ceiling value to set. - * old_ceiling - location to return the mutex ceiling priority set before. - * - * 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 - * - ****************************************************************************/ - -int nxmutex_setprioceiling(FAR mutex_t *mutex, int prioceiling, - FAR int *old_ceiling); - -/**************************************************************************** - * 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. - * - ****************************************************************************/ - -int nxrmutex_init(FAR rmutex_t *rmutex); - -/**************************************************************************** - * 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. - * - ****************************************************************************/ - -int nxrmutex_destroy(FAR rmutex_t *rmutex); - -/**************************************************************************** - * Name: nxrmutex_is_hold - * - * Description: - * This function check whether the calling thread hold the recursive mutex - * referenced by 'rmutex'. - * - * Parameters: - * rmutex - Recursive mutex descriptor. - * - * Return Value: - * - ****************************************************************************/ - -bool nxrmutex_is_hold(FAR rmutex_t *rmutex); - -/**************************************************************************** - * Name: nxrmutex_is_recursive - * - * Description: - * This function check whether the recursive mutex is currently held - * recursively. That is, whether it's locked more than once by the - * current holder. - * Note that this is inherently racy unless the calling thread is - * holding the mutex. - * - * Parameters: - * rmutex - Recursive mutex descriptor. - * - * Return Value: - * If rmutex has returned to True recursively, otherwise returns false. - * - ****************************************************************************/ - -bool nxrmutex_is_recursive(FAR rmutex_t *rmutex); - -/**************************************************************************** - * Name: nxrmutex_get_holder - * - * Description: - * This function get the holder of the mutex referenced by 'mutex'. - * Note that this is inherently racy unless the calling thread is - * holding the mutex. - * - * Parameters: - * rmutex - Rmutex descriptor. - * - * Return Value: - * - ****************************************************************************/ - -int nxrmutex_get_holder(FAR rmutex_t *rmutex); - -/**************************************************************************** - * Name: nxrmutex_is_locked - * - * Description: - * This function get the lock state the recursive mutex - * referenced by 'rmutex'. - * Note that this is inherently racy unless the calling thread is - * holding the mutex. - * - * Parameters: - * rmutex - Recursive mutex descriptor. - * - * Return Value: - * - ****************************************************************************/ - -bool nxrmutex_is_locked(FAR rmutex_t *rmutex); - /**************************************************************************** * Name: nrxmutex_lock * @@ -697,20 +367,6 @@ int nxrmutex_timedlock(FAR rmutex_t *rmutex, unsigned int timeout); int nxrmutex_unlock(FAR rmutex_t *rmutex); -/**************************************************************************** - * Name: nxrmutex_reset - * - * Description: - * This function reset lock state. - * - * Parameters: - * rmutex - rmutex descriptor. - * - ****************************************************************************/ -#if defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__) -void nxrmutex_reset(FAR rmutex_t *rmutex); -#endif - /**************************************************************************** * Name: nrxmutex_breaklock * @@ -756,6 +412,472 @@ int nxrmutex_restorelock(FAR rmutex_t *rmutex, unsigned int count); #define nxrmutex_setprioceiling(rmutex, prioceiling, old_ceiling) \ nxmutex_setprioceiling(&(rmutex)->mutex, prioceiling, old_ceiling) +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxmutex_get_holder + * + * Description: + * This function get the holder of the mutex referenced by 'mutex'. + * Note that this is inherently racy unless the calling thread is + * holding the mutex. + * + * Parameters: + * mutex - mutex descriptor. + * + * Return Value: + * + ****************************************************************************/ + +static inline_function pid_t nxmutex_get_holder(FAR mutex_t *mutex) +{ + uint32_t mholder = mutex->sem.val.mholder & ~NXSEM_MBLOCKING_BIT; + return NXSEM_MACQUIRED(mholder) ? (pid_t)mholder : -1; +} + +/**************************************************************************** + * Name: nxmutex_is_locked + * + * Description: + * This function get the lock state the mutex referenced by 'mutex'. + * Note that this is inherently racy unless the calling thread is + * holding the mutex. + * + * Parameters: + * mutex - mutex descriptor. + * + * Return Value: + * + ****************************************************************************/ + +static inline_function bool nxmutex_is_locked(FAR mutex_t *mutex) +{ + return NXSEM_MACQUIRED(mutex->sem.val.mholder); +} + +/**************************************************************************** + * Name: nxmutex_destroy + * + * Description: + * This function initializes the UNNAMED mutex. Following a + * successful call to nxmutex_init(), the mutex may be used in subsequent + * calls to nxmutex_lock(), nxmutex_unlock(), and nxmutex_trylock(). The + * mutex remains usable until it is destroyed. + * + * Parameters: + * mutex - Semaphore 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_function int nxmutex_destroy(FAR mutex_t *mutex) +{ + return nxsem_destroy(&mutex->sem); +} + +/**************************************************************************** + * Name: nxmutex_lock + * + * Description: + * This function attempts to lock the mutex referenced by 'mutex'. The + * mutex is implemented with a semaphore, so if the semaphore value is + * (<=) zero, then the calling task will not return until it successfully + * acquires the lock. + * + * Parameters: + * mutex - 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_function int nxmutex_lock(FAR mutex_t *mutex) +{ + int ret; + + ret = nxsem_wait(&mutex->sem); + if (ret >= 0) + { + nxmutex_add_backtrace(mutex); + } + + return ret; +} + +/**************************************************************************** + * Name: nxmutex_trylock + * + * Description: + * This function locks the mutex only if the mutex is currently not locked. + * If the mutex has been locked already, the call returns without blocking. + * + * Parameters: + * mutex - 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 mutex + * -EAGAIN - The mutex is not available. + * + ****************************************************************************/ + +static inline_function int nxmutex_trylock(FAR mutex_t *mutex) +{ + int ret; + + ret = nxsem_trywait(&mutex->sem); + if (ret >= 0) + { + nxmutex_add_backtrace(mutex); + } + + return ret; +} + +/**************************************************************************** + * Name: nxmutex_unlock + * + * Description: + * This function attempts to unlock the mutex referenced by 'mutex'. + * + * Parameters: + * mutex - 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_function int nxmutex_unlock(FAR mutex_t *mutex) +{ + return nxsem_post(&mutex->sem); +} + +/**************************************************************************** + * Name: nxmutex_reset + * + * Description: + * This function reset lock state. + * + * Parameters: + * mutex - mutex descriptor. + * + ****************************************************************************/ + +#if defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__) +static inline_function void nxmutex_reset(FAR mutex_t *mutex) +{ + nxsem_reset(&mutex->sem, 1); +} +#endif + +/**************************************************************************** + * Name: nxmutex_breaklock + * + * Description: + * This function attempts to break the mutex + * + * Parameters: + * mutex - Mutex descriptor. + * locked - Is the mutex break success + * + * 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_function int nxmutex_breaklock(FAR mutex_t *mutex, + FAR unsigned int *locked) +{ + int ret = OK; + + *locked = false; + ret = nxmutex_unlock(mutex); + if (ret >= 0) + { + *locked = true; + } + + return ret; +} + +/**************************************************************************** + * Name: nxmutex_restorelock + * + * Description: + * This function attempts to restore the mutex. + * + * Parameters: + * mutex - mutex descriptor. + * locked - true: it's mean that the mutex is broke success + * + * 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_function int nxmutex_restorelock(FAR mutex_t *mutex, + unsigned int locked) +{ + return locked ? nxmutex_lock(mutex) : OK; +} + +/**************************************************************************** + * Name: nxmutex_set_protocol + * + * Description: + * This function attempts to set the priority protocol of a mutex. + * + * Parameters: + * mutex - mutex descriptor. + * protocol - mutex protocol value to set. + * + * 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_function int nxmutex_set_protocol(FAR mutex_t *mutex, + int protocol) +{ + return nxsem_set_protocol(&mutex->sem, protocol); +} + +/**************************************************************************** + * Name: nxmutex_getprioceiling + * + * Description: + * This function attempts to get the priority ceiling of a mutex. + * + * Parameters: + * mutex - mutex descriptor. + * prioceiling - location to return the mutex priority ceiling. + * + * 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 + * + ****************************************************************************/ + +#ifdef CONFIG_PRIORITY_PROTECT +static inline_function int nxmutex_getprioceiling(FAR const mutex_t *mutex, + FAR int *prioceiling) +{ + return nxsem_getprioceiling(&mutex->sem, prioceiling); +} +#endif + +/**************************************************************************** + * Name: nxmutex_setprioceiling + * + * Description: + * This function attempts to set the priority ceiling of a mutex. + * + * Parameters: + * mutex - mutex descriptor. + * prioceiling - mutex priority ceiling value to set. + * old_ceiling - location to return the mutex ceiling priority set before. + * + * 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 + * + ****************************************************************************/ + +#ifdef CONFIG_PRIORITY_PROTECT +static inline_function int nxmutex_setprioceiling(FAR mutex_t *mutex, + int prioceiling, + FAR int *old_ceiling) +{ + return nxsem_setprioceiling(&mutex->sem, prioceiling, old_ceiling); +} +#endif + +/**************************************************************************** + * 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_function int nxrmutex_init(FAR rmutex_t *rmutex) +{ + rmutex->count = 0; + 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_function int nxrmutex_destroy(FAR rmutex_t *rmutex) +{ + int ret = nxmutex_destroy(&rmutex->mutex); + + if (ret >= 0) + { + rmutex->count = 0; + } + + return ret; +} + +/**************************************************************************** + * Name: nxrmutex_is_hold + * + * Description: + * This function check whether the calling thread hold the recursive mutex + * referenced by 'rmutex'. + * + * Parameters: + * rmutex - Recursive mutex descriptor. + * + * Return Value: + * + ****************************************************************************/ + +static inline_function bool nxrmutex_is_hold(FAR rmutex_t *rmutex) +{ + return nxmutex_is_hold(&rmutex->mutex); +} + +/**************************************************************************** + * Name: nxrmutex_is_recursive + * + * Description: + * This function check whether the recursive mutex is currently held + * recursively. That is, whether it's locked more than once by the + * current holder. + * Note that this is inherently racy unless the calling thread is + * holding the mutex. + * + * Parameters: + * rmutex - Recursive mutex descriptor. + * + * Return Value: + * If rmutex has returned to True recursively, otherwise returns false. + * + ****************************************************************************/ + +static inline_function bool nxrmutex_is_recursive(FAR rmutex_t *rmutex) +{ + return rmutex->count > 1; +} + +/**************************************************************************** + * Name: nxrmutex_get_holder + * + * Description: + * This function get the holder of the mutex referenced by 'mutex'. + * Note that this is inherently racy unless the calling thread is + * holding the mutex. + * + * Parameters: + * rmutex - Rmutex descriptor. + * + * Return Value: + * + ****************************************************************************/ + +static inline_function int nxrmutex_get_holder(FAR rmutex_t *rmutex) +{ + return nxmutex_get_holder(&rmutex->mutex); +} + +/**************************************************************************** + * Name: nxrmutex_is_locked + * + * Description: + * This function get the lock state the recursive mutex + * referenced by 'rmutex'. + * Note that this is inherently racy unless the calling thread is + * holding the mutex. + * + * Parameters: + * rmutex - Recursive mutex descriptor. + * + * Return Value: + * + ****************************************************************************/ + +static inline_function bool nxrmutex_is_locked(FAR rmutex_t *rmutex) +{ + return nxmutex_is_locked(&rmutex->mutex); +} + +/**************************************************************************** + * Name: nxrmutex_reset + * + * Description: + * This function reset lock state. + * + * Parameters: + * rmutex - rmutex descriptor. + * + ****************************************************************************/ + +#if defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__) +static inline_function void nxrmutex_reset(FAR rmutex_t *rmutex) +{ + rmutex->count = 0; + nxmutex_reset(&rmutex->mutex); +} +#endif + #undef EXTERN #ifdef __cplusplus } diff --git a/include/pthread.h b/include/pthread.h index 37fb220cf22..ef6a831af7d 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -350,8 +350,7 @@ typedef struct pthread_mutex_s pthread_mutex_t; #define PTHREAD_NXMUTEX_INITIALIZER { \ NXSEM_INITIALIZER(NXSEM_NO_MHOLDER, \ - SEM_TYPE_MUTEX | PTHREAD_MUTEX_DEFAULT_PRIO_FLAGS), \ - NXMUTEX_NO_HOLDER} + SEM_TYPE_MUTEX | PTHREAD_MUTEX_DEFAULT_PRIO_FLAGS)} #define PTHREAD_NXRMUTEX_INITIALIZER {PTHREAD_NXMUTEX_INITIALIZER, 0} #if defined(CONFIG_PTHREAD_MUTEX_TYPES) && !defined(CONFIG_PTHREAD_MUTEX_UNSAFE) diff --git a/libs/libc/misc/lib_mutex.c b/libs/libc/misc/lib_mutex.c index d9e030a4c42..bdc89a2d434 100644 --- a/libs/libc/misc/lib_mutex.c +++ b/libs/libc/misc/lib_mutex.c @@ -32,33 +32,9 @@ #include /**************************************************************************** - * Pre-processor Definitions + * Public Functions ****************************************************************************/ -#define NXMUTEX_RESET ((pid_t)-2) - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: nxmutex_is_reset - * - * Description: - * This function check whether the mutex is reset - * - * Parameters: - * mutex - mutex descriptor. - * - * Return Value: - * - ****************************************************************************/ - -static bool nxmutex_is_reset(FAR mutex_t *mutex) -{ - return mutex->holder == NXMUTEX_RESET; -} - /**************************************************************************** * Name: nxmutex_add_backtrace * @@ -73,25 +49,19 @@ static bool nxmutex_is_reset(FAR mutex_t *mutex) ****************************************************************************/ #if CONFIG_LIBC_MUTEX_BACKTRACE > 0 -static void nxmutex_add_backtrace(FAR mutex_t *mutex) +void nxmutex_add_backtrace(FAR mutex_t *mutex) { int n; - n = sched_backtrace(mutex->holder, mutex->backtrace, + n = sched_backtrace(nxmutex_get_holder(&mutex), mutex->backtrace, CONFIG_LIBC_MUTEX_BACKTRACE, 0); if (n < CONFIG_LIBC_MUTEX_BACKTRACE) { mutex->backtrace[n] = NULL; } } -#else -# define nxmutex_add_backtrace(mutex) #endif -/**************************************************************************** - * Public Functions - ****************************************************************************/ - /**************************************************************************** * Name: nxmutex_init * @@ -120,7 +90,6 @@ int nxmutex_init(FAR mutex_t *mutex) return ret; } - mutex->holder = NXMUTEX_NO_HOLDER; #ifdef CONFIG_PRIORITY_INHERITANCE nxsem_set_protocol(&mutex->sem, SEM_TYPE_MUTEX | SEM_PRIO_INHERIT); #else @@ -129,38 +98,6 @@ int nxmutex_init(FAR mutex_t *mutex) return ret; } -/**************************************************************************** - * Name: nxmutex_destroy - * - * Description: - * This function initializes the UNNAMED mutex. Following a - * successful call to nxmutex_init(), the mutex may be used in subsequent - * calls to nxmutex_lock(), nxmutex_unlock(), and nxmutex_trylock(). The - * mutex remains usable until it is destroyed. - * - * Parameters: - * mutex - Semaphore 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. - * - ****************************************************************************/ - -int nxmutex_destroy(FAR mutex_t *mutex) -{ - int ret = nxsem_destroy(&mutex->sem); - - if (ret < 0) - { - return ret; - } - - mutex->holder = NXMUTEX_NO_HOLDER; - return ret; -} - /**************************************************************************** * Name: nxmutex_is_hold * @@ -177,129 +114,7 @@ int nxmutex_destroy(FAR mutex_t *mutex) bool nxmutex_is_hold(FAR mutex_t *mutex) { - return mutex->holder == _SCHED_GETTID(); -} - -/**************************************************************************** - * Name: nxmutex_get_holder - * - * Description: - * This function get the holder of the mutex referenced by 'mutex'. - * Note that this is inherently racy unless the calling thread is - * holding the mutex. - * - * Parameters: - * mutex - mutex descriptor. - * - * Return Value: - * - ****************************************************************************/ - -int nxmutex_get_holder(FAR mutex_t *mutex) -{ - return mutex->holder; -} - -/**************************************************************************** - * Name: nxmutex_is_locked - * - * Description: - * This function get the lock state the mutex referenced by 'mutex'. - * Note that this is inherently racy unless the calling thread is - * holding the mutex. - * - * Parameters: - * mutex - mutex descriptor. - * - * Return Value: - * - ****************************************************************************/ - -bool nxmutex_is_locked(FAR mutex_t *mutex) -{ - return NXSEM_MACQUIRED(mutex->sem.val.mholder); -} - -/**************************************************************************** - * Name: nxmutex_lock - * - * Description: - * This function attempts to lock the mutex referenced by 'mutex'. The - * mutex is implemented with a semaphore, so if the semaphore value is - * (<=) zero, then the calling task will not return until it successfully - * acquires the lock. - * - * Parameters: - * mutex - 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: - * - ****************************************************************************/ - -int nxmutex_lock(FAR mutex_t *mutex) -{ - int ret; - - DEBUGASSERT(!nxmutex_is_hold(mutex)); - for (; ; ) - { - /* Take the semaphore (perhaps waiting) */ - - ret = nxsem_wait(&mutex->sem); - if (ret >= 0) - { - mutex->holder = _SCHED_GETTID(); - nxmutex_add_backtrace(mutex); - break; - } - else if (ret != -EINTR && ret != -ECANCELED) - { - break; - } - } - - return ret; -} - -/**************************************************************************** - * Name: nxmutex_trylock - * - * Description: - * This function locks the mutex only if the mutex is currently not locked. - * If the mutex has been locked already, the call returns without blocking. - * - * Parameters: - * mutex - 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 mutex - * -EAGAIN - The mutex is not available. - * - ****************************************************************************/ - -int nxmutex_trylock(FAR mutex_t *mutex) -{ - int ret; - - ret = nxsem_trywait(&mutex->sem); - if (ret < 0) - { - return ret; - } - - mutex->holder = _SCHED_GETTID(); - nxmutex_add_backtrace(mutex); - - return ret; + return nxmutex_get_holder(mutex) == _SCHED_GETTID(); } /**************************************************************************** @@ -345,7 +160,6 @@ int nxmutex_ticklock(FAR mutex_t *mutex, uint32_t delay) if (ret >= 0) { - mutex->holder = _SCHED_GETTID(); nxmutex_add_backtrace(mutex); } @@ -384,22 +198,17 @@ int nxmutex_clocklock(FAR mutex_t *mutex, clockid_t clockid, /* Wait until we get the lock or until the timeout expires */ - do + if (abstime) { - if (abstime) - { - ret = nxsem_clockwait(&mutex->sem, clockid, abstime); - } - else - { - ret = nxsem_wait(&mutex->sem); - } + ret = nxsem_clockwait(&mutex->sem, clockid, abstime); + } + else + { + ret = nxsem_wait(&mutex->sem); } - while (ret == -EINTR || ret == -ECANCELED); if (ret >= 0) { - mutex->holder = _SCHED_GETTID(); nxmutex_add_backtrace(mutex); } @@ -445,334 +254,6 @@ int nxmutex_timedlock(FAR mutex_t *mutex, unsigned int timeout) return nxmutex_clocklock(mutex, CLOCK_MONOTONIC, &rqtp); } -/**************************************************************************** - * Name: nxmutex_unlock - * - * Description: - * This function attempts to unlock the mutex referenced by 'mutex'. - * - * Parameters: - * mutex - 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. - * - ****************************************************************************/ - -int nxmutex_unlock(FAR mutex_t *mutex) -{ - int ret; - - if (nxmutex_is_reset(mutex)) - { - return OK; - } - - DEBUGASSERT(nxmutex_is_hold(mutex)); - - mutex->holder = NXMUTEX_NO_HOLDER; - - ret = nxsem_post(&mutex->sem); - if (ret < 0) - { - mutex->holder = _SCHED_GETTID(); - } - - return ret; -} - -/**************************************************************************** - * Name: nxmutex_reset - * - * Description: - * This function reset lock state. - * - * Parameters: - * mutex - mutex descriptor. - * - ****************************************************************************/ - -#if defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__) -void nxmutex_reset(FAR mutex_t *mutex) -{ - mutex->holder = NXMUTEX_RESET; - - nxsem_reset(&mutex->sem, 1); -} -#endif - -/**************************************************************************** - * Name: nxmutex_breaklock - * - * Description: - * This function attempts to break the mutex - * - * Parameters: - * mutex - Mutex descriptor. - * locked - Is the mutex break success - * - * 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: - * - ****************************************************************************/ - -int nxmutex_breaklock(FAR mutex_t *mutex, FAR unsigned int *locked) -{ - int ret = OK; - - *locked = false; - if (nxmutex_is_hold(mutex)) - { - ret = nxmutex_unlock(mutex); - if (ret >= 0) - { - *locked = true; - } - } - - return ret; -} - -/**************************************************************************** - * Name: nxmutex_restorelock - * - * Description: - * This function attempts to restore the mutex. - * - * Parameters: - * mutex - mutex descriptor. - * locked - true: it's mean that the mutex is broke success - * - * 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 - * - ****************************************************************************/ - -int nxmutex_restorelock(FAR mutex_t *mutex, unsigned int locked) -{ - return locked ? nxmutex_lock(mutex) : OK; -} - -/**************************************************************************** - * Name: nxmutex_set_protocol - * - * Description: - * This function attempts to set the priority protocol of a mutex. - * - * Parameters: - * mutex - mutex descriptor. - * protocol - mutex protocol value to set. - * - * 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 - * - ****************************************************************************/ - -int nxmutex_set_protocol(FAR mutex_t *mutex, int protocol) -{ - return nxsem_set_protocol(&mutex->sem, protocol); -} - -/**************************************************************************** - * Name: nxmutex_getprioceiling - * - * Description: - * This function attempts to get the priority ceiling of a mutex. - * - * Parameters: - * mutex - mutex descriptor. - * prioceiling - location to return the mutex priority ceiling. - * - * 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 - * - ****************************************************************************/ - -#ifdef CONFIG_PRIORITY_PROTECT -int nxmutex_getprioceiling(FAR const mutex_t *mutex, FAR int *prioceiling) -{ - return nxsem_getprioceiling(&mutex->sem, prioceiling); -} -#endif - -/**************************************************************************** - * Name: nxmutex_setprioceiling - * - * Description: - * This function attempts to set the priority ceiling of a mutex. - * - * Parameters: - * mutex - mutex descriptor. - * prioceiling - mutex priority ceiling value to set. - * old_ceiling - location to return the mutex ceiling priority set before. - * - * 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 - * - ****************************************************************************/ - -#ifdef CONFIG_PRIORITY_PROTECT -int nxmutex_setprioceiling(FAR mutex_t *mutex, int prioceiling, - FAR int *old_ceiling) -{ - return nxsem_setprioceiling(&mutex->sem, prioceiling, old_ceiling); -} -#endif - -/**************************************************************************** - * 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. - * - ****************************************************************************/ - -int nxrmutex_init(FAR rmutex_t *rmutex) -{ - rmutex->count = 0; - 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. - * - ****************************************************************************/ - -int nxrmutex_destroy(FAR rmutex_t *rmutex) -{ - int ret = nxmutex_destroy(&rmutex->mutex); - - if (ret >= 0) - { - rmutex->count = 0; - } - - return ret; -} - -/**************************************************************************** - * Name: nxrmutex_is_hold - * - * Description: - * This function check whether the calling thread hold the recursive mutex - * referenced by 'rmutex'. - * - * Parameters: - * rmutex - Recursive mutex descriptor. - * - * Return Value: - * - ****************************************************************************/ - -bool nxrmutex_is_hold(FAR rmutex_t *rmutex) -{ - return nxmutex_is_hold(&rmutex->mutex); -} - -/**************************************************************************** - * Name: nxrmutex_is_recursive - * - * Description: - * This function check whether the recursive mutex is currently held - * recursively. That is, whether it's locked more than once by the - * current holder. - * Note that this is inherently racy unless the calling thread is - * holding the mutex. - * - * Parameters: - * rmutex - Recursive mutex descriptor. - * - * Return Value: - * If rmutex has returned to True recursively, otherwise returns false. - * - ****************************************************************************/ - -bool nxrmutex_is_recursive(FAR rmutex_t *rmutex) -{ - return rmutex->count > 1; -} - -/**************************************************************************** - * Name: nxrmutex_get_holder - * - * Description: - * This function get the holder of the mutex referenced by 'mutex'. - * Note that this is inherently racy unless the calling thread is - * holding the mutex. - * - * Parameters: - * rmutex - Rmutex descriptor. - * - * Return Value: - * - ****************************************************************************/ - -int nxrmutex_get_holder(FAR rmutex_t *rmutex) -{ - return nxmutex_get_holder(&rmutex->mutex); -} - -/**************************************************************************** - * Name: nxrmutex_is_locked - * - * Description: - * This function get the lock state the recursive mutex - * referenced by 'rmutex'. - * Note that this is inherently racy unless the calling thread is - * holding the mutex. - * - * Parameters: - * rmutex - Recursive mutex descriptor. - * - * Return Value: - * - ****************************************************************************/ - -bool nxrmutex_is_locked(FAR rmutex_t *rmutex) -{ - return nxmutex_is_locked(&rmutex->mutex); -} - /**************************************************************************** * Name: nrxmutex_lock * @@ -1021,25 +502,6 @@ int nxrmutex_unlock(FAR rmutex_t *rmutex) return ret; } -/**************************************************************************** - * Name: nxrmutex_reset - * - * Description: - * This function reset lock state. - * - * Parameters: - * rmutex - rmutex descriptor. - * - ****************************************************************************/ - -#if defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__) -void nxrmutex_reset(FAR rmutex_t *rmutex) -{ - rmutex->count = 0; - nxmutex_reset(&rmutex->mutex); -} -#endif - /**************************************************************************** * Name: nrxmutex_breaklock * diff --git a/sched/misc/deadlock.c b/sched/misc/deadlock.c index 2a14806460b..68dd7798404 100644 --- a/sched/misc/deadlock.c +++ b/sched/misc/deadlock.c @@ -100,8 +100,8 @@ static void collect_deadlock(FAR struct tcb_s *tcb, FAR void *arg) pid_t holder; size_t i; - holder = mutex->holder; - if (holder == NXMUTEX_NO_HOLDER) + holder = nxmutex_get_holder(mutex); + if (holder < 0) { break; } diff --git a/sched/sched/sched_get_stateinfo.c b/sched/sched/sched_get_stateinfo.c index e5a59b7e044..1d7d2c5575b 100644 --- a/sched/sched/sched_get_stateinfo.c +++ b/sched/sched/sched_get_stateinfo.c @@ -101,7 +101,7 @@ void nxsched_get_stateinfo(FAR struct tcb_s *tcb, FAR char *state, if (tcb->task_state == TSTATE_WAIT_SEM && ((FAR sem_t *)(tcb->waitobj))->flags & SEM_TYPE_MUTEX) { - pid_t holder = ((FAR mutex_t *)(tcb->waitobj))->holder; + pid_t holder = nxmutex_get_holder((FAR mutex_t *)tcb->waitobj); leave_critical_section(flags); snprintf(state, length, "Waiting,Mutex:%d", holder);