/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: Entrypoint.cpp Date: 2021-5-13 Author: Reece ***/ #define _AURORA_RUNTIME_BUILD_API_INTERFACES #include #include #include "RuntimeInternal.hpp" #include "AuCrypto.hpp" #include "Processes/AuProcesses.hpp" #include "RNG/AuRNG.hpp" #include "Locale/Locale.hpp" #include "Console/Console.hpp" #include "IO/FS/FS.hpp" #include "IO/FS/Resources.hpp" #include "IO/IO.hpp" #include "IO/Net/Net.hpp" #include "Hashing/AuHashing.hpp" #include "Debug/Debug.hpp" #include "Async/Async.hpp" #include "HWInfo/AuHWInfo.hpp" #include "Telemetry/Telemetry.hpp" #include "Threading/Threads/AuOSThread.hpp" #include "SWInfo/AuSWInfo.hpp" #if defined(AURORA_PLATFORM_WIN32) #include "Extensions/Win32/DarkTheme.hpp" #include #endif #include "Debug/MemoryCrunch.hpp" #include "Process/Process.hpp" #include "Exit/AuExit.hpp" #include "CmdLine/AuCmdLine.hpp" #include "Grug/AuGrug.hpp" #include "Threading/AuSleep.hpp" #include "Memory/Cache.hpp" #include "Threading/Primitives/SMTYield.hpp" #include #include "Process/AuProcessStartTime.hpp" #include "AuProcAddresses.hpp" #if defined(AURORA_IS_LINUX_DERIVED) void LinuxSuperSecretIOTick(); #endif namespace Aurora::IO::TLS { void TLSInit(); } static thread_local bool tlsHackIsMainThread {}; static void Pump(); static void Init() { Aurora::Threading::Primitives::InitCfg(); Aurora::InitProcAddresses(); gRuntimeRunLevel = 1; tlsHackIsMainThread = true; #if defined(AURORA_PLATFORM_WIN32) Aurora::Extensions::Win32::InitDarkMode(); #endif Aurora::Memory::Cache::InitCache(); Aurora::RNG::Init(); Crypto::InitCrypto(); Aurora::IO::TLS::TLSInit(); AuProcess::WarmStartupCaches(); Aurora::Threading::InitSleep(); Aurora::Process::InitProcess(); Aurora::SWInfo::InitSwInfo(); #if defined(AURORA_PLATFORM_WIN32) Aurora::Win32DropInit(); Aurora::Win32DropSchedulerResolution(); #endif Aurora::Threading::Threads::InitThreading(); Aurora::Exit::InitExit(); Aurora::IO::Net::InitNetworking(); Aurora::Console::Init(); Aurora::IO::FS::InitResources(); Aurora::IO::Init(); Aurora::Console::Init2(); Aurora::HWInfo::Init(); Aurora::Telemetry::Init(); Aurora::Grug::InitGrug(); Aurora::Debug::InitDebug(); Aurora::Locale::Init(); Aurora::CmdLine::Init(); Aurora::Processes::Init(); Aurora::Hashing::InitHashing(); Aurora::Async::InitAsync(); Aurora::Threading::Primitives::InitAdaptiveThresholdFirstTime(); gRuntimeRunLevel = 2; #if defined(AURORA_PLATFORM_WIN32) if (!gRuntimeConfig.console.asyncVSLog) { if (IsDebuggerPresent()) { AuLogWarn("A debugger is attached and RuntimeStartInfo::console.asyncVSLog is assigned false - log-lines will be flushed to Visual Studios output window immediately. Expect a slowdown. Do not benchmark."); } else { gRuntimeConfig.console.asyncVSLog = true; } } #endif Pump(); } static void Pump() { Aurora::Console::Pump(); #if defined(AURORA_IS_LINUX_DERIVED) ::LinuxSuperSecretIOTick(); #endif #if defined(AURORA_PLATFORM_WIN32) Aurora::Win32DropSchedulerResolution(); #endif } static void RuntimeLateClean(); static void Deinit() { //tlsHackIsMainThread = true; gRuntimeRunLevel = 3; Aurora::Exit::PostLevel(AuThreads::GetThread(), Aurora::Exit::ETriggerLevel::eSafeTermination); gRuntimeRunLevel = 4; Aurora::Async::ShutdownAsync(); RuntimeLateClean(); } static void RuntimeLateClean() { // TODO: elevate leval, freeze all threads Aurora::Console::Exit(); // Final flush (i hope? coping?) Aurora::Grug::DeinitGrug(); // TODO: this was once broken above "deinit" for some unix crash reason. // now that the runtime is far more stable, im putting this down here to ensure // console exit doesnt slam into a deadlocked grug thread. Aurora::Processes::Deinit(); // Static variables we should probably manually release -> // (there is no real logic under the following functions) Aurora::IO::Deinit(); Aurora::Exit::DeinitExit(); Aurora::IO::FS::DeinitResources(); Aurora::CmdLine::Deinit(); Aurora::RNG::Release(); // RNG and crypto should remain alive whilst IO work is ongoing. // At this point, we should assume libtomcrypt and mbedtls wont be called // The default gFastDevice shouldn't be hit for any reason // ...we should be clear to start freeing those contexts and related system handles // Exterminate reserve debug memory which may very well be in use // So long as we assume aurora runtime users are dead, bye bye underlying (low-memory condition) heap AuDebug::gReservePoolStart = 0; AuDebug::gReservePoolEnd = 0; AuDebug::gReserveHeap.reset(); gRuntimeRunLevel = 5; // TODO: forcefully terminate spawned threads // TODO: debate terminate process for safety reasons i cant be bothered to explain (including AuDebug heap) } namespace Aurora { static bool gRuntimeHasStarted {}; bool RuntimeIsMainThread() { return tlsHackIsMainThread; } AUKN_SYM void RuntimeStart(const RuntimeStartInfo &info) { gRuntimeConfig = info; if (gRuntimeHasStarted) { SysPanic("Do not nest RuntimeStart/RuntimeShutdowns. Modules should respect RuntimeHasStarted()"); } try { Init(); } catch (...) { SysPanic("A fatal error occurred during the initialization of Aurora Runtime"); } gRuntimeHasStarted = true; } AUKN_SYM bool RuntimeHasStarted() { return gRuntimeHasStarted; } AUKN_SYM void RuntimeShutdown() { RuntimeSysPump(); gRuntimeHasStarted = false; Deinit(); } AUKN_SYM void RuntimeSysPump() { Pump(); } AUKN_SYM void RuntimeWaitForSecondaryTick() { Grug::WaitForGrugTick(); } void RuntimeLateClean() { ::RuntimeLateClean(); } } #if defined(AURORA_PLATFORM_WIN32) BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) { if (fdwReason == DLL_PROCESS_ATTACH) { //DisableThreadLibraryCalls(hinstDLL); } if (fdwReason == DLL_THREAD_DETACH) { mi_thread_done(); } return TRUE; } #endif