Two defects in the CONFIG_TICKET_SPINLOCK paths of spinlock.h:
1. spin_trylock_notrace() passed &lock->owner as the "expected" pointer
of atomic_cmpxchg(). A failed compare-exchange writes the current
value of the target object back through that pointer, so a losing
trylock stores lock->next into lock->owner. owner then equals next,
which is the unlocked state: a lock still held by another CPU reports
itself as free, spin_is_locked() returns false and the lock can be
taken again. Every later unlock keeps incrementing owner past next,
so the ticket of a real waiter never matches and the lock stays
locked forever. Keep the expected value in a local variable.
2. spin_unlock() was wrapped in #ifdef __SP_UNLOCK_FUNCTION, a macro
that is never defined anywhere in the tree. The function body was
therefore dead code and spin_unlock() always expanded to
"do { *(l) = SP_UNLOCKED; } while (0)", which zeroes both ticket
counters instead of releasing one ticket with
atomic_fetch_add(&lock->owner, 1). That drops queued waiters, lets a
newcomer draw ticket 0 and enter the critical section, and also skips
the UP_DMB/UP_DSB/UP_SEV release barriers and the
sched_note_spinlock_unlock() note. Drop the dead #ifdef so
spin_unlock() is always the function.
Both were reproduced on qemu-armv7a:smp (cortex-a7 x4) with
CONFIG_TICKET_SPINLOCK=y, where the compare-exchange lowers to native
ldrex/strex. This confirms the root cause is the C-level aliasing of
the expected pointer, not the atomic implementation.
Refs: https://github.com/apache/nuttx/issues/19808
Signed-off-by: hujun5 <hujun5@xiaomi.com>
Apache NuttX is a real-time operating system (RTOS) with an emphasis on standards compliance and small footprint. Scalable from 8-bit to 64-bit microcontroller environments, the primary governing standards in NuttX are POSIX and ANSI standards. Additional standard APIs from Unix and other common RTOSs (such as VxWorks) are adopted for functionality not available under these standards, or for functionality that is not appropriate for deeply-embedded environments (such as fork()).
For brevity, many parts of the documentation will refer to Apache NuttX as simply NuttX.
Getting Started
First time on NuttX? Read the Getting Started guide! If you don't have a board available, NuttX has its own simulator that you can run on terminal.
Documentation
You can find the current NuttX documentation on the Documentation Page.
Alternatively, you can build the documentation yourself by following the Documentation Build Instructions.
The old NuttX documentation is still available in the Apache wiki.
Supported Boards
NuttX supports a wide variety of platforms. See the full list on the Supported Platforms page.
Contributing
If you wish to contribute to the NuttX project, read the Contributing guidelines for information on Git usage, coding standard, workflow and the NuttX principles.
License
The code in this repository is under either the Apache 2 license, or a license compatible with the Apache 2 license. See the License Page for more information.
