69 lines
4.5 KiB
Plaintext
69 lines
4.5 KiB
Plaintext
/**
|
|
* Footnotes:
|
|
* "Wakes the count of currently sleeping threads without guaranteed respect for ordering."
|
|
* "Assuming correctness of your mutex paths, this will wake all threads up-to your everyone-be-alert condition"
|
|
* [...]
|
|
* "Schedules a single thread for wake up without guaranteed respect for ordering.
|
|
*
|
|
* A simple explaination:
|
|
*---------------------------------------------
|
|
* Problematic broadcasts:
|
|
*
|
|
* Under mutex:
|
|
* Sleep: [A, B, C]
|
|
*
|
|
* Under or out of mutex (it doesnt matter so long as you barrier the mutex after the state change):
|
|
* ~awake all? shutdown condition? who knows~
|
|
* Broadcast
|
|
*
|
|
* Out of mutex (Bad Use Case !!!):
|
|
* if (~missed/incorrect if !work available check before sleep~)
|
|
* Sleep: [D]
|
|
* // given that WaitForSignal forces you to unlock and relock a mutex, this illogical branch should never happen
|
|
*
|
|
* Effect:
|
|
* Awake: [B, C, D]
|
|
* Sleeping: [A]
|
|
*
|
|
*---------------------------------------------
|
|
* Problematic signals:
|
|
*
|
|
* Under mutex:
|
|
* Sleep: [A, B, C]
|
|
*
|
|
* Not under mutex (it doesnt matter so long as you barrier the mutex after the state change):
|
|
* Signal
|
|
*
|
|
* Under mutex:
|
|
* Sleep: [D]
|
|
*
|
|
* Effect:
|
|
* Awake: [D]
|
|
* Sleeping: [A, B, C]
|
|
*
|
|
*---------------------------------------------
|
|
* Cause:
|
|
* The condition variables account for the amount of threads sleeping accuarely, not the order.
|
|
* This is usually a good thing because ordering under a spinloop generally does not happen in time and/or does not matter.
|
|
* The lowest common denominator of kernel thread scheduling is fundamentally that of a semaphore scheduled with respect to buckets of integer thread priority levels, and nothing more complex than that.
|
|
* To implement ordering, is to implement cache-thrashing and increased context-switching for an abstract idea of "correctness" that doesn't apply to real code or performance goals.
|
|
* (spoilers: using a condvar, your work pool of uniform priorities couldn't care less which thread wakes up first, nor does a single waiter pattern; but your end product will certainly bleed performance with ticket yield thrashing or suboptimal spinning )
|
|
* ( : the same can be said for semaphores; what part of waiting while an available work count is not zero needs ordering? )
|
|
* ( : yield thrashing, that might i add, serves no purpose other than to get the right thread local context and decoupled-from-parent thread id of a context on a given physical core of a highly limited set )
|
|
* ( : the only valid use case for ordered lock types is in the instance of RWLock read exhausting writers, and thats easily accounted by separating the read and write wake queues )
|
|
*
|
|
*---------------------------------------------
|
|
* The fix[es] / Mitigations:
|
|
* * Ensure to check the correctness of the sleep condition, and that the mutex is properly locked, before calling any Aurora condition primitives' sleep routines
|
|
* (why the fuck would you be sleeping on a variable state observer without checking its' state, causing an unwanted defect? this is counter to the purpose of using a condvar.)
|
|
*
|
|
* * Increase the size of the condition variable to account for a counter and implement inefficient rescheduling, to fix fundamentally flawed user code
|
|
* (no thanks. implement ticket primitives yourself, see: the hacky workaround.)
|
|
*
|
|
* * "Problematic signals:" I know what you're trying to do, and you're being stupid for attempting to force condvars to act as barriers this way. Instead, just use the actual timeline-capable semaphore of AuFutexSemaphore::LockUntilAtleastAbsNS and bPreferEmulatedWakeOnAddress = true.
|
|
*---------------------------------------------
|
|
* The hacky workaround:
|
|
* * If you can somehow justify this, i doubt it, but if you can, you can aim for the slow-path ordered sleep of/by using AuFutex[Mutex/Semaphore/Cond] with ThreadingConfig::bPreferEmulatedWakeOnAddress = true.
|
|
* * Noting that all futex paths can still take a fast path to bypass ordering.
|
|
*/
|