[+] while_bc

This commit is contained in:
Reece Wilson 2024-04-13 22:49:05 +01:00
parent e3745d0efa
commit 0164919cd9
5 changed files with 33 additions and 3 deletions

View File

@ -122,7 +122,11 @@ namespace Aurora::Threading::Waitables
AuUInt32 uWaitCount {}; AuUInt32 uWaitCount {};
AuUInt32 uWaiters {}; AuUInt32 uWaiters {};
#if defined(AURORA_RUNTIME_FUTEX_AGGRESSIVE_COND_WAKE)
while ((uWaiters = AuAtomicLoad(&this->uAtomicSleeping))) while ((uWaiters = AuAtomicLoad(&this->uAtomicSleeping)))
#else
if ((uWaiters = AuAtomicLoad(&this->uAtomicSleeping)))
#endif
{ {
AuAtomicAdd(&this->uAtomicState, uWaiters); AuAtomicAdd(&this->uAtomicState, uWaiters);
WakeNOnAddress((const void *)&this->uAtomicState, uWaiters); WakeNOnAddress((const void *)&this->uAtomicState, uWaiters);

View File

@ -8,6 +8,7 @@
#include <Source/RuntimeInternal.hpp> #include <Source/RuntimeInternal.hpp>
#include "AuConditionEx.hpp" #include "AuConditionEx.hpp"
#include "AuSemaphore.Generic.hpp" #include "AuSemaphore.Generic.hpp"
#include "SMTYield.hpp" // for: while_bc
namespace Aurora::Threading::Primitives namespace Aurora::Threading::Primitives
{ {
@ -144,7 +145,7 @@ namespace Aurora::Threading::Primitives
AuUInt32 uWaitCount {}; AuUInt32 uWaitCount {};
AuUInt32 uWaiters {}; AuUInt32 uWaiters {};
while ((uWaiters = AuAtomicLoad(&this->uWaiters_))) while_bc ((uWaiters = AuAtomicLoad(&this->uWaiters_)))
{ {
this->s_.Unlock(uWaiters); this->s_.Unlock(uWaiters);
uWaitCount = uWaiters; uWaitCount = uWaiters;

View File

@ -90,7 +90,7 @@ namespace Aurora::Threading::Primitives
AuUInt32 uWaitCount {}; AuUInt32 uWaitCount {};
AuUInt32 uWaiters {}; AuUInt32 uWaiters {};
while ((uWaiters = AuAtomicLoad(&this->uSleeping_))) while_bc (uWaiters = AuAtomicLoad(&this->uSleeping_))
{ {
AuAtomicAdd(&this->uState_, uWaiters); AuAtomicAdd(&this->uState_, uWaiters);
InternalLTSWakeCount(&this->uState_, uWaiters); InternalLTSWakeCount(&this->uState_, uWaiters);

View File

@ -180,7 +180,7 @@ namespace Aurora::Threading::Primitives
AuUInt32 uWaitCount {}; AuUInt32 uWaitCount {};
AuUInt32 uWaiters {}; AuUInt32 uWaiters {};
while ((uWaiters = AuAtomicLoad(&this->uSleeping_))) while_bc ((uWaiters = AuAtomicLoad(&this->uSleeping_)))
{ {
AuAtomicAdd(&this->uState_, uWaiters); AuAtomicAdd(&this->uState_, uWaiters);
futex_wake(&this->uState_, uWaiters); futex_wake(&this->uState_, uWaiters);

View File

@ -22,6 +22,31 @@ extern "C"
#define SPIN_FOUR 1 #define SPIN_FOUR 1
#define while_bc___(exp, ex) \
AuUInt32 __wsc ## ex {}; \
while ((exp) && ((__wsc ## ex++) < 2))
#define while_bc__(exp, ex) while_bc___(exp, ex)
#define while_bc_(exp, ex) while_bc__(exp, AU_WHAT(ex))
#if defined(AURORA_RUNTIME_ALWAYS_SPIN_ON_BROADCAST)
#define while_bc(exp) while (exp)
#elif defined(AURORA_RUNTIME_ALWAYS_CHECK_ONCE_ON_BROADCAST)
#define while_bc(exp) if (exp)
#elif defined(__COUNTER__)
#define while_bc(exp) while_bc_(exp, __COUNTER__)
#else
#define while_bc(exp) while_bc_(exp, __LINE__)
#endif
// Replace condition variable broadcasts: `if/while (waiters) { signal() }` loops with while_bc.
// while_bc will attempt to rebroadcast if another sleeper turns up. On unicore systems,
// depending on the scheduler, spinning in this fashion may result in a deadlock in a tight
// enough wait loop. In other systems, having a `while (waiters) { signal(); }` may help
// improve performance when other threads are tying up the system scheduler on the wake side.
// That way some threads can be late in, and we dont have to worry so much about there being a
// wake-up spin lock under real world use cases. To strike a balance between the two conditions,
// we add a little bit of extra branching overhead to ensure we don't spin more than 2-3 times.
namespace Aurora::Threading::Primitives namespace Aurora::Threading::Primitives
{ {
namespace ThrdCfg namespace ThrdCfg