Rename poorly named constants in the lock_core/spin_lock workarounds, and add some more tests #3164

Merged
kilograham merged 3 commits from spin-lock-updates into develop 2026-09-02 13:57:14 -05:00
kilograham commented 2026-08-29 18:36:29 -05:00 (Migrated from github.com)
  • Rename PICO_SPIN_LOCK_UNLOCK_CAUSES_SEV to PICO_EXCLUSIVE_ACCESS_SETS_OWN_EVENT
  • Rename PICO_SYNC_RP2350_SPIN_LOCK_WORKAROUND to PICO_SYNC_EXCLUSIVE_ACCESS_EVENT_WORKAROUND
  • Add some more sync tests
* Rename `PICO_SPIN_LOCK_UNLOCK_CAUSES_SEV` to `PICO_EXCLUSIVE_ACCESS_SETS_OWN_EVENT` * Rename `PICO_SYNC_RP2350_SPIN_LOCK_WORKAROUND` to `PICO_SYNC_EXCLUSIVE_ACCESS_EVENT_WORKAROUND` * Add some more sync tests
Wren6991 (Migrated from github.com) reviewed 2026-08-29 18:36:29 -05:00
will-v-pi commented 2026-09-01 05:51:22 -05:00 (Migrated from github.com)

Both sync_interop_test_baseline and sync_interop_test_baseline_rev are failing on RP2350 Arm and Risc-V in CI - are they working locally for you?

The output on Arm was:


=== pico-sdk sync interop test ===
platform: rp2350-arm-s
config: baseline, no RTOS (SDK lock_core macros, core 0 drives, core 1 agents)
spin locks: hardware, unlock sets the event
lock_core: the SDK's own; RP2350 workaround disabled; pico_time sleeps on a bare __wfe()
default alarm pool: core 0
calibration:
spinner: no scheduler, so yielding does not apply (yield checks skipped)
cycles (agent core, 32-bit): busy 149/us, asleep 125/us -> does not separate, so the counter cannot see sleep; note omitted
agent core DWT_CTRL=0x40080001 DEMCR=0x01100000 (CYCCNTENA=1 TRCENA=1)
sleep detection: wait-loop iteration count (<=8 means it blocked)
DWT_SLEEPCNT (agent core): moved across a known sleep and held still while busy - a direct sleep signal is available

--- D1: blocking discipline (mutex_enter_blocking, as pico_malloc) ---
[PASS ] D0     cycle counter 149/us; sleep counter moved (inline d=123, boundary d=123)
[PASS ] D1.1   1000 uncontended cycles, 489ns each
blocked wait duration: n=20 min=19998us mean=19999us max=20000us early=0
[PASS ] D1.2   max wait 20000us for 20ms hold (no yield metric)
[SKIP ] D1.3   no scheduler, so no priority inversion to measure
[PASS ] D1.4   other core blocked: 2 wait iterations, 20011us, SLEEPCNT agrees (d=77)
[PASS ] D1.5   cross-core wakeup in 20001us
ISR notify -> waiter wake: n=20 min=4us mean=5us max=20us early=0
[PASS ] D1.6   mean 5us, max 20us
[PASS ] D1.7   blocking acquire from ISR completed
[PASS ] D1.8   3-deep nesting released correctly
[FAIL ] D1.9   bare pattern blocked (2 iterations) but PICO_EXCLUSIVE_ACCESS_SETS_OWN_EVENT predicts it would busy-poll
[SKIP ] D1.10  needs two tasks blocked on one semaphore's event-group bit

--- D2: try-then-timed discipline (mutex_try_enter_block_until, as pico_stdio) ---
[PASS ] D2.1   immediate (5us)
timed acquire, released before deadline: n=20 min=20001us mean=20001us max=20004us early=0
[PASS ] D2.2   max wait 20004us for 20ms hold (no yield metric)
timeout overshoot: n=5 min=1us mean=1us max=3us early=0
[PASS ] D2.3   never early, overshoot max 3us, 3 waits
[PASS ] D2.4   self-owner detected immediately (3us)
[PASS ] D2.5   timed acquire from ISR returned (timed out)
[PASS ] D2.6   immediate from ISR (5us)
[PASS ] D2.7   timed out at 50011us, 4 wait iterations
repeated-deadline overshoot: n=10 min=1us mean=1us max=3us early=0
[PASS ] D2.8   never early, overshoot max 3us, 3 waits
[PASS ] D2.9   repeated waits on an expired deadline returned promptly (50018us)
[SKIP ] D2.10  needs a scheduler: a sub-tick deadline only means something against a tick
[PASS ] D2.11  20ms deadline met by sleeping (20011us, 7 iterations) with an earlier alarm firing at 12001us
[PASS ] D2.12  slept a 20ms deadline (pool IRQ on the other core, adds async): 20003us, 3 iterations
[INFO ] D2.13  39 iterations for 9 interferer fires (4.33x) over 20007us
[PASS ] D2.14  slept a 20ms deadline with a later alarm queued (20002us, 3 iterations)
[PASS ] D2.15  6 rounds of 6 cancellations, pool still places every one (pool IRQ on the other core, adds async)
[PASS ] D2.16  timed out at 50005us, 4 wait iterations
[PASS ] D2.17  timed out at 50007us, 5 wait iterations with both cores waiting

--- D3: sleep_ms / sleep_until (ms-scale, concurrent, cross-core) ---
sleep_ms lateness: n=20 min=1us mean=1us max=5us early=0
[PASS ] D3.1   never early, worst oversleep 5us, slept in 20/20
[SKIP ] D3.2   needs tasks: more than one concurrent sleeper
[PASS ] D3.3   50ms sleep on the other core took 50001us (confirmed asleep)
[SKIP ] D3.4   needs tasks: a thief must block on an aliasing lock

--- D4: alarm pool state ---
[PASS ] D4.1   pool left hardware alarm 0 armed after emptying (armed=0x09)

=== summary ===
26 pass, 1 fail, 5 skip, 0 expected-fail, 1 info

failures:
D1.9   bare pattern blocked (2 iterations) but PICO_EXCLUSIVE_ACCESS_SETS_OWN_EVENT predicts it would busy-poll
FAILED
Both `sync_interop_test_baseline` and `sync_interop_test_baseline_rev` are failing on RP2350 Arm and Risc-V in CI - are they working locally for you? The output on Arm was: ``` === pico-sdk sync interop test === platform: rp2350-arm-s config: baseline, no RTOS (SDK lock_core macros, core 0 drives, core 1 agents) spin locks: hardware, unlock sets the event lock_core: the SDK's own; RP2350 workaround disabled; pico_time sleeps on a bare __wfe() default alarm pool: core 0 calibration: spinner: no scheduler, so yielding does not apply (yield checks skipped) cycles (agent core, 32-bit): busy 149/us, asleep 125/us -> does not separate, so the counter cannot see sleep; note omitted agent core DWT_CTRL=0x40080001 DEMCR=0x01100000 (CYCCNTENA=1 TRCENA=1) sleep detection: wait-loop iteration count (<=8 means it blocked) DWT_SLEEPCNT (agent core): moved across a known sleep and held still while busy - a direct sleep signal is available --- D1: blocking discipline (mutex_enter_blocking, as pico_malloc) --- [PASS ] D0 cycle counter 149/us; sleep counter moved (inline d=123, boundary d=123) [PASS ] D1.1 1000 uncontended cycles, 489ns each blocked wait duration: n=20 min=19998us mean=19999us max=20000us early=0 [PASS ] D1.2 max wait 20000us for 20ms hold (no yield metric) [SKIP ] D1.3 no scheduler, so no priority inversion to measure [PASS ] D1.4 other core blocked: 2 wait iterations, 20011us, SLEEPCNT agrees (d=77) [PASS ] D1.5 cross-core wakeup in 20001us ISR notify -> waiter wake: n=20 min=4us mean=5us max=20us early=0 [PASS ] D1.6 mean 5us, max 20us [PASS ] D1.7 blocking acquire from ISR completed [PASS ] D1.8 3-deep nesting released correctly [FAIL ] D1.9 bare pattern blocked (2 iterations) but PICO_EXCLUSIVE_ACCESS_SETS_OWN_EVENT predicts it would busy-poll [SKIP ] D1.10 needs two tasks blocked on one semaphore's event-group bit --- D2: try-then-timed discipline (mutex_try_enter_block_until, as pico_stdio) --- [PASS ] D2.1 immediate (5us) timed acquire, released before deadline: n=20 min=20001us mean=20001us max=20004us early=0 [PASS ] D2.2 max wait 20004us for 20ms hold (no yield metric) timeout overshoot: n=5 min=1us mean=1us max=3us early=0 [PASS ] D2.3 never early, overshoot max 3us, 3 waits [PASS ] D2.4 self-owner detected immediately (3us) [PASS ] D2.5 timed acquire from ISR returned (timed out) [PASS ] D2.6 immediate from ISR (5us) [PASS ] D2.7 timed out at 50011us, 4 wait iterations repeated-deadline overshoot: n=10 min=1us mean=1us max=3us early=0 [PASS ] D2.8 never early, overshoot max 3us, 3 waits [PASS ] D2.9 repeated waits on an expired deadline returned promptly (50018us) [SKIP ] D2.10 needs a scheduler: a sub-tick deadline only means something against a tick [PASS ] D2.11 20ms deadline met by sleeping (20011us, 7 iterations) with an earlier alarm firing at 12001us [PASS ] D2.12 slept a 20ms deadline (pool IRQ on the other core, adds async): 20003us, 3 iterations [INFO ] D2.13 39 iterations for 9 interferer fires (4.33x) over 20007us [PASS ] D2.14 slept a 20ms deadline with a later alarm queued (20002us, 3 iterations) [PASS ] D2.15 6 rounds of 6 cancellations, pool still places every one (pool IRQ on the other core, adds async) [PASS ] D2.16 timed out at 50005us, 4 wait iterations [PASS ] D2.17 timed out at 50007us, 5 wait iterations with both cores waiting --- D3: sleep_ms / sleep_until (ms-scale, concurrent, cross-core) --- sleep_ms lateness: n=20 min=1us mean=1us max=5us early=0 [PASS ] D3.1 never early, worst oversleep 5us, slept in 20/20 [SKIP ] D3.2 needs tasks: more than one concurrent sleeper [PASS ] D3.3 50ms sleep on the other core took 50001us (confirmed asleep) [SKIP ] D3.4 needs tasks: a thief must block on an aliasing lock --- D4: alarm pool state --- [PASS ] D4.1 pool left hardware alarm 0 armed after emptying (armed=0x09) === summary === 26 pass, 1 fail, 5 skip, 0 expected-fail, 1 info failures: D1.9 bare pattern blocked (2 iterations) but PICO_EXCLUSIVE_ACCESS_SETS_OWN_EVENT predicts it would busy-poll FAILED ```
lurch (Migrated from github.com) reviewed 2026-09-01 06:58:00 -05:00
@ -49,3 +52,4 @@
#endif
#endif
/** \file lock_core.h
lurch (Migrated from github.com) commented 2026-09-01 06:58:00 -05:00

For backwards-compatibility, do we need to do something like

#ifndef PICO_SYNC_EXCLUSIVE_ACCESS_EVENT_WORKAROUND
#ifdef PICO_SYNC_RP2350_SPIN_LOCK_WORKAROUND
#define PICO_SYNC_EXCLUSIVE_ACCESS_EVENT_WORKAROUND PICO_SYNC_RP2350_SPIN_LOCK_WORKAROUND
#else
#define PICO_SYNC_EXCLUSIVE_ACCESS_EVENT_WORKAROUND (PICO_USE_SW_SPIN_LOCKS && PICO_EXCLUSIVE_ACCESS_SETS_OWN_EVENT)
#endif
#endif
For backwards-compatibility, do we need to do something like ```suggestion #ifndef PICO_SYNC_EXCLUSIVE_ACCESS_EVENT_WORKAROUND #ifdef PICO_SYNC_RP2350_SPIN_LOCK_WORKAROUND #define PICO_SYNC_EXCLUSIVE_ACCESS_EVENT_WORKAROUND PICO_SYNC_RP2350_SPIN_LOCK_WORKAROUND #else #define PICO_SYNC_EXCLUSIVE_ACCESS_EVENT_WORKAROUND (PICO_USE_SW_SPIN_LOCKS && PICO_EXCLUSIVE_ACCESS_SETS_OWN_EVENT) #endif #endif ```
kilograham commented 2026-09-01 16:50:12 -05:00 (Migrated from github.com)

Both sync_interop_test_baseline and sync_interop_test_baseline_rev are failing on RP2350 Arm and Risc-V in CI - are they working locally for you?

The output on Arm was:


=== pico-sdk sync interop test ===
platform: rp2350-arm-s
config: baseline, no RTOS (SDK lock_core macros, core 0 drives, core 1 agents)
spin locks: hardware, unlock sets the event
lock_core: the SDK's own; RP2350 workaround disabled; pico_time sleeps on a bare __wfe()
default alarm pool: core 0
calibration:
spinner: no scheduler, so yielding does not apply (yield checks skipped)
cycles (agent core, 32-bit): busy 149/us, asleep 125/us -> does not separate, so the counter cannot see sleep; note omitted
agent core DWT_CTRL=0x40080001 DEMCR=0x01100000 (CYCCNTENA=1 TRCENA=1)
sleep detection: wait-loop iteration count (<=8 means it blocked)
DWT_SLEEPCNT (agent core): moved across a known sleep and held still while busy - a direct sleep signal is available

--- D1: blocking discipline (mutex_enter_blocking, as pico_malloc) ---
[PASS ] D0     cycle counter 149/us; sleep counter moved (inline d=123, boundary d=123)
[PASS ] D1.1   1000 uncontended cycles, 489ns each
blocked wait duration: n=20 min=19998us mean=19999us max=20000us early=0
[PASS ] D1.2   max wait 20000us for 20ms hold (no yield metric)
[SKIP ] D1.3   no scheduler, so no priority inversion to measure
[PASS ] D1.4   other core blocked: 2 wait iterations, 20011us, SLEEPCNT agrees (d=77)
[PASS ] D1.5   cross-core wakeup in 20001us
ISR notify -> waiter wake: n=20 min=4us mean=5us max=20us early=0
[PASS ] D1.6   mean 5us, max 20us
[PASS ] D1.7   blocking acquire from ISR completed
[PASS ] D1.8   3-deep nesting released correctly
[FAIL ] D1.9   bare pattern blocked (2 iterations) but PICO_EXCLUSIVE_ACCESS_SETS_OWN_EVENT predicts it would busy-poll
[SKIP ] D1.10  needs two tasks blocked on one semaphore's event-group bit

--- D2: try-then-timed discipline (mutex_try_enter_block_until, as pico_stdio) ---
[PASS ] D2.1   immediate (5us)
timed acquire, released before deadline: n=20 min=20001us mean=20001us max=20004us early=0
[PASS ] D2.2   max wait 20004us for 20ms hold (no yield metric)
timeout overshoot: n=5 min=1us mean=1us max=3us early=0
[PASS ] D2.3   never early, overshoot max 3us, 3 waits
[PASS ] D2.4   self-owner detected immediately (3us)
[PASS ] D2.5   timed acquire from ISR returned (timed out)
[PASS ] D2.6   immediate from ISR (5us)
[PASS ] D2.7   timed out at 50011us, 4 wait iterations
repeated-deadline overshoot: n=10 min=1us mean=1us max=3us early=0
[PASS ] D2.8   never early, overshoot max 3us, 3 waits
[PASS ] D2.9   repeated waits on an expired deadline returned promptly (50018us)
[SKIP ] D2.10  needs a scheduler: a sub-tick deadline only means something against a tick
[PASS ] D2.11  20ms deadline met by sleeping (20011us, 7 iterations) with an earlier alarm firing at 12001us
[PASS ] D2.12  slept a 20ms deadline (pool IRQ on the other core, adds async): 20003us, 3 iterations
[INFO ] D2.13  39 iterations for 9 interferer fires (4.33x) over 20007us
[PASS ] D2.14  slept a 20ms deadline with a later alarm queued (20002us, 3 iterations)
[PASS ] D2.15  6 rounds of 6 cancellations, pool still places every one (pool IRQ on the other core, adds async)
[PASS ] D2.16  timed out at 50005us, 4 wait iterations
[PASS ] D2.17  timed out at 50007us, 5 wait iterations with both cores waiting

--- D3: sleep_ms / sleep_until (ms-scale, concurrent, cross-core) ---
sleep_ms lateness: n=20 min=1us mean=1us max=5us early=0
[PASS ] D3.1   never early, worst oversleep 5us, slept in 20/20
[SKIP ] D3.2   needs tasks: more than one concurrent sleeper
[PASS ] D3.3   50ms sleep on the other core took 50001us (confirmed asleep)
[SKIP ] D3.4   needs tasks: a thief must block on an aliasing lock

--- D4: alarm pool state ---
[PASS ] D4.1   pool left hardware alarm 0 armed after emptying (armed=0x09)

=== summary ===
26 pass, 1 fail, 5 skip, 0 expected-fail, 1 info

failures:
D1.9   bare pattern blocked (2 iterations) but PICO_EXCLUSIVE_ACCESS_SETS_OWN_EVENT predicts it would busy-poll
FAILED

this is now fixed

> Both `sync_interop_test_baseline` and `sync_interop_test_baseline_rev` are failing on RP2350 Arm and Risc-V in CI - are they working locally for you? > > The output on Arm was: > > ``` > > === pico-sdk sync interop test === > platform: rp2350-arm-s > config: baseline, no RTOS (SDK lock_core macros, core 0 drives, core 1 agents) > spin locks: hardware, unlock sets the event > lock_core: the SDK's own; RP2350 workaround disabled; pico_time sleeps on a bare __wfe() > default alarm pool: core 0 > calibration: > spinner: no scheduler, so yielding does not apply (yield checks skipped) > cycles (agent core, 32-bit): busy 149/us, asleep 125/us -> does not separate, so the counter cannot see sleep; note omitted > agent core DWT_CTRL=0x40080001 DEMCR=0x01100000 (CYCCNTENA=1 TRCENA=1) > sleep detection: wait-loop iteration count (<=8 means it blocked) > DWT_SLEEPCNT (agent core): moved across a known sleep and held still while busy - a direct sleep signal is available > > --- D1: blocking discipline (mutex_enter_blocking, as pico_malloc) --- > [PASS ] D0 cycle counter 149/us; sleep counter moved (inline d=123, boundary d=123) > [PASS ] D1.1 1000 uncontended cycles, 489ns each > blocked wait duration: n=20 min=19998us mean=19999us max=20000us early=0 > [PASS ] D1.2 max wait 20000us for 20ms hold (no yield metric) > [SKIP ] D1.3 no scheduler, so no priority inversion to measure > [PASS ] D1.4 other core blocked: 2 wait iterations, 20011us, SLEEPCNT agrees (d=77) > [PASS ] D1.5 cross-core wakeup in 20001us > ISR notify -> waiter wake: n=20 min=4us mean=5us max=20us early=0 > [PASS ] D1.6 mean 5us, max 20us > [PASS ] D1.7 blocking acquire from ISR completed > [PASS ] D1.8 3-deep nesting released correctly > [FAIL ] D1.9 bare pattern blocked (2 iterations) but PICO_EXCLUSIVE_ACCESS_SETS_OWN_EVENT predicts it would busy-poll > [SKIP ] D1.10 needs two tasks blocked on one semaphore's event-group bit > > --- D2: try-then-timed discipline (mutex_try_enter_block_until, as pico_stdio) --- > [PASS ] D2.1 immediate (5us) > timed acquire, released before deadline: n=20 min=20001us mean=20001us max=20004us early=0 > [PASS ] D2.2 max wait 20004us for 20ms hold (no yield metric) > timeout overshoot: n=5 min=1us mean=1us max=3us early=0 > [PASS ] D2.3 never early, overshoot max 3us, 3 waits > [PASS ] D2.4 self-owner detected immediately (3us) > [PASS ] D2.5 timed acquire from ISR returned (timed out) > [PASS ] D2.6 immediate from ISR (5us) > [PASS ] D2.7 timed out at 50011us, 4 wait iterations > repeated-deadline overshoot: n=10 min=1us mean=1us max=3us early=0 > [PASS ] D2.8 never early, overshoot max 3us, 3 waits > [PASS ] D2.9 repeated waits on an expired deadline returned promptly (50018us) > [SKIP ] D2.10 needs a scheduler: a sub-tick deadline only means something against a tick > [PASS ] D2.11 20ms deadline met by sleeping (20011us, 7 iterations) with an earlier alarm firing at 12001us > [PASS ] D2.12 slept a 20ms deadline (pool IRQ on the other core, adds async): 20003us, 3 iterations > [INFO ] D2.13 39 iterations for 9 interferer fires (4.33x) over 20007us > [PASS ] D2.14 slept a 20ms deadline with a later alarm queued (20002us, 3 iterations) > [PASS ] D2.15 6 rounds of 6 cancellations, pool still places every one (pool IRQ on the other core, adds async) > [PASS ] D2.16 timed out at 50005us, 4 wait iterations > [PASS ] D2.17 timed out at 50007us, 5 wait iterations with both cores waiting > > --- D3: sleep_ms / sleep_until (ms-scale, concurrent, cross-core) --- > sleep_ms lateness: n=20 min=1us mean=1us max=5us early=0 > [PASS ] D3.1 never early, worst oversleep 5us, slept in 20/20 > [SKIP ] D3.2 needs tasks: more than one concurrent sleeper > [PASS ] D3.3 50ms sleep on the other core took 50001us (confirmed asleep) > [SKIP ] D3.4 needs tasks: a thief must block on an aliasing lock > > --- D4: alarm pool state --- > [PASS ] D4.1 pool left hardware alarm 0 armed after emptying (armed=0x09) > > === summary === > 26 pass, 1 fail, 5 skip, 0 expected-fail, 1 info > > failures: > D1.9 bare pattern blocked (2 iterations) but PICO_EXCLUSIVE_ACCESS_SETS_OWN_EVENT predicts it would busy-poll > FAILED > ``` this is now fixed
will-v-pi (Migrated from github.com) approved these changes 2026-09-02 04:10:53 -05:00
will-v-pi (Migrated from github.com) left a comment

LGTM

LGTM
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-raspberrypi/pico-sdk!3164
No description provided.