3 ms·
Why not "just" fall back to a mutex after enough spinning? I guess this would require an extra branch in the unlocking function (to check whether there are thr
by comex 11y ago
Why not "just" fall back to a mutex after enough spinning? I guess this would require an extra branch in the unlocking function (to check whether there are threads blocked in the kernel that need to be woken up), but that doesn't sound too awful especially as the branch would very rarely be taken. (It would sort of break OSSpinLock's ABI though. Sort of.)
AKA an adaptive mutex.
- eridius 11y ago(rewritten after looking up Linux's adaptive mutex) Assuming you mean something like http://stackoverflow.com/a/25168942/582 http://stackoverflow.com/a/25168942/582, you basically need a full mutex anyway, so I'm not sure why you wouldn't just use a mutex directly. I don't think you can really implement this adaptive mutex in userland because you can't just use a spinlock + a mutex (you'd have to lock the mutex every time anyway, which defeats the point of having the spinlock) and syscalls are not considered public API (the kernel is allowed to change syscalls between versions, libc/libsystem is the only public API for them). FWIW pthread mutexes were sped up 2-2.5x in "new OSs" to compensate for spinlocks being illegal (https://twitter.com/catfish_man/status/676852111527706624 https://twitter.com/catfish_man/status/676852111527706624).
- pcwalton 11y ago> you'd have to lock the mutex every time anyway I don't understand. Could you explain this in more detail? In Linux, adaptive mutexes are implemented entirely in userspace with futex as the primitive syscall. This is because atomic CAS (cmpxchg, ldrex/strex, etc) suffices to ensure synchronization during the spinning.
- eridius 11y agosyscalls aren't public API on Darwin platforms (e.g. iOS, OS X). The only supported interface to syscalls is libc/libsystem. And I'm not aware of any equivalent to futex. So AFAIK there's no way to implement a userspace mutex that isn't just a wrapper around a system-provided mutex (e.g. pthread_mutex, or a serial libdispatch queue). And if you're wrapping pthread_mutex, adding a spinlock doesn't provide any benefit. FWIW, libdispatch itself definitely uses Mach SPI. For example, skimming through the source, it calls thread_switch() using a non-public option (there's 3 non-public options to thread_switch now, two of which are intended for dealing with the QOS issues that my article talked about; the private os_lock_handoff_s that the objc runtime uses internally uses one called SWITCH_OPTION_OSLOCK_WAIT and libdispatch appears to use the other, SWITCH_OPTION_OSLOCK_DEPRESS, as well as the third option which was added just for libdispatch called SWITCH_OOPTION_DISPATCH_CONTENTION).