@@ -34,26 +34,47 @@ extern "C" {
3434//--------------------------------------------------------------------+
3535// Spinlock API
3636//--------------------------------------------------------------------+
37+ // Note: This implementation is designed for bare-metal single-core systems without RTOS.
38+ // - Supports nested locking within the same execution context
39+ // - NOT suitable for true SMP (Symmetric Multi-Processing) systems
40+ // - NOT thread-safe for multi-threaded environments
41+ // - Primarily manages interrupt enable/disable state for critical sections
3742typedef struct {
3843 void (* interrupt_set )(bool enabled );
44+ uint32_t nested_count ;
3945} osal_spinlock_t ;
4046
4147// For SMP, spinlock must be locked by hardware, cannot just use interrupt
4248#define OSAL_SPINLOCK_DEF (_name , _int_set ) \
43- osal_spinlock_t _name = { .interrupt_set = _int_set }
49+ osal_spinlock_t _name = { .interrupt_set = _int_set, .nested_count = 0 }
4450
4551TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init (osal_spinlock_t * ctx ) {
4652 (void ) ctx ;
4753}
4854
4955TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock (osal_spinlock_t * ctx , bool in_isr ) {
50- if (!in_isr ) {
56+ // Disable interrupts first to make nested_count increment atomic
57+ if (!in_isr && ctx -> nested_count == 0 ) {
5158 ctx -> interrupt_set (false);
5259 }
60+ ctx -> nested_count ++ ;
5361}
5462
5563TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock (osal_spinlock_t * ctx , bool in_isr ) {
56- if (!in_isr ) {
64+ // Check for underflow - unlock without lock
65+ if (ctx -> nested_count == 0 ) {
66+ // Re-enable interrupts before asserting to avoid leaving interrupts disabled
67+ if (!in_isr ) {
68+ ctx -> interrupt_set (true);
69+ }
70+ TU_ASSERT (0 ,);
71+ return ;
72+ }
73+
74+ ctx -> nested_count -- ;
75+
76+ // Only re-enable interrupts when fully unlocked
77+ if (!in_isr && ctx -> nested_count == 0 ) {
5778 ctx -> interrupt_set (true);
5879 }
5980}
0 commit comments