This is an automated email from the ASF dual-hosted git repository. sjanc pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git
commit b580364e2f43c2eb661aabae67e6c5dcc9560359 Author: Szymon Janc <[email protected]> AuthorDate: Thu Oct 8 17:46:16 2026 +0200 porting/npl/linux: Add ble_npl_mutex_locked_by_cur_task() This allows to check if mutex is held by calling thread. Owner and lock depth are tracked in ble_npl_mutex itself instead of relying on C library internals (e.g. glibc specific pthread_mutex_t fields) so this works with any pthreads implementation, including musl. Availability is indicated by BLE_NPL_MUTEX_LOCKED_BY_CUR_TASK define. Based on idea from PR #1562 by Deomid "rojer" Ryabkov <[email protected]>. Assisted-by: Claude:claude-opus-5-5 --- porting/npl/linux/include/nimble/nimble_npl_os.h | 3 +++ porting/npl/linux/include/nimble/os_types.h | 2 ++ porting/npl/linux/src/os_mutex.c | 31 +++++++++++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/porting/npl/linux/include/nimble/nimble_npl_os.h b/porting/npl/linux/include/nimble/nimble_npl_os.h index 0006f8b40..de6d82a2f 100644 --- a/porting/npl/linux/include/nimble/nimble_npl_os.h +++ b/porting/npl/linux/include/nimble/nimble_npl_os.h @@ -38,6 +38,9 @@ extern "C" { struct ble_npl_eventq *ble_npl_eventq_dflt_get(void); void ble_npl_eventq_run(struct ble_npl_eventq *evq); +#define BLE_NPL_MUTEX_LOCKED_BY_CUR_TASK 1 +int ble_npl_mutex_locked_by_cur_task(struct ble_npl_mutex *mu); + #ifdef __cplusplus } #endif diff --git a/porting/npl/linux/include/nimble/os_types.h b/porting/npl/linux/include/nimble/os_types.h index fa92cd182..4cf09c529 100644 --- a/porting/npl/linux/include/nimble/os_types.h +++ b/porting/npl/linux/include/nimble/os_types.h @@ -56,6 +56,8 @@ struct ble_npl_mutex { pthread_mutex_t lock; pthread_mutexattr_t attr; struct timespec wait; + pthread_t owner; + unsigned int depth; }; struct ble_npl_sem { diff --git a/porting/npl/linux/src/os_mutex.c b/porting/npl/linux/src/os_mutex.c index 3d3a72ef1..e746c62db 100644 --- a/porting/npl/linux/src/os_mutex.c +++ b/porting/npl/linux/src/os_mutex.c @@ -33,6 +33,7 @@ ble_npl_mutex_init(struct ble_npl_mutex *mu) pthread_mutexattr_init(&mu->attr); pthread_mutexattr_settype(&mu->attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&mu->lock, &mu->attr); + mu->depth = 0; return BLE_NPL_OK; } @@ -44,6 +45,11 @@ ble_npl_mutex_release(struct ble_npl_mutex *mu) return BLE_NPL_INVALID_PARAM; } + /* Update depth while mutex is still held by current thread */ + if (ble_npl_mutex_locked_by_cur_task(mu)) { + __atomic_store_n(&mu->depth, mu->depth - 1, __ATOMIC_RELEASE); + } + if (pthread_mutex_unlock(&mu->lock)) { return BLE_NPL_BAD_MUTEX; } @@ -85,5 +91,28 @@ ble_npl_mutex_pend(struct ble_npl_mutex *mu, uint32_t timeout) } } - return (err) ? BLE_NPL_ERROR : BLE_NPL_OK; + if (err) { + return BLE_NPL_ERROR; + } + + __atomic_store_n(&mu->owner, pthread_self(), __ATOMIC_RELAXED); + __atomic_store_n(&mu->depth, mu->depth + 1, __ATOMIC_RELEASE); + + return BLE_NPL_OK; +} + +int +ble_npl_mutex_locked_by_cur_task(struct ble_npl_mutex *mu) +{ + /* Owner and depth are modified only by thread holding the mutex. Owner + * is written before depth so if non-zero depth is observed, owner is + * up to date and can match current thread only if it holds the mutex. + * This makes it safe to call from any thread. + */ + if (__atomic_load_n(&mu->depth, __ATOMIC_ACQUIRE) == 0) { + return 0; + } + + return pthread_equal(__atomic_load_n(&mu->owner, __ATOMIC_RELAXED), + pthread_self()); }
