From 0555e8cc32cf80259de041f2e887bd4d732f0020 Mon Sep 17 00:00:00 2001 From: Jamie Reece Wilson Date: Sun, 30 Jun 2024 05:13:55 +0100 Subject: [PATCH] [*] Update: WakeOnAddress.hpp comments --- Include/Aurora/Threading/WakeOnAddress.hpp | 37 +++++++++++++++++----- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/Include/Aurora/Threading/WakeOnAddress.hpp b/Include/Aurora/Threading/WakeOnAddress.hpp index 1feaf6b2..3f07093d 100644 --- a/Include/Aurora/Threading/WakeOnAddress.hpp +++ b/Include/Aurora/Threading/WakeOnAddress.hpp @@ -49,11 +49,25 @@ 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. + + Memory note: Weakly ordered memory is an alien concept. AuAtomicXXX operations ensure all previous stores are + visible across all cores (useful for semaphore increment and mutex-unlock operations), and that loads + are evaluated in order. For all intents and purposes, you should treat the au ecosystem like any + other strongly ordered processor and program pair. For memeworthy lockless algorithms, you can use + spec-of-the-year atomic word containers and related methods; we dont care about optimizing some midwits + weakly-ordered cas spinning and ABA-hell container, thats genuinely believed to be the best thing ever. + Sincerely, you are doing something wrong if you're write-locking a container for any notable length of + time, and more often than not, lock-free algorithms are bloated to all hell, just to end up losing in + most real world use cases. + + tldr: Dont worry about memory ordering or ABA. Use the locks, atomic utilities, and primitives as expected. + (you'll be fine) ***/ #pragma once namespace Aurora::Threading { + // Break sleep when volatile pTargetAddress [...] constant pCompareAddress AUE_DEFINE(EWaitMethod, ( eNotEqual, eEqual, eLessThanCompare, eGreaterThanCompare, eLessThanOrEqualsCompare, eGreaterThanOrEqualsCompare )) @@ -67,9 +81,9 @@ namespace Aurora::Threading AuUInt8 uNMaximumThreads); // On systems with processors of shared execution pipelines, these try-series of operations will spin (eg: mm_pause) for a configurable - // amount of time, so long as the the process-wide state isn't overly contested. This means you can use these arbitrarily without - // worrying about an accidental thundering mm_pause herd. If you wish to call WaitOnAddress[...] afterwards, you should report you already - // spun via optAlreadySpun. If the application is configured to spin later on, this hint may be used to prevent a double spin. + // amount of time, or enter a low power mode, so long as the the process-wide state isn't overly contested. This means you can use these + // arbitrarily without worrying about an accidental thundering mm_pause herd. If you wish to call WaitOnAddress[...] afterwards, you should + // report you already spun via optAlreadySpun. If the application is configured to spin later on, this hint may be used to prevent a double spin. AUKN_SYM bool TryWaitOnAddress(const void *pTargetAddress, const void *pCompareAddress, AuUInt8 uWordSize); @@ -80,9 +94,9 @@ namespace Aurora::Threading AuUInt8 uWordSize); // On systems with processors of shared execution pipelines, these try-series of operations will spin (eg: mm_pause) for a configurable - // amount of time, so long as the the process-wide state isn't overly contested. This means you can use these arbitrarily without - // worrying about an accidental thundering mm_pause herd. If you wish to call WaitOnAddress[...] afterwards, you should report you already - // spun via optAlreadySpun. If the application is configured to spin later on, this hint may be used to prevent a double spin. + // amount of time, or enter a low power mode, so long as the the process-wide state isn't overly contested. This means you can use these + // arbitrarily without worrying about an accidental thundering mm_pause herd. If you wish to call WaitOnAddress[...] afterwards, you should + // report you already spun via optAlreadySpun. If the application is configured to spin later on, this hint may be used to prevent a double spin. // In the case of a pTargetAddress != pCompareAddress condition, the optional check parameter is used to verify the wake condition. // Otherwise, spinning will continue. AUKN_SYM bool TryWaitOnAddressEx(const void *pTargetAddress, @@ -90,13 +104,16 @@ namespace Aurora::Threading AuUInt8 uWordSize, const AuFunction &check); + // See: TryWaitOnAddressEx AUKN_SYM bool TryWaitOnAddressSpecialEx(EWaitMethod eMethod, const void *pTargetAddress, const void *pCompareAddress, AuUInt8 uWordSize, const AuFunction &check); - // Relative timeout variant of nanosecond resolution WoA. 0 = indefinite + // Relative timeout variant of nanosecond resolution eNotEqual WoA. 0 = indefinite. + // In Wrapper Mode, it is possible to bypass the WoA implementation, and bail straight into the kernel. + // For improved order and EWaitMethod, do not use Wrapper Mode. AUKN_SYM bool WaitOnAddress(const void *pTargetAddress, const void *pCompareAddress, AuUInt8 uWordSize, @@ -104,6 +121,7 @@ namespace Aurora::Threading AuOptional optAlreadySpun = {} /*hint: do not spin before switching. subject to global config.*/); // Relative timeout variant of nanosecond resolution WoA. 0 = indefinite + // Emulation Mode over Wrapper Mode is recommended for applications that heavily depend on these wait functions. AUKN_SYM bool WaitOnAddressSpecial(EWaitMethod eMethod, const void *pTargetAddress, const void *pCompareAddress, @@ -111,7 +129,9 @@ namespace Aurora::Threading AuUInt64 qwNanoseconds, AuOptional optAlreadySpun = {} /*hint: do not spin before switching. subject to global config.*/); - // Absolute timeout variant of nanosecond resolution WoA. Nanoseconds are in steady clock time. 0 = indefinite + // Absolute timeout variant of nanosecond resolution eNotEqual WoA. Nanoseconds are in steady clock time. 0 = indefinite + // In Wrapper Mode, it is possible to bypass the WoA implementation, and bail straight into the kernel. + // For improved order and EWaitMethod, do not use Wrapper Mode. AUKN_SYM bool WaitOnAddressSteady(const void *pTargetAddress, const void *pCompareAddress, AuUInt8 uWordSize, @@ -119,6 +139,7 @@ namespace Aurora::Threading AuOptional optAlreadySpun = {} /*hint: do not spin before switching. subject to global config.*/); // Absolute timeout variant of nanosecond resolution WoA. Nanoseconds are in steady clock time. 0 = indefinite + // Emulation Mode over Wrapper Mode is recommended for applications that heavily depend on these wait functions. AUKN_SYM bool WaitOnAddressSpecialSteady(EWaitMethod eMethod, const void *pTargetAddress, const void *pCompareAddress,