/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: ThreadHandles.cpp Date: 2021-6-19 Author: Reece ***/ #include #include "Threads.hpp" #include "ThreadHandles.hpp" #include "OSThread.hpp" namespace Aurora::Threading::Threads { static IAuroraThread *OsThreadAnnounce(AuUInt64 threadId); static void OsThreadShutdown(AuUInt64 threadId); static AuUInt64 GetThreadIdHandle() { #if defined(AURORA_IS_MODERNNT_DERIVED) // Note: The OsThreadAnnounce function takes ownership of win32 handles. // The detor of OSThread is responsible for cleaning up this handle. HANDLE ret; auto process = GetCurrentProcess(); auto thread = GetCurrentProcess(); if (!DuplicateHandle(process, thread, process, &ret, DUPLICATE_SAME_ACCESS, FALSE, DUPLICATE_SAME_ACCESS)) { return reinterpret_cast(INVALID_HANDLE_VALUE); } return reinterpret_cast(ret); #elif defined(AURORA_HAS_PTHREADS) return pthread_self(); #endif } struct OSFallbackThread { AuUInt64 threadId; IAuroraThread *handle; OSFallbackThread() { threadId = GetThreadIdHandle(); handle = OsThreadAnnounce(threadId); } ~OSFallbackThread() { OsThreadShutdown(threadId); } }; #if defined(AURORA_COMPILER_MSVC) || defined(AURORA_COMPILER_CLANG) #define DEFINE_SPEEDY_TLS(type, name) static thread_local type name; #elif defined(AURORA_COMPILER_GCC) #define DEFINE_SPEEDY_TLS(type, name) __thread type name __attribute__((tls_model("initial-exec"))); #else #define DEFINE_SPEEDY_TLS(type, name) static thread_local type name; #endif DEFINE_SPEEDY_TLS(OSFallbackThread, tlsOsFallbackThread); DEFINE_SPEEDY_TLS(IAuroraThread*, tlsCurrentThread); void HandleRemove() { tlsCurrentThread = nullptr; } void HandleRegister(IAuroraThread *thread) { tlsCurrentThread = thread; } IAuroraThread *HandleCurrent() { return tlsCurrentThread; } IAuroraThread *OsThreadAnnounce(AuUInt64 threadId) { SysAssertDbg(tlsOsFallbackThread.threadId == threadId); return _new OSThread(threadId); } void OsThreadShutdown(AuUInt64 threadId) { SysAssertDbg(tlsOsFallbackThread.threadId == threadId); if (tlsOsFallbackThread.handle) { SafeDelete(tlsOsFallbackThread.handle); } } AUKN_SYM IAuroraThread *GetThread() { auto ret = tlsCurrentThread; if (ret) { return ret; } ret = tlsOsFallbackThread.handle; if (ret) { return ret; } SysPanic("no tls context"); } AUKN_SYM AuThreadId_t GetThreadId() { return reinterpret_cast(GetThread()); } }