CVSROOT: /cvs Module name: src Changes by: d...@cvs.openbsd.org 2025/04/29 18:26:02
Modified files: sys/kern : kern_synch.c Log message: avoid timeout_del_barrier when cancelling the timeout in sleep_finish. because of src/sys/kern/kern_timeout.c r.1.101, timeout_del_barrier now unconditionally calls timeout_barrier. timeout_barrier now unconditionally queues a timeout and tries to "wake up" the context that services the queue of pending timeouts, which in this case is the softclock interrupt. unfortunately softclock isn't MPSAFE, so it tries to take the kernel lock, which is often already held by another part of the system. bluhm@ has a network stress test which manages to produce this contention almost 100% of the time, and the performance is terrible because of it. sleep_finish is currently relying on timeout_del_barrier to ensure that the endtsleep handler has finished running. this diff changes it so sleep_finish tracks where endtsleep is up to itself, which avoids the timeout barrier, which in turn avoids the kernel lock contention. this comment added to the code explains it further: /* * There are three situations to handle when cancelling the * p_sleep_to timeout: * * 1. The timeout has not fired yet * 2. The timeout is running * 3. The timeout has run * * If timeout_del succeeds then the timeout won't run and * situation 1 is dealt with. * * If timeout_del does not remove the timeout, then we're * handling 2 or 3, but it won't tell us which one. Instead, * the P_TIMEOUTRAN flag is used to figure out when we move * from 2 to 3. endtsleep() (the p_sleep_to handler) sets the * flag when it's finished running, so we spin waiting for * it. * * We spin instead of sleeping because endtsleep() takes * the sched lock to do all it's work. If we wanted to go * to sleep to wait for endtsleep to run, we'd also have to * take the sched lock, so we'd be spinning against it anyway. */ ok visa@ claudio@ mpi@ tested by bluhm@