/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuOSThread.hpp Date: 2021-6-12 Author: Reece ***/ #pragma once #if defined(AURORA_IS_POSIX_DERIVED) #include #if !defined(POSIX_USE_SIGJMP) #define POSIX_USE_SIGJMP 1 #endif #endif namespace Aurora::Threading::Threads { struct OSThread : IAuroraThread { OSThread(); OSThread(const ThreadInfo &info); OSThread(AuUInt64); ~OSThread(); bool Run() override; void Terminate() override; void UnsafeForceTerminateSignal() override; bool Exiting() override; void SendExitSignal() 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 GetAffinityMask() override; AuString GetName() override; AuUInt32 GetNameIdentity() override; void ExecuteInDeadThread(AuFunction callback) override; void AddLastHopeTlsHook(const AuSPtr &feature) override; AuUInt64 SetNoUnwindTerminateExitWatchDogTimeoutInMS(AuUInt64 uMS) override; void Detach() override; AuUInt64 GetThreadCreationTime(Time::EClock eClock) override; void InitThreadCreateTime(); void _ThreadEP(); AuSPtr GetShutdownSignalLoopSource() override; AuSPtr GetShutdownLoopSource() override; AuSPtr GetShutdownWaitable() override; AuSPtr GetShutdownSignalWaitable() override; bool InternalKillForceNtfy(); void SignalDeath(); bool InternalKill(bool locked); void AffinityPrioThrottleTickAmendECores(); // !protected! void MakeMain(); protected: bool Exit(bool willReturnToOS, bool isEOL = false); bool ExecuteNewOSContext(AuFunction task); void UpdatePrio(EThreadThrottle throttle, EThreadPriority prio); void UpdateAffinity(const HWInfo::CpuBitId &mask); void UpdateName(); void OSAttach(); void OSDeatach(); void TeminateOSContext(bool calledFromThis); void TeminateOSContext2(bool calledFromThis); void FreeOSContext(); bool HasValidThreadIdYet(); bool HasValidThreadHandleYet(); void HookReleaseThreadResources(); void HookOnExit(); private: #if defined(AURORA_IS_POSIX_DERIVED) #if defined(POSIX_USE_SIGJMP) && POSIX_USE_SIGJMP == 1 sigjmp_buf env; #else jmp_buf env; #endif #endif Primitives::Mutex tlsLock_; AuUInt32 tls_ {}; OSThread * tlsReferenceThread_ {}; AuString name_; ThreadInfo info_; HWInfo::CpuBitId mask_ = HWInfo::CpuBitId().Not(); HWInfo::CpuBitId throttleMask_ = HWInfo::CpuBitId().Not(); EThreadPriority prio_ = EThreadPriority::ePrioNormal; EThreadThrottle throttle_ = EThreadThrottle::eNormal; bool bSupportsAltKill {}; bool userManagingAffinity_ {}; bool exiting_{}; bool contextUsed_{}; // can this thread instance execute code again? Primitives::EventShared_t terminated_; Primitives::EventShared_t terminateSignal_; struct Lock { bool bLock {}; AuMutex mutex; }; AuSPtr pFlag = AuMakeSharedPanic(); AuSPtr terminateSignalLs_; AuSPtr terminatedSignalLs_; bool bLongJmpOnce {}; AuUInt64 qwExitTimeout { AuSToMS(15) }; bool bNotOwned {}; Primitives::CriticalSection exitOnlyOnce_; AuList> threadFeatures_; AuBinarySemaphore epExecEvent; AuUInt64 uClockCreationTime[3] {}; AuFunction task_; #if defined(AURORA_IS_MODERNNT_DERIVED) HANDLE handle_ = INVALID_HANDLE_VALUE; #elif defined(AURORA_HAS_PTHREADS) pthread_t handle_ {}; #endif AuOptional optUnixThreadId_; bool detached_ {}; AuUInt32 uNameIdentity_ {}; AuCriticalSection metaMutex; }; void InitThreading(); }