From bec9676493c51a454541e885ad33030e58d9d257 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 15 Jun 2025 12:02:15 +0200 Subject: [PATCH 1/2] osal/none: add nested count to spin lock Signed-off-by: HiFiPhile --- src/osal/osal_none.h | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index bc86dcb28..d9890efbc 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -34,26 +34,46 @@ extern "C" { //--------------------------------------------------------------------+ // Spinlock API //--------------------------------------------------------------------+ +// Note: This implementation is designed for bare-metal single-core systems without RTOS. +// - Supports nested locking within the same execution context +// - NOT suitable for true SMP (Symmetric Multi-Processing) systems +// - NOT thread-safe for multi-threaded environments +// - Primarily manages interrupt enable/disable state for critical sections typedef struct { void (* interrupt_set)(bool enabled); + uint32_t nested_count; } osal_spinlock_t; // For SMP, spinlock must be locked by hardware, cannot just use interrupt #define OSAL_SPINLOCK_DEF(_name, _int_set) \ - osal_spinlock_t _name = { .interrupt_set = _int_set } + osal_spinlock_t _name = { .interrupt_set = _int_set, .nested_count = 0 } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { (void) ctx; } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { - if (!in_isr) { + // Disable interrupts first to make nested_count increment atomic + if (!in_isr && ctx->nested_count == 0) { ctx->interrupt_set(false); } + ctx->nested_count++; } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { - if (!in_isr) { + // Check for underflow - unlock without lock + if (ctx->nested_count == 0) { + // Re-enable interrupts before asserting to avoid leaving interrupts disabled + if (!in_isr) { + ctx->interrupt_set(true); + } + TU_ASSERT(0,); + } + + ctx->nested_count--; + + // Only re-enable interrupts when fully unlocked + if (!in_isr && ctx->nested_count == 0) { ctx->interrupt_set(true); } } From 650c4b061c45c20d3d059f1c5ce6013b700ce1f1 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 19 Nov 2025 17:06:19 +0700 Subject: [PATCH 2/2] return if spin is underflow --- src/osal/osal_none.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index d9890efbc..174136e38 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -61,13 +61,8 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bo } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { - // Check for underflow - unlock without lock if (ctx->nested_count == 0) { - // Re-enable interrupts before asserting to avoid leaving interrupts disabled - if (!in_isr) { - ctx->interrupt_set(true); - } - TU_ASSERT(0,); + return; // spin is not locked to begin with } ctx->nested_count--;