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());
 }

Reply via email to