2021-06-27 21:25:29 +00:00
/***
Copyright ( C ) 2021 J Reece Wilson ( a / k / a " Reece " ) . All rights reserved .
2022-11-17 07:46:07 +00:00
File : AuOSThread . cpp
2021-06-27 21:25:29 +00:00
Date : 2021 - 6 - 12
Author : Reece
* * */
2021-09-30 14:57:41 +00:00
# include <Source/RuntimeInternal.hpp>
2022-11-17 07:46:07 +00:00
# include "AuThreads.hpp"
# include <Source/Threading/AuWaitFor.hpp>
# include "AuOSThread.hpp"
# include "AuThreadHandles.hpp"
2021-06-27 21:25:29 +00:00
# include "TLSView.hpp"
2021-09-06 10:58:08 +00:00
# if defined(AURORA_IS_LINUX_DERIVED)
2022-01-24 18:37:06 +00:00
# include <sys/resource.h>
2022-08-14 22:59:48 +00:00
# include <cxxabi.h>
2021-06-27 21:25:29 +00:00
# endif
# if defined(AURORA_HAS_PTHREADS)
2022-01-24 18:37:06 +00:00
# include <sched.h>
2021-06-27 21:25:29 +00:00
# endif
2021-09-06 10:58:08 +00:00
# if defined(AURORA_PLATFORM_WIN32)
2022-01-24 18:37:06 +00:00
# include <Aux_ulib.h>
2021-09-06 10:58:08 +00:00
# endif
2022-12-14 01:35:18 +00:00
# if defined(AURORA_IS_MODERNNT_DERIVED)
2023-07-09 09:03:29 +00:00
static auto const kThreadPowerThrottling = Aurora : : THREAD_INFORMATION_CLASS : : ThreadPowerThrottling ;
2022-12-14 01:35:18 +00:00
struct THREAD_POWER_THROTTLING_STATE2
{
ULONG Version ;
ULONG ControlMask ;
ULONG StateMask ;
} ;
# endif
2023-08-27 11:41:51 +00:00
# if defined(AURORA_COMPILER_CLANG)
// warning: enumeration values 'kEnumCount' and 'kEnumInvalid' not handled in switch [-Wswitch
# pragma clang diagnostic ignored "-Wswitch"
// Yea, I don't give a shit.
# endif
2022-11-17 07:46:07 +00:00
# include "AuSpawnThread.hpp"
2021-09-06 10:58:08 +00:00
2022-08-14 13:41:19 +00:00
namespace Aurora
{
void RuntimeLateClean ( ) ;
}
2021-06-27 21:25:29 +00:00
namespace Aurora : : Threading : : Threads
{
2022-04-02 00:48:29 +00:00
static struct DtorFlipper
{
DtorFlipper ( ) : bActive ( true )
{
}
~ DtorFlipper ( )
{
bActive = false ;
}
bool bActive ;
} gGlobal ;
2021-10-24 10:19:47 +00:00
static ThreadInfo gDummyThreadInfo ;
2021-09-06 10:58:08 +00:00
2022-08-06 19:50:40 +00:00
# if defined(AURORA_IS_POSIX_DERIVED)
2022-08-02 04:52:17 +00:00
static void HandleSigAbortThread ( int a )
{
2022-08-06 19:50:40 +00:00
( ( OSThread * ) HandleCurrent ( ) ) - > InternalKillForceNtfy ( ) ;
2022-08-02 04:52:17 +00:00
SysPanic ( " Couldn't terminate thread context " ) ;
}
2022-08-06 19:50:40 +00:00
2022-08-02 04:52:17 +00:00
# endif
2023-09-23 19:32:01 +00:00
OSThread : : OSThread ( const ThreadInfo & info ) : info_ ( info ) ,
epExecEvent ( false , false , true )
2021-06-27 21:25:29 +00:00
{
2022-03-16 17:12:08 +00:00
this - > name_ = info . name . value_or ( " Aurora Thread " ) ;
2021-10-25 17:08:28 +00:00
// maybe we should atomic exchange compare these when needed frogthink
2022-08-14 11:01:54 +00:00
this - > terminatedSignalLs_ = AuLoop : : NewLSEvent ( true , false , true ) ;
2022-06-11 23:52:46 +00:00
this - > terminateSignalLs_ = AuLoop : : NewLSEvent ( true , false , true ) ;
2021-10-25 17:08:28 +00:00
2023-04-30 06:54:28 +00:00
this - > terminated_ = AuThreadPrimitives : : EventShared ( true , false , true ) ;
this - > terminateSignal_ = AuThreadPrimitives : : EventShared ( true , false , true ) ;
SysAssert ( this - > terminatedSignalLs_ & & this - > terminateSignalLs_ & & this - > terminated_ & & this - > terminateSignal_ ) ;
2021-06-27 21:25:29 +00:00
}
2021-09-06 10:58:08 +00:00
2023-09-23 19:32:01 +00:00
OSThread : : OSThread ( ) : info_ ( gDummyThreadInfo ) ,
epExecEvent ( false , false , true )
2021-06-27 21:25:29 +00:00
{
2022-03-16 17:12:08 +00:00
this - > name_ = " Main Thread " ;
2023-04-30 06:54:28 +00:00
this - > terminated_ = AuThreadPrimitives : : EventShared ( true , false , true ) ;
this - > terminateSignal_ = AuThreadPrimitives : : EventShared ( true , false , true ) ;
SysAssert ( this - > terminated_ & & this - > terminateSignal_ ) ;
2023-08-23 23:03:05 +00:00
this - > bNotOwned = true ;
2021-06-27 21:25:29 +00:00
}
2023-09-23 19:32:01 +00:00
OSThread : : OSThread ( AuUInt64 id ) : info_ ( gDummyThreadInfo ) ,
epExecEvent ( false , false , true )
2021-06-27 21:25:29 +00:00
{
2022-03-16 17:12:08 +00:00
this - > name_ = " System Thread " ;
this - > handle_ = reinterpret_cast < decltype ( handle_ ) > ( id ) ;
2022-08-02 04:52:17 +00:00
this - > bNotOwned = true ;
2021-06-27 21:25:29 +00:00
}
2022-04-02 00:48:29 +00:00
bool DeadTest ( ) ;
2021-06-27 21:25:29 +00:00
OSThread : : ~ OSThread ( )
{
2021-11-05 17:34:23 +00:00
bool bDetached { } ;
bool bDetachedSuccess { } ;
2022-08-02 04:52:17 +00:00
if ( this - > bNotOwned )
{
2022-10-14 06:14:56 +00:00
# if defined(AURORA_IS_MODERNNT_DERIVED)
auto hHandle = ( HANDLE ) this - > handle_ ;
AuWin32CloseHandle ( hHandle ) ;
# endif
2022-08-02 04:52:17 +00:00
return ;
}
2022-08-14 13:41:19 +00:00
if ( ! gGlobal . bActive )
2022-04-02 00:48:29 +00:00
{
return ;
}
2022-08-14 21:09:25 +00:00
#if 0
2022-08-14 13:41:19 +00:00
if ( DeadTest ( ) )
2022-04-02 00:48:29 +00:00
{
return ;
}
2022-08-14 21:09:25 +00:00
# endif
2022-03-16 17:12:08 +00:00
if ( this - > contextUsed_ )
2021-06-27 21:25:29 +00:00
{
2023-09-23 19:32:01 +00:00
this - > epExecEvent - > Wait ( ) ;
{
AU_LOCK_GUARD ( this - > pFlag - > mutex ) ;
this - > pFlag - > bLock = true ;
}
2022-03-16 17:12:08 +00:00
if ( this - > detached_ )
2021-11-05 17:34:23 +00:00
{
bDetached = true ;
}
else
2021-10-25 18:19:49 +00:00
{
2022-08-14 22:59:48 +00:00
if ( gRuntimeRunLevel < = 3 )
2022-08-14 11:01:54 +00:00
{
Exit ( ) ;
}
2022-08-14 13:41:19 +00:00
else if ( gRuntimeRunLevel > = 5 )
{
// Application is dead
}
2022-08-14 11:01:54 +00:00
else
{
2022-08-15 02:31:35 +00:00
if ( this - > terminated_ )
{
this - > exiting_ = true ;
2023-04-30 06:54:28 +00:00
if ( this - > terminated_ - > LockMS ( 5'000 ) )
2022-08-15 02:31:35 +00:00
{
return ;
}
}
2022-08-14 11:01:54 +00:00
// Kill the current OS thread instance
TeminateOSContext ( false ) ;
2022-08-14 22:59:48 +00:00
2023-10-01 13:12:22 +00:00
this - > exitOnlyOnce_ - > Unlock ( ) ;
2022-08-14 22:59:48 +00:00
# if defined(AURORA_IS_POSIX_DERIVED)
if ( this - > terminated_ )
{
2023-09-14 23:10:40 +00:00
this - > terminated_ - > Lock ( ) ;
2022-08-14 22:59:48 +00:00
}
# endif
2022-08-14 11:01:54 +00:00
}
2021-10-25 18:19:49 +00:00
}
2021-06-27 21:25:29 +00:00
}
2023-08-23 23:03:05 +00:00
else
{
if ( auto pTerminated = AuExchange ( this - > terminatedSignalLs_ , { } ) )
{
pTerminated - > Set ( ) ;
}
if ( auto pTerminated = AuExchange ( this - > terminated_ , { } ) )
{
pTerminated - > Set ( ) ;
}
}
2021-09-06 10:58:08 +00:00
2021-06-27 21:25:29 +00:00
FreeOSContext ( ) ;
2022-08-14 22:59:48 +00:00
2021-11-05 17:34:23 +00:00
if ( bDetached )
{
if ( this - > tlsReferenceThread_ )
{
AU_LOCK_GUARD ( this - > tlsLock_ ) ;
AU_LOCK_GUARD ( this - > tlsReferenceThread_ - > tlsLock_ ) ;
2023-04-30 06:54:28 +00:00
SetThreadKey ( this - > tlsReferenceThread_ - > tls_ ) ;
2022-01-19 17:08:13 +00:00
AuExchange ( this - > tlsReferenceThread_ - > tls_ , this - > tls_ ) ;
AuExchange ( this - > tlsReferenceThread_ - > threadFeatures_ , this - > threadFeatures_ ) ;
2021-11-05 17:34:23 +00:00
bDetachedSuccess = true ;
}
}
if ( bDetachedSuccess | | ! bDetached )
{
HookReleaseThreadResources ( ) ;
}
2021-06-27 21:25:29 +00:00
}
// Called whenever an aurora thread is exiting
void OSThread : : HookOnExit ( )
{
}
// Called whenever a thread object is released, or on thread termination
// Whichever is soonest
// It is possible a user may wish to keep a thread handle open
// Is is expected for a system thread to release on dtor unlike our aurora threads
void OSThread : : HookReleaseThreadResources ( )
{
2023-04-30 06:54:28 +00:00
AU_LOCK_GUARD ( this - > tlsLock_ ) ;
2022-03-16 17:12:08 +00:00
for ( const auto & feature : this - > threadFeatures_ )
2021-09-06 10:58:08 +00:00
{
feature - > Cleanup ( ) ;
}
}
2023-08-23 16:01:56 +00:00
AuUInt64 OSThread : : SetNoUnwindTerminateExitWatchDogTimeoutInMS ( AuUInt64 uMS )
{
if ( ! uMS )
{
uMS = AuSToMS < AuUInt64 > ( 15 ) ;
}
qwExitTimeout = uMS ;
2023-08-23 18:04:48 +00:00
return qwExitTimeout ;
2023-08-23 16:01:56 +00:00
}
2021-11-05 17:34:23 +00:00
void OSThread : : AddLastHopeTlsHook ( const AuSPtr < AuThreads : : IThreadFeature > & feature )
2021-09-06 10:58:08 +00:00
{
2023-04-30 06:54:28 +00:00
AU_LOCK_GUARD ( this - > tlsLock_ ) ;
2021-11-05 17:34:23 +00:00
if ( ! feature )
{
return ;
}
2022-03-16 17:12:08 +00:00
AuTryInsert ( this - > threadFeatures_ , feature ) ;
2021-06-27 21:25:29 +00:00
}
2021-10-25 18:19:49 +00:00
void OSThread : : Detach ( )
{
2022-03-16 17:12:08 +00:00
this - > detached_ = true ;
2021-10-25 18:19:49 +00:00
}
2021-09-06 10:58:08 +00:00
AuSPtr < IWaitable > OSThread : : AsWaitable ( )
2021-06-27 21:25:29 +00:00
{
2023-08-24 09:40:15 +00:00
if ( ! this - > terminated_ )
{
this - > terminated_ = AuThreadPrimitives : : EventShared ( true , false , true ) ;
}
2022-03-16 17:12:08 +00:00
return this - > terminated_ ;
2021-06-27 21:25:29 +00:00
}
void OSThread : : SendExitSignal ( )
{
2022-03-16 17:12:08 +00:00
this - > exiting_ = true ;
2021-10-25 17:08:28 +00:00
if ( this - > terminateSignalLs_ )
{
this - > terminateSignalLs_ - > Set ( ) ;
}
if ( this - > terminateSignal_ )
{
this - > terminateSignal_ - > Set ( ) ;
}
2021-06-27 21:25:29 +00:00
}
2022-08-13 23:32:39 +00:00
void OSThread : : UnsafeForceTerminateSignal ( )
{
TeminateOSContext ( false ) ;
}
2021-09-06 10:58:08 +00:00
bool OSThread : : Run ( )
2021-06-27 21:25:29 +00:00
{
2022-03-16 17:12:08 +00:00
if ( ! this - > terminated_ )
2021-06-27 21:25:29 +00:00
{
SysPanic ( " ::Run called on system thread " ) ;
}
2022-03-16 17:12:08 +00:00
if ( AuExchange ( this - > contextUsed_ , true ) )
2021-06-27 21:25:29 +00:00
{
2021-09-06 10:58:08 +00:00
return false ;
2021-06-27 21:25:29 +00:00
}
2022-03-16 17:12:08 +00:00
this - > terminated_ - > Reset ( ) ;
2021-06-27 21:25:29 +00:00
2021-09-06 10:58:08 +00:00
return ExecuteNewOSContext ( [ = ] ( )
2021-06-27 21:25:29 +00:00
{
try
{
2021-10-23 18:25:43 +00:00
// this functional backends are being deprecated
2022-03-16 17:12:08 +00:00
if ( this - > info_ . callbacks )
2021-10-23 18:25:43 +00:00
{
2022-03-16 17:12:08 +00:00
this - > info_ . callbacks - > OnEntry ( this ) ;
2021-10-23 18:25:43 +00:00
}
2021-06-27 21:25:29 +00:00
}
catch ( . . . )
{
Debug : : PrintError ( ) ;
}
} ) ;
}
void OSThread : : Exit ( )
{
2023-06-04 16:28:29 +00:00
this - > PrivateUserDataClear ( ) ;
2022-03-16 17:12:08 +00:00
while ( ( ! this - > terminated_ ) | | ( ! this - > terminated_ - > TryLock ( ) ) )
2021-06-27 21:25:29 +00:00
{
if ( Exit ( false ) ) break ;
}
}
2022-04-02 00:48:29 +00:00
bool OSThread : : Exit ( bool willReturnToOS , bool isEOL )
2021-06-27 21:25:29 +00:00
{
if ( GetThread ( ) = = this )
{
if ( ! this - > InternalKill ( false ) )
{
return false ;
}
// release handle + sigterm
if ( ! willReturnToOS )
{
TeminateOSContext ( true ) ;
while ( true )
{
2023-09-12 17:21:36 +00:00
ContextYield ( ) ;
2021-06-27 21:25:29 +00:00
}
}
}
else
{
// exit signal
2022-03-16 17:12:08 +00:00
this - > exiting_ = true ;
2021-06-27 21:25:29 +00:00
2022-03-16 17:12:08 +00:00
if ( ! this - > terminated_ )
2021-06-27 21:25:29 +00:00
{
return true ;
}
2022-08-14 13:41:19 +00:00
2021-06-27 21:25:29 +00:00
// attempt to join with the thread once it has exited, or timeout
2023-08-23 16:01:56 +00:00
if ( this - > terminated_ - > LockMS ( this - > qwExitTimeout ) )
2021-06-27 21:25:29 +00:00
{
return true ;
}
// Do not force terminate if we're marked as dead and still running
// The thread must've requested suicide and got stuck in a lengthy clean up effort
2022-03-16 17:12:08 +00:00
if ( ! this - > exitOnlyOnce_ - > TryLock ( ) )
2021-06-27 21:25:29 +00:00
{
2023-08-23 16:01:56 +00:00
AuLogWarn ( " Watchdog error - OS thread context didn't finish in {} MS, but he should exiting now. " , this - > qwExitTimeout ) ;
2021-06-27 21:25:29 +00:00
return false ;
}
2023-08-23 16:01:56 +00:00
AuLogWarn ( " Watchdog error - OS thread context didn't finish in {} MS, forcefully terminating without a watchdog overlooking onExit " , this - > qwExitTimeout ) ;
2021-06-27 21:25:29 +00:00
// Kill the current OS thread instance
TeminateOSContext ( false ) ;
// Dispatch kill callback from within an emulated thread context (no switch, just just change thread tls)
ExecuteInDeadThread ( [ = ] ( )
{
this - > InternalKill ( true ) ;
} ) ;
2022-03-16 17:12:08 +00:00
this - > exitOnlyOnce_ - > Unlock ( ) ;
2021-06-27 21:25:29 +00:00
}
return true ;
}
bool OSThread : : Exiting ( )
{
2022-03-16 17:12:08 +00:00
return this - > exiting_ ;
2021-06-27 21:25:29 +00:00
}
void OSThread : : SetName ( const AuString & name )
{
2023-07-30 09:00:54 +00:00
if ( gRuntimeConfig . threadingConfig . bNoThreadNames )
{
return ;
}
2022-03-16 17:12:08 +00:00
this - > name_ = name ;
2022-10-14 06:14:56 +00:00
this - > UpdateName ( ) ;
2021-06-27 21:25:29 +00:00
}
2022-03-21 07:16:12 +00:00
EThreadThrottle OSThread : : GetThrottle ( )
{
return this - > throttle_ ;
}
EThreadPriority OSThread : : GetPriority ( )
2021-06-27 21:25:29 +00:00
{
2022-03-16 17:12:08 +00:00
return this - > prio_ ;
2021-06-27 21:25:29 +00:00
}
2022-03-16 17:12:08 +00:00
AuHwInfo : : CpuBitId OSThread : : GetMask ( )
2021-06-27 21:25:29 +00:00
{
2022-03-16 17:12:08 +00:00
return this - > mask_ ;
2021-06-27 21:25:29 +00:00
}
AuString OSThread : : GetName ( )
{
2022-03-16 17:12:08 +00:00
return this - > name_ ;
2021-06-27 21:25:29 +00:00
}
2022-03-16 17:12:08 +00:00
void OSThread : : SetAffinity ( const HWInfo : : CpuBitId & mask )
2021-06-27 21:25:29 +00:00
{
2022-03-16 17:12:08 +00:00
auto zero = HWInfo : : CpuBitId ( ) ;
if ( mask = = zero | |
mask = = zero . Not ( ) )
{
2022-03-20 12:50:36 +00:00
this - > mask_ = HWInfo : : GetCPUInfo ( ) . maskAllCores ;
2022-03-21 07:16:12 +00:00
this - > userManagingAffinity_ = false ;
UpdatePrio ( this - > throttle_ , this - > prio_ ) ;
2022-03-16 17:12:08 +00:00
}
else
{
this - > mask_ = mask ;
2022-03-21 07:16:12 +00:00
this - > userManagingAffinity_ = true ;
2022-03-16 17:12:08 +00:00
}
UpdateAffinity ( this - > mask_ ) ;
2023-01-23 15:23:43 +00:00
AffinityPrioThrottleTickAmendECores ( ) ;
2021-06-27 21:25:29 +00:00
}
2022-03-21 07:16:12 +00:00
void OSThread : : SetPriority ( EThreadPriority prio )
2021-06-27 21:25:29 +00:00
{
2022-03-21 07:16:12 +00:00
if ( ! EThreadPriorityIsValid ( prio ) )
{
return ;
}
UpdatePrio ( this - > throttle_ , prio ) ;
2023-01-23 15:23:43 +00:00
AffinityPrioThrottleTickAmendECores ( ) ;
2022-03-21 07:16:12 +00:00
}
void OSThread : : SetThrottle ( EThreadThrottle throttle )
{
if ( ! EThreadThrottleIsValid ( throttle ) )
{
return ;
}
2023-08-23 17:08:48 +00:00
UpdatePrio ( throttle , this - > prio_ ) ;
2022-03-21 07:16:12 +00:00
this - > throttle_ = throttle ;
2023-01-23 15:23:43 +00:00
AffinityPrioThrottleTickAmendECores ( ) ;
2021-06-27 21:25:29 +00:00
}
AuSPtr < TLSView > OSThread : : GetTlsView ( )
{
2023-04-30 06:54:28 +00:00
SysPanic ( " Deprecated Concept " ) ;
2021-06-27 21:25:29 +00:00
}
2022-01-19 17:08:13 +00:00
bool OSThread : : ExecuteNewOSContext ( AuFunction < void ( ) > task )
2021-06-27 21:25:29 +00:00
{
2022-03-16 17:12:08 +00:00
this - > task_ = task ;
2021-06-27 21:25:29 +00:00
2022-10-14 06:14:56 +00:00
this - > handle_ = 0 ;
2022-01-24 18:37:06 +00:00
auto ret = SpawnThread ( [ this ] ( )
2021-09-06 10:58:08 +00:00
{
2023-01-23 15:23:43 +00:00
while ( ( ! this - > handle_ ) | |
2023-08-11 15:51:42 +00:00
# if defined(INVALID_HANDLE_VALUE)
2023-01-23 15:23:43 +00:00
( this - > handle_ = = INVALID_HANDLE_VALUE )
2023-08-11 15:51:42 +00:00
# else
0
# endif
2023-01-23 15:23:43 +00:00
)
2022-10-14 06:14:56 +00:00
{
2023-01-23 15:23:43 +00:00
AuThreading : : ContextYield ( ) ;
}
2022-10-14 06:14:56 +00:00
2023-04-30 06:54:28 +00:00
if ( ! this - > tls_ )
{
this - > tls_ = GetThreadKey ( ) ;
}
2022-01-24 18:37:06 +00:00
this - > _ThreadEP ( ) ;
2022-03-16 17:12:08 +00:00
} , GetName ( ) , this - > info_ . stackSize ) ;
2022-01-24 18:37:06 +00:00
if ( ret . first )
2021-09-06 10:58:08 +00:00
{
2022-03-16 17:12:08 +00:00
this - > handle_ = ( decltype ( handle_ ) ) ret . second ;
2021-09-06 10:58:08 +00:00
}
2021-06-27 21:25:29 +00:00
2022-01-24 18:37:06 +00:00
return ret . first ;
2021-06-27 21:25:29 +00:00
}
2023-01-23 15:23:43 +00:00
void OSThread : : AffinityPrioThrottleTickAmendECores ( )
{
auto zero = HWInfo : : CpuBitId ( ) ;
auto & cpuInfo = AuHwInfo : : GetCPUInfo ( ) ;
auto sysEcores = cpuInfo . maskECores ;
bool bIsMaskProbablyDefault = this - > mask_ = = zero | | this - > mask_ = = zero . Not ( ) ;
bool bSystemHasNoECores = sysEcores = = zero ;
EThreadPriority prio = this - > prio_ ;
if ( this - > throttle_ = = EThreadThrottle : : eEfficient & &
bSystemHasNoECores )
{
if ( bIsMaskProbablyDefault )
{
sysEcores = cpuInfo . maskAllCores ;
}
/**
* We have a lot of code that will specify an efficiency throttle and then
* arbitrarily use prio levels to ( hopefully ) order work in the os scheduler .
* Systems without ecores would see a higher prio work than normal tasks if
* we do nothing about this . On systems without ecores , efficiency throttle
* will just lock the prio to low .
*/
prio = EThreadPriority : : ePrioLow ;
UpdatePrio ( this - > throttle_ , prio ) ;
UpdateAffinity ( sysEcores ) ;
}
}
2023-08-28 18:13:18 +00:00
void AttachSignalKiller ( ) ;
2021-06-27 21:25:29 +00:00
void OSThread : : _ThreadEP ( )
{
2021-11-05 17:34:23 +00:00
// Poke TLS reference thread entity
// TODO: we need an internal OSThread *TryPokeTLSThread()
auto osThread = static_cast < OSThread * > ( GetThread ( ) ) ;
this - > tlsReferenceThread_ = osThread ;
2022-08-14 13:41:19 +00:00
bool bFailing { } ;
2021-11-05 17:34:23 +00:00
2021-10-25 18:19:49 +00:00
OSAttach ( ) ;
2022-08-14 22:59:48 +00:00
# if defined(AURORA_IS_POSIX_DERIVED)
this - > bLongJmpOnce = false ;
if ( setjmp ( env ) ! = 0 )
{
Exit ( true ) ;
2022-08-15 02:31:35 +00:00
return ;
2022-08-14 22:59:48 +00:00
}
2023-08-29 00:58:48 +00:00
2023-08-28 18:13:18 +00:00
this - > bSupportsAltKill = true ;
2022-08-14 22:59:48 +00:00
# endif
2023-09-23 19:32:01 +00:00
auto pFlag = this - > pFlag ;
2023-10-07 19:04:47 +00:00
auto pA = this - > terminatedSignalLs_ ;
auto pB = this - > terminated_ ;
2022-01-21 16:26:35 +00:00
try
{
2023-09-23 19:32:01 +00:00
if ( auto task = task_ )
2022-08-02 04:52:17 +00:00
{
2023-09-23 19:32:01 +00:00
this - > epExecEvent - > Set ( ) ;
task ( ) ;
2022-08-02 04:52:17 +00:00
}
2022-01-21 16:26:35 +00:00
}
2022-08-14 11:01:54 +00:00
# if !defined(AURORA_IS_POSIX_DERIVED)
2022-01-21 16:26:35 +00:00
catch ( . . . )
{
SysPushErrorHAL ( " OS Thread Aborted " ) ;
}
2023-09-23 19:32:01 +00:00
AU_LOCK_GUARD ( pFlag - > mutex ) ;
if ( pFlag - > bLock )
{
2023-10-07 19:04:47 +00:00
if ( pA )
{
pA - > Set ( ) ;
}
if ( pB )
{
pB - > Set ( ) ;
}
2023-09-23 19:32:01 +00:00
return ;
}
2023-10-07 19:04:47 +00:00
this - > SignalDeath ( ) ;
2021-06-27 21:25:29 +00:00
Exit ( true ) ;
2022-08-14 11:01:54 +00:00
# else
2022-08-14 22:59:48 +00:00
# if defined(AURORA_COMPILER_GCC)
catch ( abi : : __forced_unwind & )
{
throw ;
}
# endif
2022-08-14 11:01:54 +00:00
catch ( . . . )
{
2023-09-23 19:32:01 +00:00
AU_LOCK_GUARD ( pFlag - > mutex ) ;
if ( pFlag - > bLock )
{
return ;
}
2022-08-14 13:41:19 +00:00
bFailing = true ;
2022-08-14 11:01:54 +00:00
if ( ! Aurora : : kIsDebugBuild )
{
SysPushErrorHAL ( " OS Thread Aborted " ) ;
}
2022-08-14 13:41:19 +00:00
// "Safer" update
this - > HookOnExit ( ) ;
2023-10-01 13:12:22 +00:00
this - > SignalDeath ( ) ;
2022-08-14 13:41:19 +00:00
}
2023-09-23 19:32:01 +00:00
AU_LOCK_GUARD ( pFlag - > mutex ) ;
if ( pFlag - > bLock )
{
2023-10-07 19:04:47 +00:00
if ( pA )
{
pA - > Set ( ) ;
}
if ( pB )
{
pB - > Set ( ) ;
}
2023-09-23 19:32:01 +00:00
return ;
}
2022-08-14 13:41:19 +00:00
if ( ! bFailing )
{
2022-08-14 11:01:54 +00:00
Exit ( true ) ;
}
# endif
2021-06-27 21:25:29 +00:00
}
2022-01-19 17:08:13 +00:00
void OSThread : : ExecuteInDeadThread ( AuFunction < void ( ) > callback )
2021-06-27 21:25:29 +00:00
{
auto old = HandleCurrent ( ) ;
if ( this = = old ) [[unlikely]]
{
callback ( ) ;
return ;
}
if ( old )
{
2021-10-25 18:19:49 +00:00
static_cast < OSThread * > ( old ) - > OSDeatach ( ) ;
2021-06-27 21:25:29 +00:00
}
2023-04-30 08:05:14 +00:00
auto uOldHandle = GetThreadKey ( ) ;
2021-10-25 18:19:49 +00:00
this - > OSAttach ( ) ;
2021-06-27 21:25:29 +00:00
callback ( ) ;
if ( old )
{
HandleRegister ( old ) ;
2021-10-25 18:19:49 +00:00
static_cast < OSThread * > ( old ) - > OSDeatach ( ) ;
2021-06-27 21:25:29 +00:00
}
else [[unlikely]]
{
HandleRemove ( ) ;
}
2023-04-30 08:05:14 +00:00
SetThreadKey ( uOldHandle ) ;
2021-06-27 21:25:29 +00:00
}
void OSThread : : UpdateName ( )
{
2023-07-30 09:00:54 +00:00
if ( gRuntimeConfig . threadingConfig . bNoThreadNames )
{
return ;
}
2022-03-16 16:34:55 +00:00
# if defined(AURORA_IS_MODERNNT_DERIVED)
2021-06-27 21:25:29 +00:00
2022-03-16 16:34:55 +00:00
if ( this - > handle_ = = INVALID_HANDLE_VALUE )
2021-06-27 21:25:29 +00:00
{
return ;
}
2022-03-16 16:34:55 +00:00
if ( ( AuBuild : : kCurrentPlatform = = AuBuild : : EPlatform : : ePlatformWin32 ) & & ( ! AuSwInfo : : IsWindows10OrGreater ( ) ) )
2021-06-27 21:25:29 +00:00
{
2022-03-16 16:34:55 +00:00
static const DWORD kMSVCExceptionSetName = 0x406D1388 ;
2021-06-27 21:25:29 +00:00
2022-03-16 16:34:55 +00:00
# pragma pack(push,8)
typedef struct tagTHREADNAME_INFO
{
DWORD dwType ;
LPCSTR szName ;
DWORD dwThreadID ;
DWORD dwFlags ;
} THREADNAME_INFO ;
# pragma pack(pop)
if ( ! IsDebuggerPresent ( ) )
{
return ;
}
2021-06-27 21:25:29 +00:00
2022-03-16 16:34:55 +00:00
THREADNAME_INFO info ;
info . dwType = 0x1000 ;
info . szName = this - > name_ . c_str ( ) ;
2023-07-24 11:48:42 +00:00
if ( pGetThreadId )
{
info . dwThreadID = pGetThreadId ( this - > handle_ ) ;
}
else if ( this - > unixThreadId_ = = GetCurrentThreadId ( ) )
{
info . dwThreadID = this - > unixThreadId_ ;
}
else
{
return ;
}
2022-03-16 16:34:55 +00:00
info . dwFlags = 0 ;
2022-03-16 17:12:08 +00:00
auto raise = AuStaticCast < void ( __cdecl * ) ( THREADNAME_INFO & ) > ( [ ] ( THREADNAME_INFO & info )
2022-03-16 16:34:55 +00:00
{
2022-03-16 17:12:08 +00:00
__try
{
RaiseException ( kMSVCExceptionSetName , 0 , sizeof ( info ) / sizeof ( ULONG_PTR ) , ( ULONG_PTR * ) & info ) ;
}
__except ( EXCEPTION_EXECUTE_HANDLER )
{
}
} ) ;
raise ( info ) ;
2021-06-27 21:25:29 +00:00
}
2022-03-16 16:34:55 +00:00
else
2021-06-27 21:25:29 +00:00
{
2023-07-09 09:03:29 +00:00
if ( pSetThreadDescription )
2022-03-16 16:34:55 +00:00
{
2023-07-09 09:03:29 +00:00
pSetThreadDescription ( this - > handle_ , AuLocale : : ConvertFromUTF8 ( this - > name_ ) . c_str ( ) ) ;
2022-03-16 16:34:55 +00:00
}
2021-06-27 21:25:29 +00:00
}
2022-03-16 16:34:55 +00:00
2021-06-27 21:25:29 +00:00
# elif defined(AURORA_HAS_PTHREADS)
2023-08-11 15:51:42 +00:00
if ( ! this - > handle_ )
{
return ;
}
2022-03-16 17:12:08 +00:00
pthread_setname_np ( this - > handle_ , this - > name_ . c_str ( ) ) ;
2021-06-27 21:25:29 +00:00
# endif
}
2022-08-06 19:50:40 +00:00
static void AttachSignalKiller ( )
{
# if defined(AURORA_IS_POSIX_DERIVED)
struct sigaction action =
{
2023-08-29 00:58:48 +00:00
. sa_handler = HandleSigAbortThread ,
. sa_flags = 0
2022-08-06 19:50:40 +00:00
} ;
: : sigemptyset ( & action . sa_mask ) ;
2023-08-29 00:58:48 +00:00
: : sigaction ( SIGRTMIN + gRuntimeConfig . linuxConfig . uSignalTerminate , & action , nullptr ) ;
2022-08-06 19:50:40 +00:00
# endif
}
2023-08-23 23:03:05 +00:00
void OSThread : : MakeMain ( )
2021-06-27 21:25:29 +00:00
{
2023-08-23 23:03:05 +00:00
this - > bNotOwned = true ;
this - > name_ = " Main System Thread " ;
this - > OSAttach ( ) ;
}
2022-08-02 04:52:17 +00:00
2023-08-23 23:03:05 +00:00
void OSThread : : OSAttach ( )
{
2021-06-27 21:25:29 +00:00
HandleRegister ( this ) ;
2021-09-06 10:58:08 +00:00
# if defined(AURORA_IS_LINUX_DERIVED)
2021-06-27 21:25:29 +00:00
this - > unixThreadId_ = gettid ( ) ;
2021-09-06 10:58:08 +00:00
# elif defined(AURORA_IS_XNU_DERIVED)
2021-06-27 21:25:29 +00:00
this - > unixThreadId_ = pthread_getthreadid_np ( ) ;
2021-09-06 10:58:08 +00:00
# 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
2021-06-27 21:25:29 +00:00
# elif defined(AURORA_HAS_PTHREADS)
this - > unixThreadId_ = 0 ; // !!!!
# endif
2022-03-21 07:16:12 +00:00
2023-07-24 11:48:42 +00:00
# if defined(AURORA_PLATFORM_WIN32)
this - > unixThreadId_ = GetCurrentThreadId ( ) ;
# endif
2023-04-30 08:05:14 +00:00
if ( this - > tls_ )
{
SetThreadKey ( this - > tls_ ) ;
}
2023-08-23 23:03:05 +00:00
2022-03-21 07:16:12 +00:00
UpdatePrio ( this - > throttle_ , this - > prio_ ) ;
2022-03-16 17:12:08 +00:00
SetAffinity ( this - > mask_ ) ;
2023-01-23 15:23:43 +00:00
AffinityPrioThrottleTickAmendECores ( ) ;
2021-06-27 21:25:29 +00:00
UpdateName ( ) ;
}
2022-03-21 07:16:12 +00:00
static AuHashMap < EThreadPriority , int > kNiceMap
2021-06-27 21:25:29 +00:00
{
{
2022-03-21 07:16:12 +00:00
EThreadPriority : : ePrioRT , - 19
2021-06-27 21:25:29 +00:00
} ,
{
2023-08-23 17:08:48 +00:00
EThreadPriority : : ePrioAboveHigh , - 15
2021-06-27 21:25:29 +00:00
} ,
{
2022-03-21 07:16:12 +00:00
EThreadPriority : : ePrioHigh , - 11
2021-06-27 21:25:29 +00:00
} ,
{
2022-03-21 07:16:12 +00:00
EThreadPriority : : ePrioNormal , - 2
2021-06-27 21:25:29 +00:00
} ,
{
2022-03-21 07:16:12 +00:00
EThreadPriority : : ePrioLow , 5
} ,
{
EThreadPriority : : ePrioLowest , 15
2021-06-27 21:25:29 +00:00
}
} ;
2021-09-06 10:58:08 +00:00
# if defined(AURORA_IS_MODERNNT_DERIVED)
2022-03-21 07:16:12 +00:00
static const AuHashMap < EThreadPriority , int > kWin32Map
2021-06-27 21:25:29 +00:00
{
{
2022-03-21 07:16:12 +00:00
EThreadPriority : : ePrioRT , THREAD_PRIORITY_TIME_CRITICAL
} ,
{
EThreadPriority : : ePrioAboveHigh , THREAD_PRIORITY_HIGHEST
} ,
{
EThreadPriority : : ePrioHigh , THREAD_PRIORITY_ABOVE_NORMAL
} ,
{
EThreadPriority : : ePrioNormal , THREAD_PRIORITY_NORMAL
} ,
{
EThreadPriority : : ePrioLow , THREAD_PRIORITY_BELOW_NORMAL
} ,
{
EThreadPriority : : ePrioLowest , THREAD_PRIORITY_LOWEST
}
} ;
# endif
# if defined(AURORA_IS_XNU_DERIVED)
static const AuHashMap < AuPair < EThreadThrottle , EThreadPriority > , AuPair < AuUInt32 , int > > kXnuQoSLevel
{
// Rt
{
AuMakePair ( EThreadThrottle : : eNormal , EThreadPriority : : ePrioRT ) , AuMakePair ( DISPATCH_QUEUE_PRIORITY_HIGH , 10 )
} ,
{
AuMakePair ( EThreadThrottle : : eNormal , EThreadPriority : : ePrioAboveHigh ) , AuMakePair ( DISPATCH_QUEUE_PRIORITY_DEFAULT , 5 )
} ,
{
AuMakePair ( EThreadThrottle : : eNormal , EThreadPriority : : ePrioHigh ) , AuMakePair ( DISPATCH_QUEUE_PRIORITY_DEFAULT , 1 )
} ,
{
AuMakePair ( EThreadThrottle : : eNormal , EThreadPriority : : ePrioNormal ) , AuMakePair ( DISPATCH_QUEUE_PRIORITY_DEFAULT , 0 )
} ,
{
AuMakePair ( EThreadThrottle : : eNormal , EThreadPriority : : ePrioLow ) , AuMakePair ( DISPATCH_QUEUE_PRIORITY_LOW , 0 )
} ,
{
AuMakePair ( EThreadThrottle : : eNormal , EThreadPriority : : ePrioLowest ) , AuMakePair ( DISPATCH_QUEUE_PRIORITY_BACKGROUND , 0 )
} ,
// Perf
{
AuMakePair ( EThreadThrottle : : ePerformance , EThreadPriority : : ePrioRT ) , AuMakePair ( DISPATCH_QUEUE_PRIORITY_HIGH , 10 )
} ,
{
AuMakePair ( EThreadThrottle : : ePerformance , EThreadPriority : : ePrioAboveHigh ) , AuMakePair ( DISPATCH_QUEUE_PRIORITY_HIGH , 8 )
} ,
{
AuMakePair ( EThreadThrottle : : ePerformance , EThreadPriority : : ePrioHigh ) , AuMakePair ( DISPATCH_QUEUE_PRIORITY_HIGH , 3 )
2021-06-27 21:25:29 +00:00
} ,
{
2022-03-21 07:16:12 +00:00
AuMakePair ( EThreadThrottle : : ePerformance , EThreadPriority : : ePrioNormal ) , AuMakePair ( DISPATCH_QUEUE_PRIORITY_HIGH , 0 )
2021-06-27 21:25:29 +00:00
} ,
{
2022-03-21 07:16:12 +00:00
AuMakePair ( EThreadThrottle : : ePerformance , EThreadPriority : : ePrioLow ) , AuMakePair ( DISPATCH_QUEUE_PRIORITY_DEFAULT , 1 )
2021-06-27 21:25:29 +00:00
} ,
{
2022-03-21 07:16:12 +00:00
AuMakePair ( EThreadThrottle : : ePerformance , EThreadPriority : : ePrioLowest ) , AuMakePair ( DISPATCH_QUEUE_PRIORITY_DEFAULT , 0 )
2021-06-27 21:25:29 +00:00
} ,
2022-03-21 07:16:12 +00:00
// Efficient
2021-06-27 21:25:29 +00:00
{
2022-03-21 07:16:12 +00:00
AuMakePair ( EThreadThrottle : : eEfficient , EThreadPriority : : ePrioRT ) , AuMakePair ( DISPATCH_QUEUE_PRIORITY_LOW , 10 )
} ,
{
AuMakePair ( EThreadThrottle : : eEfficient , EThreadPriority : : ePrioAboveHigh ) , AuMakePair ( DISPATCH_QUEUE_PRIORITY_LOW , 1 )
} ,
{
AuMakePair ( EThreadThrottle : : eEfficient , EThreadPriority : : ePrioHigh ) , AuMakePair ( DISPATCH_QUEUE_PRIORITY_LOW , 0 )
} ,
{
AuMakePair ( EThreadThrottle : : eEfficient , EThreadPriority : : ePrioNormal ) , AuMakePair ( DISPATCH_QUEUE_PRIORITY_BACKGROUND , 0 )
} ,
{
AuMakePair ( EThreadThrottle : : eEfficient , EThreadPriority : : ePrioLow ) , AuMakePair ( DISPATCH_QUEUE_PRIORITY_BACKGROUND , - 1 )
} ,
{
AuMakePair ( EThreadThrottle : : eEfficient , EThreadPriority : : ePrioLowest ) , AuMakePair ( DISPATCH_QUEUE_PRIORITY_BACKGROUND , - 2 )
2021-06-27 21:25:29 +00:00
}
} ;
# endif
2022-03-21 07:16:12 +00:00
void OSThread : : UpdatePrio ( EThreadThrottle throttle , EThreadPriority prio )
2021-06-27 21:25:29 +00:00
{
2021-09-06 10:58:08 +00:00
# if defined(AURORA_IS_MODERNNT_DERIVED)
2021-06-27 21:25:29 +00:00
2022-03-21 07:16:12 +00:00
if ( this - > handle_ = = INVALID_HANDLE_VALUE )
2021-06-27 21:25:29 +00:00
{
return ;
}
const int * val ;
2021-09-06 10:58:08 +00:00
if ( ! AuTryFind ( kWin32Map , prio , val ) )
2021-06-27 21:25:29 +00:00
{
return ;
}
2022-03-21 07:16:12 +00:00
if ( ! SetThreadPriority ( this - > handle_ , * val ) )
{
SysPushErrorHAL ( " Couldn't update thread priority " ) ;
}
2022-12-14 01:35:18 +00:00
THREAD_POWER_THROTTLING_STATE2 throttlingState { } ;
2022-03-21 07:16:12 +00:00
throttlingState . Version = THREAD_POWER_THROTTLING_CURRENT_VERSION ;
switch ( throttle )
{
case EThreadThrottle : : eNormal :
throttlingState . ControlMask = 0 ;
throttlingState . StateMask = 0 ;
break ;
case EThreadThrottle : : ePerformance :
throttlingState . ControlMask = THREAD_POWER_THROTTLING_EXECUTION_SPEED ;
throttlingState . StateMask = 0 ;
break ;
case EThreadThrottle : : eEfficient :
throttlingState . ControlMask = THREAD_POWER_THROTTLING_EXECUTION_SPEED ;
throttlingState . StateMask = THREAD_POWER_THROTTLING_EXECUTION_SPEED ;
break ;
}
2023-07-09 09:03:29 +00:00
if ( pSetThreadInformation )
2022-12-14 01:35:18 +00:00
{
2023-07-09 09:03:29 +00:00
pSetThreadInformation ( this - > handle_ ,
kThreadPowerThrottling ,
& throttlingState ,
sizeof ( throttlingState ) ) ;
2022-12-14 01:35:18 +00:00
}
2022-03-21 07:16:12 +00:00
//#elif defined(AURORA_IS_XNU_DERIVED)
2021-06-27 21:25:29 +00:00
# elif defined(AURORA_HAS_PTHREADS)
2023-08-23 17:08:48 +00:00
sched_param param { } ;
int policyNonRT { } ;
int schedA { } ;
int scheduler { } ;
# if defined(AURORA_IS_LINUX_DERIVED)
rlimit rl ;
# endif
# if defined(AURORA_IS_POSIX_DERIVED)
static const auto GetPrioLevel = [ ] ( int sched , EThreadPriority prio )
{
const int * val ;
if ( ! AuTryFind ( kNiceMap , prio , val ) )
{
return ( int ) sched_get_priority_max ( sched ) ;
}
int min = sched_get_priority_min ( sched ) ;
int max = sched_get_priority_max ( sched ) ;
float f = ( ( 1.0 - ( ( float ( * val ) + 19.0 ) / ( 19.0 + 20.0 ) ) ) * float ( max - min ) ) + float ( min ) ;
return ( int ) f ;
} ;
# endif
2021-06-27 21:25:29 +00:00
2022-03-21 07:16:12 +00:00
if ( ! this - > handle_ )
2021-06-27 21:25:29 +00:00
{
return ;
}
2022-03-21 07:16:12 +00:00
if ( prio = = EThreadPriority : : ePrioRT )
2021-06-27 21:25:29 +00:00
{
2023-08-23 17:08:48 +00:00
# if defined(AURORA_IS_POSIX_DERIVED)
# if defined(SCHED_RR)
param . sched_priority = sched_get_priority_max ( ( schedA = SCHED_RR ) ) ;
# else
param . sched_priority = sched_get_priority_max ( ( schedA = SCHED_FIFO ) ) ;
# endif
if ( : : sched_setscheduler ( this - > unixThreadId_ , schedA , & param ) = = 0 )
{
goto gtfo ;
}
{
# if defined(AURORA_IS_LINUX_DERIVED)
if ( getrlimit ( RLIMIT_RTPRIO , & rl ) = = 0 )
{
2023-08-28 18:13:18 +00:00
bool bWarnOnce { } ;
2023-08-23 17:08:48 +00:00
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 " ) ;
2023-08-28 18:13:18 +00:00
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 ;
2023-08-23 17:08:48 +00:00
rl . rlim_cur = rl . rlim_max ;
}
else
{
rl . rlim_cur = rl . rlim_max ;
}
param . sched_priority = rl . rlim_cur ;
# if defined(SCHED_RR)
if ( : : sched_setscheduler ( this - > unixThreadId_ , SCHED_RR , & param ) = = 0 )
{
goto gtfo ;
}
# endif
2023-08-28 18:13:18 +00:00
if ( : : setrlimit ( RLIMIT_RTPRIO , & rl ) ! = 0 & &
! bWarnOnce )
2023-08-23 17:08:48 +00:00
{
AuLogWarn ( " We will not use RT-Kit to keep your Linux machine alive through XDG_FREEEEEEDESKTOP_HOPES_AND_DREAMS " ) ;
2023-08-28 18:13:18 +00:00
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 " ) ;
2023-08-23 17:08:48 +00:00
}
# if defined(SCHED_RR)
if ( : : sched_setscheduler ( this - > unixThreadId_ , SCHED_RR , & param ) = = 0 )
{
goto gtfo ;
}
# endif
param . sched_priority = sched_get_priority_max ( SCHED_FIFO ) ;
if ( : : sched_setscheduler ( this - > unixThreadId_ , SCHED_FIFO , & param ) = = 0 )
{
goto gtfo ;
}
}
else
# endif
{
param . sched_priority = sched_get_priority_max ( SCHED_FIFO ) ;
if ( : : sched_setscheduler ( this - > unixThreadId_ , SCHED_FIFO , & param ) = = 0 )
{
goto gtfo ;
}
}
}
# else
# if defined(SCHED_RR)
2021-06-27 21:25:29 +00:00
param . sched_priority = sched_get_priority_min ( SCHED_RR ) ;
2022-03-16 17:12:08 +00:00
if ( pthread_setschedparam ( this - > handle_ , SCHED_RR , & param ) = = 0 )
2021-06-27 21:25:29 +00:00
{
2023-08-23 17:08:48 +00:00
goto gtfo ;
}
# endif
param . sched_priority = GetPrioLevel ( SCHED_FIFO , prio ) ;
if ( pthread_setschedparam ( this - > handle_ , SCHED_FIFO , & param ) = = 0 )
{
goto gtfo ;
2021-06-27 21:25:29 +00:00
}
2023-08-23 17:08:48 +00:00
# endif
2021-06-27 21:25:29 +00:00
// fall through on error
}
2023-08-23 17:08:48 +00:00
# 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 , & param ) = = 0 )
{
goto gtfo ;
}
// fail
return ;
}
else if ( this - > throttle_ = = EThreadThrottle : : eEfficient | |
this - > prio_ = = EThreadPriority : : ePrioRT )
# else
2022-03-21 07:16:12 +00:00
else if ( this - > prio_ = = EThreadPriority : : ePrioRT )
2023-08-23 17:08:48 +00:00
# endif
2021-11-05 17:34:23 +00:00
{
2023-08-23 17:08:48 +00:00
# if defined(AURORA_IS_POSIX_DERIVED)
policyNonRT =
2021-11-05 17:34:23 +00:00
# if defined(AURORA_IS_XNU_DERIVED)
SCHED_FIFO ;
# else
SCHED_OTHER ;
# endif
2023-08-23 17:08:48 +00:00
param . sched_priority = GetPrioLevel ( policyNonRT , prio ) ;
if ( : : sched_setscheduler ( this - > unixThreadId_ , policyNonRT , & param ) = = 0 )
{
goto gtfo ;
}
2021-06-27 21:25:29 +00:00
return ;
2023-08-23 17:08:48 +00:00
# endif
2021-06-27 21:25:29 +00:00
}
{
2023-08-23 17:08:48 +00:00
scheduler = : : sched_getscheduler ( this - > unixThreadId_ ) ;
param . sched_priority = GetPrioLevel ( scheduler , prio ) ;
if ( : : sched_setscheduler ( this - > unixThreadId_ , scheduler , & param ) = = 0 )
{
goto gtfo ;
}
2021-06-27 21:25:29 +00:00
}
2023-08-23 17:08:48 +00:00
// TODO: We used to set the legacy unix niceness value here.
AuLogWarn ( " Couldn't set affinity " ) ;
2021-11-05 17:34:23 +00:00
# endif
2023-08-23 17:08:48 +00:00
gtfo :
2022-03-21 07:16:12 +00:00
# if defined(AURORA_IS_LINUX_DERIVED) || defined(AURORA_IS_BSD_DERIVED)
switch ( throttle )
{
case EThreadThrottle : : eNormal :
2022-03-30 14:18:07 +00:00
this - > throttleMask_ = AuHwInfo : : GetCPUInfo ( ) . maskAllCores ;
2022-03-21 07:16:12 +00:00
break ;
case EThreadThrottle : : ePerformance :
this - > throttleMask_ = AuHwInfo : : GetCPUInfo ( ) . maskPCores ;
break ;
case EThreadThrottle : : eEfficient :
this - > throttleMask_ = AuHwInfo : : GetCPUInfo ( ) . maskECores ;
break ;
}
2022-03-21 07:31:01 +00:00
UpdateAffinity ( this - > mask_ ) ;
2022-03-21 07:16:12 +00:00
# endif
2022-03-30 14:18:07 +00:00
2022-03-16 17:12:08 +00:00
this - > prio_ = prio ;
2021-06-27 21:25:29 +00:00
}
2022-03-16 17:12:08 +00:00
void OSThread : : UpdateAffinity ( const HWInfo : : CpuBitId & mask )
2021-06-27 21:25:29 +00:00
{
2022-04-06 06:25:34 +00:00
2021-09-06 10:58:08 +00:00
# if defined(AURORA_IS_MODERNNT_DERIVED)
2022-03-21 07:16:12 +00:00
2022-03-16 17:12:08 +00:00
if ( this - > handle_ = = INVALID_HANDLE_VALUE )
{
return ;
}
2023-01-23 15:23:43 +00:00
if ( ( AuBuild : : kCurrentPlatform ! = AuBuild : : EPlatform : : ePlatformWin32 ) | |
( AuSwInfo : : IsWindows10OrGreater ( ) ) )
2022-03-16 17:12:08 +00:00
{
2022-04-10 16:18:21 +00:00
auto sets = mask . CpuBitCount ( ) ?
mask . ToCpuSets ( ) :
AuHwInfo : : GetCPUInfo ( ) . maskAllCores . ToCpuSets ( ) ;
2022-03-16 17:12:08 +00:00
2023-07-09 09:03:29 +00:00
if ( pSetThreadSelectedCpuSets )
2022-03-16 17:12:08 +00:00
{
2023-07-09 09:03:29 +00:00
if ( pSetThreadSelectedCpuSets ( this - > handle_ , sets . data ( ) , sets . size ( ) ) )
2022-03-16 17:12:08 +00:00
{
return ;
}
SysPushErrorUnavailableError ( " SetThreadSelectedCpuSets is expected on modern NT (CoreOS?) excluding Windows; or Win10+ " ) ;
}
}
# if defined(AURORA_PLATFORM_WIN32)
2023-07-14 15:31:47 +00:00
if ( pSetThreadGroupAffinity )
2021-06-27 21:25:29 +00:00
{
2023-07-14 15:31:47 +00:00
GROUP_AFFINITY affinityGroup { 0 } ;
mask . ToMsWin7GroupAffinity ( & affinityGroup ) ;
if ( pSetThreadGroupAffinity ( this - > handle_ , & affinityGroup , nullptr ) )
{
return ;
}
2021-06-27 21:25:29 +00:00
}
2023-07-14 15:31:47 +00:00
2023-08-23 16:09:19 +00:00
if ( mask . CpuBitCount ( ) < = 32 )
{
DWORD_PTR uProcMask { } ;
DWORD_PTR uSysMask { } ;
2023-08-23 18:04:48 +00:00
AuUInt32 uProcmask { AuUInt32 ( mask . lower ) } ;
2023-08-23 16:09:19 +00:00
if ( : : GetProcessAffinityMask ( GetCurrentProcess ( ) , & uProcMask , & uSysMask ) )
{
uProcmask & = uProcMask ;
}
if ( : : SetThreadAffinityMask ( this - > handle_ , uProcmask ) )
{
return ;
}
}
2021-06-27 21:25:29 +00:00
# endif
2022-03-16 17:12:08 +00:00
2022-03-21 07:16:12 +00:00
SysPushErrorUnavailableError ( " Couldn't set thread affinity " ) ;
return ;
2022-03-16 17:12:08 +00:00
2022-03-21 07:16:12 +00:00
# elif defined(AURORA_HAS_PTHREADS)
2023-08-11 15:51:42 +00:00
if ( ! this - > handle_ )
{
return ;
}
2022-03-21 07:16:12 +00:00
auto mask2 = mask . And ( this - > throttleMask_ ) ;
if ( mask2 . CpuBitCount ( ) = = 0 )
{
switch ( this - > throttle_ )
{
case EThreadThrottle : : eNormal :
2022-04-06 06:25:34 +00:00
mask2 = AuHwInfo : : GetCPUInfo ( ) . maskAllCores ;
2022-03-21 07:16:12 +00:00
break ;
case EThreadThrottle : : ePerformance :
mask2 = AuHwInfo : : GetCPUInfo ( ) . maskPCores ;
break ;
case EThreadThrottle : : eEfficient :
mask2 = AuHwInfo : : GetCPUInfo ( ) . maskECores ;
break ;
}
}
2022-03-16 17:12:08 +00:00
2022-03-21 07:16:12 +00:00
cpu_set_t cpuset ;
CPU_ZERO ( & cpuset ) ;
AuUInt8 index { } ;
while ( mask2 . CpuBitScanForward ( index , index ) )
{
CPU_SET ( index , & cpuset ) ;
index + + ;
}
2022-03-16 17:12:08 +00:00
2022-04-06 06:25:34 +00:00
if ( ! CPU_COUNT ( & cpuset ) )
{
return ;
}
2022-03-21 07:16:12 +00:00
if ( pthread_setaffinity_np ( this - > handle_ , sizeof ( cpuset ) , & cpuset ) ! = 0 )
{
SysPushErrorHAL ( " Couldn't set affinity mask " ) ;
}
return ;
# endif
2021-06-27 21:25:29 +00:00
}
2021-10-25 18:19:49 +00:00
void OSThread : : OSDeatach ( )
2021-06-27 21:25:29 +00:00
{
2022-08-06 19:50:40 +00:00
# if defined(AURORA_IS_POSIX_DERIVED)
2023-08-29 00:58:48 +00:00
this - > bSupportsAltKill = false ;
//struct sigaction action =
//{
// .sa_handler = SIG_DFL
//};
//::sigemptyset(&action.sa_mask);
//::sigaction(SIGRTMIN + gRuntimeConfig.linuxConfig.uSignalTerminate, &action, nullptr);
2022-08-02 04:52:17 +00:00
# endif
2021-06-27 21:25:29 +00:00
}
bool OSThread : : InternalKill ( bool locked )
{
2023-06-04 16:28:29 +00:00
this - > PrivateUserDataClear ( ) ;
2022-03-16 17:12:08 +00:00
if ( this - > terminated_ )
2021-06-27 21:25:29 +00:00
{
if ( ! locked )
{
2022-03-21 07:16:12 +00:00
if ( ! this - > exitOnlyOnce_ - > TryLock ( ) )
2021-06-27 21:25:29 +00:00
{
return false ;
}
}
}
HookOnExit ( ) ;
2021-10-23 18:25:43 +00:00
try
2021-06-27 21:25:29 +00:00
{
2021-10-23 18:25:43 +00:00
// dispatch kill callback
2022-03-21 07:16:12 +00:00
if ( this - > info_ . callbacks )
2021-06-27 21:25:29 +00:00
{
2022-03-21 07:16:12 +00:00
this - > info_ . callbacks - > OnExit ( this ) ;
2021-06-27 21:25:29 +00:00
}
}
2021-10-23 18:25:43 +00:00
catch ( . . . )
{
Debug : : PrintError ( ) ;
2022-01-24 18:37:06 +00:00
AuLogWarn ( " Couldn't deinitialize thread " ) ;
AuLogWarn ( " The smart thing to do at this point would be to panic " ) ;
AuLogWarn ( " ...but we could continue " ) ;
AuLogWarn ( " Carrying on despite the potential for data integrity loss and memory leaks " ) ;
2021-10-23 18:25:43 +00:00
Telemetry : : Mayday ( ) ;
}
2021-06-27 21:25:29 +00:00
HookReleaseThreadResources ( ) ;
2023-10-01 13:12:22 +00:00
this - > SignalDeath ( ) ;
return true ;
}
void OSThread : : SignalDeath ( )
{
2022-03-21 07:16:12 +00:00
if ( this - > terminatedSignalLs_ )
2021-10-25 17:08:28 +00:00
{
2022-03-21 07:16:12 +00:00
this - > terminatedSignalLs_ - > Set ( ) ;
2021-06-27 21:25:29 +00:00
}
2021-10-25 17:08:28 +00:00
2023-02-11 19:37:30 +00:00
if ( this - > terminated_ )
{
this - > exitOnlyOnce_ - > Unlock ( ) ;
2023-10-01 13:12:22 +00:00
this - > terminated_ - > Set ( ) ;
}
2021-06-27 21:25:29 +00:00
}
2022-08-06 19:50:40 +00:00
bool OSThread : : InternalKillForceNtfy ( )
{
2023-10-01 13:12:22 +00:00
this - > SignalDeath ( ) ;
2022-08-06 19:50:40 +00:00
2022-08-07 22:42:13 +00:00
// Great C++ ABI guys...
# if defined(AURORA_HAS_PTHREADS)
2022-08-14 13:41:19 +00:00
{
2022-08-15 02:31:35 +00:00
if ( gettid ( ) = = getpid ( ) )
{
AuProcess : : Exit ( 0 ) ;
return true ;
}
2022-08-14 13:41:19 +00:00
: : longjmp ( env , 1 ) ;
}
2022-08-15 02:31:35 +00:00
: : pthread_exit ( nullptr ) ;
2022-08-07 22:42:13 +00:00
# endif
2022-08-06 19:50:40 +00:00
return true ;
}
2021-06-27 21:25:29 +00:00
void OSThread : : TeminateOSContext ( bool calledFromThis )
{
2021-09-06 10:58:08 +00:00
# if defined(AURORA_IS_MODERNNT_DERIVED)
2021-06-27 21:25:29 +00:00
2022-03-16 17:12:08 +00:00
if ( this - > handle_ = = INVALID_HANDLE_VALUE )
2021-06-27 21:25:29 +00:00
{
return ;
}
if ( calledFromThis )
{
2022-08-06 19:50:40 +00:00
: : ExitThread ( 0 ) ;
2021-06-27 21:25:29 +00:00
}
else
{
2022-08-06 19:50:40 +00:00
: : TerminateThread ( this - > handle_ , 0 ) ;
2021-06-27 21:25:29 +00:00
}
# elif defined(AURORA_HAS_PTHREADS)
2022-08-06 19:50:40 +00:00
if ( calledFromThis )
2022-08-02 04:52:17 +00:00
{
2022-08-15 02:31:35 +00:00
: : longjmp ( env , 1 ) ;
2022-08-14 22:59:48 +00:00
: : pthread_exit ( nullptr ) ;
2022-08-02 04:52:17 +00:00
}
else
{
// pthreads is fun. thats not how unix works...
// pthread_kill(this->handle_, SIGKILL);
// remember signal inheritance is a cluster fuck & the tree will be walked
// this is giving me flashbacks to hacking in apcs into the kernel
// gross...
// let's let nptl handle it
//pthread_cancel(this->handle_);
// ...doesnt work with c++ bc catch handlers get in the way. FUCK
if ( this - > bSupportsAltKill )
{
2023-08-29 00:58:48 +00:00
: : pthread_kill ( this - > handle_ , SIGRTMIN + gRuntimeConfig . linuxConfig . uSignalTerminate ) ;
2022-08-02 04:52:17 +00:00
}
else
{
2022-08-06 19:50:40 +00:00
: : pthread_cancel ( this - > handle_ ) ;
2022-08-02 04:52:17 +00:00
}
}
2021-06-27 21:25:29 +00:00
# else
SysPanic ( " Not implemented " ) ;
# endif
}
void OSThread : : FreeOSContext ( )
{
2021-09-06 10:58:08 +00:00
# if defined(AURORA_IS_MODERNNT_DERIVED)
2022-03-16 17:12:08 +00:00
AuWin32CloseHandle ( this - > handle_ ) ;
2021-06-27 21:25:29 +00:00
# endif
}
2021-10-25 17:08:28 +00:00
2022-06-11 23:52:46 +00:00
AuSPtr < AuLoop : : ILoopSource > OSThread : : AsLoopSource ( )
2021-10-25 17:08:28 +00:00
{
2023-08-24 09:40:15 +00:00
if ( ! this - > terminatedSignalLs_ )
{
this - > terminatedSignalLs_ = AuLoop : : NewLSEvent ( true , false , true ) ;
}
return this - > terminatedSignalLs_ ;
2021-10-25 17:08:28 +00:00
}
AuSPtr < IWaitable > OSThread : : GetShutdownSignalWaitable ( )
{
return this - > terminateSignal_ ;
}
2022-06-11 23:52:46 +00:00
AuSPtr < AuLoop : : ILoopSource > OSThread : : GetShutdownSignalLS ( )
2021-10-25 17:08:28 +00:00
{
return this - > terminateSignalLs_ ;
}
2022-01-18 16:02:24 +00:00
void InitThreading ( )
{
2022-03-16 17:12:08 +00:00
# if defined(AURORA_PLATFORM_WIN32)
2022-01-18 16:02:24 +00:00
AuxUlibInitialize ( ) ;
2022-03-16 17:12:08 +00:00
# endif
2022-12-14 01:35:18 +00:00
2023-08-29 00:58:48 +00:00
AttachSignalKiller ( ) ;
2023-08-23 23:03:05 +00:00
if ( auto pThread = GetThread ( ) )
{
AuStaticCast < OSThread > ( pThread ) - > MakeMain ( ) ;
}
2022-01-18 16:02:24 +00:00
}
2022-03-21 07:16:12 +00:00
}