[+] while_bc
This commit is contained in:
parent
e3745d0efa
commit
0164919cd9
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user