[issues-find] filed on 2026-09-02, lens Concurrency, at commit 545f501.
Severity: S3 (minor)
What is wrong
Random32 load-modify-stores gRngValue with interrupts enabled. VBlankIntr in src/main.c calls AdvanceRandom (line 383), which calls Random32 whenever sRngLoopUnlocked is TRUE; that lock is only taken around LOOP_RANDOM macros, not around Random32 itself.
Where
src/random.c:45 in Random32
u32 NAKED Random32(void)
{
asm(".thumb\n\
push {r4, r5, r6}\n\
mov r6, #11\n\
ldr r5, =gRngValue\n\
ldmia r5!, {r1, r2, r3, r4}\n\
@ result = a + b + (d+=STREAM1)\n\
add r1, r1, r2\n\
add r0, r1, r4\n\
add r4, r4, #" STR(STREAM1) "\n\
Why it matters
A VBlank nested inside Random32 tears gRngValue, so later Random/Random32 results are wrong (and can desync non-link systems that consume the same stream).
How to observe it
Static finding; not executed.
Recommended fix
In src/random.c, make Random32 (and Random2_32) reuse sRngLoopUnlocked around the state update, matching LOOP_RANDOM_START/END; keep AdvanceRandom skipping when the lock is held.
Done when
A test in test/random.c that calls Random32 in a tight loop while VBlank AdvanceRandom is enabled never observes a gRngValue that is not a valid successor of the previous state.
Lead check: snippet present at src/random.c:45; claim confirmed.
[issues-find] filed on 2026-09-02, lens Concurrency, at commit 545f501.
Severity: S3 (minor)
What is wrong
Random32 load-modify-stores gRngValue with interrupts enabled. VBlankIntr in src/main.c calls AdvanceRandom (line 383), which calls Random32 whenever sRngLoopUnlocked is TRUE; that lock is only taken around LOOP_RANDOM macros, not around Random32 itself.
Where
src/random.c:45inRandom32Why it matters
A VBlank nested inside Random32 tears gRngValue, so later Random/Random32 results are wrong (and can desync non-link systems that consume the same stream).
How to observe it
Static finding; not executed.
Recommended fix
In src/random.c, make Random32 (and Random2_32) reuse sRngLoopUnlocked around the state update, matching LOOP_RANDOM_START/END; keep AdvanceRandom skipping when the lock is held.
Done when
A test in test/random.c that calls Random32 in a tight loop while VBlank AdvanceRandom is enabled never observes a gRngValue that is not a valid successor of the previous state.
Lead check: snippet present at
src/random.c:45; claim confirmed.