4 ms·
It turns out that you can make something a lot like an array of shared copies of the days, protected by a seqlock that is “almost” wait-free: https://link.spri
by amluto 3y ago
It turns out that you can make something a lot like an array of shared copies of the days, protected by a seqlock that is “almost” wait-free:
https://link.springer.com/content/pdf/10.1007/978-3-540-92221-6_40.pdf https://link.springer.com/content/pdf/10.1007/978-3-540-9222...
“Almost” means that you can have n copies of the data, and the probability of waiting scales like 2^-n. Alternatively, and perhaps better, the degree of relative slowness of the reader needed to cause a wait goes like 2^n, so for any reasonable n, reads will never wait in practice. And it’s genuinely lock-free: the writer can hang at any point and read will continue to complete.
Somewhat sadly, this algorithm doesn’t seem to get much traction. I’ve considered implementing it for Linux clock reads to reduce tail latency. It’s really quite simple, and the common case works just like a seqlock.
I need to dig up the terms and conditions of this journal and post a non-paywalled version somewhere.
(Lock-free means that each thread is guaranteed to make progress even if any combination of other threads stop at arbitrary points. Normal seqlocks are not lock-free. Wait-free means that each thread completes each operation in a bounded about of running time, regardless of what the other threads do. In other words, livelocks are impossible. One can straightforwardly use a two copies of a data structure, write to them alternately, and protect them with the obvious sequence count, and get a lock-free, but not wait-free, data structure. The linked algorithm extends this to more than 2 copies, written with exponentially decreasing frequency.)
- loeg 3y agoIn Linux kernel context, you could plausibly prevent write stalls (other than NMIs) by masking interrupts for the write section. I guess there are some seriously slow NMIs though and we would prefer something that worked well despite those.
- amluto 3y agoThis doesn’t work in a VM or if there’s an SMI or if there is any other glitch. There’s a more fundamental and harder-to-solve issue, though: time (CLOCK_MONOTONIC or whatever) is a function of the underlying clock source (TSC, for example), and that function is defined piecewise (and must be if it changes in ways that are not known in advance). And, fundamentally, if the thread evaluating the function after some change gets ahead of the thread making the change in the first place, it’s awkward to get the right answer without waiting. The best I’ve come up with is for the thread running the show to record that, for TSC values above t, a new function is used, and to do this well in advance of t. I don’t know a way to do an atomic commit of a change if and only iff TSC < some threshold.
- loeg 3y agoYeah, SMIs are exactly the kind of very slow NMI I had in mind.