From 0d6de4c0a7222cc13bf69ae1b4b7012241513b98 Mon Sep 17 00:00:00 2001 From: chao an Date: Wed, 2 Apr 2025 17:25:11 +0800 Subject: [PATCH] sched/mutex: add ticked lock version for mutex/rmutex Added ticked lock version for mutex to reduce time calculation overhead Signed-off-by: chao an --- include/nuttx/mutex.h | 56 +++++++++++++++++++++++ libs/libc/misc/lib_mutex.c | 94 ++++++++++++++++++++++++++++++++++++++ sched/pthread/pthread.h | 2 + 3 files changed, 152 insertions(+) diff --git a/include/nuttx/mutex.h b/include/nuttx/mutex.h index 3b44cd2733..640a4df425 100644 --- a/include/nuttx/mutex.h +++ b/include/nuttx/mutex.h @@ -215,6 +215,34 @@ int nxmutex_lock(FAR mutex_t *mutex); int nxmutex_trylock(FAR mutex_t *mutex); +/**************************************************************************** + * Name: nxmutex_ticklock + * + * Description: + * This function attempts to lock the mutex referenced by 'mutex'. If the + * mutex value is (<=) zero, then the calling task will not return until it + * successfully acquires the lock or timed out + * + * Input Parameters: + * mutex - Mutex object + * delay - Ticks to wait from the start time until the semaphore is + * posted. If ticks is zero, then this function is equivalent + * to nxmutex_trylock(). + * + * Returned Value: + * OK The mutex successfully acquires + * EINVAL The mutex argument does not refer to a valid mutex. Or the + * thread would have blocked, and the abstime parameter specified + * a nanoseconds field value less than zero or greater than or + * equal to 1000 million. + * ETIMEDOUT The mutex could not be locked before the specified timeout + * expired. + * EDEADLK A deadlock condition was detected. + * + ****************************************************************************/ + +int nxmutex_ticklock(FAR mutex_t *mutex, uint32_t delay); + /**************************************************************************** * Name: nxmutex_clocklock * @@ -561,6 +589,34 @@ int nxrmutex_lock(FAR rmutex_t *rmutex); int nxrmutex_trylock(FAR rmutex_t *rmutex); +/**************************************************************************** + * Name: nxrmutex_ticklock + * + * Description: + * This function attempts to lock the mutex referenced by 'mutex'. If the + * mutex value is (<=) zero, then the calling task will not return until it + * successfully acquires the lock or timed out + * + * Input Parameters: + * rmutex - Rmutex object + * delay - Ticks to wait from the start time until the semaphore is + * posted. If ticks is zero, then this function is equivalent + * to nxrmutex_trylock(). + * + * Returned Value: + * OK The mutex successfully acquires + * EINVAL The mutex argument does not refer to a valid mutex. Or the + * thread would have blocked, and the abstime parameter specified + * a nanoseconds field value less than zero or greater than or + * equal to 1000 million. + * ETIMEDOUT The mutex could not be locked before the specified timeout + * expired. + * EDEADLK A deadlock condition was detected. + * + ****************************************************************************/ + +int nxrmutex_ticklock(FAR rmutex_t *rmutex, uint32_t delay); + /**************************************************************************** * Name: nxrmutex_clocklock * diff --git a/libs/libc/misc/lib_mutex.c b/libs/libc/misc/lib_mutex.c index 4cf0c2b3d1..f23c5a46db 100644 --- a/libs/libc/misc/lib_mutex.c +++ b/libs/libc/misc/lib_mutex.c @@ -307,6 +307,56 @@ int nxmutex_trylock(FAR mutex_t *mutex) return ret; } +/**************************************************************************** + * Name: nxmutex_ticklock + * + * Description: + * This function attempts to lock the mutex referenced by 'mutex'. If the + * mutex value is (<=) zero, then the calling task will not return until it + * successfully acquires the lock or timed out + * + * Input Parameters: + * mutex - Mutex object + * delay - Ticks to wait from the start time until the semaphore is + * posted. If ticks is zero, then this function is equivalent + * to sem_trywait(). + * + * Returned Value: + * OK The mutex successfully acquires + * EINVAL The mutex argument does not refer to a valid mutex. Or the + * thread would have blocked, and the abstime parameter specified + * a nanoseconds field value less than zero or greater than or + * equal to 1000 million. + * ETIMEDOUT The mutex could not be locked before the specified timeout + * expired. + * EDEADLK A deadlock condition was detected. + * + ****************************************************************************/ + +int nxmutex_ticklock(FAR mutex_t *mutex, uint32_t delay) +{ + int ret; + + /* Wait until we get the lock or until the timeout expires */ + + if (delay) + { + ret = nxsem_tickwait(&mutex->sem, delay); + } + else + { + ret = nxsem_trywait(&mutex->sem); + } + + if (ret >= 0) + { + mutex->holder = _SCHED_GETTID(); + nxmutex_add_backtrace(mutex); + } + + return ret; +} + /**************************************************************************** * Name: nxmutex_clocklock * @@ -806,6 +856,50 @@ int nxrmutex_trylock(FAR rmutex_t *rmutex) return ret; } +/**************************************************************************** + * Name: nxrmutex_ticklock + * + * Description: + * This function attempts to lock the mutex referenced by 'mutex'. If the + * mutex value is (<=) zero, then the calling task will not return until it + * successfully acquires the lock or timed out + * + * Input Parameters: + * rmutex - Rmutex object + * delay - Ticks to wait from the start time until the semaphore is + * posted. If ticks is zero, then this function is equivalent + * to nxrmutex_trylock(). + * + * Returned Value: + * OK The mutex successfully acquires + * EINVAL The mutex argument does not refer to a valid mutex. Or the + * thread would have blocked, and the abstime parameter specified + * a nanoseconds field value less than zero or greater than or + * equal to 1000 million. + * ETIMEDOUT The mutex could not be locked before the specified timeout + * expired. + * EDEADLK A deadlock condition was detected. + * + ****************************************************************************/ + +int nxrmutex_ticklock(FAR rmutex_t *rmutex, uint32_t delay) +{ + int ret = 0; + + if (!nxrmutex_is_hold(rmutex)) + { + ret = nxmutex_ticklock(&rmutex->mutex, delay); + } + + if (ret >= 0) + { + DEBUGASSERT(rmutex->count < UINT_MAX); + ++rmutex->count; + } + + return ret; +} + /**************************************************************************** * Name: nxrmutex_clocklock * diff --git a/sched/pthread/pthread.h b/sched/pthread/pthread.h index baf48407c3..bc6d684589 100644 --- a/sched/pthread/pthread.h +++ b/sched/pthread/pthread.h @@ -55,6 +55,7 @@ # define mutex_trylock(m) nxrmutex_trylock(m) # define mutex_breaklock(m,v) nxrmutex_breaklock(m,v) # define mutex_restorelock(m,v) nxrmutex_restorelock(m,v) +# define mutex_ticklock(m,t) nxrmutex_ticklock(m,t) # define mutex_clocklock(m,t) nxrmutex_clocklock(m,CLOCK_REALTIME,t) # define mutex_set_protocol(m,p) nxrmutex_set_protocol(m,p) # define mutex_getprioceiling(m,p) nxrmutex_getprioceiling(m,p) @@ -72,6 +73,7 @@ # define mutex_trylock(m) nxmutex_trylock(m) # define mutex_breaklock(m,v) nxmutex_breaklock(m, v) # define mutex_restorelock(m,v) nxmutex_restorelock(m, v) +# define mutex_ticklock(m,t) nxmutex_ticklock(m,t) # define mutex_clocklock(m,t) nxmutex_clocklock(m,CLOCK_REALTIME,t) # define mutex_set_protocol(m,p) nxmutex_set_protocol(m,p) # define mutex_getprioceiling(m,p) nxmutex_getprioceiling(m,p)