[+] while_bc
This commit is contained in:
parent
e3745d0efa
commit
0164919cd9
@ -122,7 +122,11 @@ namespace Aurora::Threading::Waitables
|
||||
AuUInt32 uWaitCount {};
|
||||
AuUInt32 uWaiters {};
|
||||
|
||||
#if defined(AURORA_RUNTIME_FUTEX_AGGRESSIVE_COND_WAKE)
|
||||
while ((uWaiters = AuAtomicLoad(&this->uAtomicSleeping)))
|
||||
#else
|
||||
if ((uWaiters = AuAtomicLoad(&this->uAtomicSleeping)))
|
||||
#endif
|
||||
{
|
||||
AuAtomicAdd(&this->uAtomicState, uWaiters);
|
||||
WakeNOnAddress((const void *)&this->uAtomicState, uWaiters);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "AuConditionEx.hpp"
|
||||
#include "AuSemaphore.Generic.hpp"
|
||||
#include "SMTYield.hpp" // for: while_bc
|
||||
|
||||
namespace Aurora::Threading::Primitives
|
||||
{
|
||||
@ -144,7 +145,7 @@ namespace Aurora::Threading::Primitives
|
||||
AuUInt32 uWaitCount {};
|
||||
AuUInt32 uWaiters {};
|
||||
|
||||
while ((uWaiters = AuAtomicLoad(&this->uWaiters_)))
|
||||
while_bc ((uWaiters = AuAtomicLoad(&this->uWaiters_)))
|
||||
{
|
||||
this->s_.Unlock(uWaiters);
|
||||
uWaitCount = uWaiters;
|
||||
|
@ -90,7 +90,7 @@ namespace Aurora::Threading::Primitives
|
||||
AuUInt32 uWaitCount {};
|
||||
AuUInt32 uWaiters {};
|
||||
|
||||
while ((uWaiters = AuAtomicLoad(&this->uSleeping_)))
|
||||
while_bc (uWaiters = AuAtomicLoad(&this->uSleeping_))
|
||||
{
|
||||
AuAtomicAdd(&this->uState_, uWaiters);
|
||||
InternalLTSWakeCount(&this->uState_, uWaiters);
|
||||
|
@ -180,7 +180,7 @@ namespace Aurora::Threading::Primitives
|
||||
AuUInt32 uWaitCount {};
|
||||
AuUInt32 uWaiters {};
|
||||
|
||||
while ((uWaiters = AuAtomicLoad(&this->uSleeping_)))
|
||||
while_bc ((uWaiters = AuAtomicLoad(&this->uSleeping_)))
|
||||
{
|
||||
AuAtomicAdd(&this->uState_, uWaiters);
|
||||
futex_wake(&this->uState_, uWaiters);
|
||||
|
@ -22,6 +22,31 @@ extern "C"
|
||||
|
||||
#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 ThrdCfg
|
||||
|
Loading…
Reference in New Issue
Block a user