const MAX_SPINS: u32 = u32::MAX /* 4_294_967_295u32 */;Expand description
Spinning for a queue lock, or for holders to drop a task, is bounded by can_loop alone, as lib/edq’s is. On JITs with timed may_goto, x86 and arm64 among them, that is a quarter of a second per program run, not BPF_MAX_LOOPS iterations. A holder can be held up for milliseconds, by an interrupt or, on a virtual machine, by the host descheduling its vCPU.
The lock’s spin runs in lock_slow(), whose frame is small. With CONFIG_EXT_SUB_SCHED, ops.dispatch() runs on a private stack, which the verifier gives every subprogram of 64 bytes of stack or more, and x86’s arch_bpf_timed_may_goto() looks for its timestamp off %rbp rather than the private frame pointer: it reads garbage there and ends the loop after its first 0xffff iterations. Inlined into dispatch’s frames, the spin gave up after a few hundred microseconds under steal contention in a 64-vCPU guest, where lib/edq’s, in small subprograms, waited.