[*] AuOSThread harden set piro and name against race conditions
amend: i didnt want to lock so deep of a callstack, but oh well. amend: win32 regression
This commit is contained in:
parent
27b18c0a37
commit
bd034aec31
@ -418,12 +418,16 @@ namespace Aurora::Threading::Threads
|
||||
|
||||
void OSThread::SetName(const AuString &name)
|
||||
{
|
||||
AU_LOCK_GUARD(this->metaMutex);
|
||||
|
||||
if (gRuntimeConfig.threadingConfig.bNoThreadNames)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->name_ = name;
|
||||
this->uNameIdentity_ = AuFnv1a32Runtime(name.data(), name.size());
|
||||
|
||||
this->UpdateName();
|
||||
}
|
||||
|
||||
@ -510,13 +514,7 @@ namespace Aurora::Threading::Threads
|
||||
|
||||
auto ret = SpawnThread([this]()
|
||||
{
|
||||
while ((!this->handle_) ||
|
||||
#if defined(INVALID_HANDLE_VALUE)
|
||||
(this->handle_ == INVALID_HANDLE_VALUE)
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
)
|
||||
while (!this->HasValidThreadHandleYet())
|
||||
{
|
||||
AuThreading::ContextYield();
|
||||
}
|
||||
@ -744,6 +742,13 @@ namespace Aurora::Threading::Threads
|
||||
|
||||
void OSThread::UpdateName()
|
||||
{
|
||||
AU_LOCK_GUARD(this->metaMutex);
|
||||
|
||||
if (!this->HasValidThreadIdYet())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (gRuntimeConfig.threadingConfig.bNoThreadNames)
|
||||
{
|
||||
return;
|
||||
@ -782,9 +787,9 @@ namespace Aurora::Threading::Threads
|
||||
{
|
||||
info.dwThreadID = pGetThreadId(this->handle_);
|
||||
}
|
||||
else if (this->unixThreadId_ == GetCurrentThreadId())
|
||||
else if (this->optUnixThreadId_.ValueOr(0) == GetCurrentThreadId())
|
||||
{
|
||||
info.dwThreadID = this->unixThreadId_;
|
||||
info.dwThreadID = this->optUnixThreadId_.ValueOr(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -852,37 +857,45 @@ namespace Aurora::Threading::Threads
|
||||
AU_DEBUG_MEMCRUNCH;
|
||||
|
||||
HandleRegister(this);
|
||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||
this->unixThreadId_ = gettid();
|
||||
#elif defined(AURORA_IS_XNU_DERIVED)
|
||||
this->unixThreadId_ = pthread_getthreadid_np();
|
||||
#elif defined(AURORA_IS_BSD_DERIVED)
|
||||
#if __FreeBSD_version < 900031
|
||||
long lwpid;
|
||||
thr_self(&lwpid);
|
||||
this->unixThreadId_ = lwpid;
|
||||
#elif __FreeBSD_version > 900030
|
||||
this->unixThreadId_ = pthread_getthreadid_np();
|
||||
#else
|
||||
static_assert(false);
|
||||
#endif
|
||||
#elif defined(AURORA_HAS_PTHREADS)
|
||||
this->unixThreadId_ = 0; // !!!!
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
this->unixThreadId_ = GetCurrentThreadId();
|
||||
#endif
|
||||
{
|
||||
AU_LOCK_GUARD(this->metaMutex);
|
||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||
this->optUnixThreadId_ = gettid();
|
||||
#elif defined(AURORA_IS_XNU_DERIVED)
|
||||
this->optUnixThreadId_ = pthread_getthreadid_np();
|
||||
#elif defined(AURORA_IS_BSD_DERIVED)
|
||||
#if __FreeBSD_version < 900031
|
||||
long lwpid;
|
||||
thr_self(&lwpid);
|
||||
this->optUnixThreadId_ = lwpid;
|
||||
#elif __FreeBSD_version > 900030
|
||||
this->optUnixThreadId_ = pthread_getthreadid_np();
|
||||
#else
|
||||
static_assert(false);
|
||||
#endif
|
||||
#elif defined(AURORA_HAS_PTHREADS)
|
||||
this->optUnixThreadId_ = 0; // !!!!
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
this->optUnixThreadId_ = GetCurrentThreadId();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (this->tls_)
|
||||
{
|
||||
SetThreadKey(this->tls_);
|
||||
}
|
||||
|
||||
UpdatePrio(this->throttle_, this->prio_);
|
||||
SetAffinityMask(this->mask_);
|
||||
AffinityPrioThrottleTickAmendECores();
|
||||
UpdateName();
|
||||
{
|
||||
AU_LOCK_GUARD(this->metaMutex);
|
||||
|
||||
UpdatePrio(this->throttle_, this->prio_);
|
||||
SetAffinityMask(this->mask_);
|
||||
AffinityPrioThrottleTickAmendECores();
|
||||
UpdateName();
|
||||
}
|
||||
}
|
||||
|
||||
static AuHashMap<EThreadPriority, int> kNiceMap
|
||||
@ -995,10 +1008,59 @@ namespace Aurora::Threading::Threads
|
||||
AuMakePair(EThreadThrottle::eEfficient, EThreadPriority::ePrioLowest), AuMakePair(DISPATCH_QUEUE_PRIORITY_BACKGROUND, -2)
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
bool OSThread::HasValidThreadIdYet()
|
||||
{
|
||||
// set by the new thread context on attachment
|
||||
return bool(this->optUnixThreadId_);
|
||||
}
|
||||
|
||||
bool OSThread::HasValidThreadHandleYet()
|
||||
{
|
||||
// set by thread spawner
|
||||
return this->handle_ &&
|
||||
#if defined(INVALID_HANDLE_VALUE)
|
||||
!(this->handle_ == INVALID_HANDLE_VALUE)
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||
|
||||
static void DoWarnBadOperatingSystem()
|
||||
{
|
||||
static AuInitOnce gInitOnce;
|
||||
gInitOnce.Call([]()
|
||||
{
|
||||
AuLogWarn("We will not use RT-Kit to keep your Linux machine alive through XDG_FREEEEeeEEEeEeEEeeeDESKTOP_HOPES_AND_DREAMS, dbus-slop, and systemd-specific daemons");
|
||||
AuLogWarn("Obligatory sod off System-D, IBM Red Hat, and Lennart Poettering 🤮");
|
||||
AuLogWarn("Hint: try (1) : append:\n"
|
||||
"* hard rtprio unlimited\n"
|
||||
"* soft rtprio unlimited\n"
|
||||
"* hard priority unlimited\n"
|
||||
"* soft priority unlimited\n"
|
||||
"... to /etc/security/limits.conf");
|
||||
AuLogWarn("Hint: try (2) : in bash, elevate using: '[doas/sudo] prlimit --rtprio=unlimited --pid=$$' before running the main executable");
|
||||
AuLogWarn("Hint: try (3) : check /etc/systemd/[system/user].conf");
|
||||
});
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void OSThread::UpdatePrio(EThreadThrottle throttle, EThreadPriority prio)
|
||||
{
|
||||
AU_LOCK_GUARD(this->metaMutex);
|
||||
|
||||
if (!this->HasValidThreadIdYet())
|
||||
{
|
||||
this->prio_ = prio;
|
||||
this->throttle_ = throttle;
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
|
||||
if (this->handle_ == INVALID_HANDLE_VALUE)
|
||||
@ -1047,10 +1109,14 @@ namespace Aurora::Threading::Threads
|
||||
//#elif defined(AURORA_IS_XNU_DERIVED)
|
||||
|
||||
#elif defined(AURORA_HAS_PTHREADS)
|
||||
|
||||
auto unixThreadId = this->optUnixThreadId_.Value();
|
||||
|
||||
sched_param param {};
|
||||
int policyNonRT {};
|
||||
int schedA {};
|
||||
int scheduler {};
|
||||
|
||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||
rlimit rl;
|
||||
#endif
|
||||
@ -1072,13 +1138,10 @@ namespace Aurora::Threading::Threads
|
||||
};
|
||||
#endif
|
||||
|
||||
if (!this->handle_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if switch to rtprio scheduling
|
||||
if (prio == EThreadPriority::ePrioRT)
|
||||
{
|
||||
/////////////////////////////////
|
||||
#if defined(AURORA_IS_POSIX_DERIVED)
|
||||
|
||||
#if defined(SCHED_RR)
|
||||
@ -1087,26 +1150,23 @@ namespace Aurora::Threading::Threads
|
||||
param.sched_priority = sched_get_priority_max((schedA = SCHED_FIFO));
|
||||
#endif
|
||||
|
||||
if (::sched_setscheduler(this->unixThreadId_, schedA, ¶m) == 0)
|
||||
if (::sched_setscheduler(unixThreadId, schedA, ¶m) == 0)
|
||||
{
|
||||
goto gtfo;
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
// if switch to rtprio with linux scheduling and rlimit adjustments
|
||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
if (getrlimit(RLIMIT_RTPRIO, &rl) == 0)
|
||||
{
|
||||
bool bWarnOnce {};
|
||||
rl.rlim_max = param.sched_priority;
|
||||
|
||||
if (rl.rlim_max != RLIM_INFINITY)
|
||||
{
|
||||
AuLogWarn("We will not use RT-Kit to keep your Linux machine alive through XDG_FREEEEEEDESKTOP_HOPES_AND_DREAMS");
|
||||
AuLogWarn("Hint: try (1) : in bash, elevate using: '[doas/sudo] prlimit --rtprio=unlimited --pid=$$' before running the main executable");
|
||||
AuLogWarn("Hint: try (2) : append '* hard rtprio unlimited' to /etc/security/limits.conf");
|
||||
AuLogWarn("Hint: try (3) : check /etc/systemd/[system/user].conf");
|
||||
bWarnOnce = true;
|
||||
DoWarnBadOperatingSystem();
|
||||
rl.rlim_cur = rl.rlim_max;
|
||||
}
|
||||
else
|
||||
@ -1117,23 +1177,19 @@ namespace Aurora::Threading::Threads
|
||||
param.sched_priority = rl.rlim_cur;
|
||||
|
||||
#if defined(SCHED_RR)
|
||||
if (::sched_setscheduler(this->unixThreadId_, SCHED_RR, ¶m) == 0)
|
||||
if (::sched_setscheduler(unixThreadId, SCHED_RR, ¶m) == 0)
|
||||
{
|
||||
goto gtfo;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (::setrlimit(RLIMIT_RTPRIO, &rl) != 0 &&
|
||||
!bWarnOnce)
|
||||
if (::setrlimit(RLIMIT_RTPRIO, &rl) != 0)
|
||||
{
|
||||
AuLogWarn("We will not use RT-Kit to keep your Linux machine alive through XDG_FREEEEEEDESKTOP_HOPES_AND_DREAMS");
|
||||
AuLogWarn("Hint: try (1) : in bash, elevate using: '[doas/sudo] prlimit --rtprio=unlimited --pid=$$' before running the main executable");
|
||||
AuLogWarn("Hint: try (2) : append '* hard rtprio unlimited' to /etc/security/limits.conf");
|
||||
AuLogWarn("Hint: try (3) : check /etc/systemd/[system/user].conf");
|
||||
DoWarnBadOperatingSystem();
|
||||
}
|
||||
|
||||
#if defined(SCHED_RR)
|
||||
if (::sched_setscheduler(this->unixThreadId_, SCHED_RR, ¶m) == 0)
|
||||
if (::sched_setscheduler(unixThreadId, SCHED_RR, ¶m) == 0)
|
||||
{
|
||||
goto gtfo;
|
||||
}
|
||||
@ -1141,49 +1197,58 @@ namespace Aurora::Threading::Threads
|
||||
|
||||
param.sched_priority = sched_get_priority_max(SCHED_FIFO);
|
||||
|
||||
if (::sched_setscheduler(this->unixThreadId_, SCHED_FIFO, ¶m) == 0)
|
||||
if (::sched_setscheduler(unixThreadId, SCHED_FIFO, ¶m) == 0)
|
||||
{
|
||||
goto gtfo;
|
||||
}
|
||||
}
|
||||
// else if switch to posix RTPRIO with posix SCHED_FIFO + sched_setscheduler
|
||||
else
|
||||
#endif
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
param.sched_priority = sched_get_priority_max(SCHED_FIFO);
|
||||
|
||||
if (::sched_setscheduler(this->unixThreadId_, SCHED_FIFO, ¶m) == 0)
|
||||
if (::sched_setscheduler(unixThreadId, SCHED_FIFO, ¶m) == 0)
|
||||
{
|
||||
goto gtfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// !defined(AURORA_IS_POSIX_DERIVED) with pthreads
|
||||
#else
|
||||
#if defined(SCHED_RR)
|
||||
param.sched_priority = sched_get_priority_min(SCHED_RR);
|
||||
|
||||
if (pthread_setschedparam(this->handle_, SCHED_RR, ¶m) == 0)
|
||||
{
|
||||
goto gtfo;
|
||||
}
|
||||
#endif
|
||||
#if defined(SCHED_RR)
|
||||
param.sched_priority = sched_get_priority_min(SCHED_RR);
|
||||
|
||||
param.sched_priority = GetPrioLevel(SCHED_FIFO, prio);
|
||||
// set SCHED_RR with pthreads, if available
|
||||
if (pthread_setschedparam(this->handle_, SCHED_RR, ¶m) == 0)
|
||||
{
|
||||
goto gtfo;
|
||||
}
|
||||
|
||||
if (pthread_setschedparam(this->handle_, SCHED_FIFO, ¶m) == 0)
|
||||
{
|
||||
goto gtfo;
|
||||
}
|
||||
#endif
|
||||
|
||||
param.sched_priority = GetPrioLevel(SCHED_FIFO, prio);
|
||||
|
||||
// set SCHED_FIFO to the highest prio level with pthreads, if available
|
||||
if (pthread_setschedparam(this->handle_, SCHED_FIFO, ¶m) == 0)
|
||||
{
|
||||
goto gtfo;
|
||||
}
|
||||
#endif
|
||||
|
||||
// fall through on error
|
||||
}
|
||||
|
||||
// if linux and the next throttle type requires shifting down to SCHED_IDLE scheduling
|
||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||
else if (throttle == EThreadThrottle::eEfficient)
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
param.sched_priority = GetPrioLevel(SCHED_IDLE, prio);
|
||||
|
||||
if (::sched_setscheduler(this->unixThreadId_, SCHED_IDLE, ¶m) == 0)
|
||||
if (::sched_setscheduler(unixThreadId, SCHED_IDLE, ¶m) == 0)
|
||||
{
|
||||
goto gtfo;
|
||||
}
|
||||
@ -1191,11 +1256,14 @@ namespace Aurora::Threading::Threads
|
||||
// fail
|
||||
return;
|
||||
}
|
||||
|
||||
// else if restore to regular scheduling condition
|
||||
else if (this->throttle_ == EThreadThrottle::eEfficient ||
|
||||
this->prio_ == EThreadPriority::ePrioRT)
|
||||
#else
|
||||
else if (this->prio_ == EThreadPriority::ePrioRT)
|
||||
#endif
|
||||
//////////////////////////////////////////////////
|
||||
{
|
||||
#if defined(AURORA_IS_POSIX_DERIVED)
|
||||
policyNonRT =
|
||||
@ -1206,8 +1274,7 @@ namespace Aurora::Threading::Threads
|
||||
#endif
|
||||
|
||||
param.sched_priority = GetPrioLevel(policyNonRT, prio);
|
||||
|
||||
if (::sched_setscheduler(this->unixThreadId_, policyNonRT, ¶m) == 0)
|
||||
if (::sched_setscheduler(unixThreadId, policyNonRT, ¶m) == 0)
|
||||
{
|
||||
goto gtfo;
|
||||
}
|
||||
@ -1217,10 +1284,10 @@ namespace Aurora::Threading::Threads
|
||||
}
|
||||
|
||||
{
|
||||
scheduler = ::sched_getscheduler(this->unixThreadId_);
|
||||
scheduler = ::sched_getscheduler(unixThreadId);
|
||||
param.sched_priority = GetPrioLevel(scheduler, prio);
|
||||
|
||||
if (::sched_setscheduler(this->unixThreadId_, scheduler, ¶m) == 0)
|
||||
if (::sched_setscheduler(unixThreadId, scheduler, ¶m) == 0)
|
||||
{
|
||||
goto gtfo;
|
||||
}
|
||||
@ -1230,6 +1297,7 @@ namespace Aurora::Threading::Threads
|
||||
AuLogWarn("Couldn't set affinity");
|
||||
#endif
|
||||
|
||||
// epilogue
|
||||
gtfo:
|
||||
#if defined(AURORA_IS_LINUX_DERIVED) || defined(AURORA_IS_BSD_DERIVED)
|
||||
switch (throttle)
|
||||
|
@ -76,6 +76,8 @@ namespace Aurora::Threading::Threads
|
||||
void OSDeatach();
|
||||
void TeminateOSContext(bool calledFromThis);
|
||||
void FreeOSContext();
|
||||
bool HasValidThreadIdYet();
|
||||
bool HasValidThreadHandleYet();
|
||||
|
||||
void HookReleaseThreadResources();
|
||||
void HookOnExit();
|
||||
@ -123,9 +125,10 @@ namespace Aurora::Threading::Threads
|
||||
pthread_t handle_ {};
|
||||
#endif
|
||||
|
||||
AuUInt64 unixThreadId_ = 0;
|
||||
AuOptional<AuUInt64> optUnixThreadId_;
|
||||
bool detached_ {};
|
||||
AuUInt32 uNameIdentity_ {};
|
||||
AuCriticalSection metaMutex;
|
||||
};
|
||||
|
||||
void InitThreading();
|
||||
|
Loading…
Reference in New Issue
Block a user