[*] 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

@ -38,25 +38,61 @@ namespace Aurora::Threading::Threads
struct IAuroraThread struct IAuroraThread
{ {
virtual bool Run() = 0; virtual bool Run() = 0;
virtual void Exit() = 0;
virtual bool Exiting() = 0;
virtual void SendExitSignal() = 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;
/**
* @brief Terminate's force kill path with even less niceness and less waiting around by the caller
*/
virtual void UnsafeForceTerminateSignal() = 0; virtual void UnsafeForceTerminateSignal() = 0;
virtual void SetPriority(EThreadPriority prio) = 0; /**
virtual void SetThrottle(EThreadThrottle throttle) = 0; * @brief Dispatches the shutdown signals (the IO objects, not in the POSIX or NT DPC sense, more APC-like)
virtual void SetAffinity(const HWInfo::CpuBitId &mask) = 0; */
virtual void SetName(const AuString &name) = 0; virtual void SendExitSignal() = 0;
virtual void SetNameIdentity(AuUInt32 uNameIdentity) = 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 EThreadPriority GetPriority() = 0;
virtual void SetThrottle(EThreadThrottle throttle) = 0;
virtual EThreadThrottle GetThrottle() = 0; virtual EThreadThrottle GetThrottle() = 0;
virtual HWInfo::CpuBitId GetMask() = 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; 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; virtual AuUInt32 GetNameIdentity() = 0;
virtual AuUInt64 GetThreadCreationTime(Time::EClock eClock) = 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 // 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] /// Registers a thread feature _not_ calling on init [for now]
@ -64,16 +100,35 @@ namespace Aurora::Threading::Threads
/// Use this to register teardown functions /// Use this to register teardown functions
virtual void AddLastHopeTlsHook(const AuSPtr<Threading::Threads::IThreadFeature> &feature) = 0; 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;
/**
* @brief Read only signal.
*/
virtual AuSPtr<IWaitable> GetShutdownSignalWaitable() = 0; virtual AuSPtr<IWaitable> GetShutdownSignalWaitable() = 0;
virtual AuSPtr<IO::Loop::ILoopSource> GetShutdownSignalLS() = 0;
/**
* @brief Read only signal.
*/
virtual AuSPtr<IO::Loop::ILoopSource> GetShutdownSignalLoopSource() = 0;
/**
* @brief Do not force ::Terminate-like shutdown on release.
*/
virtual void Detach() = 0; 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; virtual void ExecuteInDeadThread(AuFunction<void()> callback) = 0;
AURT_ADD_USR_DATA; AURT_ADD_USR_DATA;

View File

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

View File

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

View File

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

View File

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

View File

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