AuroraRuntime/Source/Threading/Primitives/SMTYield.hpp

155 lines
3.6 KiB
C++
Raw Normal View History

/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: SMTYield.hpp
Date: 2023-3-12
Author: Reece
***/
#pragma once
namespace Aurora::Threading
{
inline AuUInt32 gHasThreadLocalTimeout {};
2023-08-20 08:50:41 +00:00
inline thread_local AuUInt8 tlsSpinCountLocal {};
}
namespace Aurora::Threading::Primitives
{
2023-08-22 11:57:47 +00:00
inline AuUInt32 gSpinAdaptiveThreshold {};
inline AuUInt32 gSpinAdaptiveCurrentCount {};
inline AuUInt32 gUseFutexRWLock {};
2023-08-22 11:57:47 +00:00
void InitAdaptiveThreshold();
void InitAdaptiveThresholdFirstTime();
static auline void SMPPause()
{
#if (defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86))
_mm_pause();
#elif defined(AURORA_ARCH_ARM)
#if defined(AURORA_COMPILER_GCC)
asm volatile("yield");
#else
__yield();
#endif
#else
// TODO: your platform here
AuThreading::ContextYield();
#endif
}
template <typename T>
bool auline YieldToSharedCore(long spin, T callback)
{
if (callback())
{
return true;
}
2023-08-22 11:57:47 +00:00
if (gSpinAdaptiveThreshold)
{
2023-08-22 11:57:47 +00:00
auto uNow = AuAtomicAdd(&gSpinAdaptiveCurrentCount, 1u);
if (uNow <= gSpinAdaptiveThreshold)
{
2023-08-27 18:43:21 +00:00
int loops = spin;
2023-08-22 11:57:47 +00:00
while (loops > 0)
{
loops -= 1;
if (callback())
{
AuAtomicSub(&gSpinAdaptiveCurrentCount, 1u);
return true;
}
}
2023-08-22 11:57:47 +00:00
if (gHasThreadLocalTimeout)
{
auto uCount = tlsSpinCountLocal;
int loops = (1 << uCount);
while (loops > 0)
{
SMPPause();
loops -= 1;
if (callback())
{
AuAtomicSub(&gSpinAdaptiveCurrentCount, 1u);
return true;
}
}
}
2023-08-22 11:57:47 +00:00
AuAtomicSub(&gSpinAdaptiveCurrentCount, 1u);
}
else
{
2023-08-27 18:43:21 +00:00
int loops = (spin) / 3;
2023-08-22 11:57:47 +00:00
while (loops > 0)
{
SMPPause();
loops -= 1;
if (callback())
{
AuAtomicSub(&gSpinAdaptiveCurrentCount, 1u);
return true;
}
}
}
2023-08-22 11:57:47 +00:00
AuAtomicSub(&gSpinAdaptiveCurrentCount, 1u);
}
else
{
2023-08-27 18:43:21 +00:00
int loops = spin;
while (loops > 0)
{
loops -= 1;
if (callback())
{
return true;
}
}
2023-08-22 11:57:47 +00:00
if (gHasThreadLocalTimeout)
{
auto uCount = tlsSpinCountLocal;
int loops = (1 << uCount);
while (loops > 0)
{
SMPPause();
loops -= 1;
if (callback())
{
return true;
}
}
}
}
return callback();
}
template <typename T>
bool auline DoTryIf(T callback)
{
if (gRuntimeConfig.threadingConfig.bPlatformIsSMPProcessorOptimized)
{
return YieldToSharedCore(gRuntimeConfig.threadingConfig.uSpinLoopPowerA, callback);
}
else
{
return callback();
}
}
}