Sync Primitives Research: SRW Spin, Adaptive CS, Condvar PI

Historical research archive retained as background for the CS-PI, condvar-PI, and SRW-spin design choices.


1. Windows Behavior (what apps expect)

SRW Locks

Critical Sections

WaitOnAddress

Condition Variables


2. Linux/glibc Behavior (what our platform provides)

glibc Adaptive Mutex (PTHREAD_MUTEX_ADAPTIVE_NP)

glibc pthread_rwlock

Linux Kernel rwsem (CONFIG_RWSEM_SPIN_ON_OWNER)

Linux Kernel Mutex Adaptive Spin (CONFIG_MUTEX_SPIN_ON_OWNER)

PI for Read-Write Locks – State of the Art


3. Upstream Wine vs Wine-NSPA Implementation

SRW Locks (dlls/ntdll/sync.c)

Aspect Upstream Wine Wine-NSPA (v5)
Spin count 0 – straight to RtlWaitOnAddress 256 iterations
RT behavior Same as normal threads RT threads skip spin entirely (SCHED_FIFO starvation prevention)
Wait path RtlWaitOnAddress -> FIFO queue -> futex_wait Same (spin is before this path)
PI support None None (SRW PI deferred – unsolved problem)

Bit layout (both): struct srw_lock { short exclusive_waiters; unsigned short owners; } = 4 bytes. Wait is via RtlWaitOnAddress -> user-space FIFO queue -> NtWaitForAlertByThreadId -> futex_wait. No spin in RtlWaitOnAddress itself – the spin phase is in the acquire functions.

Critical Sections (dlls/ntdll/sync.c)

Aspect Upstream Wine Wine-NSPA
Contended path Keyed event wait (NtWaitForKeyedEvent) FUTEX_LOCK_PI (kernel rt_mutex PI chain)
Spin loop Fixed YieldProcessor, bailout on LockCount > 0 Same spin loop, PI path handles contention
DYNAMIC_SPIN flag FIXME stub FIXME stub (planned)
PI support None Full PI via nspa_cs_enter_pi()

Condition Variables (dlls/ntdll/sync.c + libs/librtpi/rtpi.h)

Aspect Upstream Wine Wine-NSPA (v5)
Win32 condvar (RtlSleepConditionVariableCS) RtlWaitOnAddress, no PI Same (no PI – uses RtlWaitOnAddress, not pi_cond)
Unix-side condvar (pi_cond_t) Not present FUTEX_WAIT_REQUEUE_PI
pi_cond consumers N/A ntdll file I/O, virtual memory, audio drivers, gstreamer
PI gap on wake N/A Closed – kernel atomically requeues waiter onto PI mutex

RtlWaitOnAddress (dlls/ntdll/sync.c)


4. librtpi Integration

What librtpi provides

Wine-NSPA integration


5. Comparison Table

Implementation Spin Count Algorithm Owner-Aware PI Support
Windows SRW ~1024 (fixed) test + pause loop No No
Windows CS 0 or caller-set (DYNAMIC_SPIN: ~2000-4000) test + YieldProcessor No No (kernel Mutant only)
glibc adaptive mutex 100 (fixed) atomic_load + pause No Separate (PTHREAD_PRIO_INHERIT)
glibc rwlock 0 (no spinning) Direct futex wait No No
Kernel mutex Unbounded (owner-tracking) OSQ + spin while owner on CPU Yes Via rt_mutex on PREEMPT_RT
Kernel rwsem (writer) Unbounded (owner) + 10-25us (reader-owned) OSQ + owner tracking + time cap Yes Partial (writer only) on PREEMPT_RT
Upstream Wine SRW 0 (no spinning) Direct RtlWaitOnAddress No No
Wine-NSPA SRW 256 (fixed, RT skips) test + YieldProcessor No No
Upstream Wine CS Static (caller-set) YieldProcessor + early bailout No No
Wine-NSPA CS Static (caller-set) YieldProcessor + early bailout No FUTEX_LOCK_PI
Wine-NSPA pi_cond N/A FUTEX_WAIT_REQUEUE_PI N/A Requeue-PI (atomic)

6. Remaining Design Work

A – CS DYNAMIC_SPIN (Planned)

Implement RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN properly: - Substitute system default spincount (~4000, matching Windows) - Gate behind !nspa_cs_pi_active() – when PI is active, the kernel handles contention better than userspace spinning - Low priority since the PI path is the primary contention mechanism

C2 – SRW PI (Deferred Indefinitely)

SRW locks have no owner by design. PI requires an owner. This is unsolved even in the Linux kernel: - No FUTEX_RDLOCK_PI or equivalent exists - PREEMPT_RT’s rwsem approach (serialize writers through rt_mutex) has known reader-starvation issues - Windows itself has no SRW PI – apps don’t expect it

Decision: Don’t pursue. Focus PI effort on CS (done) and condvar (done). For RT paths that need PI, apps should use CriticalSection not SRW.


7. Implementation Status

  1. B – SRW spin phaseIMPLEMENTED

  2. C1 – pi_cond requeue-PIIMPLEMENTED

  3. A – CS DYNAMIC_SPINPlanned

  4. C2 – SRW PIDeferred indefinitely


8. Open Questions