[+] More threading options

[+] AuThreading::SetSpinCountTimeout
[+] AuThreading::SetThreadLocalAdditionalSpinCountTimeout
This commit is contained in:
Reece Wilson 2023-08-19 18:14:28 +01:00
parent e6bf022bef
commit 8bf6bdd963
11 changed files with 116 additions and 9 deletions

View File

@ -338,6 +338,12 @@ namespace Aurora
bool bPreferNt51XpCondvarsOver8 { false }; bool bPreferNt51XpCondvarsOver8 { false };
bool bPreferNtCondvarModernWinSpin { false }; bool bPreferNtCondvarModernWinSpin { false };
bool bPreferNtCondvarOlderWinSpin { true }; bool bPreferNtCondvarOlderWinSpin { true };
bool bPreferNtSemaphoreSpinTryLock { true };
bool bPreferNtMutexSpinTryLock { true };
bool bPreferNtCondMutexSpinTryLock { true };
bool bPreferLinuxSemaphoreSpinTryLock { true };
bool bPreferLinuxMutexSpinTryLock { true };
bool bPreferLinuxCondMutexSpinTryLock { true };
bool bPreferEmulatedWakeOnAddress { false }; bool bPreferEmulatedWakeOnAddress { false };
}; };

View File

@ -0,0 +1,17 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: SpinTime.hpp
Date: 2023-08-19
Author: Reece
***/
#pragma once
namespace Aurora::Threading
{
// Note: the following APIs are in powers of 2!
AUKN_SYM void SetSpinCountTimeout(AuUInt8 uTimeout);
AUKN_SYM AuUInt8 GetSpinCountTimeout();
AUKN_SYM void SetThreadLocalAdditionalSpinCountTimeout(AuUInt8 uTimeout);
}

View File

@ -24,4 +24,6 @@ namespace Aurora::Threading
#include "LockGuard.hpp" #include "LockGuard.hpp"
#include "LockGuardTry.hpp" #include "LockGuardTry.hpp"
#include "SpinTime.hpp"
#include "Threads/Threads.hpp" #include "Threads/Threads.hpp"

View File

@ -46,11 +46,23 @@ namespace Aurora::Threading::Primitives
#if defined(AURORA_FORCE_SRW_LOCKS) #if defined(AURORA_FORCE_SRW_LOCKS)
return ::TryAcquireSRWLockExclusive(&this->lock_); return ::TryAcquireSRWLockExclusive(&this->lock_);
#else #else
if (gRuntimeConfig.threadingConfig.bPreferNtCondMutexSpinTryLock)
{
return TryLockHeavy();
}
else
{
return TryLockNoSpin();
}
#endif
}
bool Win32ConditionMutex::TryLockHeavy()
{
return DoTryIf([=]() return DoTryIf([=]()
{ {
return this->TryLockNoSpin(); return TryLockNoSpin();
}); });
#endif
} }
bool Win32ConditionMutex::TryLockNoSpin() bool Win32ConditionMutex::TryLockNoSpin()
@ -68,7 +80,7 @@ namespace Aurora::Threading::Primitives
::AcquireSRWLockExclusive(&this->lock_); ::AcquireSRWLockExclusive(&this->lock_);
#else #else
if (this->TryLock()) if (this->TryLockHeavy())
{ {
return; return;
} }

View File

@ -41,6 +41,7 @@ namespace Aurora::Threading::Primitives
AuUInt GetOSHandle() override; AuUInt GetOSHandle() override;
auline bool TryLockNoSpin(); auline bool TryLockNoSpin();
auline bool TryLockHeavy();
#if !defined(AURORA_FORCE_SRW_LOCKS) #if !defined(AURORA_FORCE_SRW_LOCKS)
NT4Mutex lock_; NT4Mutex lock_;

View File

@ -44,7 +44,7 @@ namespace Aurora::Threading::Primitives
return false; return false;
} }
bool MutexImpl::TryLock() bool MutexImpl::TryLockHeavy()
{ {
return DoTryIf([=]() return DoTryIf([=]()
{ {
@ -52,6 +52,18 @@ namespace Aurora::Threading::Primitives
}); });
} }
bool MutexImpl::TryLock()
{
if (gRuntimeConfig.threadingConfig.bPreferNtMutexSpinTryLock)
{
return TryLockHeavy();
}
else
{
return TryLockNoSpin();
}
}
bool MutexImpl::TryLockNoSpin() bool MutexImpl::TryLockNoSpin()
{ {
return AuAtomicTestAndSet(&this->state_, 0) == 0; return AuAtomicTestAndSet(&this->state_, 0) == 0;
@ -82,7 +94,7 @@ namespace Aurora::Threading::Primitives
{ {
bool returnValue = false; bool returnValue = false;
if (this->TryLock()) if (this->TryLockHeavy())
{ {
return true; return true;
} }

View File

@ -22,7 +22,8 @@ namespace Aurora::Threading::Primitives
bool LockNS(AuUInt64 timeout) override; bool LockNS(AuUInt64 timeout) override;
void Unlock() override; void Unlock() override;
auline bool TryLockNoSpin(); auline bool TryLockNoSpin();
auline bool TryLockHeavy();
private: private:
#if defined(AURORA_FORCE_SRW_LOCKS) #if defined(AURORA_FORCE_SRW_LOCKS)

View File

@ -35,20 +35,32 @@ namespace Aurora::Threading::Primitives
{ {
return true; return true;
} }
bool SemaphoreImpl::TryLockNoSpin() bool SemaphoreImpl::TryLockNoSpin()
{ {
auto old = this->dwState_; auto old = this->dwState_;
return (old != 0 && AuAtomicCompareExchange(&this->dwState_, old - 1, old) == old); return (old != 0 && AuAtomicCompareExchange(&this->dwState_, old - 1, old) == old);
} }
bool SemaphoreImpl::TryLock() bool SemaphoreImpl::TryLockHeavy()
{ {
return DoTryIf([=]() return DoTryIf([=]()
{ {
return TryLockNoSpin(); return TryLockNoSpin();
}); });
} }
bool SemaphoreImpl::TryLock()
{
if (gRuntimeConfig.threadingConfig.bPreferNtSemaphoreSpinTryLock)
{
return TryLockHeavy();
}
else
{
return TryLockNoSpin();
}
}
bool SemaphoreImpl::LockMS(AuUInt64 uTimeout) bool SemaphoreImpl::LockMS(AuUInt64 uTimeout)
{ {
@ -57,7 +69,7 @@ namespace Aurora::Threading::Primitives
bool SemaphoreImpl::LockNS(AuUInt64 uTimeout) bool SemaphoreImpl::LockNS(AuUInt64 uTimeout)
{ {
if (this->TryLock()) if (this->TryLockHeavy())
{ {
return true; return true;
} }

View File

@ -27,6 +27,7 @@ namespace Aurora::Threading::Primitives
void Unlock() override; void Unlock() override;
auline bool TryLockNoSpin(); auline bool TryLockNoSpin();
auline bool TryLockHeavy();
private: private:
AuUInt32 dwState_ {}; AuUInt32 dwState_ {};

View File

@ -8,6 +8,25 @@
#include <Source/RuntimeInternal.hpp> #include <Source/RuntimeInternal.hpp>
#include "SMTYield.hpp" #include "SMTYield.hpp"
namespace Aurora::Threading
{
AUKN_SYM void SetSpinCountTimeout(AuUInt8 uTimeout)
{
gRuntimeConfig.threadingConfig.uSpinLoopPowerA = uTimeout;
}
AUKN_SYM AuUInt8 GetSpinCountTimeout()
{
return gRuntimeConfig.threadingConfig.uSpinLoopPowerA;
}
AUKN_SYM void SetThreadLocalAdditionalSpinCountTimeout(AuUInt8 uTimeout)
{
gHasThreadLocalTimeout = 1;
tlSpinCountLocal = uTimeout;
}
}
namespace Aurora::Threading::Primitives namespace Aurora::Threading::Primitives
{ {

View File

@ -7,6 +7,12 @@
***/ ***/
#pragma once #pragma once
namespace Aurora::Threading
{
inline AuUInt32 gHasThreadLocalTimeout {};
inline thread_local AuUInt8 tlSpinCountLocal { 6 };
}
namespace Aurora::Threading::Primitives namespace Aurora::Threading::Primitives
{ {
static auline void SMPPause() static auline void SMPPause()
@ -46,6 +52,24 @@ namespace Aurora::Threading::Primitives
} }
} }
if (gHasThreadLocalTimeout)
{
auto uCount = tlSpinCountLocal;
int loops = (1 << uCount);
while (loops > 0)
{
SMPPause();
loops -= 1;
if (callback())
{
return true;
}
}
}
return callback(); return callback();
} }