[*] Refactor IAuroraThread

This commit is contained in:
Reece Wilson 2024-05-27 13:26:20 +01:00
parent 5ab97be4e3
commit e4fa5d549e
6 changed files with 118 additions and 61 deletions

View File

@ -37,26 +37,62 @@ namespace Aurora::Threading::Threads
///
struct IAuroraThread
{
virtual bool Run() = 0;
virtual void Exit() = 0;
virtual bool Exiting() = 0;
virtual void SendExitSignal() = 0;
virtual bool Run() = 0;
virtual void UnsafeForceTerminateSignal() = 0;
/**
* @brief Forcefully terminates the thread from within the threads context or externally
* In the event another thread requests termination, the thread has until (SetNoUnwindTerminateExitWatchDogTimeoutInMS)
* to terminate before the context is forcefully destroyed, and the RAII objects are forever leaked.
* At this point it is up to the application to start recycling memory heaps.
*/
virtual void Terminate() = 0;
virtual void SetPriority(EThreadPriority prio) = 0;
virtual void SetThrottle(EThreadThrottle throttle) = 0;
virtual void SetAffinity(const HWInfo::CpuBitId &mask) = 0;
virtual void SetName(const AuString &name) = 0;
virtual void SetNameIdentity(AuUInt32 uNameIdentity) = 0;
/**
* @brief Terminate's force kill path with even less niceness and less waiting around by the caller
*/
virtual void UnsafeForceTerminateSignal() = 0;
virtual EThreadPriority GetPriority() = 0;
virtual EThreadThrottle GetThrottle() = 0;
virtual HWInfo::CpuBitId GetMask() = 0;
virtual AuString GetName() = 0;
virtual AuUInt32 GetNameIdentity() = 0;
/**
* @brief Dispatches the shutdown signals (the IO objects, not in the POSIX or NT DPC sense, more APC-like)
*/
virtual void SendExitSignal() = 0;
virtual AuUInt64 GetThreadCreationTime(Time::EClock eClock) = 0;
virtual bool Exiting() = 0;
/**
* @brief
* @param eClock EClock::eWall, EClock::eSteady, or EClock::eProcessTime
* @return
*/
virtual AuUInt64 GetThreadCreationTime(Time::EClock eClock) = 0;
virtual void SetPriority(EThreadPriority prio) = 0;
virtual EThreadPriority GetPriority() = 0;
virtual void SetThrottle(EThreadThrottle throttle) = 0;
virtual EThreadThrottle GetThrottle() = 0;
virtual void SetAffinityMask(const HWInfo::CpuBitId &mask) = 0;
virtual HWInfo::CpuBitId GetAffinityMask() = 0;
virtual void SetName(const AuString &name) = 0;
virtual AuString GetName() = 0;
/**
* @brief Optional:
*/
virtual void SetNameIdentity(AuUInt32 uNameIdentity) = 0;
/**
* @brief returns SetNameIdentity or a hash for SetName.
Ship processes with anti-debug may not wish to provide users a hint towards which thread does what with English strings.
Deterministic thread identities are still useful for debugging and telemetry.
*/
virtual AuUInt32 GetNameIdentity() = 0;
/**
* @brief Defer to ::Terminate()
*/
virtual AuUInt64 SetNoUnwindTerminateExitWatchDogTimeoutInMS(AuUInt64 uMS) = 0;
// TODO: will deprecate with a version that does call init on thread and deinit on deinit
/// Registers a thread feature _not_ calling on init [for now]
@ -64,17 +100,36 @@ namespace Aurora::Threading::Threads
/// Use this to register teardown functions
virtual void AddLastHopeTlsHook(const AuSPtr<Threading::Threads::IThreadFeature> &feature) = 0;
virtual AuUInt64 SetNoUnwindTerminateExitWatchDogTimeoutInMS(AuUInt64 uMS) = 0;
/**
* @brief Read only signal.
*/
virtual AuSPtr<IWaitable> GetShutdownWaitable() = 0;
virtual AuSPtr<IWaitable> AsWaitable() = 0;
virtual AuSPtr<IO::Loop::ILoopSource> AsLoopSource() = 0;
/**
* @brief Read only signal.
*/
virtual AuSPtr<IO::Loop::ILoopSource> GetShutdownLoopSource() = 0;
virtual AuSPtr<IWaitable> GetShutdownSignalWaitable() = 0;
virtual AuSPtr<IO::Loop::ILoopSource> GetShutdownSignalLS() = 0;
/**
* @brief Read only signal.
*/
virtual AuSPtr<IWaitable> GetShutdownSignalWaitable() = 0;
virtual void Detach() = 0;
/**
* @brief Read only signal.
*/
virtual AuSPtr<IO::Loop::ILoopSource> GetShutdownSignalLoopSource() = 0;
virtual void ExecuteInDeadThread(AuFunction<void()> callback) = 0;
/**
* @brief Do not force ::Terminate-like shutdown on release.
*/
virtual void Detach() = 0;
/**
* @brief Impersonation for AuThreads::TLSVariable<T> access.
* Useful for shutting down thread local subsystems with c-like C++.
*/
virtual void ExecuteInDeadThread(AuFunction<void()> callback) = 0;
AURT_ADD_USR_DATA;
};

View File

@ -667,7 +667,7 @@ namespace Aurora::Async
{
if (thread.get() != pSelf)
{
thread->Exit();
thread->Terminate();
}
}

View File

@ -161,7 +161,7 @@ namespace Aurora::Processes
AuSPtr<Threading::IWaitable> ProcessImpl::AsWaitable()
{
if (!this->thread_) return nullptr;
return this->thread_->AsWaitable();
return this->thread_->GetShutdownWaitable();
}
AuSPtr<AuLoop::ILoopSource> ProcessImpl::AsLoopSource()

View File

@ -166,7 +166,7 @@ namespace Aurora::Threading::Threads
{
if (gRuntimeRunLevel <= 3)
{
Exit();
Terminate();
}
else if (gRuntimeRunLevel >= 5)
{
@ -278,7 +278,7 @@ namespace Aurora::Threading::Threads
this->detached_ = true;
}
AuSPtr<IWaitable> OSThread::AsWaitable()
AuSPtr<IWaitable> OSThread::GetShutdownWaitable()
{
if (!this->terminated_)
{
@ -302,11 +302,6 @@ namespace Aurora::Threading::Threads
}
}
void OSThread::UnsafeForceTerminateSignal()
{
TeminateOSContext(false);
}
bool OSThread::Run()
{
AU_DEBUG_MEMCRUNCH;
@ -341,7 +336,7 @@ namespace Aurora::Threading::Threads
});
}
void OSThread::Exit()
void OSThread::Terminate()
{
this->PrivateUserDataClear();
@ -351,6 +346,11 @@ namespace Aurora::Threading::Threads
}
}
void OSThread::UnsafeForceTerminateSignal()
{
TeminateOSContext(false);
}
bool OSThread::Exit(bool willReturnToOS, bool isEOL)
{
if (GetThread() == this)
@ -442,7 +442,7 @@ namespace Aurora::Threading::Threads
return this->prio_;
}
AuHwInfo::CpuBitId OSThread::GetMask()
AuHwInfo::CpuBitId OSThread::GetAffinityMask()
{
return this->mask_;
}
@ -457,7 +457,7 @@ namespace Aurora::Threading::Threads
return this->uNameIdentity_;
}
void OSThread::SetAffinity(const HWInfo::CpuBitId &mask)
void OSThread::SetAffinityMask(const HWInfo::CpuBitId &mask)
{
auto zero = HWInfo::CpuBitId();
@ -556,10 +556,11 @@ namespace Aurora::Threading::Threads
/**
* 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.
* arbitrarily use prio levels to (hopefully) order work in the os scheduler.
* Systems without ecores would see a higher prio thread than normal tasks, if
* we do nothing about this condition. On systems without ecores, the efficiency
* throttle should just lock the prio to low, instead of attempting to use prio
* as a localized ecore scheduler hint.
*/
prio = EThreadPriority::ePrioLow;
@ -879,7 +880,7 @@ namespace Aurora::Threading::Threads
}
UpdatePrio(this->throttle_, this->prio_);
SetAffinity(this->mask_);
SetAffinityMask(this->mask_);
AffinityPrioThrottleTickAmendECores();
UpdateName();
}
@ -1510,7 +1511,7 @@ namespace Aurora::Threading::Threads
#endif
}
AuSPtr<AuLoop::ILoopSource> OSThread::AsLoopSource()
AuSPtr<AuLoop::ILoopSource> OSThread::GetShutdownLoopSource()
{
if (!this->terminatedSignalLs_)
{
@ -1524,7 +1525,7 @@ namespace Aurora::Threading::Threads
return this->terminateSignal_;
}
AuSPtr<AuLoop::ILoopSource> OSThread::GetShutdownSignalLS()
AuSPtr<AuLoop::ILoopSource> OSThread::GetShutdownSignalLoopSource()
{
return this->terminateSignalLs_;
}

View File

@ -20,27 +20,26 @@ namespace Aurora::Threading::Threads
OSThread(AuUInt64);
~OSThread();
bool Run() override;
void Exit() override;
bool Exiting() override;
void SendExitSignal() override;
bool Run() override;
void Terminate() override;
void UnsafeForceTerminateSignal() override;
bool Exiting() override;
void SendExitSignal() override;
void UnsafeForceTerminateSignal() override;
void SetPriority(EThreadPriority prio) override;
void SetThrottle(EThreadThrottle prio) override;
void SetAffinity(const HWInfo::CpuBitId &mask) override;
void SetName(const AuString &name) override;
void SetNameIdentity(AuUInt32 uNameIdentity) override;
void SetPriority(EThreadPriority prio) override;
void SetThrottle(EThreadThrottle prio) override;
void SetAffinityMask(const HWInfo::CpuBitId &mask) override;
void SetName(const AuString &name) override;
void SetNameIdentity(AuUInt32 uNameIdentity) override;
EThreadPriority GetPriority() override;
EThreadThrottle GetThrottle() override;
HWInfo::CpuBitId GetMask() override;
AuString GetName() override;
AuUInt32 GetNameIdentity() override;
EThreadPriority GetPriority() override;
EThreadThrottle GetThrottle() override;
HWInfo::CpuBitId GetAffinityMask() override;
AuString GetName() override;
AuUInt32 GetNameIdentity() override;
void ExecuteInDeadThread(AuFunction<void()> callback) override;
AuSPtr<IWaitable> AsWaitable() override;
void AddLastHopeTlsHook(const AuSPtr<Threading::Threads::IThreadFeature> &feature) override;
AuUInt64 SetNoUnwindTerminateExitWatchDogTimeoutInMS(AuUInt64 uMS) override;
@ -52,9 +51,11 @@ namespace Aurora::Threading::Threads
void InitThreadCreateTime();
void _ThreadEP();
AuSPtr<AuLoop::ILoopSource> AsLoopSource() override;
AuSPtr<AuLoop::ILoopSource> GetShutdownSignalLoopSource() override;
AuSPtr<AuLoop::ILoopSource> GetShutdownLoopSource() override;
AuSPtr<IWaitable> GetShutdownWaitable() override;
AuSPtr<IWaitable> GetShutdownSignalWaitable() override;
AuSPtr<AuLoop::ILoopSource> GetShutdownSignalLS() override;
bool InternalKillForceNtfy();
void SignalDeath();

View File

@ -32,7 +32,7 @@ namespace Aurora::Threading::Threads
auto thread = GetThread();
if (thread && gRuntimeRunLevel < 4)
{
thread->Exit();
thread->Terminate();
}
}
}