[*] Updated WakeOnAddress comments

This commit is contained in:
Reece Wilson 2024-03-13 09:37:07 +00:00
parent 3f265cf19b
commit a80f6091c5

View File

@ -4,39 +4,51 @@
File: WakeOnAddress.hpp
Date: 2023-3-11
Author: Reece
Note: In emulation mode (*):
1: Wakes occur in FIFO order
Note:
This API can be configured to run in one of two modes - Emulation and Wrapper modes
In Emulation Mode:
1: Wakes occur in FIFO order so long as the thread is in the kernel
2: uWordSize can be any length not exceeding 32 bytes
otherwise
otherwise Wrapper Mode:
1: Wakes are orderless
2: uWordSize must be less than or equal to 8 bytes
2: uWordSize must be less than or equal to 8 bytes (todo: no?)
3: only the least significant 32bits are guaranteed to be used as wake signals
4: The special EWaitMethod variants will suffer a performance hit
in either mode:
1: WaitOnAddress[...] can wake at any-time if a fast-path permits.
(we only care about strict order guarantees during the deep slow-path yield operation.
after the first test, after an exchange miss, after a fast path succeeds,
it's anybodys guess who will *return* first. on the other hand, a set of 5 threads
already in the kernel *should* wake in the expected order. otherwise, the WaitOnAddress[...]
functions merely assumes the comparison operation is an orderless return condition.)
1 cont: This extends to correcting spurious wakeups. If the condition is lost, we will not return.
* By default: UNIXes and targets below/inc Windows 7 will be in userland emulation mode for performance reasons.
* Linux and other targets can directly interface with their futex interface under a smaller wrapper;
* however, these applications are limited to internal synchronization primitives. The added bloat
* of the WaitOnAddress/FUTEX/atomic wait emulation layer improves performance in real world dumb
* code with spurious wakes, odd word sizes, and pointer alignments. Not to mention some targets
* are stuck with semaphores or condition variables to start off with, and therefore need this
* for the sake of porting modern applications. The aforementioned synchronization primitives
* are written with OS specific optimizations in mind, and therefore consider emulation bloat.
* bPreferEmulatedWakeOnAddress disables the emulation layer, if theres a reasonable native
* interface available.
* Defer to ThreadingConfig::bPreferEmulatedWakeOnAddress = !AuBuild::kIsNtDerived
1: WaitOnAddress[...] can wake at anytime the wakeup method is successful
2: WaitOnAddress[...] can drop any wakeup if the wakeup method would fail
WARNING: Windows 10+ WILL NOT HAVE EFFICIENT IMPLEMENTATIONS OF THE SPECIAL VARIANTS
Windows XP - 7 will by necessity; Linux will by default; Windows 10, on the other hand, is biased towards a thinner eNotEqual wrapper.
WARNING: ThreadingConfig::bPreferEmulatedWakeOnAddress == FALSE WILL IMPACT THE SPECIAL VARIANTS PERFORMANCE
By default:
Windows XP - Windows 7 => Emulation Mode
Windows 10+ => Wrapper Mode
Linux => Emulation Mode; however, Wrapper Mode is available
**************************************************************************************
All platforms : ThreadingConfig::bPreferEmulatedWakeOnAddress = !AuBuild::kIsNtDerived
**************************************************************************************
Also note: Alongside Wrapper Mode, there is an internal set of APIs that allow for 32-bit word WoA support for
AuThread primitives. These are only used if the operating system has a futex interface available at
runtime. MacOS, iOS, and <= Windows 7 support requires these paths to be disabled. In other cases,
the internal wrapper and Wrapper Mode should use this path to quickly yield to kernel
Generally speaking, AuThreadPrimitives will use the futex layer or some OS specific mechanism to
bail out into the kernels' thread scheduler as quickly as possible.
In any mode, AuThreadPrimitives will go from: Primitive -> kernel/platform; or
Primitive -> WoA Internal Wrapper -> kernel/platform
In ThreadingConfig::bPreferEmulatedWakeOnAddress mode, AuThreading::WaitOnAddress -> Emulation Mode.
In !ThreadingConfig::bPreferEmulatedWakeOnAddress mode, AuThreading::WaitOnAddress -> Wrapper Mode -> [...]
[...] -> Internal Wrapper -> kernel/platform
In any mode, the futex reference primitives including AuBarrier, AuInitOnce, AuFutexMutex, etc,
will always go from: inlined header template definition -> relinked symbol -> AuThreading::WaitOnAddress
-> [...].
Note that some edge case platforms can follow AuThreadPrimitives *.Generic -> Internal Wrapper -> [...]
[...] -> AuThreading::WaitOnAddress -> Emulation Mode.
This is only the case when, we lack OS specific wait paths for our primitives; and lack a native
wait on address interface to develop the internal wrapper. Fortunately, only more esoteric UNIX machines
require these. Further platform support can be added with this; only a semaphore or conditionvar/mutex
pair is required to bootstrap this path.
***/
#pragma once