AuroraRuntime/Source/Threading/Threads/AuOSThread.cpp

1239 lines
32 KiB
C++
Raw Normal View History

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)
#include <sys/resource.h>
#include <cxxabi.h>
2021-06-27 21:25:29 +00:00
#endif
#if defined(AURORA_HAS_PTHREADS)
#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)
#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)
BOOL (*SetThreadInformation_f)(
HANDLE hThread,
DWORD ThreadInformationClass,
LPVOID ThreadInformation,
DWORD ThreadInformationSize
);
static auto const kThreadPowerThrottling = 3;
struct THREAD_POWER_THROTTLING_STATE2
{
ULONG Version;
ULONG ControlMask;
ULONG StateMask;
};
#endif
2022-11-17 07:46:07 +00:00
#include "AuSpawnThread.hpp"
2021-09-06 10:58:08 +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;
static ThreadInfo gDummyThreadInfo;
2021-09-06 10:58:08 +00:00
#if defined(AURORA_IS_POSIX_DERIVED)
static const auto kSignalAbort = SIGUSR1;
Further Linux support [+] Begin work on IO futexes for io release on process/thread exit [+] Linux ::readdir iteration [+] AuConsole buffering API [*] Fix sleep as to not get interrupted by signals [*] Switch the type of FS lock used under Linux [*] Linux: Use new IPCHandle encoding scheme [*] Fix undefined behaviour: unintialized timeout values (AuLoop/Linux) [*] Fix undefined behaviour: ConsoleTTY clear line was called of a color of a random value on stack [-] Remainings of std dir iterator [*] Fix pthread_kill (aka send signal to pthread handle) always kills process. This is what you expect bc signal handler inheritance. [*] Reformat the build Aurora.json file [+] Added clang warning ignores to the build file [*] Fix: UNIX need to use STDOUT_FILENO. Was using CRT handle in place of fd by mistake. [+] Linux implementation for IO yield (AuIO::IOYield() - UNIX::LinuxOverlappedYield()) [*] Fix: Linux async end of stream processing. res 0 = zero bytes consumed. <= was detecting this as an error of code 0. Should succeed with zero bytes. [+] Linux LoopQueue missing epilogue hook for the IO processor [*] Various refactors and minor bug fixes [*] Linux fix: Handle pipe EOS as zero [*] Linux fix: thread termination via a user signal of 77. Need a force terminate. [*] IPC handle: fix improper int to bool cast in the header setup within ToString [*] Linux fix: HWInfo CPU topology regression [-] Linux fix: remove SIGABRT handler [*] Missing override in compression, exit, and consoletty headers. [+] Unix Syslog logger backend
2022-08-02 04:52:17 +00:00
static void HandleSigAbortThread(int a)
{
((OSThread *)HandleCurrent())->InternalKillForceNtfy();
Further Linux support [+] Begin work on IO futexes for io release on process/thread exit [+] Linux ::readdir iteration [+] AuConsole buffering API [*] Fix sleep as to not get interrupted by signals [*] Switch the type of FS lock used under Linux [*] Linux: Use new IPCHandle encoding scheme [*] Fix undefined behaviour: unintialized timeout values (AuLoop/Linux) [*] Fix undefined behaviour: ConsoleTTY clear line was called of a color of a random value on stack [-] Remainings of std dir iterator [*] Fix pthread_kill (aka send signal to pthread handle) always kills process. This is what you expect bc signal handler inheritance. [*] Reformat the build Aurora.json file [+] Added clang warning ignores to the build file [*] Fix: UNIX need to use STDOUT_FILENO. Was using CRT handle in place of fd by mistake. [+] Linux implementation for IO yield (AuIO::IOYield() - UNIX::LinuxOverlappedYield()) [*] Fix: Linux async end of stream processing. res 0 = zero bytes consumed. <= was detecting this as an error of code 0. Should succeed with zero bytes. [+] Linux LoopQueue missing epilogue hook for the IO processor [*] Various refactors and minor bug fixes [*] Linux fix: Handle pipe EOS as zero [*] Linux fix: thread termination via a user signal of 77. Need a force terminate. [*] IPC handle: fix improper int to bool cast in the header setup within ToString [*] Linux fix: HWInfo CPU topology regression [-] Linux fix: remove SIGABRT handler [*] Missing override in compression, exit, and consoletty headers. [+] Unix Syslog logger backend
2022-08-02 04:52:17 +00:00
SysPanic("Couldn't terminate thread context");
}
Further Linux support [+] Begin work on IO futexes for io release on process/thread exit [+] Linux ::readdir iteration [+] AuConsole buffering API [*] Fix sleep as to not get interrupted by signals [*] Switch the type of FS lock used under Linux [*] Linux: Use new IPCHandle encoding scheme [*] Fix undefined behaviour: unintialized timeout values (AuLoop/Linux) [*] Fix undefined behaviour: ConsoleTTY clear line was called of a color of a random value on stack [-] Remainings of std dir iterator [*] Fix pthread_kill (aka send signal to pthread handle) always kills process. This is what you expect bc signal handler inheritance. [*] Reformat the build Aurora.json file [+] Added clang warning ignores to the build file [*] Fix: UNIX need to use STDOUT_FILENO. Was using CRT handle in place of fd by mistake. [+] Linux implementation for IO yield (AuIO::IOYield() - UNIX::LinuxOverlappedYield()) [*] Fix: Linux async end of stream processing. res 0 = zero bytes consumed. <= was detecting this as an error of code 0. Should succeed with zero bytes. [+] Linux LoopQueue missing epilogue hook for the IO processor [*] Various refactors and minor bug fixes [*] Linux fix: Handle pipe EOS as zero [*] Linux fix: thread termination via a user signal of 77. Need a force terminate. [*] IPC handle: fix improper int to bool cast in the header setup within ToString [*] Linux fix: HWInfo CPU topology regression [-] Linux fix: remove SIGABRT handler [*] Missing override in compression, exit, and consoletty headers. [+] Unix Syslog logger backend
2022-08-02 04:52:17 +00:00
#endif
OSThread::OSThread(const ThreadInfo &info) : info_(info)
2021-06-27 21:25:29 +00:00
{
this->name_ = info.name.value_or("Aurora Thread");
this->terminated_ = Primitives::EventShared(true, false, true);
// maybe we should atomic exchange compare these when needed frogthink
this->terminateSignal_ = Primitives::EventShared(true, false, true);
this->terminatedSignalLs_ = AuLoop::NewLSEvent(true, false, true);
this->terminateSignalLs_ = AuLoop::NewLSEvent(true, false, true);
this->exitOnlyOnce_ = Primitives::CriticalSectionUnique();
SysAssert(this->terminated_ ? true : false, "out of memory");
2021-06-27 21:25:29 +00:00
}
2021-09-06 10:58:08 +00:00
OSThread::OSThread() : info_(gDummyThreadInfo)
2021-06-27 21:25:29 +00:00
{
this->name_ = "Main Thread";
this->terminated_ = Primitives::EventShared(true, false);
this->exitOnlyOnce_ = Primitives::CriticalSectionUnique();
2021-06-27 21:25:29 +00:00
}
2021-09-06 10:58:08 +00:00
OSThread::OSThread(AuUInt64 id) : info_(gDummyThreadInfo)
2021-06-27 21:25:29 +00:00
{
this->name_ = "System Thread";
this->handle_ = reinterpret_cast<decltype(handle_)>(id);
Further Linux support [+] Begin work on IO futexes for io release on process/thread exit [+] Linux ::readdir iteration [+] AuConsole buffering API [*] Fix sleep as to not get interrupted by signals [*] Switch the type of FS lock used under Linux [*] Linux: Use new IPCHandle encoding scheme [*] Fix undefined behaviour: unintialized timeout values (AuLoop/Linux) [*] Fix undefined behaviour: ConsoleTTY clear line was called of a color of a random value on stack [-] Remainings of std dir iterator [*] Fix pthread_kill (aka send signal to pthread handle) always kills process. This is what you expect bc signal handler inheritance. [*] Reformat the build Aurora.json file [+] Added clang warning ignores to the build file [*] Fix: UNIX need to use STDOUT_FILENO. Was using CRT handle in place of fd by mistake. [+] Linux implementation for IO yield (AuIO::IOYield() - UNIX::LinuxOverlappedYield()) [*] Fix: Linux async end of stream processing. res 0 = zero bytes consumed. <= was detecting this as an error of code 0. Should succeed with zero bytes. [+] Linux LoopQueue missing epilogue hook for the IO processor [*] Various refactors and minor bug fixes [*] Linux fix: Handle pipe EOS as zero [*] Linux fix: thread termination via a user signal of 77. Need a force terminate. [*] IPC handle: fix improper int to bool cast in the header setup within ToString [*] Linux fix: HWInfo CPU topology regression [-] Linux fix: remove SIGABRT handler [*] Missing override in compression, exit, and consoletty headers. [+] Unix Syslog logger backend
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()
{
bool bDetached {};
bool bDetachedSuccess {};
Further Linux support [+] Begin work on IO futexes for io release on process/thread exit [+] Linux ::readdir iteration [+] AuConsole buffering API [*] Fix sleep as to not get interrupted by signals [*] Switch the type of FS lock used under Linux [*] Linux: Use new IPCHandle encoding scheme [*] Fix undefined behaviour: unintialized timeout values (AuLoop/Linux) [*] Fix undefined behaviour: ConsoleTTY clear line was called of a color of a random value on stack [-] Remainings of std dir iterator [*] Fix pthread_kill (aka send signal to pthread handle) always kills process. This is what you expect bc signal handler inheritance. [*] Reformat the build Aurora.json file [+] Added clang warning ignores to the build file [*] Fix: UNIX need to use STDOUT_FILENO. Was using CRT handle in place of fd by mistake. [+] Linux implementation for IO yield (AuIO::IOYield() - UNIX::LinuxOverlappedYield()) [*] Fix: Linux async end of stream processing. res 0 = zero bytes consumed. <= was detecting this as an error of code 0. Should succeed with zero bytes. [+] Linux LoopQueue missing epilogue hook for the IO processor [*] Various refactors and minor bug fixes [*] Linux fix: Handle pipe EOS as zero [*] Linux fix: thread termination via a user signal of 77. Need a force terminate. [*] IPC handle: fix improper int to bool cast in the header setup within ToString [*] Linux fix: HWInfo CPU topology regression [-] Linux fix: remove SIGABRT handler [*] Missing override in compression, exit, and consoletty headers. [+] Unix Syslog logger backend
2022-08-02 04:52:17 +00:00
if (this->bNotOwned)
{
#if defined(AURORA_IS_MODERNNT_DERIVED)
auto hHandle = (HANDLE)this->handle_;
AuWin32CloseHandle(hHandle);
#endif
Further Linux support [+] Begin work on IO futexes for io release on process/thread exit [+] Linux ::readdir iteration [+] AuConsole buffering API [*] Fix sleep as to not get interrupted by signals [*] Switch the type of FS lock used under Linux [*] Linux: Use new IPCHandle encoding scheme [*] Fix undefined behaviour: unintialized timeout values (AuLoop/Linux) [*] Fix undefined behaviour: ConsoleTTY clear line was called of a color of a random value on stack [-] Remainings of std dir iterator [*] Fix pthread_kill (aka send signal to pthread handle) always kills process. This is what you expect bc signal handler inheritance. [*] Reformat the build Aurora.json file [+] Added clang warning ignores to the build file [*] Fix: UNIX need to use STDOUT_FILENO. Was using CRT handle in place of fd by mistake. [+] Linux implementation for IO yield (AuIO::IOYield() - UNIX::LinuxOverlappedYield()) [*] Fix: Linux async end of stream processing. res 0 = zero bytes consumed. <= was detecting this as an error of code 0. Should succeed with zero bytes. [+] Linux LoopQueue missing epilogue hook for the IO processor [*] Various refactors and minor bug fixes [*] Linux fix: Handle pipe EOS as zero [*] Linux fix: thread termination via a user signal of 77. Need a force terminate. [*] IPC handle: fix improper int to bool cast in the header setup within ToString [*] Linux fix: HWInfo CPU topology regression [-] Linux fix: remove SIGABRT handler [*] Missing override in compression, exit, and consoletty headers. [+] Unix Syslog logger backend
2022-08-02 04:52:17 +00:00
return;
}
if (!gGlobal.bActive)
2022-04-02 00:48:29 +00:00
{
return;
}
#if 0
if (DeadTest())
2022-04-02 00:48:29 +00:00
{
return;
}
#endif
if (this->contextUsed_)
2021-06-27 21:25:29 +00:00
{
if (this->detached_)
{
bDetached = true;
}
else
2021-10-25 18:19:49 +00:00
{
if (gRuntimeRunLevel <= 3)
{
Exit();
}
else if (gRuntimeRunLevel >= 5)
{
// Application is dead
}
else
{
if (this->terminated_)
{
this->exiting_ = true;
if (WaitFor(this->terminated_.get(), 5000))
{
return;
}
}
// Kill the current OS thread instance
TeminateOSContext(false);
if (this->exitOnlyOnce_)
{
this->exitOnlyOnce_->Unlock();
}
#if defined(AURORA_IS_POSIX_DERIVED)
if (this->terminated_)
{
WaitFor(this->terminated_.get());
}
#endif
}
2021-10-25 18:19:49 +00:00
}
2021-06-27 21:25:29 +00:00
}
2021-09-06 10:58:08 +00:00
this->terminated_.reset();
2021-06-27 21:25:29 +00:00
FreeOSContext();
if (bDetached)
{
if (this->tlsReferenceThread_)
{
AU_LOCK_GUARD(this->tlsLock_);
AU_LOCK_GUARD(this->tlsReferenceThread_->tlsLock_);
2022-01-19 17:08:13 +00:00
AuExchange(this->tlsReferenceThread_->tls_, this->tls_);
AuExchange(this->tlsReferenceThread_->threadFeatures_, this->threadFeatures_);
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()
{
tls_.reset();
2021-09-06 10:58:08 +00:00
for (const auto &feature : this->threadFeatures_)
2021-09-06 10:58:08 +00:00
{
feature->Cleanup();
}
}
void OSThread::AddLastHopeTlsHook(const AuSPtr<AuThreads::IThreadFeature> &feature)
2021-09-06 10:58:08 +00:00
{
// TODO: mutex
if (!feature)
{
return;
}
AuTryInsert(this->threadFeatures_, feature);
2021-06-27 21:25:29 +00:00
}
2021-10-25 18:19:49 +00:00
void OSThread::Detach()
{
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
{
return this->terminated_;
2021-06-27 21:25:29 +00:00
}
void OSThread::SendExitSignal()
{
this->exiting_ = true;
if (this->terminateSignalLs_)
{
this->terminateSignalLs_->Set();
}
if (this->terminateSignal_)
{
this->terminateSignal_->Set();
}
2021-06-27 21:25:29 +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
{
if (!this->terminated_)
2021-06-27 21:25:29 +00:00
{
SysPanic("::Run called on system thread");
}
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
}
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
{
// this functional backends are being deprecated
if (this->info_.callbacks)
{
this->info_.callbacks->OnEntry(this);
}
2021-06-27 21:25:29 +00:00
}
catch (...)
{
Debug::PrintError();
}
});
}
void OSThread::Exit()
{
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)
{
YieldToOtherThread();
}
}
}
else
{
// exit signal
this->exiting_ = true;
2021-06-27 21:25:29 +00:00
if (!this->terminated_)
2021-06-27 21:25:29 +00:00
{
return true;
}
if (!this->exitOnlyOnce_)
{
return true;
}
2021-06-27 21:25:29 +00:00
// attempt to join with the thread once it has exited, or timeout
if (WaitFor(this->terminated_.get(), 15 * 1000))
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
if (!this->exitOnlyOnce_->TryLock())
2021-06-27 21:25:29 +00:00
{
AuLogWarn("Watchdog error - OS thread context didn't finish in 15 seconds, but he should exiting now.");
2021-06-27 21:25:29 +00:00
return false;
}
AuLogWarn("Watchdog error - OS thread context didn't finish in 15 seconds, forcefully terminating without a watchdog overlooking onExit");
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);
});
this->exitOnlyOnce_->Unlock();
2021-06-27 21:25:29 +00:00
}
return true;
}
bool OSThread::Exiting()
{
return this->exiting_;
2021-06-27 21:25:29 +00:00
}
void OSThread::SetName(const AuString &name)
{
this->name_ = name;
this->UpdateName();
2021-06-27 21:25:29 +00:00
}
EThreadThrottle OSThread::GetThrottle()
{
return this->throttle_;
}
EThreadPriority OSThread::GetPriority()
2021-06-27 21:25:29 +00:00
{
return this->prio_;
2021-06-27 21:25:29 +00:00
}
AuHwInfo::CpuBitId OSThread::GetMask()
2021-06-27 21:25:29 +00:00
{
return this->mask_;
2021-06-27 21:25:29 +00:00
}
AuString OSThread::GetName()
{
return this->name_;
2021-06-27 21:25:29 +00:00
}
void OSThread::SetAffinity(const HWInfo::CpuBitId &mask)
2021-06-27 21:25:29 +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;
this->userManagingAffinity_ = false;
UpdatePrio(this->throttle_, this->prio_);
}
else
{
this->mask_ = mask;
this->userManagingAffinity_ = true;
}
UpdateAffinity(this->mask_);
AffinityPrioThrottleTickAmendECores();
2021-06-27 21:25:29 +00:00
}
void OSThread::SetPriority(EThreadPriority prio)
2021-06-27 21:25:29 +00:00
{
if (!EThreadPriorityIsValid(prio))
{
return;
}
UpdatePrio(this->throttle_, prio);
AffinityPrioThrottleTickAmendECores();
}
void OSThread::SetThrottle(EThreadThrottle throttle)
{
if (!EThreadThrottleIsValid(throttle))
{
return;
}
this->throttle_ = throttle;
UpdatePrio(this->throttle_, this->prio_);
AffinityPrioThrottleTickAmendECores();
2021-06-27 21:25:29 +00:00
}
AuSPtr<TLSView> OSThread::GetTlsView()
{
if (!this->tls_)
2021-06-27 21:25:29 +00:00
{
this->tls_ = AuMakeShared<TLSViewImpl>();
2021-06-27 21:25:29 +00:00
}
return this->tls_;
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
{
this->task_ = task;
2021-06-27 21:25:29 +00:00
this->handle_ = 0;
auto ret = SpawnThread([this]()
2021-09-06 10:58:08 +00:00
{
while ((!this->handle_) ||
#if defined(INVALID_HANDLE_VALUE)
(this->handle_ == INVALID_HANDLE_VALUE)
#endif
)
{
AuThreading::ContextYield();
}
this->_ThreadEP();
}, GetName(), this->info_.stackSize);
if (ret.first)
2021-09-06 10:58: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
return ret.first;
2021-06-27 21:25:29 +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);
}
}
2021-06-27 21:25:29 +00:00
void OSThread::_ThreadEP()
{
// Poke TLS reference thread entity
// TODO: we need an internal OSThread *TryPokeTLSThread()
auto osThread = static_cast<OSThread *>(GetThread());
this->tlsReferenceThread_ = osThread;
bool bFailing {};
2021-10-25 18:19:49 +00:00
OSAttach();
#if defined(AURORA_IS_POSIX_DERIVED)
this->bLongJmpOnce = false;
if (setjmp(env) != 0)
{
Exit(true);
return;
}
#endif
try
{
Further Linux support [+] Begin work on IO futexes for io release on process/thread exit [+] Linux ::readdir iteration [+] AuConsole buffering API [*] Fix sleep as to not get interrupted by signals [*] Switch the type of FS lock used under Linux [*] Linux: Use new IPCHandle encoding scheme [*] Fix undefined behaviour: unintialized timeout values (AuLoop/Linux) [*] Fix undefined behaviour: ConsoleTTY clear line was called of a color of a random value on stack [-] Remainings of std dir iterator [*] Fix pthread_kill (aka send signal to pthread handle) always kills process. This is what you expect bc signal handler inheritance. [*] Reformat the build Aurora.json file [+] Added clang warning ignores to the build file [*] Fix: UNIX need to use STDOUT_FILENO. Was using CRT handle in place of fd by mistake. [+] Linux implementation for IO yield (AuIO::IOYield() - UNIX::LinuxOverlappedYield()) [*] Fix: Linux async end of stream processing. res 0 = zero bytes consumed. <= was detecting this as an error of code 0. Should succeed with zero bytes. [+] Linux LoopQueue missing epilogue hook for the IO processor [*] Various refactors and minor bug fixes [*] Linux fix: Handle pipe EOS as zero [*] Linux fix: thread termination via a user signal of 77. Need a force terminate. [*] IPC handle: fix improper int to bool cast in the header setup within ToString [*] Linux fix: HWInfo CPU topology regression [-] Linux fix: remove SIGABRT handler [*] Missing override in compression, exit, and consoletty headers. [+] Unix Syslog logger backend
2022-08-02 04:52:17 +00:00
if (task_)
{
task_();
}
}
#if !defined(AURORA_IS_POSIX_DERIVED)
catch (...)
{
SysPushErrorHAL("OS Thread Aborted");
}
2021-06-27 21:25:29 +00:00
Exit(true);
#else
#if defined(AURORA_COMPILER_GCC)
catch (abi::__forced_unwind&)
{
throw;
}
#endif
catch (...)
{
bFailing = true;
if (!Aurora::kIsDebugBuild)
{
SysPushErrorHAL("OS Thread Aborted");
}
// "Safer" update
this->HookOnExit();
if (this->terminated_)
{
if (this->exitOnlyOnce_)
{
this->exitOnlyOnce_->Unlock();
}
this->terminated_->Set();
}
if (this->terminatedSignalLs_)
{
this->terminatedSignalLs_->Set();
}
}
if (!bFailing)
{
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
}
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();
}
}
void OSThread::UpdateName()
{
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();
info.dwThreadID = ::GetThreadId(this->handle_);
info.dwFlags = 0;
auto raise = AuStaticCast<void(__cdecl *)(THREADNAME_INFO &)>([](THREADNAME_INFO &info)
2022-03-16 16:34:55 +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
{
2022-03-16 16:34:55 +00:00
static HRESULT(WINAPI * SetThreadDescription_f)(HANDLE, PCWSTR);
if (!SetThreadDescription_f)
{
#if !defined(AURORA_PLATFORM_WIN32)
SetThreadDescription_f = SetThreadDescription;
#else
2022-03-16 16:34:55 +00:00
SetThreadDescription_f = AuReinterpretCast<decltype(SetThreadDescription_f)>(GetProcAddress(GetModuleHandleW(L"Kernel32.dll"), "SetThreadDescription"));
#endif
2022-03-16 16:34:55 +00:00
}
if (SetThreadDescription_f)
{
SetThreadDescription_f(this->handle_, AuLocale::ConvertFromUTF8(this->name_).c_str());
}
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)
pthread_setname_np(this->handle_, this->name_.c_str());
2021-06-27 21:25:29 +00:00
#endif
}
static void AttachSignalKiller()
{
#if defined(AURORA_IS_POSIX_DERIVED)
struct sigaction action =
{
.sa_handler = HandleSigAbortThread,
};
::sigemptyset(&action.sa_mask);
::sigaction(kSignalAbort, &action, nullptr);
#endif
}
2021-10-25 18:19:49 +00:00
void OSThread::OSAttach()
2021-06-27 21:25:29 +00:00
{
Further Linux support [+] Begin work on IO futexes for io release on process/thread exit [+] Linux ::readdir iteration [+] AuConsole buffering API [*] Fix sleep as to not get interrupted by signals [*] Switch the type of FS lock used under Linux [*] Linux: Use new IPCHandle encoding scheme [*] Fix undefined behaviour: unintialized timeout values (AuLoop/Linux) [*] Fix undefined behaviour: ConsoleTTY clear line was called of a color of a random value on stack [-] Remainings of std dir iterator [*] Fix pthread_kill (aka send signal to pthread handle) always kills process. This is what you expect bc signal handler inheritance. [*] Reformat the build Aurora.json file [+] Added clang warning ignores to the build file [*] Fix: UNIX need to use STDOUT_FILENO. Was using CRT handle in place of fd by mistake. [+] Linux implementation for IO yield (AuIO::IOYield() - UNIX::LinuxOverlappedYield()) [*] Fix: Linux async end of stream processing. res 0 = zero bytes consumed. <= was detecting this as an error of code 0. Should succeed with zero bytes. [+] Linux LoopQueue missing epilogue hook for the IO processor [*] Various refactors and minor bug fixes [*] Linux fix: Handle pipe EOS as zero [*] Linux fix: thread termination via a user signal of 77. Need a force terminate. [*] IPC handle: fix improper int to bool cast in the header setup within ToString [*] Linux fix: HWInfo CPU topology regression [-] Linux fix: remove SIGABRT handler [*] Missing override in compression, exit, and consoletty headers. [+] Unix Syslog logger backend
2022-08-02 04:52:17 +00:00
this->bSupportsAltKill = true;
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
UpdatePrio(this->throttle_, this->prio_);
SetAffinity(this->mask_);
AffinityPrioThrottleTickAmendECores();
2021-06-27 21:25:29 +00:00
UpdateName();
AttachSignalKiller();
2021-06-27 21:25:29 +00:00
}
static AuHashMap<EThreadPriority, int> kNiceMap
2021-06-27 21:25:29 +00:00
{
{
EThreadPriority::ePrioRT, -19
2021-06-27 21:25:29 +00:00
},
{
EThreadPriority::ePrioAboveHigh, -19
2021-06-27 21:25:29 +00:00
},
{
EThreadPriority::ePrioHigh, -11
2021-06-27 21:25:29 +00:00
},
{
EThreadPriority::ePrioNormal, -2
2021-06-27 21:25:29 +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)
static const AuHashMap<EThreadPriority, int> kWin32Map
2021-06-27 21:25:29 +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
},
{
AuMakePair(EThreadThrottle::ePerformance, EThreadPriority::ePrioNormal), AuMakePair(DISPATCH_QUEUE_PRIORITY_HIGH, 0)
2021-06-27 21:25:29 +00:00
},
{
AuMakePair(EThreadThrottle::ePerformance, EThreadPriority::ePrioLow), AuMakePair(DISPATCH_QUEUE_PRIORITY_DEFAULT, 1)
2021-06-27 21:25:29 +00:00
},
{
AuMakePair(EThreadThrottle::ePerformance, EThreadPriority::ePrioLowest), AuMakePair(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
2021-06-27 21:25:29 +00:00
},
// Efficient
2021-06-27 21:25:29 +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
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
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;
}
if (!SetThreadPriority(this->handle_, *val))
{
SysPushErrorHAL("Couldn't update thread priority");
}
2022-12-14 01:35:18 +00:00
THREAD_POWER_THROTTLING_STATE2 throttlingState {};
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;
}
2022-12-14 01:35:18 +00:00
if (SetThreadInformation_f)
{
SetThreadInformation_f(this->handle_,
kThreadPowerThrottling,
&throttlingState,
sizeof(throttlingState));
2022-12-14 01:35:18 +00:00
}
//#elif defined(AURORA_IS_XNU_DERIVED)
2021-06-27 21:25:29 +00:00
#elif defined(AURORA_HAS_PTHREADS)
if (!this->handle_)
2021-06-27 21:25:29 +00:00
{
return;
}
if (prio == EThreadPriority::ePrioRT)
2021-06-27 21:25:29 +00:00
{
sched_param param {};
param.sched_priority = sched_get_priority_min(SCHED_RR);
if (pthread_setschedparam(this->handle_, SCHED_RR, &param) == 0)
2021-06-27 21:25:29 +00:00
{
return;
}
// fall through on error
}
else if (this->prio_ == EThreadPriority::ePrioRT)
{
int policyNonRT =
#if defined(AURORA_IS_XNU_DERIVED)
SCHED_FIFO;
#else
SCHED_OTHER;
#endif
sched_param param {};
param.sched_priority = sched_get_priority_min(policyNonRT);
pthread_setschedparam(this->handle_, policyNonRT, &param);
}
2021-06-27 21:25:29 +00:00
const int *val;
2021-09-06 10:58:08 +00:00
if (!AuTryFind(kNiceMap, prio, val))
2021-06-27 21:25:29 +00:00
{
return;
}
if (auto tid = unixThreadId_)
{
// TODO: per thread beaviour is a linux bug
setpriority(PRIO_PROCESS, tid, *val);
2021-06-27 21:25:29 +00:00
}
#endif
#if defined(AURORA_IS_LINUX_DERIVED) || defined(AURORA_IS_BSD_DERIVED)
switch (throttle)
{
case EThreadThrottle::eNormal:
this->throttleMask_ = AuHwInfo::GetCPUInfo().maskAllCores;
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_);
#endif
this->prio_ = prio;
2021-06-27 21:25:29 +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)
if (this->handle_ == INVALID_HANDLE_VALUE)
{
return;
}
if ((AuBuild::kCurrentPlatform != AuBuild::EPlatform::ePlatformWin32) ||
(AuSwInfo::IsWindows10OrGreater()))
{
static BOOL(WINAPI * SetThreadSelectedCpuSets_f)(HANDLE, const ULONG *, ULONG);
if (!SetThreadSelectedCpuSets_f)
{
#if !defined(AURORA_PLATFORM_WIN32)
SetThreadSelectedCpuSets_f = SetThreadSelectedCpuSets;
#else
SetThreadSelectedCpuSets_f = AuReinterpretCast<decltype(SetThreadSelectedCpuSets_f)>(GetProcAddress(GetModuleHandleW(L"Kernel32.dll"), "SetThreadSelectedCpuSets"));
#endif
}
2022-04-10 16:18:21 +00:00
auto sets = mask.CpuBitCount() ?
mask.ToCpuSets() :
AuHwInfo::GetCPUInfo().maskAllCores.ToCpuSets();
if (SetThreadSelectedCpuSets_f)
{
if (SetThreadSelectedCpuSets_f(this->handle_, sets.data(), sets.size()))
{
return;
}
SysPushErrorUnavailableError("SetThreadSelectedCpuSets is expected on modern NT (CoreOS?) excluding Windows; or Win10+");
}
}
#if defined(AURORA_PLATFORM_WIN32)
GROUP_AFFINITY affinityGroup {0};
mask.ToMsWin7GroupAffinity(&affinityGroup);
if (SetThreadGroupAffinity(this->handle_, &affinityGroup, nullptr))
2021-06-27 21:25:29 +00:00
{
return;
}
#endif
SysPushErrorUnavailableError("Couldn't set thread affinity");
return;
#elif defined(AURORA_HAS_PTHREADS)
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;
break;
case EThreadThrottle::ePerformance:
mask2 = AuHwInfo::GetCPUInfo().maskPCores;
break;
case EThreadThrottle::eEfficient:
mask2 = AuHwInfo::GetCPUInfo().maskECores;
break;
}
}
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
AuUInt8 index {};
while (mask2.CpuBitScanForward(index, index))
{
CPU_SET(index, &cpuset);
index++;
}
2022-04-06 06:25:34 +00:00
if (!CPU_COUNT(&cpuset))
{
return;
}
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
{
#if defined(AURORA_IS_POSIX_DERIVED)
Further Linux support [+] Begin work on IO futexes for io release on process/thread exit [+] Linux ::readdir iteration [+] AuConsole buffering API [*] Fix sleep as to not get interrupted by signals [*] Switch the type of FS lock used under Linux [*] Linux: Use new IPCHandle encoding scheme [*] Fix undefined behaviour: unintialized timeout values (AuLoop/Linux) [*] Fix undefined behaviour: ConsoleTTY clear line was called of a color of a random value on stack [-] Remainings of std dir iterator [*] Fix pthread_kill (aka send signal to pthread handle) always kills process. This is what you expect bc signal handler inheritance. [*] Reformat the build Aurora.json file [+] Added clang warning ignores to the build file [*] Fix: UNIX need to use STDOUT_FILENO. Was using CRT handle in place of fd by mistake. [+] Linux implementation for IO yield (AuIO::IOYield() - UNIX::LinuxOverlappedYield()) [*] Fix: Linux async end of stream processing. res 0 = zero bytes consumed. <= was detecting this as an error of code 0. Should succeed with zero bytes. [+] Linux LoopQueue missing epilogue hook for the IO processor [*] Various refactors and minor bug fixes [*] Linux fix: Handle pipe EOS as zero [*] Linux fix: thread termination via a user signal of 77. Need a force terminate. [*] IPC handle: fix improper int to bool cast in the header setup within ToString [*] Linux fix: HWInfo CPU topology regression [-] Linux fix: remove SIGABRT handler [*] Missing override in compression, exit, and consoletty headers. [+] Unix Syslog logger backend
2022-08-02 04:52:17 +00:00
struct sigaction action =
{
.sa_handler = SIG_DFL
};
::sigemptyset(&action.sa_mask);
::sigaction(kSignalAbort, &action, nullptr);
#endif
2021-06-27 21:25:29 +00:00
}
bool OSThread::InternalKill(bool locked)
{
if (this->terminated_)
2021-06-27 21:25:29 +00:00
{
if (!locked)
{
if (!this->exitOnlyOnce_)
{
return true;
}
if (!this->exitOnlyOnce_->TryLock())
2021-06-27 21:25:29 +00:00
{
return false;
}
}
}
HookOnExit();
try
2021-06-27 21:25:29 +00:00
{
// dispatch kill callback
if (this->info_.callbacks)
2021-06-27 21:25:29 +00:00
{
this->info_.callbacks->OnExit(this);
2021-06-27 21:25:29 +00:00
}
}
catch (...)
{
Debug::PrintError();
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");
Telemetry::Mayday();
}
2021-06-27 21:25:29 +00:00
HookReleaseThreadResources();
if (this->terminatedSignalLs_)
{
this->terminatedSignalLs_->Set();
2021-06-27 21:25:29 +00:00
}
2023-02-11 19:37:30 +00:00
if (this->terminated_)
{
this->exitOnlyOnce_->Unlock();
this->terminated_->Set(); // must be set last, after which point we cannot use this!
}
2021-06-27 21:25:29 +00:00
return true;
}
bool OSThread::InternalKillForceNtfy()
{
if (this->terminated_)
{
if (this->exitOnlyOnce_)
{
this->exitOnlyOnce_->Unlock();
}
this->terminated_->Set();
}
if (this->terminatedSignalLs_)
{
this->terminatedSignalLs_->Set();
}
// Great C++ ABI guys...
#if defined(AURORA_HAS_PTHREADS)
{
if (gettid() == getpid())
{
AuProcess::Exit(0);
return true;
}
::longjmp(env, 1);
}
::pthread_exit(nullptr);
#endif
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
if (this->handle_ == INVALID_HANDLE_VALUE)
2021-06-27 21:25:29 +00:00
{
return;
}
if (calledFromThis)
{
::ExitThread(0);
2021-06-27 21:25:29 +00:00
}
else
{
::TerminateThread(this->handle_, 0);
2021-06-27 21:25:29 +00:00
}
#elif defined(AURORA_HAS_PTHREADS)
if (calledFromThis)
Further Linux support [+] Begin work on IO futexes for io release on process/thread exit [+] Linux ::readdir iteration [+] AuConsole buffering API [*] Fix sleep as to not get interrupted by signals [*] Switch the type of FS lock used under Linux [*] Linux: Use new IPCHandle encoding scheme [*] Fix undefined behaviour: unintialized timeout values (AuLoop/Linux) [*] Fix undefined behaviour: ConsoleTTY clear line was called of a color of a random value on stack [-] Remainings of std dir iterator [*] Fix pthread_kill (aka send signal to pthread handle) always kills process. This is what you expect bc signal handler inheritance. [*] Reformat the build Aurora.json file [+] Added clang warning ignores to the build file [*] Fix: UNIX need to use STDOUT_FILENO. Was using CRT handle in place of fd by mistake. [+] Linux implementation for IO yield (AuIO::IOYield() - UNIX::LinuxOverlappedYield()) [*] Fix: Linux async end of stream processing. res 0 = zero bytes consumed. <= was detecting this as an error of code 0. Should succeed with zero bytes. [+] Linux LoopQueue missing epilogue hook for the IO processor [*] Various refactors and minor bug fixes [*] Linux fix: Handle pipe EOS as zero [*] Linux fix: thread termination via a user signal of 77. Need a force terminate. [*] IPC handle: fix improper int to bool cast in the header setup within ToString [*] Linux fix: HWInfo CPU topology regression [-] Linux fix: remove SIGABRT handler [*] Missing override in compression, exit, and consoletty headers. [+] Unix Syslog logger backend
2022-08-02 04:52:17 +00:00
{
::longjmp(env, 1);
::pthread_exit(nullptr);
Further Linux support [+] Begin work on IO futexes for io release on process/thread exit [+] Linux ::readdir iteration [+] AuConsole buffering API [*] Fix sleep as to not get interrupted by signals [*] Switch the type of FS lock used under Linux [*] Linux: Use new IPCHandle encoding scheme [*] Fix undefined behaviour: unintialized timeout values (AuLoop/Linux) [*] Fix undefined behaviour: ConsoleTTY clear line was called of a color of a random value on stack [-] Remainings of std dir iterator [*] Fix pthread_kill (aka send signal to pthread handle) always kills process. This is what you expect bc signal handler inheritance. [*] Reformat the build Aurora.json file [+] Added clang warning ignores to the build file [*] Fix: UNIX need to use STDOUT_FILENO. Was using CRT handle in place of fd by mistake. [+] Linux implementation for IO yield (AuIO::IOYield() - UNIX::LinuxOverlappedYield()) [*] Fix: Linux async end of stream processing. res 0 = zero bytes consumed. <= was detecting this as an error of code 0. Should succeed with zero bytes. [+] Linux LoopQueue missing epilogue hook for the IO processor [*] Various refactors and minor bug fixes [*] Linux fix: Handle pipe EOS as zero [*] Linux fix: thread termination via a user signal of 77. Need a force terminate. [*] IPC handle: fix improper int to bool cast in the header setup within ToString [*] Linux fix: HWInfo CPU topology regression [-] Linux fix: remove SIGABRT handler [*] Missing override in compression, exit, and consoletty headers. [+] Unix Syslog logger backend
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)
{
::pthread_kill(this->handle_, kSignalAbort);
Further Linux support [+] Begin work on IO futexes for io release on process/thread exit [+] Linux ::readdir iteration [+] AuConsole buffering API [*] Fix sleep as to not get interrupted by signals [*] Switch the type of FS lock used under Linux [*] Linux: Use new IPCHandle encoding scheme [*] Fix undefined behaviour: unintialized timeout values (AuLoop/Linux) [*] Fix undefined behaviour: ConsoleTTY clear line was called of a color of a random value on stack [-] Remainings of std dir iterator [*] Fix pthread_kill (aka send signal to pthread handle) always kills process. This is what you expect bc signal handler inheritance. [*] Reformat the build Aurora.json file [+] Added clang warning ignores to the build file [*] Fix: UNIX need to use STDOUT_FILENO. Was using CRT handle in place of fd by mistake. [+] Linux implementation for IO yield (AuIO::IOYield() - UNIX::LinuxOverlappedYield()) [*] Fix: Linux async end of stream processing. res 0 = zero bytes consumed. <= was detecting this as an error of code 0. Should succeed with zero bytes. [+] Linux LoopQueue missing epilogue hook for the IO processor [*] Various refactors and minor bug fixes [*] Linux fix: Handle pipe EOS as zero [*] Linux fix: thread termination via a user signal of 77. Need a force terminate. [*] IPC handle: fix improper int to bool cast in the header setup within ToString [*] Linux fix: HWInfo CPU topology regression [-] Linux fix: remove SIGABRT handler [*] Missing override in compression, exit, and consoletty headers. [+] Unix Syslog logger backend
2022-08-02 04:52:17 +00:00
}
else
{
::pthread_cancel(this->handle_);
Further Linux support [+] Begin work on IO futexes for io release on process/thread exit [+] Linux ::readdir iteration [+] AuConsole buffering API [*] Fix sleep as to not get interrupted by signals [*] Switch the type of FS lock used under Linux [*] Linux: Use new IPCHandle encoding scheme [*] Fix undefined behaviour: unintialized timeout values (AuLoop/Linux) [*] Fix undefined behaviour: ConsoleTTY clear line was called of a color of a random value on stack [-] Remainings of std dir iterator [*] Fix pthread_kill (aka send signal to pthread handle) always kills process. This is what you expect bc signal handler inheritance. [*] Reformat the build Aurora.json file [+] Added clang warning ignores to the build file [*] Fix: UNIX need to use STDOUT_FILENO. Was using CRT handle in place of fd by mistake. [+] Linux implementation for IO yield (AuIO::IOYield() - UNIX::LinuxOverlappedYield()) [*] Fix: Linux async end of stream processing. res 0 = zero bytes consumed. <= was detecting this as an error of code 0. Should succeed with zero bytes. [+] Linux LoopQueue missing epilogue hook for the IO processor [*] Various refactors and minor bug fixes [*] Linux fix: Handle pipe EOS as zero [*] Linux fix: thread termination via a user signal of 77. Need a force terminate. [*] IPC handle: fix improper int to bool cast in the header setup within ToString [*] Linux fix: HWInfo CPU topology regression [-] Linux fix: remove SIGABRT handler [*] Missing override in compression, exit, and consoletty headers. [+] Unix Syslog logger backend
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)
AuWin32CloseHandle(this->handle_);
2021-06-27 21:25:29 +00:00
#endif
}
AuSPtr<AuLoop::ILoopSource> OSThread::AsLoopSource()
{
return this->terminateSignalLs_;
}
AuSPtr<IWaitable> OSThread::GetShutdownSignalWaitable()
{
return this->terminateSignal_;
}
AuSPtr<AuLoop::ILoopSource> OSThread::GetShutdownSignalLS()
{
return this->terminateSignalLs_;
}
void InitThreading()
{
#if defined(AURORA_PLATFORM_WIN32)
AuxUlibInitialize();
#endif
2022-12-14 01:35:18 +00:00
#if defined(AURORA_IS_MODERNNT_DERIVED)
SetThreadInformation_f = AuReinterpretCast<decltype(SetThreadInformation_f)>(GetProcAddress(GetModuleHandleW(L"Kernel32.dll"), "SetThreadInformation"));
#endif
AttachSignalKiller();
}
}