Page MenuHomeFreeBSD

Avoid a race when we're setting the event timer while going idle
AcceptedPublic

Authored by jtl on Mar 24 2018, 2:48 PM.
Tags
None
Referenced Files
Unknown Object (File)
Dec 26 2023, 3:22 AM
Unknown Object (File)
Dec 23 2023, 1:32 AM
Unknown Object (File)
Nov 1 2023, 10:41 PM
Unknown Object (File)
Jul 3 2023, 8:03 AM
Unknown Object (File)
Jun 17 2023, 7:34 AM
Unknown Object (File)
Jun 15 2023, 5:30 PM
Unknown Object (File)
May 14 2023, 6:22 AM
Unknown Object (File)
May 10 2023, 9:31 PM
Subscribers

Details

Summary

Avoid a race when we're setting the event timer while going idle by not reading the next event until we hold the lock and are ready to set the timer.

Previously, cpu_idleclock() could race with another thread trying to set an earlier event. cpu_idleclock() would read the next event time. The other thread would set an earlier event. Then, cpu_idleclock() would acquire the lock and set the event timer based on the later event it had previously read.

By acquiring the lock before reading the next event, cpu_idleclock() will get a consistent view of the next event. And, the other thread will get a consistent view of the state of the timers which are actually set.

Test Plan

I ran this against a test which measured the delay encountered by direct timeouts. With this change and D14827 and D14826, it appears that all the spurious delays have been eliminated, and the delay from the deadline averaged 2.111 microseconds with a 2.505749 standard deviation.

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 15774
Build 15786: arc lint + arc unit

Event Timeline

What are the delays without these changes ?

This revision is now accepted and ready to land.Mar 24 2018, 3:26 PM
In D14828#311827, @kib wrote:

What are the delays without these changes ?

Without this change, I saw callouts periodically have 2ms delays on an idle system. After this change (which was applied on top of the other two changes referenced in the description), the 2ms delays went away.

Make sure you also check this code with:
debug.witness.skipspin=0

In /boot/loader.conf

--HPS

It slightly increases lock hold time, which may be a bottleneck in case of a global lock/timer, but it probably does not worth overcomplication to avoid only that.