You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ja...@apache.org on 2026/10/18 13:00:14 UTC
(mynewt-nimble) 01/03: porting/npl/linux: Add ble_npl_mutex_locked_by_cur_task()
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 <sz...@codecoup.pl>
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 <ro...@rojer.me>.
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());
}