The author should read https://webkit.org/blog/6161/locking-in-webkit/ so that they understand what they are talking about.
WebKit does it right in the sense that:
- It as an optimal amount of spinning
- Threads wait (instead of spinning) if the lock is not available immediately-ish
And we know that the algorithms are optimal based on rigorous experiments.
> - It as an optimal amount of spinning
No it isn't, it has a fixed number of yields, which has a very different duration on various CPUs
> Threads wait (instead of spinning) if the lock is not available immediately-ish
They use parking lots, which is one way to do futew (in fact, WaitOnAddress is implemented similarly). And no if you read the code, they do spin. Worse, they actually yield the thread before properly parking.
One area where I found spinlocks to be useful is in multithreaded audio applications. Audio threads are not supposed to be preempted by other user space threads because otherwise they may not complete in time, leading to audio glitches. The threads have a very high priority (or have a special scheduling policy) and may be pinned to different CPU cores.
For example, multiple audio threads might read from the same sample buffer, whose content is occasionally modified. In that case, you could use a reader-writer-spinlock where multiple readers would be able to progress in parallel without blocking each other. Only a writer would block other threads.
What would be the potential problems in that scenario?
My example above was rather about the DSP graphs themselves that are computed in parallel. These require to access to shared resources like audio buffers, but under no circumstance should they give up their timeslice and yield back to the scheduler. That's why we're using reader-writer spinlocks to synchronize access to these resources. I really don't see any other practical alternative... Any ideas?
The only time I've manually written my own spin lock was when I had to coordinate between two different threads, one of which was running 16-bit code, so using any library was out of the question, and even relying on syscalls was sketchy because making sure the 16-bit code is in the right state to call a syscall itself is tricky. Although in this case, since I didn't need to care about things like fairness (only two threads are involved), the spinlock core ended up being simple:
"thunk_spin:",
"xchg cx, es:[{in_rv}]",
"test cx, cx",
"jnz thunk_has_data",
"pause",
"jmp thunk_spin",
"thunk_has_data:",The following is an interesting talk where the author used a custom spinlock to significantly speed up a real-time physics solver.
Dennis Gustafsson – Parallelizing the physics solver – BSC 2025 https://www.youtube.com/watch?v=Kvsvd67XUKw
Yes, but sadly not all implementations... The point remains that you should prefer OS primitives when you can, profile first, reduce contention, and then only, maybe, if you reeeally know what you're doing, on a system you mostly know and control, then perhaps you may start doing it yourself. And if you do, the fallback under contention must be the OS primitive
Real Windows, and Linux, don't have this problem. Only Wine's "malloc" in a DLL, which does.
Bug reports resulted in finger-pointing and denial.[1] "Unconfirmed", despite showing debugger output.
rdtsc may execute out of order, so sometimes an lfence (previously cpuid) can be used and there is also rdtscp
See https://github.com/torvalds/linux/blob/master/arch/x86/inclu...
And just because rdtsc is constant doesn't mean the processor clock will be constant that could be fluctuating.
Stealing is an example of an unfairness which can significantly improve overall performance.
Everyone's computers hang or get slow some of the time. Probably all of our locks have bugs in them, but good luck getting to the bottom of that, right now the industry is barely capable of picking a sorting algorithm that actually works.
I suppose someplace someone is running an embedded system without an OS on such a processor - but I'd expect they are still using extra cores and so have all of the above tricks someplace.
You may have some simple chemical life needs, and life may have some other simple chemical it can use to get the needed simple chemical, but the processing steps are complex and limited by physics themselves. Evolution almost always finds a path of using the minimum activation energy to let these reactions occur. Trying to make the process simpler just doesn't get you what you need.
It's a weak signal but the reasoning is sound.
Code has a minimum complexity to solve the problem