diff options
| author | Ha Thach <[email protected]> | 2025-11-19 17:44:32 +0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-11-19 17:44:32 +0700 |
| commit | 284895bd9c40b47731ea809dee2b7ca0bc604568 (patch) | |
| tree | 768766edb194c86aa1e51c309f8b5e2ba10c2170 | |
| parent | 6daf07bb92d7c7f8204852d80942362d7cea3ce0 (diff) | |
| parent | 650c4b061c45c20d3d059f1c5ce6013b700ce1f1 (diff) | |
Merge pull request #3151 from HiFiPhile/lock_cnt
osal/none: add nested count to spin lock
| -rw-r--r-- | src/osal/osal_none.h | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index bc86dcb28..174136e38 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -34,26 +34,41 @@ 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) { + if (ctx->nested_count == 0) { + return; // spin is not locked to begin with + } + + ctx->nested_count--; + + // Only re-enable interrupts when fully unlocked + if (!in_isr && ctx->nested_count == 0) { ctx->interrupt_set(true); } } |
