Large Commit
[*] Fix deadlock in the async subsystem (NoLockShutdown vs Shutdown in exception handler) [+] Added ProccessMap NT variant [+] Added ToolHelp image profiling [*] Improved exception awareness [*] Delegated SpawnThread to isolated TU, ready for reuse for RunAs and XNU Open - now with horrible evil alloc that could fail [+] Added header for future api 'UtilRun' [*] Improve NT core detection [*] Changed small affinity bitmap to AuUInt64 instead of AuUInt32 [+] Added data structure to hold cpuids/affinity masks [+] Implemented logger sinks [+] Implemented logger glue logic [*] Began migrating older loggers to sink-based default devices [*] Minor refactors [*] Improved internal exception discarding, not yet nothrow capable [*] Minor create directory fix
This commit is contained in:
parent
8db441ff33
commit
e5e36bd887
@ -115,7 +115,7 @@ namespace Aurora::Async
|
||||
catch (...)
|
||||
{
|
||||
Debug::PrintError();
|
||||
Shutdown();
|
||||
ShutdownNoLock();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -172,7 +172,7 @@ namespace Aurora::Async
|
||||
catch (...)
|
||||
{
|
||||
Debug::PrintError();
|
||||
Shutdown();
|
||||
ShutdownNoLock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ namespace Aurora::Console
|
||||
/// Writes a log message to the console subscribers and telemetry outputs
|
||||
AUKN_SYM void WriteLine(AuUInt8 level, const ConsoleMessage &msg);
|
||||
AUKN_SYM void SetGlobalLogger(const AuSPtr<Logging::ILogger> &defaultGlobalLogger);
|
||||
AUKN_SYM AuSPtr<Logging::ILogger> GetDefaultLogInterface();
|
||||
|
||||
/// Consider using the following function for asynchronous utf-8 processed line based input -
|
||||
/// Hooks::SetCallbackAndDisableCmdProcessing(...)
|
||||
|
@ -10,8 +10,8 @@
|
||||
namespace Aurora::Console::Logging
|
||||
{
|
||||
AUKN_INTERFACE(IBasicSink,
|
||||
AUI_METHOD(void, OnMessageBlocking, (const ConsoleMessage &, msg)),
|
||||
AUI_METHOD(void, OnMessageNonblocking, (const ConsoleMessage &, msg)),
|
||||
AUI_METHOD(void, OnMessageBlocking, (AuUInt8, level, const ConsoleMessage &, msg)),
|
||||
AUI_METHOD(void, OnMessageNonblocking, (AuUInt8, level, const ConsoleMessage &, msg)),
|
||||
AUI_METHOD(void, OnFlush, ())
|
||||
)
|
||||
}
|
@ -14,7 +14,8 @@ namespace Aurora
|
||||
|
||||
namespace Aurora::Console::Logging
|
||||
{
|
||||
AUKN_SHARED_API(NewGlobalPipeSink, IBasicSink);
|
||||
AUKN_SHARED_API(NewStdSink, IBasicSink);
|
||||
AUKN_SHARED_API(NewOSEventDirectorySink, IBasicSink);
|
||||
AUKN_SHARED_API(NewFileSink, IBasicSink, const AuString &path, bool binary = false);
|
||||
AUKN_SHARED_API(NewIPCSink, IBasicSink, const SocketConsole &console);
|
||||
AUKN_SHARED_API(NewRingLogger, IBasicSinkRB, AuUInt32 approxMaxBytes);
|
||||
|
@ -48,6 +48,9 @@ namespace Aurora::Debug
|
||||
*/
|
||||
AUKN_SYM void PrintError();
|
||||
|
||||
|
||||
AUKN_SYM void CheckErrors();
|
||||
|
||||
/**
|
||||
Immediately terminates the process.
|
||||
May attempt some hardened telemetry debug ops
|
||||
|
@ -33,6 +33,7 @@ namespace Aurora::Debug
|
||||
kFailureSyntaxError,
|
||||
kFailureDisconnected,
|
||||
kFailureUninitialized,
|
||||
kFailureUnimplemented,
|
||||
|
||||
kFailureUserBegin = 256
|
||||
};
|
||||
|
@ -13,6 +13,7 @@ namespace Aurora::Debug
|
||||
{
|
||||
AuOptional<AuString> label;
|
||||
AuUInt64 address;
|
||||
AuUInt64 relAddress;
|
||||
AuOptional<AuString> module;
|
||||
AuOptional<AuTuple<AuString, int, int>> file; // file, line, offset
|
||||
|
||||
|
@ -108,6 +108,7 @@ namespace Aurora::Debug
|
||||
#define SysPushErrorSyntaxError(...) SysPushErrorError(kFailureSyntaxError, ## __VA_ARGS__)
|
||||
#define SysPushErrorDisconnected(...) SysPushErrorError(kFailureDisconnected, ## __VA_ARGS__)
|
||||
#define SysPushErrorUninitialized(...) SysPushErrorError(kFailureUninitialized, ## __VA_ARGS__)
|
||||
#define SysPushErrorUnimplemented(...) SysPushErrorError(kFailureUnimplemented, ## __VA_ARGS__)
|
||||
|
||||
|
||||
#if defined(DEBUG) || defined(STAGING)
|
||||
@ -142,6 +143,7 @@ namespace Aurora::Debug
|
||||
#define SysPushErrorSyntaxErrorDbg SysPushErrorSyntaxError
|
||||
#define SysPushErrorDisconnectedDbg SysPushErrorDisconnected
|
||||
#define SysPushErrorUninitializedDbg SysPushErrorUninitialized
|
||||
#define SysPushErrorUnimplementedDbg SysPushErrorUnimplemented
|
||||
|
||||
#else
|
||||
|
||||
@ -174,5 +176,6 @@ namespace Aurora::Debug
|
||||
#define SysPushErrorSyntaxErrorDbg(...)
|
||||
#define SysPushErrorDisconnectedDbg(...)
|
||||
#define SysPushErrorUninitializedDbg(...)
|
||||
#define SysPushErrorUnimplementedDbg(...)
|
||||
|
||||
#endif
|
||||
|
48
Include/Aurora/HWInfo/CpuBitId.hpp
Normal file
48
Include/Aurora/HWInfo/CpuBitId.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: CpuBitId.hpp
|
||||
Date: 2022-1-24
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::HWInfo
|
||||
{
|
||||
struct CpuBitId
|
||||
{
|
||||
AuUInt64 lower {};
|
||||
AuUInt64 upper {};
|
||||
#if defined(_AU_MASSIVE_CPUID)
|
||||
AuUInt64 upper2 {};
|
||||
AuUInt64 upper3 {};
|
||||
#endif
|
||||
|
||||
inline CpuBitId();
|
||||
inline ~CpuBitId();
|
||||
inline CpuBitId(AuUInt8 id);
|
||||
|
||||
inline bool HasValue() const;
|
||||
|
||||
inline void Add(const CpuBitId &id);
|
||||
|
||||
inline CpuBitId Not() const;
|
||||
inline CpuBitId And(const CpuBitId &id) const;
|
||||
inline CpuBitId Xor(const CpuBitId &id) const;
|
||||
|
||||
inline bool CpuBitScanForward(AuUInt8 &index, AuUInt8 offset) const;
|
||||
|
||||
inline bool TestCpuIdx(AuUInt8 idx) const;
|
||||
inline void Clear();
|
||||
inline void SetBit(AuUInt8 idx);
|
||||
inline void ClearBit(AuUInt8 idx);
|
||||
inline bool TestBit(AuUInt8 idx) const;
|
||||
|
||||
inline AuString ToString() const;
|
||||
|
||||
inline CpuBitId &operator=(const CpuBitId &id);
|
||||
inline operator bool() const;
|
||||
};
|
||||
}
|
||||
|
||||
#include "CpuBitId.inl"
|
193
Include/Aurora/HWInfo/CpuBitId.inl
Normal file
193
Include/Aurora/HWInfo/CpuBitId.inl
Normal file
@ -0,0 +1,193 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: CpuBitId.hpp
|
||||
Date: 2022-1-24
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::HWInfo
|
||||
{
|
||||
CpuBitId::CpuBitId()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CpuBitId::~CpuBitId()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CpuBitId::CpuBitId(AuUInt8 id)
|
||||
{
|
||||
SetBit(id);
|
||||
}
|
||||
|
||||
AuString CpuBitId::ToString() const
|
||||
{
|
||||
#if defined(_AU_MASSIVE_CPUID)
|
||||
return fmt::format("{1:#0{0}b} {2:#0{0}b} {3:#0{0}b} {4:#0{0}b}", sizeof(decltype(lower)) * 8, lower, upper, upper2, upper3);
|
||||
#else
|
||||
return fmt::format("{1:#0{0}b} {2:#0{0}b}", sizeof(decltype(lower)) * 8, lower, upper);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CpuBitId::CpuBitScanForward(AuUInt8 &index, AuUInt8 offset) const
|
||||
{
|
||||
#if defined(_AU_MASSIVE_CPUID)
|
||||
if (offset >= 192)
|
||||
{
|
||||
if (!AuBitScanForward(index, AuUInt64(upper3) >> AuUInt64(offset - 192))) return false;
|
||||
index += 192;
|
||||
}
|
||||
else if (offset >= 128)
|
||||
{
|
||||
if (!AuBitScanForward(index, AuUInt64(upper2) >> AuUInt64(offset - 128))) return false;
|
||||
index += 128;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (offset >= 64)
|
||||
{
|
||||
if (!AuBitScanForward(index, AuUInt64(upper) >> AuUInt64(offset - 64))) return false;
|
||||
index += 64;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!AuBitScanForward(index, AuUInt64(lower) >> AuUInt64(0))) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CpuBitId::HasValue() const
|
||||
{
|
||||
return lower || upper
|
||||
#if defined(_AU_MASSIVE_CPUID)
|
||||
|| upper2
|
||||
|| upper3
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
void CpuBitId::Add(const CpuBitId &id)
|
||||
{
|
||||
lower |= id.lower;
|
||||
upper |= id.upper;
|
||||
#if defined(_AU_MASSIVE_CPUID)
|
||||
upper2 |= id.upper2;
|
||||
upper3 |= id.upper3;
|
||||
#endif
|
||||
}
|
||||
|
||||
CpuBitId CpuBitId::Not() const
|
||||
{
|
||||
CpuBitId ret = *this;
|
||||
ret.lower = ~ret.lower;
|
||||
ret.upper = ~ret.upper;
|
||||
#if defined(_AU_MASSIVE_CPUID)
|
||||
ret.upper2 = ~ret.upper2;
|
||||
ret.upper3 = ~ret.upper3;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
CpuBitId CpuBitId::And(const CpuBitId &id) const
|
||||
{
|
||||
CpuBitId ret = *this;
|
||||
ret.lower &= id.lower;
|
||||
ret.upper &= id.upper;
|
||||
#if defined(_AU_MASSIVE_CPUID)
|
||||
ret.upper2 &= id.upper2;
|
||||
ret.upper3 &= id.upper3;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
CpuBitId CpuBitId::Xor(const CpuBitId &id) const
|
||||
{
|
||||
CpuBitId ret = *this;
|
||||
ret.lower ^= id.lower;
|
||||
ret.upper ^= id.upper;
|
||||
#if defined(_AU_MASSIVE_CPUID)
|
||||
ret.upper2 ^= id.upper2;
|
||||
ret.upper3 ^= id.upper3;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
CpuBitId &CpuBitId::operator=(const CpuBitId &id)
|
||||
{
|
||||
lower = id.lower;
|
||||
upper = id.upper;
|
||||
#if defined(_AU_MASSIVE_CPUID)
|
||||
upper2 = id.upper2;
|
||||
upper3 = id.upper3;
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
CpuBitId::operator bool() const
|
||||
{
|
||||
return HasValue();
|
||||
}
|
||||
|
||||
bool CpuBitId::TestCpuIdx(AuUInt8 idx) const
|
||||
{
|
||||
return TestBit(idx);
|
||||
}
|
||||
|
||||
void CpuBitId::Clear()
|
||||
{
|
||||
lower = {};
|
||||
upper = {};
|
||||
}
|
||||
|
||||
void CpuBitId::SetBit(AuUInt8 idx)
|
||||
{
|
||||
#if defined(_AU_MASSIVE_CPUID)
|
||||
if (idx >= 192)
|
||||
upper3 |= AuUInt64(1) << AuUInt64(idx - 192);
|
||||
else if (idx >= 128)
|
||||
upper2 |= AuUInt64(1) << AuUInt64(idx - 128);
|
||||
else
|
||||
#endif
|
||||
if (idx >= 64)
|
||||
upper |= AuUInt64(1) << AuUInt64(idx - 64);
|
||||
else
|
||||
lower |= AuUInt64(1) << AuUInt64(idx);
|
||||
}
|
||||
|
||||
void CpuBitId::ClearBit(AuUInt8 idx)
|
||||
{
|
||||
#if defined(_AU_MASSIVE_CPUID)
|
||||
if (idx >= 192)
|
||||
upper3 &= ~(AuUInt64(1) << AuUInt64(idx - 192));
|
||||
else if (idx >= 128)
|
||||
upper2 &= ~(AuUInt64(1) << AuUInt64(idx - 128));
|
||||
else
|
||||
#endif
|
||||
if (idx >= 64)
|
||||
upper &= ~(AuUInt64(1) << AuUInt64(idx - 64));
|
||||
else
|
||||
lower &= ~(AuUInt64(1) << AuUInt64(idx));
|
||||
}
|
||||
|
||||
bool CpuBitId::TestBit(AuUInt8 idx) const
|
||||
{
|
||||
bool ret {};
|
||||
#if defined(_AU_MASSIVE_CPUID)
|
||||
if (idx >= 192)
|
||||
ret = upper3 & (AuUInt64(1) << AuUInt64(idx - 192));
|
||||
else if (idx >= 128)
|
||||
ret = upper2 & (AuUInt64(1) << AuUInt64(idx - 128));
|
||||
else
|
||||
#endif
|
||||
if (idx >= 64)
|
||||
ret = upper & (AuUInt64(1) << AuUInt64(idx - 64));
|
||||
else
|
||||
ret = lower & (AuUInt64(1) << AuUInt64(idx));
|
||||
return ret;
|
||||
}
|
||||
}
|
83
Include/Aurora/HWInfo/CpuId.hpp
Normal file
83
Include/Aurora/HWInfo/CpuId.hpp
Normal file
@ -0,0 +1,83 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: CpuId.hpp
|
||||
Date: 2022-1-24
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::HWInfo
|
||||
{
|
||||
struct AUKN_SYM CpuId
|
||||
{
|
||||
bool SSE3();
|
||||
bool PCLMULQDQ();
|
||||
bool MONITOR();
|
||||
bool SSSE3();
|
||||
bool FMA();
|
||||
bool CMPXCHG16B();
|
||||
bool SSE41();
|
||||
bool SSE42();
|
||||
bool MOVBE();
|
||||
bool POPCNT();
|
||||
bool AES();
|
||||
bool XSAVE();
|
||||
bool OSXSAVE();
|
||||
bool AVX();
|
||||
bool F16C();
|
||||
bool RDRAND();
|
||||
|
||||
bool MSR();
|
||||
bool CX8();
|
||||
bool SEP();
|
||||
bool CMOV();
|
||||
bool CLFSH();
|
||||
bool MMX();
|
||||
bool FXSR();
|
||||
bool SSE();
|
||||
bool SSE2();
|
||||
|
||||
bool FSGSBASE();
|
||||
bool BMI1();
|
||||
bool HLE();
|
||||
bool AVX2();
|
||||
bool BMI2();
|
||||
bool ERMS();
|
||||
bool INVPCID();
|
||||
bool RTM();
|
||||
bool AVX512F();
|
||||
bool RDSEED();
|
||||
bool ADX();
|
||||
bool AVX512PF();
|
||||
bool AVX512ER();
|
||||
bool AVX512CD();
|
||||
bool SHA();
|
||||
|
||||
bool PREFETCHWT1();
|
||||
|
||||
bool LAHF();
|
||||
bool LZCNT();
|
||||
bool ABM();
|
||||
bool SSE4a();
|
||||
bool XOP();
|
||||
bool TBM();
|
||||
|
||||
bool SYSCALL();
|
||||
bool MMXEXT();
|
||||
bool RDTSCP();
|
||||
bool _3DNOWEXT();
|
||||
bool _3DNOW();
|
||||
|
||||
AuString vendor;
|
||||
AuString brand;
|
||||
bool isIntel;
|
||||
bool isAMD;
|
||||
AuUInt32 f_1_ECX;
|
||||
AuUInt32 f_1_EDX;
|
||||
AuUInt32 f_7_EBX;
|
||||
AuUInt32 f_7_ECX;
|
||||
AuUInt32 f_81_ECX;
|
||||
AuUInt32 f_81_EDX;
|
||||
};
|
||||
}
|
@ -7,80 +7,11 @@
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#include "CpuBitId.hpp"
|
||||
#include "CpuId.hpp"
|
||||
|
||||
namespace Aurora::HWInfo
|
||||
{
|
||||
struct AUKN_SYM CpuId
|
||||
{
|
||||
bool SSE3();
|
||||
bool PCLMULQDQ();
|
||||
bool MONITOR();
|
||||
bool SSSE3();
|
||||
bool FMA();
|
||||
bool CMPXCHG16B();
|
||||
bool SSE41();
|
||||
bool SSE42();
|
||||
bool MOVBE();
|
||||
bool POPCNT();
|
||||
bool AES();
|
||||
bool XSAVE();
|
||||
bool OSXSAVE();
|
||||
bool AVX();
|
||||
bool F16C();
|
||||
bool RDRAND();
|
||||
|
||||
bool MSR();
|
||||
bool CX8();
|
||||
bool SEP();
|
||||
bool CMOV();
|
||||
bool CLFSH();
|
||||
bool MMX();
|
||||
bool FXSR();
|
||||
bool SSE();
|
||||
bool SSE2();
|
||||
|
||||
bool FSGSBASE();
|
||||
bool BMI1();
|
||||
bool HLE();
|
||||
bool AVX2();
|
||||
bool BMI2();
|
||||
bool ERMS();
|
||||
bool INVPCID();
|
||||
bool RTM();
|
||||
bool AVX512F();
|
||||
bool RDSEED();
|
||||
bool ADX();
|
||||
bool AVX512PF();
|
||||
bool AVX512ER();
|
||||
bool AVX512CD();
|
||||
bool SHA();
|
||||
|
||||
bool PREFETCHWT1();
|
||||
|
||||
bool LAHF();
|
||||
bool LZCNT();
|
||||
bool ABM();
|
||||
bool SSE4a();
|
||||
bool XOP();
|
||||
bool TBM();
|
||||
|
||||
bool SYSCALL();
|
||||
bool MMXEXT();
|
||||
bool RDTSCP();
|
||||
bool _3DNOWEXT();
|
||||
bool _3DNOW();
|
||||
|
||||
AuString vendor;
|
||||
AuString brand;
|
||||
bool isIntel;
|
||||
bool isAMD;
|
||||
AuUInt32 f_1_ECX;
|
||||
AuUInt32 f_1_EDX;
|
||||
AuUInt32 f_7_EBX;
|
||||
AuUInt32 f_7_ECX;
|
||||
AuUInt32 f_81_ECX;
|
||||
AuUInt32 f_81_EDX;
|
||||
};
|
||||
|
||||
struct CpuInfo
|
||||
{
|
||||
Aurora::Build::EArchitecture cpuArch;
|
||||
@ -89,6 +20,13 @@ namespace Aurora::HWInfo
|
||||
AuUInt8 cores;
|
||||
AuUInt8 threads;
|
||||
|
||||
AuList<AuInt64> threadTopology;
|
||||
AuList<CpuBitId> serverTopology;
|
||||
CpuBitId maskECores;
|
||||
|
||||
bool maskMTContig;
|
||||
bool maskMTHalf;
|
||||
|
||||
CpuId cpuId;
|
||||
};
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "ECodePage.hpp"
|
||||
#include "Encoding/Encoding.hpp"
|
||||
#include "LocaleStrings.hpp"
|
||||
|
||||
namespace Aurora::Locale
|
||||
{
|
||||
|
19
Include/Aurora/Locale/LocaleStrings.hpp
Normal file
19
Include/Aurora/Locale/LocaleStrings.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <Aurora/Time/ETimezoneShift.hpp>
|
||||
#include <Aurora/Time/TM.hpp>
|
||||
|
||||
namespace Aurora::Locale
|
||||
{
|
||||
AUKN_SYM AuString NumbericLocaleGetDecimal();
|
||||
#
|
||||
AUKN_SYM AuString TimeLocaleGetMSChar();
|
||||
AUKN_SYM AuString TimeLocaleS();
|
||||
AUKN_SYM AuString TimeLocaleGetDayChar();
|
||||
|
||||
AUKN_SYM AuString TimeDateToString(const Time::tm &time);
|
||||
AUKN_SYM AuString TimeDateToISO8601(const Time::tm &time, Time::ETimezoneShift shift = Time::ETimezoneShift::eUTC);
|
||||
|
||||
AUKN_SYM AuString ConvertMSToTimescale(AuUInt32 ms);
|
||||
AUKN_SYM AuString ConvertNSToTimescale(AuUInt64 ns);
|
||||
}
|
@ -9,16 +9,44 @@
|
||||
|
||||
namespace Aurora::Process
|
||||
{
|
||||
struct PublicModule;
|
||||
|
||||
struct ModuleMeta
|
||||
{
|
||||
AuString moduleName;
|
||||
AuString modulePath;
|
||||
AuUInt moduleBase;
|
||||
AuUInt origVa;
|
||||
};
|
||||
|
||||
struct PageTable
|
||||
{
|
||||
bool NX;
|
||||
bool writable;
|
||||
bool readable;
|
||||
bool acSanity;
|
||||
};
|
||||
|
||||
struct Segment
|
||||
{
|
||||
AuUInt base;
|
||||
AuUInt baseVa;
|
||||
AuUInt origVa;
|
||||
AuUInt fsOff;
|
||||
AuUInt size;
|
||||
char perms[6];
|
||||
AuString module;
|
||||
PageTable pt;
|
||||
AuString name;
|
||||
AuWPtr<PublicModule> moduleMeta;
|
||||
};
|
||||
|
||||
using Segments = AuList<Segment>;
|
||||
|
||||
struct PublicModule
|
||||
{
|
||||
AuList<Segment> segments;
|
||||
AuSPtr<ModuleMeta> moduleMeta;
|
||||
};
|
||||
|
||||
AUKN_SYM AuOptional<Segment> GetSegment(AuUInt pointer);
|
||||
AUKN_SYM Segments DumpExecutableRoot();
|
||||
AUKN_SYM PublicModule DumpExecutableRoot();
|
||||
AUKN_SYM Segments DumpExecutableAll();
|
||||
}
|
@ -10,5 +10,6 @@
|
||||
#include "ESpawnType.hpp"
|
||||
#include "IProcess.hpp"
|
||||
#include "Spawn.hpp"
|
||||
#include "UtilRun.hpp"
|
||||
|
||||
#include "Open.hpp"
|
32
Include/Aurora/Processes/UtilRun.hpp
Normal file
32
Include/Aurora/Processes/UtilRun.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: UtilRun.hpp
|
||||
Date:
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Processes
|
||||
{
|
||||
AUKN_INTERFACE(ICommandFinished,
|
||||
AUI_METHOD(void, OnLines, (const AuList<AuString> &, buffer)),
|
||||
AUI_METHOD(void, OnBuffered, (const Memory::ByteBuffer &, buffer))
|
||||
);
|
||||
|
||||
struct CommandRun_s
|
||||
{
|
||||
AuString cmd;
|
||||
AuList<AuString> args;
|
||||
Memory::ByteBuffer stdIn;
|
||||
bool stdOutLongerThan64k {false}; // common constraint on linux and windows, at the very least. linux -> max pipe = 16k, windows -> 16k minimum guaranteed
|
||||
bool stdOutIsText {true};
|
||||
bool runCallbackOnRandomThread {true};
|
||||
bool runCallbackOnWorkerPId {};
|
||||
Async::WorkerPId_t worker;
|
||||
bool syncToResult {}; // default -> async
|
||||
AuSPtr<ICommandFinished> callback;
|
||||
};
|
||||
|
||||
AUKN_SYM void RunCommand(const CommandRun_s &in);
|
||||
}
|
@ -61,16 +61,16 @@
|
||||
#include "Hashing/Hashing.hpp"
|
||||
#include "HWInfo/HWInfo.hpp"
|
||||
#include "IO/IO.hpp"
|
||||
#include "Time/Time.hpp"
|
||||
#include "Locale/Locale.hpp"
|
||||
#include "Parse/Parse.hpp"
|
||||
#include "Process/Process.hpp"
|
||||
#include "Processes/Processes.hpp"
|
||||
#include "Registry/Registry.hpp"
|
||||
#include "RNG/RNG.hpp"
|
||||
#include "Telemetry/Telemetery.hpp"
|
||||
#include "Threading/Threading.hpp"
|
||||
#include "Async/Async.hpp"
|
||||
#include "Time/Time.hpp"
|
||||
#include "Processes/Processes.hpp"
|
||||
#include "Loop/Loop.hpp"
|
||||
|
||||
#include "Memory/_ByteBuffer.hpp"
|
||||
@ -109,8 +109,6 @@ using AuMemoryViewWrite = AuMemory::MemoryViewWrite;
|
||||
using AuMemoryViewStreamRead = AuMemory::MemoryViewStreamRead;
|
||||
using AuMemoryViewStreamWrite = AuMemory::MemoryViewStreamWrite;
|
||||
|
||||
|
||||
|
||||
static bool AuIsThreadRunning()
|
||||
{
|
||||
return !AuThreads::GetThread()->Exiting();
|
||||
@ -196,6 +194,9 @@ namespace Aurora
|
||||
/// Use WxWidgets when possible
|
||||
bool enableWxWidgets {true};
|
||||
|
||||
/// Delegate stdout writes to loops -> recommended for servers
|
||||
bool asyncWrite {false};
|
||||
|
||||
#if 1
|
||||
/// FIO config
|
||||
LocalLogInfo fio;
|
||||
|
@ -24,10 +24,10 @@ namespace Aurora::Threading::Threads
|
||||
/// A common worker thread semantic:
|
||||
/// EndWorker()
|
||||
/// m_Worker->SendExitSignal(); // sets the exiting flag
|
||||
/// DestroyThread(worker); // in the dtor, a watchdog is triggered over the shutdown of the thread
|
||||
/// DestroyThread(worker); // in the dtor, a watchdog guards the shutdown of the thread, and syncs to termination
|
||||
///
|
||||
/// WorkerMain()
|
||||
/// while (!this->Exiting()) {}
|
||||
/// while (AuIsThreadRunning()) {}
|
||||
///
|
||||
/// It's similar to Java
|
||||
/// -> think while (Thread.currentThread().isAlive()) { doWork() }
|
||||
@ -42,11 +42,11 @@ namespace Aurora::Threading::Threads
|
||||
virtual void SendExitSignal() = 0;
|
||||
|
||||
virtual void SetPrio(EThreadPrio prio) = 0;
|
||||
virtual void SetAffinity(AuUInt32 mask) = 0;
|
||||
virtual void SetAffinity(AuUInt64 mask) = 0;
|
||||
virtual void SetName(const AuString &name) = 0;
|
||||
|
||||
virtual EThreadPrio GetPrio() = 0;
|
||||
virtual AuUInt32 GetMask() = 0;
|
||||
virtual AuUInt64 GetMask() = 0;
|
||||
virtual AuString GetName() = 0;
|
||||
|
||||
/// Registers a thread feature _not_ calling on init
|
||||
|
@ -7,49 +7,11 @@
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#include "ETimezoneShift.hpp"
|
||||
#include "TM.hpp"
|
||||
|
||||
namespace Aurora::Time
|
||||
{
|
||||
struct tm
|
||||
{
|
||||
int tm_sec {};
|
||||
int tm_min {};
|
||||
int tm_hour {};
|
||||
int tm_mday {1};
|
||||
int tm_mon {};
|
||||
int tm_year {70};
|
||||
int tm_wday {};
|
||||
int tm_yday {};
|
||||
int tm_isdst {-1};
|
||||
|
||||
template<typename Dest_t>
|
||||
void CopyTo(Dest_t &out) const
|
||||
{
|
||||
out.tm_sec = tm_sec;
|
||||
out.tm_min = tm_min;
|
||||
out.tm_hour = tm_hour;
|
||||
out.tm_mday = tm_mday;
|
||||
out.tm_mon = tm_mon;
|
||||
out.tm_year = tm_year;
|
||||
out.tm_wday = tm_wday;
|
||||
out.tm_yday = tm_yday;
|
||||
out.tm_isdst = tm_isdst;
|
||||
}
|
||||
|
||||
template<typename In_t>
|
||||
void CopyFrom(const In_t &in)
|
||||
{
|
||||
tm_sec = in.tm_sec;
|
||||
tm_min = in.tm_min;
|
||||
tm_hour = in.tm_hour;
|
||||
tm_mday = in.tm_mday;
|
||||
tm_mon = in.tm_mon;
|
||||
tm_year = in.tm_year;
|
||||
tm_wday = in.tm_wday;
|
||||
tm_yday = in.tm_yday;
|
||||
tm_isdst = in.tm_isdst;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
Converts milliseconds from the Aurora epoch to a civil timestamp structure
|
||||
similar to or of std::tm
|
||||
@ -65,6 +27,12 @@ namespace Aurora::Time
|
||||
*/
|
||||
AUKN_SYM AuInt64 FromCivilTime(const tm &time, bool UTC = true);
|
||||
|
||||
|
||||
/**
|
||||
Normalizes a civil data structure with respect to UTC, given the two input parameters 'in' civil and 'shiftFrom' timezone hint
|
||||
*/
|
||||
AUKN_SYM tm NormalizeCivilTimezone(const tm &in, ETimezoneShift shiftFrom = ETimezoneShift::eUTC);
|
||||
|
||||
/**
|
||||
Retrieves system clock in jiffies
|
||||
*/
|
||||
|
17
Include/Aurora/Time/ETimezoneShift.hpp
Normal file
17
Include/Aurora/Time/ETimezoneShift.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ETimezoneShift.hpp
|
||||
Date: 2022-1-24
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Time
|
||||
{
|
||||
enum ETimezoneShift
|
||||
{
|
||||
eUTC,
|
||||
eLocalTime
|
||||
};
|
||||
}
|
52
Include/Aurora/Time/TM.hpp
Normal file
52
Include/Aurora/Time/TM.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: ETimezoneShift.hpp
|
||||
Date: 2022-1-24
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Time
|
||||
{
|
||||
struct tm
|
||||
{
|
||||
int tm_sec {};
|
||||
int tm_min {};
|
||||
int tm_hour {};
|
||||
int tm_mday {1};
|
||||
int tm_mon {};
|
||||
int tm_year {70};
|
||||
int tm_wday {};
|
||||
int tm_yday {};
|
||||
int tm_isdst {-1};
|
||||
|
||||
template<typename Dest_t>
|
||||
void CopyTo(Dest_t &out) const
|
||||
{
|
||||
out.tm_sec = tm_sec;
|
||||
out.tm_min = tm_min;
|
||||
out.tm_hour = tm_hour;
|
||||
out.tm_mday = tm_mday;
|
||||
out.tm_mon = tm_mon;
|
||||
out.tm_year = tm_year;
|
||||
out.tm_wday = tm_wday;
|
||||
out.tm_yday = tm_yday;
|
||||
out.tm_isdst = tm_isdst;
|
||||
}
|
||||
|
||||
template<typename In_t>
|
||||
void CopyFrom(const In_t &in)
|
||||
{
|
||||
tm_sec = in.tm_sec;
|
||||
tm_min = in.tm_min;
|
||||
tm_hour = in.tm_hour;
|
||||
tm_mday = in.tm_mday;
|
||||
tm_mon = in.tm_mon;
|
||||
tm_year = in.tm_year;
|
||||
tm_wday = in.tm_wday;
|
||||
tm_yday = in.tm_yday;
|
||||
tm_isdst = in.tm_isdst;
|
||||
}
|
||||
};
|
||||
}
|
@ -7,114 +7,20 @@
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#include <Aurora/Time/ETimezoneShift.hpp>
|
||||
#include <Aurora/Locale/LocaleStrings.hpp>
|
||||
|
||||
namespace Aurora::Time
|
||||
{
|
||||
static auline AuString TimeLocaleGetDayChar()
|
||||
static AuString ConvertMSToTimescale(AuUInt32 ms)
|
||||
{
|
||||
return "d"; //for.now
|
||||
return Locale::ConvertMSToTimescale(ms);
|
||||
}
|
||||
|
||||
static auline AuString TimeLocaleS()
|
||||
static AuString ConvertNSToTimescale(AuUInt64 ns)
|
||||
{
|
||||
return "s";
|
||||
return Locale::ConvertNSToTimescale(ns);
|
||||
}
|
||||
|
||||
static auline AuString TimeLocaleGetMSChar()
|
||||
{
|
||||
return "ms"; //for.now
|
||||
}
|
||||
|
||||
static AuString &_TextPrepadZeroIfOne(AuString &in)
|
||||
{
|
||||
if (in.size() == 1) in.insert(in.begin(), '0');
|
||||
return in;
|
||||
}
|
||||
|
||||
static AuString _TextPrepadZeroIfOne(const AuString &in)
|
||||
{
|
||||
AuString ret = in;
|
||||
if (ret.size() == 1) ret.insert(ret.begin(), '0');
|
||||
return ret;
|
||||
}
|
||||
|
||||
static AuString _TextPrepadZeroMS(const AuString &in)
|
||||
{
|
||||
AuString ret = in;
|
||||
if (ret.size() == 1) ret.insert(0, "000", 3);
|
||||
if (ret.size() == 2) ret.insert(0, "000", 2);
|
||||
if (ret.size() == 3) ret.insert(0, "000", 1);
|
||||
while (ret.size() > 1 && ret[ret.size() - 1] == '0')
|
||||
ret.pop_back();
|
||||
return ret;
|
||||
}
|
||||
static AuString _TextPrepadZeroNS(const AuString &in)
|
||||
{
|
||||
AuString ret = in;
|
||||
if (ret.size() == 1) ret.insert(0, "000000", 6);
|
||||
if (ret.size() == 2) ret.insert(0, "000000", 5);
|
||||
if (ret.size() == 3) ret.insert(0, "000000", 4);
|
||||
if (ret.size() == 4) ret.insert(0, "000000", 3);
|
||||
if (ret.size() == 5) ret.insert(0, "000000", 2);
|
||||
if (ret.size() == 6) ret.insert(0, "000000", 1);
|
||||
while (ret.size() > 1 && ret[ret.size() - 1] == '0')
|
||||
ret.pop_back();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static auline AuString ConvertMSToTimescale(AuUInt32 ms)
|
||||
{
|
||||
const auto msDiv1000 = ms / 1000; // seconds
|
||||
const auto msDiv1000Mod60 = msDiv1000 % 60; // remaining seconds relative to next whole minute
|
||||
const auto msDiv1000Div60 = msDiv1000 / 60; // total minutes
|
||||
|
||||
if (ms < 1000)
|
||||
{
|
||||
return AuToString(ms) + TimeLocaleGetMSChar();
|
||||
}
|
||||
else if (ms < (1000 * 60))
|
||||
{
|
||||
auto s = msDiv1000;
|
||||
auto remMs = ms % 1000;
|
||||
return _TextPrepadZeroIfOne(AuToString(s)) + "." + _TextPrepadZeroMS(AuToString(remMs)) + TimeLocaleS();
|
||||
}
|
||||
else if (ms < (1000 * 60 * 60))
|
||||
{
|
||||
auto m = msDiv1000Div60;
|
||||
auto remS = msDiv1000Mod60;
|
||||
return _TextPrepadZeroIfOne(AuToString(m)) + ":" + _TextPrepadZeroIfOne(AuToString(remS));
|
||||
}
|
||||
else if (ms < (1000 * 60 * 60 * 24))
|
||||
{
|
||||
auto h = msDiv1000Div60 / 60;
|
||||
auto remM = msDiv1000Div60;
|
||||
auto remS = msDiv1000Mod60;
|
||||
|
||||
return _TextPrepadZeroIfOne(AuToString(h)) + ":" + _TextPrepadZeroIfOne(AuToString(remM)) + ":" + _TextPrepadZeroIfOne(AuToString(remS));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto d = (msDiv1000Div60 / 60 / 24);
|
||||
auto h = (msDiv1000Div60 / 60) - (d * 24);
|
||||
auto remM = msDiv1000Div60;
|
||||
auto remS = msDiv1000Mod60;
|
||||
return AuToString(d) + TimeLocaleGetDayChar() + " " + _TextPrepadZeroIfOne(AuToString(h)) + ":" + _TextPrepadZeroIfOne(AuToString(remM)) + ":" + _TextPrepadZeroIfOne(AuToString(remS));
|
||||
}
|
||||
}
|
||||
|
||||
static auline AuString ConvertNSToTimescale(AuUInt64 ns)
|
||||
{
|
||||
if (ns < AuUInt64(1000000000))
|
||||
{
|
||||
const auto ms = ns / 1000000;
|
||||
const auto remNs = ns % 1000000;
|
||||
return _TextPrepadZeroMS(AuToString(ms)) + "." + _TextPrepadZeroNS(AuToString(remNs)) + TimeLocaleGetMSChar();
|
||||
}
|
||||
else
|
||||
{
|
||||
return ConvertMSToTimescale(ns / AuUInt64(1000000000));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "Clock.hpp"
|
||||
|
@ -83,8 +83,8 @@ namespace Aurora::Async
|
||||
{
|
||||
if (entry.pool->ToThreadPool()->InRunnerMode())
|
||||
{
|
||||
LogWarn("Dropped scheduled task! Expect a leaky counter!");
|
||||
LogWarn("Would you rather `Why u no exit?!` or `WHY DID U JUST CRASH REEEE` in production?");
|
||||
AuLogWarn("Dropped scheduled task! Expect a leaky counter!");
|
||||
AuLogWarn("Would you rather `Why u no exit?!` or `WHY DID U JUST CRASH REEEE` in production?");
|
||||
}
|
||||
Debug::PrintError();
|
||||
}
|
||||
@ -103,7 +103,7 @@ namespace Aurora::Async
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LogWarn("Dropped SysRuntimePump");
|
||||
AuLogWarn("Dropped SysRuntimePump");
|
||||
Debug::PrintError();
|
||||
}
|
||||
}
|
||||
|
@ -1002,7 +1002,7 @@ namespace Aurora::Async
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LogWarn("Couldn't clean up thread feature!");
|
||||
AuLogWarn("Couldn't clean up thread feature!");
|
||||
Debug::PrintError();
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ namespace Aurora::Console::Commands
|
||||
auto cmdItr = gCommands.find(tag);
|
||||
if (cmdItr == gCommands.end())
|
||||
{
|
||||
LogWarn("Command {} does not exist", tag);
|
||||
AuLogWarn("Command {} does not exist", tag);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ namespace Aurora::Console::Commands
|
||||
|
||||
if (!status)
|
||||
{
|
||||
LogWarn("Couldn't parse command {}", string);
|
||||
AuLogWarn("Couldn't parse command {}", string);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -192,8 +192,7 @@ namespace Aurora::Console::Commands
|
||||
AuMakeShared<Async::BasicWorkStdFunc>([&commands]()
|
||||
{
|
||||
DispatchCommandsFromThis(commands);
|
||||
}),
|
||||
true)->Dispatch()->BlockUntilComplete();
|
||||
}), true)->Dispatch()->BlockUntilComplete();
|
||||
}
|
||||
|
||||
gMutex->Unlock();
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "Console.hpp"
|
||||
#include "Commands/Commands.hpp"
|
||||
#include "Hooks/Hooks.hpp"
|
||||
#include "Logging/Logger.hpp"
|
||||
#include "ConsoleStd/ConsoleStd.hpp"
|
||||
#include "ConsoleWxWidgets/ConsoleWxWidgets.hpp"
|
||||
#include "ConsoleFIO/ConsoleFIO.hpp"
|
||||
@ -22,7 +23,7 @@ namespace Aurora::Console
|
||||
|
||||
static AuSPtr<ILogger> CreateDefaultLogger()
|
||||
{
|
||||
return {};
|
||||
return Logging::NewLoggerShared(gDefaultSinks);
|
||||
}
|
||||
|
||||
AUKN_SYM void WriteLine(AuUInt8 level, const ConsoleMessage &msg)
|
||||
@ -57,6 +58,16 @@ namespace Aurora::Console
|
||||
//gDefaultSinks.clear();
|
||||
}
|
||||
|
||||
AUKN_SYM void SetGlobalLogger(const AuSPtr<Logging::ILogger> &defaultGlobalLogger)
|
||||
{
|
||||
gUserLogger = defaultGlobalLogger;
|
||||
}
|
||||
|
||||
AUKN_SYM AuSPtr<Logging::ILogger> GetDefaultLogInterface()
|
||||
{
|
||||
return gDefaultLogger;
|
||||
}
|
||||
|
||||
AUKN_SYM AuUInt32 ReadStdIn(void *buffer, AuUInt32 length)
|
||||
{
|
||||
return ConsoleStd::ReadStdIn(buffer, length);
|
||||
@ -90,6 +101,7 @@ namespace Aurora::Console
|
||||
ConsoleFIO::Init();
|
||||
InitFlusher();
|
||||
FinailizeDefaultLogger();
|
||||
Logging::InitLoggers();
|
||||
}
|
||||
|
||||
void Pump()
|
||||
@ -102,10 +114,15 @@ namespace Aurora::Console
|
||||
|
||||
void Exit()
|
||||
{
|
||||
gDefaultSinks.clear();
|
||||
gDefaultLogger.reset();
|
||||
gUserLogger.reset();
|
||||
|
||||
DeinitFlusher();
|
||||
ConsoleStd::Exit();
|
||||
ConsoleWxWidgets::Exit();
|
||||
Logging::DeinitLoggers();
|
||||
ConsoleFIO::Exit();
|
||||
ConsoleWxWidgets::Exit();
|
||||
ConsoleStd::Exit();
|
||||
Hooks::Deinit();
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
namespace Aurora::Console
|
||||
{
|
||||
|
||||
void AddDefaultLogger(const AuSPtr<IBasicSink> &logger);
|
||||
|
||||
void Init();
|
||||
|
@ -7,12 +7,12 @@
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "ConsoleFIO.hpp"
|
||||
#include "FileSink.hpp"
|
||||
#include "../Console.hpp"
|
||||
|
||||
namespace Aurora::Console::ConsoleFIO
|
||||
{
|
||||
static AuList<AuUInt8> gLogBuffer;
|
||||
static AuThreadPrimitives::RWLockUnique_t gLogMutex;
|
||||
static AuIOFS::OpenWriteUnique_t gFileHandle;
|
||||
static IBasicSink * gFileSink;
|
||||
|
||||
static const auto &gLogConfig = gRuntimeConfig.console.fio;
|
||||
|
||||
@ -21,7 +21,7 @@ namespace Aurora::Console::ConsoleFIO
|
||||
AuString path;
|
||||
AuString procName;
|
||||
|
||||
if ((gLogConfig.writeLogsToUserDir) || (!IO::FS::GetProfileDomain(path)))
|
||||
if ((!gLogConfig.writeLogsToUserDir) || (!AuIOFS::GetProfileDomain(path)))
|
||||
{
|
||||
path = ".";
|
||||
}
|
||||
@ -53,7 +53,7 @@ namespace Aurora::Console::ConsoleFIO
|
||||
{
|
||||
try
|
||||
{
|
||||
if (IO::FS::Remove(path + "/" + files[i]))
|
||||
if (AuIOFS::Remove(path + "/" + files[i]))
|
||||
{
|
||||
x++;
|
||||
}
|
||||
@ -68,17 +68,17 @@ namespace Aurora::Console::ConsoleFIO
|
||||
static void CleanupOldLogs()
|
||||
{
|
||||
AuList<AuString> files;
|
||||
AuBST<AuString, IO::FS::Stat> fileMeta;
|
||||
AuBST<AuString, AuIOFS::Stat> fileMeta;
|
||||
AuUInt32 size {};
|
||||
|
||||
auto baseLogPath = GetLogDirectory();
|
||||
|
||||
IO::FS::FilesInDirectory(baseLogPath, files);
|
||||
AuIOFS::FilesInDirectory(baseLogPath, files);
|
||||
|
||||
for (const auto &file : files)
|
||||
{
|
||||
IO::FS::Stat stat;
|
||||
IO::FS::StatFile(baseLogPath + "/" + file, stat);
|
||||
AuIOFS::Stat stat;
|
||||
AuIOFS::StatFile(baseLogPath + "/" + file, stat);
|
||||
fileMeta[file] = stat;
|
||||
size += stat.size;
|
||||
}
|
||||
@ -94,20 +94,8 @@ namespace Aurora::Console::ConsoleFIO
|
||||
|
||||
void Flush()
|
||||
{
|
||||
/// It should be expected that the TLS teardown emergency flush to dispatch after deinit
|
||||
if (!gLogMutex)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AU_LOCK_GUARD(gLogMutex->AsReadable());
|
||||
|
||||
if (gFileHandle)
|
||||
{
|
||||
gFileHandle->Write(Aurora::Memory::MemoryViewStreamRead(gLogBuffer));
|
||||
}
|
||||
|
||||
gLogBuffer.clear();
|
||||
if (!gFileSink) return;
|
||||
gFileSink->OnFlush();
|
||||
}
|
||||
|
||||
static bool OpenLogFile()
|
||||
@ -121,8 +109,8 @@ namespace Aurora::Console::ConsoleFIO
|
||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
|
||||
gFileHandle = IO::FS::OpenWriteUnique(path);
|
||||
return static_cast<bool>(gFileHandle);
|
||||
gFileSink = NewFileSinkNew(path);
|
||||
return gFileSink;
|
||||
}
|
||||
|
||||
void FIOCleanup()
|
||||
@ -143,26 +131,7 @@ namespace Aurora::Console::ConsoleFIO
|
||||
return;
|
||||
}
|
||||
|
||||
gLogMutex = AuThreadPrimitives::RWLockUnique();
|
||||
if (!gLogMutex)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Console::Hooks::AddFunctionalHook([&](const Console::ConsoleMessage &string) -> void
|
||||
{
|
||||
AU_LOCK_GUARD(gLogMutex->AsWritable());
|
||||
auto str = string.ToSimplified();
|
||||
|
||||
gLogBuffer.reserve(gLogBuffer.size() + str.size() + 2);
|
||||
|
||||
gLogBuffer.insert(gLogBuffer.end(), reinterpret_cast<AuUInt8 *>(str.data()), reinterpret_cast<AuUInt8 *>(str.data()) + str.size());
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
gLogBuffer.insert(gLogBuffer.end(), AuUInt8('\r'));
|
||||
#endif
|
||||
gLogBuffer.insert(gLogBuffer.end(), AuUInt8('\n'));
|
||||
});
|
||||
Console::AddDefaultLogger(AuUnsafeRaiiToShared(gFileSink));
|
||||
}
|
||||
|
||||
void Pump()
|
||||
@ -173,7 +142,10 @@ namespace Aurora::Console::ConsoleFIO
|
||||
void Exit()
|
||||
{
|
||||
Flush();
|
||||
gLogMutex.reset();
|
||||
gFileHandle.reset();
|
||||
if (gFileSink)
|
||||
{
|
||||
NewFileSinkDestroy(gFileSink);
|
||||
gFileSink = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
88
Source/Console/ConsoleFIO/FileSink.cpp
Normal file
88
Source/Console/ConsoleFIO/FileSink.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: FileSink.cpp
|
||||
Date: 2022-1-24
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "FileSink.hpp"
|
||||
|
||||
namespace Aurora::Console::ConsoleFIO
|
||||
{
|
||||
FIOSink::FIOSink(const AuString &path) : path_(path)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool FIOSink::Init()
|
||||
{
|
||||
logMutex_ = AuThreadPrimitives::RWLockUnique();
|
||||
file_ = AuIOFS::OpenWriteUnique(path_);
|
||||
return static_cast<bool>(file_);
|
||||
}
|
||||
|
||||
void FIOSink::OnMessageBlocking(AuUInt8 level, const ConsoleMessage &msg)
|
||||
{
|
||||
AU_LOCK_GUARD(logMutex_->AsWritable());
|
||||
auto str = msg.ToSimplified();
|
||||
|
||||
logBuffer_.reserve(logBuffer_.size() + str.size() + 2);
|
||||
|
||||
logBuffer_.insert(logBuffer_.end(), reinterpret_cast<AuUInt8 *>(str.data()), reinterpret_cast<AuUInt8 *>(str.data()) + str.size());
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
logBuffer_.insert(logBuffer_.end(), AuUInt8('\r'));
|
||||
#endif
|
||||
logBuffer_.insert(logBuffer_.end(), AuUInt8('\n'));
|
||||
}
|
||||
|
||||
void FIOSink::OnMessageNonblocking(AuUInt8 level, const ConsoleMessage &msg)
|
||||
{
|
||||
}
|
||||
|
||||
void FIOSink::OnFlush()
|
||||
{
|
||||
if (!logMutex_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AU_LOCK_GUARD(logMutex_->AsReadable());
|
||||
|
||||
if (logMutex_)
|
||||
{
|
||||
file_->Write(Aurora::Memory::MemoryViewStreamRead(logBuffer_));
|
||||
}
|
||||
|
||||
logBuffer_.clear();
|
||||
}
|
||||
|
||||
IBasicSink *NewFileSinkNew(const AuString &str)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto logger = _new FIOSink(str);
|
||||
if (!logger)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!logger->Init())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return logger;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void NewFileSinkRelease(IBasicSink *logger)
|
||||
{
|
||||
SafeDelete<FIOSink *>(logger);
|
||||
}
|
||||
}
|
31
Source/Console/ConsoleFIO/FileSink.hpp
Normal file
31
Source/Console/ConsoleFIO/FileSink.hpp
Normal file
@ -0,0 +1,31 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: FileSink.hpp
|
||||
Date: 2022-1-24
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Console::ConsoleFIO
|
||||
{
|
||||
struct FIOSink : IBasicSink
|
||||
{
|
||||
FIOSink(const AuString &path);
|
||||
|
||||
bool Init();
|
||||
|
||||
void OnMessageBlocking(AuUInt8 level, const ConsoleMessage &msg) override;
|
||||
void OnMessageNonblocking(AuUInt8 level, const ConsoleMessage &msg) override;
|
||||
void OnFlush() override;
|
||||
|
||||
private:
|
||||
const AuString path_;
|
||||
AuIOFS::OpenWriteUnique_t file_;
|
||||
AuList<AuUInt8> logBuffer_;
|
||||
AuThreadPrimitives::RWLockUnique_t logMutex_;
|
||||
};
|
||||
|
||||
void NewFileSinkRelease(IBasicSink *logger);
|
||||
IBasicSink *NewFileSinkNew(const AuString &str);
|
||||
}
|
@ -29,6 +29,8 @@ namespace Aurora::Console
|
||||
};
|
||||
|
||||
AuString ConsoleMessage::StringifyTime(bool simple) const
|
||||
{
|
||||
try
|
||||
{
|
||||
std::tm localized;
|
||||
|
||||
@ -43,6 +45,11 @@ namespace Aurora::Console
|
||||
return fmt::format("{:%Y-%m-%d %H:%M:%S}", localized);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
AuString ConsoleMessage::GetWrappedTag() const
|
||||
{
|
||||
@ -51,11 +58,33 @@ namespace Aurora::Console
|
||||
|
||||
AuString ConsoleMessage::ToConsole() const
|
||||
{
|
||||
return fmt::format("{}[{}] {:<7} | {}{}", kAnsiCheats[static_cast<size_t>(color)], StringifyTime(), GetWrappedTag(), line, kAnsiCheats[static_cast<size_t>(EAnsiColor::eReset)]);
|
||||
try
|
||||
{
|
||||
return fmt::format("{}[{}] {:<7} | {}{}",
|
||||
static_cast<EAnsiColor>(color) <= EAnsiColor::eCount ?
|
||||
kAnsiCheats[static_cast<size_t>(color)] :
|
||||
"",
|
||||
StringifyTime(),
|
||||
GetWrappedTag(),
|
||||
line,
|
||||
kAnsiCheats[static_cast<size_t>(EAnsiColor::eReset)]);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AuString ConsoleMessage::ToSimplified() const
|
||||
{
|
||||
try
|
||||
{
|
||||
return fmt::format("{:<9} {:<7} | {}", StringifyTime(true), GetWrappedTag(), line);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,8 @@
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "ConsoleStd.hpp"
|
||||
#include "Source/Locale/Locale.hpp"
|
||||
#include <Source/Locale/Locale.hpp>
|
||||
#include <Source/Console/Console.hpp>
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED) || defined(AURORA_IS_POSIX_DERIVED)
|
||||
|
||||
@ -77,6 +78,43 @@ namespace Aurora::Console::ConsoleStd
|
||||
}
|
||||
#endif
|
||||
|
||||
static void WriteStdOut(AuUInt8 level, const ConsoleMessage &msg);
|
||||
|
||||
struct ConsoleStdLogger : IBasicSink
|
||||
{
|
||||
void OnMessageBlocking(AuUInt8 level, const ConsoleMessage &msg) override;
|
||||
void OnMessageNonblocking(AuUInt8 level, const ConsoleMessage &msg) override;
|
||||
void OnFlush() override;
|
||||
};
|
||||
|
||||
void ConsoleStdLogger::OnMessageBlocking(AuUInt8 level, const ConsoleMessage &msg)
|
||||
{
|
||||
if (!gRuntimeConfig.console.asyncWrite) return;
|
||||
WriteStdOut(level, msg);
|
||||
}
|
||||
|
||||
void ConsoleStdLogger::OnMessageNonblocking(AuUInt8 level, const ConsoleMessage &msg)
|
||||
{
|
||||
if (gRuntimeConfig.console.asyncWrite) return;
|
||||
WriteStdOut(level, msg);
|
||||
}
|
||||
|
||||
void ConsoleStdLogger::OnFlush()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static ConsoleStdLogger gStdConsoleSink;
|
||||
|
||||
IBasicSink *NewStdSinkNew()
|
||||
{
|
||||
return &gStdConsoleSink;
|
||||
}
|
||||
|
||||
void NewStdSinkRelease(IBasicSink *registry)
|
||||
{}
|
||||
|
||||
|
||||
static void StartLogger()
|
||||
{
|
||||
if (gRuntimeConfig.console.enableStdPassthrough && gRuntimeConfig.console.enableStdOut)
|
||||
@ -84,51 +122,12 @@ namespace Aurora::Console::ConsoleStd
|
||||
return;
|
||||
}
|
||||
|
||||
Console::Hooks::AddFunctionalHook([](const Aurora::Console::ConsoleMessage &string) -> void
|
||||
{
|
||||
#if (defined(DEBUG) || defined(STAGING)) && defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
auto debugLine = string.ToSimplified() + "\r\n";
|
||||
OutputDebugStringW(Locale::ConvertFromUTF8(debugLine).c_str());
|
||||
#endif
|
||||
|
||||
if (!gRuntimeConfig.console.enableStdOut)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto writeLine = string.ToConsole();
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
writeLine += '\r';
|
||||
#endif
|
||||
writeLine += '\n';
|
||||
|
||||
#if defined(IO_POSIX_STREAMS)
|
||||
if (Locale::GetInternalCodePage() == Locale::ECodePage::eUTF8)
|
||||
{
|
||||
WriteStdOut(writeLine.data(), writeLine.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
AuString slow;
|
||||
slow.resize(writeLine.size() * 4);
|
||||
auto len = Locale::Encoding::EncodeUTF8(writeLine, Aurora::Memory::MemoryViewWrite {slow.data(), slow.size()}, Locale::ECodePage::eSysUnk);
|
||||
if (len.first != 0)
|
||||
{
|
||||
WriteStdOut(slow.data(), len.second);
|
||||
}
|
||||
else
|
||||
{
|
||||
// better write this than nothing
|
||||
WriteStdOut(writeLine.data(), writeLine.size());
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
WriteStdOut(writeLine.data(), writeLine.size());
|
||||
#endif
|
||||
|
||||
});
|
||||
Console::AddDefaultLogger(AuUnsafeRaiiToShared(&gStdConsoleSink));
|
||||
}
|
||||
|
||||
void Start()
|
||||
@ -288,6 +287,46 @@ namespace Aurora::Console::ConsoleStd
|
||||
return written;
|
||||
}
|
||||
|
||||
static void WriteStdOut(AuUInt8 level, const ConsoleMessage &msg)
|
||||
{
|
||||
#if (defined(DEBUG) || defined(STAGING)) && defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
auto debugLine = msg.ToSimplified() + "\r\n";
|
||||
OutputDebugStringW(Locale::ConvertFromUTF8(debugLine).c_str());
|
||||
#endif
|
||||
|
||||
auto writeLine = msg.ToConsole();
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
writeLine += '\r';
|
||||
#endif
|
||||
writeLine += '\n';
|
||||
|
||||
#if defined(IO_POSIX_STREAMS)
|
||||
if (Locale::GetInternalCodePage() == Locale::ECodePage::eUTF8)
|
||||
{
|
||||
WriteStdOut(writeLine.data(), writeLine.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
AuString slow;
|
||||
slow.resize(writeLine.size() * 4);
|
||||
auto len = Locale::Encoding::EncodeUTF8(writeLine, Aurora::Memory::MemoryViewWrite {slow.data(), slow.size()}, Locale::ECodePage::eSysUnk);
|
||||
if (len.first != 0)
|
||||
{
|
||||
WriteStdOut(slow.data(), len.second);
|
||||
}
|
||||
else
|
||||
{
|
||||
// better write this than nothing
|
||||
WriteStdOut(writeLine.data(), writeLine.size());
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
WriteStdOut(writeLine.data(), writeLine.size());
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool InputStreamAvailable()
|
||||
{
|
||||
#if defined(IO_POSIX_STREAMS)
|
||||
|
@ -15,6 +15,10 @@ namespace Aurora::Console::ConsoleStd
|
||||
|
||||
void Start();
|
||||
|
||||
|
||||
IBasicSink *NewStdSinkNew();
|
||||
void NewStdSinkRelease(IBasicSink *registry);
|
||||
|
||||
AuUInt32 ReadStdIn(void *data, AuUInt32 length);
|
||||
AuUInt32 WriteStdOut(const void *data, AuUInt32 length);
|
||||
}
|
@ -605,7 +605,7 @@ void ConsoleFrame::OnAbout(wxCommandEvent &event)
|
||||
|
||||
void ConsoleFrame::OnHello(wxCommandEvent &event)
|
||||
{
|
||||
LogGame("nani?!");
|
||||
AuLogGame("nani?!");
|
||||
}
|
||||
|
||||
void ConsoleFrame::OnBugWrite(wxCommandEvent &event)
|
||||
|
@ -9,10 +9,13 @@
|
||||
#include "Flusher.hpp"
|
||||
|
||||
#include "ConsoleFIO/ConsoleFIO.hpp"
|
||||
#include "Logging/Logger.hpp"
|
||||
|
||||
namespace Aurora::Console
|
||||
{
|
||||
static AuThreads::ThreadUnique_t gWriterThread;
|
||||
static AuThreadPrimitives::ConditionVariableUnique_t gCondVar;
|
||||
static AuThreadPrimitives::ConditionMutexUnique_t gMutex;
|
||||
|
||||
class ShutdownFlushHook : public AuThreads::IThreadFeature
|
||||
{
|
||||
@ -38,13 +41,13 @@ namespace Aurora::Console
|
||||
|
||||
static void LogThreadEP()
|
||||
{
|
||||
auto thread = AuThreads::GetThread();
|
||||
|
||||
SlowStartupTasks();
|
||||
|
||||
while (!thread->Exiting())
|
||||
AU_LOCK_GUARD(gMutex);
|
||||
|
||||
while (AuIsThreadRunning())
|
||||
{
|
||||
Threading::Sleep(500);
|
||||
gCondVar->WaitForSignal(500);
|
||||
ForceFlush();
|
||||
}
|
||||
}
|
||||
@ -57,16 +60,17 @@ namespace Aurora::Console
|
||||
static void InitFlushThread()
|
||||
{
|
||||
// Startup a runner thread that will take care of all the stress inducing IO every so often on a remote thread
|
||||
|
||||
gWriterThread = AuThreads::ThreadUnique(AuThreads::ThreadInfo(
|
||||
AuMakeShared<AuThreads::IThreadVectorsFunctional>(AuThreads::IThreadVectorsFunctional::OnEntry_t(std::bind(LogThreadEP)),
|
||||
AuThreads::IThreadVectorsFunctional::OnExit_t{}),
|
||||
"CasualConsoleAsyncWritter"
|
||||
));
|
||||
|
||||
if (!gWriterThread)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gWriterThread->Run();
|
||||
}
|
||||
|
||||
@ -75,9 +79,23 @@ namespace Aurora::Console
|
||||
// Add a 'ShutdownFlushHook' object to the main threads TLS hook
|
||||
AuThreads::GetThread()->AddLastHopeTlsHook(AuMakeShared<ShutdownFlushHook>());
|
||||
|
||||
gMutex = AuThreadPrimitives::ConditionMutexUnique();
|
||||
SysAssert(gMutex);
|
||||
|
||||
gCondVar = AuThreadPrimitives::ConditionVariableUnique(AuUnsafeRaiiToShared(gMutex));
|
||||
SysAssert(gCondVar);
|
||||
|
||||
InitFlushThread();
|
||||
}
|
||||
|
||||
void PingFlushers()
|
||||
{
|
||||
if (gCondVar)
|
||||
{
|
||||
gCondVar->Signal();
|
||||
}
|
||||
}
|
||||
|
||||
void DeinitFlusher()
|
||||
{
|
||||
DestroyFlushThread();
|
||||
@ -85,6 +103,7 @@ namespace Aurora::Console
|
||||
|
||||
void ForceFlush()
|
||||
{
|
||||
Logging::ForceFlushLoggers();
|
||||
ConsoleFIO::Flush();
|
||||
}
|
||||
}
|
@ -9,6 +9,8 @@
|
||||
|
||||
namespace Aurora::Console
|
||||
{
|
||||
void PingFlushers();
|
||||
|
||||
void ForceFlush();
|
||||
void InitFlusher();
|
||||
void DeinitFlusher();
|
||||
|
@ -0,0 +1,235 @@
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "Logger.hpp"
|
||||
|
||||
namespace Aurora::Console::Logging
|
||||
{
|
||||
static AuList<AuTuple<Logger *, AuUInt8, ConsoleMessage>> gLogTasks;
|
||||
static AuThreadPrimitives::SpinLock gGlobalSpin;
|
||||
static AuList<Logger *> gFlushableLoggers;
|
||||
|
||||
Logger::Logger(const AuList<AuSPtr<IBasicSink>> &sinks) : sinks(sinks)
|
||||
{
|
||||
AuMemset(shouldFilter, 0, sizeof(shouldFilter));
|
||||
{
|
||||
AU_LOCK_GUARD(gGlobalSpin);
|
||||
AuTryInsert(gFlushableLoggers, this);
|
||||
}
|
||||
}
|
||||
|
||||
Logger::~Logger()
|
||||
{
|
||||
Disable();
|
||||
}
|
||||
|
||||
void Logger::WriteMessage(AuUInt8 level, const ConsoleMessage &msg)
|
||||
{
|
||||
{
|
||||
AU_LOCK_GUARD(spin);
|
||||
|
||||
if (shouldFilter[level])
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
AddToPushQueue(level, msg);
|
||||
WriteNow(level, msg);
|
||||
}
|
||||
|
||||
void Logger::AddToPushQueue(AuUInt8 level, const ConsoleMessage &msg)
|
||||
{
|
||||
AU_LOCK_GUARD(gGlobalSpin);
|
||||
|
||||
while (!AuTryInsert(gLogTasks, AuMakeTuple(this, level, msg)))
|
||||
{
|
||||
SysPushErrorMem("Push failed - trying again");
|
||||
spin.Unlock();
|
||||
AuThreading::Sleep(100);
|
||||
spin.Lock();
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::PushFilter(AuUInt8 level, bool shouldFilter)
|
||||
{
|
||||
AU_LOCK_GUARD(spin);
|
||||
|
||||
try
|
||||
{
|
||||
while (!AuTryInsert(filters, AuMakeTuple(level, shouldFilter)))
|
||||
{
|
||||
SysPushErrorMem("Push failed - trying again. wont be able to handle pop - wont syspanic yet");
|
||||
AuThreading::Sleep(100);
|
||||
}
|
||||
|
||||
AuMemset(this->shouldFilter, 0, sizeof(this->shouldFilter));
|
||||
|
||||
for (auto &tuple : filters)
|
||||
{
|
||||
auto level = std::get<0>(tuple);
|
||||
auto shouldFilter = std::get<1>(tuple);
|
||||
this->shouldFilter[level] = shouldFilter;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::PopFilter()
|
||||
{
|
||||
try
|
||||
{
|
||||
AU_LOCK_GUARD(spin);
|
||||
filters.pop_back();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ForceFlushLoggers()
|
||||
{
|
||||
AU_LOCK_GUARD(gGlobalSpin);
|
||||
decltype(gLogTasks) logTasks;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
logTasks = AuExchange(gLogTasks, {});
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (logTasks.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
for (const auto &logEntry : logTasks)
|
||||
{
|
||||
auto &logger = std::get<0>(logEntry);
|
||||
auto &level = std::get<1>(logEntry);
|
||||
auto &message = std::get<2>(logEntry);
|
||||
|
||||
logger->WriteLater(level, message);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
for (const auto &logger : gFlushableLoggers)
|
||||
{
|
||||
for (const auto &sink : logger->sinks)
|
||||
{
|
||||
try
|
||||
{
|
||||
sink->OnFlush();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
SysPushErrorGeneric("...");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::Disable()
|
||||
{
|
||||
{
|
||||
AU_LOCK_GUARD(spin);
|
||||
AuMemset(shouldFilter, 1, sizeof(shouldFilter));
|
||||
}
|
||||
|
||||
{
|
||||
AU_LOCK_GUARD(gGlobalSpin);
|
||||
AuTryDeleteList(gFlushableLoggers, this);
|
||||
}
|
||||
|
||||
ForceFlushLoggers();
|
||||
}
|
||||
|
||||
void Logger::WriteNow(AuUInt8 level, const ConsoleMessage &msg)
|
||||
{
|
||||
try
|
||||
{
|
||||
for (const auto &sink : this->sinks)
|
||||
{
|
||||
try
|
||||
{
|
||||
sink->OnMessageNonblocking(level, msg);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
SysPushErrorGeneric("Failed to pump a logger");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::WriteLater(AuUInt8 level, const ConsoleMessage &msg)
|
||||
{
|
||||
try
|
||||
{
|
||||
for (const auto &sink : this->sinks)
|
||||
{
|
||||
try
|
||||
{
|
||||
sink->OnMessageBlocking(level, msg);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
SysPushErrorGeneric("Failed to pump a logger");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void InitLoggers()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DeinitLoggers()
|
||||
{
|
||||
ForceFlushLoggers();
|
||||
}
|
||||
|
||||
AUKN_SYM ILogger *NewLoggerNew(const AuList<AuSPtr<IBasicSink>> &sinks)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto logger = _new Logger(sinks);
|
||||
if (!logger)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return logger;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
AUKN_SYM void NewLoggerRelease(ILogger *logger)
|
||||
{
|
||||
SafeDelete<Logger *>(logger);
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Console::Logging
|
||||
{
|
||||
struct Logger : ILogger
|
||||
{
|
||||
Logger(const AuList<AuSPtr<IBasicSink>> &sinks);
|
||||
~Logger();
|
||||
|
||||
void WriteMessage(AuUInt8 level, const ConsoleMessage &msg) override;
|
||||
|
||||
void PushFilter(AuUInt8 level, bool shouldFilter) override;
|
||||
void PopFilter() override;
|
||||
|
||||
void AddToPushQueue(AuUInt8 level, const ConsoleMessage &msg);
|
||||
void WriteNow(AuUInt8 level, const ConsoleMessage &msg);
|
||||
void WriteLater(AuUInt8 level, const ConsoleMessage &msg);
|
||||
|
||||
void Disable();
|
||||
|
||||
AuThreadPrimitives::SpinLock spin;
|
||||
AuList<AuSPtr<IBasicSink>> sinks;
|
||||
AuList<AuTuple<AuUInt8, bool>> filters; // std::vector > std::stack performance. dont ask me why or for the benchmarks, just trust me bro
|
||||
AuUInt8 shouldFilter[0xFF];
|
||||
};
|
||||
|
||||
void ForceFlushLoggers();
|
||||
|
||||
void DeinitLoggers();
|
||||
void InitLoggers();
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "Sinks.hpp"
|
||||
|
||||
#include "../ConsoleStd/ConsoleStd.hpp"
|
||||
#include "../ConsoleFIO/FileSink.hpp"
|
||||
|
||||
namespace Aurora::Console::Logging
|
||||
{
|
||||
AUKN_SYM IBasicSink *NewStdSinkNew()
|
||||
{
|
||||
return ConsoleStd::NewStdSinkNew();
|
||||
}
|
||||
|
||||
AUKN_SYM void NewStdSinkRelease(IBasicSink *sink)
|
||||
{
|
||||
ConsoleStd::NewStdSinkRelease(sink);
|
||||
}
|
||||
|
||||
AUKN_SYM IBasicSink *NewOSEventDirectorySinkNew()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
AUKN_SYM void NewOSEventDirectorySinkRelease(IBasicSink *registry)
|
||||
{}
|
||||
|
||||
AUKN_SYM IBasicSink *NewFileSinkNew(const AuString &path, bool binary)
|
||||
{
|
||||
return ConsoleFIO::NewFileSinkNew(path);
|
||||
}
|
||||
|
||||
AUKN_SYM void NewFileSinkRelease(IBasicSink *sink)
|
||||
{
|
||||
ConsoleFIO::NewFileSinkRelease(sink);
|
||||
}
|
||||
|
||||
AUKN_SYM IBasicSink *NewIPCSinkNew(const SocketConsole &console)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
AUKN_SYM void NewIPCSinkRelease(IBasicSink *registry)
|
||||
{}
|
||||
|
||||
|
||||
AUKN_SYM IBasicSinkRB *NewRingLoggerNew(AuUInt32 approxMaxBytes)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
AUKN_SYM void NewRingLoggerRelease(IBasicSinkRB *registry)
|
||||
{}
|
||||
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Console::Logging
|
||||
{
|
||||
|
||||
}
|
@ -16,12 +16,12 @@
|
||||
namespace Aurora::Debug
|
||||
{
|
||||
static thread_local AuUInt32 tlsLastBackTrace = 0xFFFFFFFF;
|
||||
static thread_local StackTrace tlsLastStackTrace;
|
||||
static thread_local AuString tlsLastExceptionMessage;
|
||||
|
||||
static StackTrace gLastStackTrace;
|
||||
static AuUInt32 gStackTraceFence;
|
||||
static AuUInt32 gFenceId;
|
||||
static AuThreadPrimitives::SpinLock gLock;
|
||||
static AuString gLastExceptionMessage;
|
||||
static AuUInt32 gFenceOSError = -1;
|
||||
|
||||
AuUInt32 GetOSErrorFence()
|
||||
@ -175,8 +175,8 @@ namespace Aurora::Debug
|
||||
AuUInt32 ReportStackTrace(const StackTrace& trace, const AuString& message)
|
||||
{
|
||||
AU_LOCK_GUARD(gLock);
|
||||
gLastStackTrace = trace;
|
||||
gLastExceptionMessage = message;
|
||||
tlsLastStackTrace = trace;
|
||||
tlsLastExceptionMessage = message;
|
||||
tlsLastBackTrace = gStackTraceFence++;
|
||||
gFenceId++;
|
||||
return tlsLastBackTrace;
|
||||
@ -195,13 +195,13 @@ namespace Aurora::Debug
|
||||
AUKN_SYM StackTrace GetLastStackTrace()
|
||||
{
|
||||
AU_LOCK_GUARD(gLock);
|
||||
return gLastStackTrace;
|
||||
return tlsLastStackTrace;
|
||||
}
|
||||
|
||||
AUKN_SYM AuString GetLastException()
|
||||
{
|
||||
AU_LOCK_GUARD(gLock);
|
||||
return gLastExceptionMessage;
|
||||
return tlsLastExceptionMessage;
|
||||
}
|
||||
|
||||
AUKN_SYM OSError_t GetLastSystemMessage()
|
||||
@ -223,7 +223,7 @@ namespace Aurora::Debug
|
||||
auto cError = TryGetOrFetchCError();
|
||||
if ((cError) && (cFence != cLastFence))
|
||||
{
|
||||
LogWarn("Language Error: {} ({})", strerror(*cError), *cError);
|
||||
AuLogWarn("Language Error: {} ({})", strerror(*cError), *cError);
|
||||
cLastFence = cFence;
|
||||
}
|
||||
|
||||
@ -232,7 +232,7 @@ namespace Aurora::Debug
|
||||
auto osError = TryGetOrFetchOSError();
|
||||
if ((osError) && (osFence != osLastFence))
|
||||
{
|
||||
LogWarn("Operating System Error: {} (0x{:x})", osError->second, osError->first);
|
||||
AuLogWarn("Operating System Error: {} (0x{:x})", osError->second, osError->first);
|
||||
osLastFence = osFence;
|
||||
}
|
||||
|
||||
@ -245,7 +245,7 @@ namespace Aurora::Debug
|
||||
Telemetry::EndBlock();
|
||||
}
|
||||
|
||||
void CheckErrors()
|
||||
AUKN_SYM void CheckErrors()
|
||||
{
|
||||
AuUInt32 rng = GetFenceId();
|
||||
Telemetry::BeginBlock();
|
||||
@ -301,7 +301,7 @@ namespace Aurora::Debug
|
||||
|
||||
#if defined(DEBUG) || defined(STAGING)
|
||||
PrintError();
|
||||
LogWarn("ERROR: {}", error.dbg);
|
||||
AuLogWarn("ERROR: {}", error.dbg);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -310,9 +310,11 @@ namespace Aurora::Debug
|
||||
const auto frame = *this;
|
||||
AuString backTraceBuffer;
|
||||
|
||||
try
|
||||
{
|
||||
backTraceBuffer.reserve(512 - 32); // 512 seems like a nice length minus some overhead for a bucket allocator
|
||||
|
||||
backTraceBuffer += fmt::format("\tAddress: {:x}", frame.address);
|
||||
backTraceBuffer += fmt::format("\tAddress: 0x{:x} (0x{:x})", frame.relAddress ? frame.relAddress : frame.address, frame.relAddress ? frame.address : frame.relAddress);
|
||||
|
||||
if (frame.module)
|
||||
{
|
||||
@ -352,11 +354,18 @@ namespace Aurora::Debug
|
||||
|
||||
return backTraceBuffer;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
AUKN_SYM AuString StringifyStackTrace(const StackTrace &backtrace)
|
||||
{
|
||||
AuString backTraceBuffer;
|
||||
|
||||
try
|
||||
{
|
||||
backTraceBuffer.reserve(2048);
|
||||
|
||||
backTraceBuffer += "Unwinding call frame:";
|
||||
@ -369,6 +378,11 @@ namespace Aurora::Debug
|
||||
|
||||
return backTraceBuffer;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void InitDebug()
|
||||
{
|
||||
|
@ -19,10 +19,33 @@
|
||||
#include <vcruntime_exception.h>
|
||||
#include <ehdata.h>
|
||||
|
||||
#include <Source/Process/ProcessMap.hpp>
|
||||
|
||||
static thread_local int gDebugLocked = 0;
|
||||
|
||||
namespace Aurora::Debug
|
||||
{
|
||||
static AuUInt GetImageBase(HMODULE mod)
|
||||
{
|
||||
if (!mod)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mod == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto cache = Process::GetFromModuleCache(reinterpret_cast<AuUInt>(mod));
|
||||
if (!cache.moduleMeta)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cache.moduleMeta->origVa;
|
||||
}
|
||||
|
||||
static void ParseStack(CONTEXT *ctx, StackTrace &backTrace)
|
||||
{
|
||||
char buffer[sizeof(SYMBOL_INFO) + (MAX_SYM_NAME + 1) * sizeof(char)] = { 0 };
|
||||
@ -80,26 +103,17 @@ namespace Aurora::Debug
|
||||
pSymbol->MaxNameLen = MAX_SYM_NAME;
|
||||
|
||||
frameCurrent.address = stack.AddrPC.Offset;
|
||||
frameCurrent.relAddress = frameCurrent.address;
|
||||
|
||||
if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)(stack.AddrPC.Offset), &hModule))
|
||||
{
|
||||
if (hModule != NULL)
|
||||
{
|
||||
frameCurrent.module = Process::ModuleToPath(hModule);
|
||||
frameCurrent.relAddress = frameCurrent.relAddress - reinterpret_cast<AuUInt>(hModule) + GetImageBase(hModule);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
//if (SymFromAddr(process, (ULONG64)stack.AddrPC.Offset, &displacement, pSymbol))
|
||||
{
|
||||
//frameCurrent.label = pSymbol->Name;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(DEBUG) || defined(STAGING)
|
||||
IMAGEHLP_LINE64 line;
|
||||
DWORD disp;
|
||||
@ -336,8 +350,8 @@ namespace Aurora::Debug
|
||||
|
||||
if ((isCritical || isInternal) && (minimal == 0))
|
||||
{
|
||||
LogWarn("NT Exception: 0x{:x}, {}", ExceptionInfo->ExceptionRecord->ExceptionCode, entry.wincxx.str);
|
||||
LogWarn("{}", StringifyStackTrace(entry.wincxx.stack.backtrace));
|
||||
AuLogWarn("NT Exception: 0x{:x}, {}", ExceptionInfo->ExceptionRecord->ExceptionCode, entry.wincxx.str);
|
||||
AuLogWarn("{}", StringifyStackTrace(entry.wincxx.stack.backtrace));
|
||||
}
|
||||
|
||||
try
|
||||
|
@ -24,6 +24,7 @@
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
#include "Extensions/Win32/DarkTheme.hpp"
|
||||
#endif
|
||||
#include "Process/ProcessMap.hpp"
|
||||
|
||||
static void Init()
|
||||
{
|
||||
@ -44,6 +45,7 @@ static void Init()
|
||||
Aurora::Async::InitAsync();
|
||||
Aurora::HWInfo::Init();
|
||||
Aurora::Telemetry::Init();
|
||||
Aurora::Process::InitProcessMap();
|
||||
}
|
||||
|
||||
static void Pump()
|
||||
@ -66,7 +68,14 @@ namespace Aurora
|
||||
AUKN_SYM void RuntimeStart(const RuntimeStartInfo &info)
|
||||
{
|
||||
gRuntimeConfig = info;
|
||||
try
|
||||
{
|
||||
Init();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
SysPanic("A fatal error occurred during the initialization of Aurora Runtime");
|
||||
}
|
||||
gRuntimeHasStarted = true;
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,10 @@
|
||||
#include <cpuid.h>
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
#include <VersionHelpers.h>
|
||||
#endif
|
||||
|
||||
namespace Aurora::HWInfo
|
||||
{
|
||||
static CpuInfo gCpuInfo;
|
||||
@ -348,10 +352,10 @@ namespace Aurora::HWInfo
|
||||
}
|
||||
|
||||
char vendor[0x20];
|
||||
memset(vendor, 0, sizeof(vendor));
|
||||
*reinterpret_cast<int*>(vendor) = cpuInfo.ebx;
|
||||
*reinterpret_cast<int*>(vendor + 4) = cpuInfo.edx;
|
||||
*reinterpret_cast<int*>(vendor + 8) = cpuInfo.ecx;
|
||||
AuMemset(vendor, 0, sizeof(vendor));
|
||||
*reinterpret_cast<AuUInt32 *>(vendor) = cpuInfo.ebx;
|
||||
*reinterpret_cast<AuUInt32 *>(vendor + 4) = cpuInfo.edx;
|
||||
*reinterpret_cast<AuUInt32 *>(vendor + 8) = cpuInfo.ecx;
|
||||
|
||||
gCpuInfo.cpuId.vendor = vendor;
|
||||
|
||||
@ -383,7 +387,7 @@ namespace Aurora::HWInfo
|
||||
auto nExIds = cpui.eax;
|
||||
|
||||
char brand[0x40];
|
||||
memset(brand, 0, sizeof(brand));
|
||||
AuMemset(brand, 0, sizeof(brand));
|
||||
|
||||
for (int i = 0x80000000; i <= nExIds; ++i)
|
||||
{
|
||||
@ -400,20 +404,112 @@ namespace Aurora::HWInfo
|
||||
// Interpret CPU brand string if reported
|
||||
if (nExIds >= 0x80000004)
|
||||
{
|
||||
memcpy(brand, &extdata[2], sizeof(cpui));
|
||||
memcpy(brand + 16, &extdata[3], sizeof(cpui));
|
||||
memcpy(brand + 32, &extdata[4], sizeof(cpui));
|
||||
AuMemcpy(brand, &extdata[2], sizeof(cpui));
|
||||
AuMemcpy(brand + 16, &extdata[3], sizeof(cpui));
|
||||
AuMemcpy(brand + 32, &extdata[4], sizeof(cpui));
|
||||
gCpuInfo.cpuId.brand = brand;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SetCpuTopology()
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
static bool IsWindowsLTSC()
|
||||
{
|
||||
OSVERSIONINFOEXW osvi = {sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0, VER_SUITE_ENTERPRISE, 0};
|
||||
DWORDLONG const dwlConditionMask = VerSetConditionMask(0, VER_SUITENAME, VER_EQUAL);
|
||||
|
||||
return !VerifyVersionInfoW(&osvi, VER_SUITENAME, dwlConditionMask);
|
||||
}
|
||||
|
||||
static bool TrySetNtCpuSetInfoSlowExtended()
|
||||
{
|
||||
SYSTEM_CPU_SET_INFORMATION cpuSetInfo[128];
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION sysinfo[128];
|
||||
DWORD length = {};
|
||||
|
||||
if (!GetSystemCpuSetInformation(cpuSetInfo, sizeof(cpuSetInfo), &length, 0, 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
struct CpuInfo
|
||||
{
|
||||
AuList<AuUInt8> low;
|
||||
AuList<CpuBitId> server;
|
||||
CpuBitId mask;
|
||||
};
|
||||
AuBST<AuUInt8, CpuInfo> cpuThreads;
|
||||
AuUInt8 cpuCount;
|
||||
|
||||
cpuCount = length / sizeof(decltype(*cpuSetInfo));
|
||||
|
||||
for (int i = 0; i < cpuCount; i++)
|
||||
{
|
||||
auto &idx = cpuThreads[cpuSetInfo[i].CpuSet.CoreIndex];
|
||||
AuUInt8 id = AuUInt8(cpuSetInfo[i].CpuSet.LogicalProcessorIndex + cpuSetInfo[i].CpuSet.Group);
|
||||
auto cpuId = CpuBitId(id);
|
||||
idx.server.push_back(cpuId);
|
||||
idx.low.push_back(id);
|
||||
idx.mask.Add(cpuId);
|
||||
}
|
||||
|
||||
for (const auto &[cpuId, coreIds] : cpuThreads)
|
||||
{
|
||||
AuUInt64 shortMask {};
|
||||
for (const auto &id : coreIds.server)
|
||||
{
|
||||
// TODO (scar):
|
||||
if (false)
|
||||
{
|
||||
gCpuInfo.maskECores.Add(id);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &id : coreIds.low)
|
||||
{
|
||||
shortMask |= AuUInt64(1) << AuUInt64(id);
|
||||
}
|
||||
|
||||
gCpuInfo.serverTopology.push_back(coreIds.mask);
|
||||
gCpuInfo.threadTopology.push_back(shortMask);
|
||||
}
|
||||
|
||||
gCpuInfo.socket = 1;
|
||||
gCpuInfo.threads = cpuCount;
|
||||
gCpuInfo.cores = cpuThreads.size();
|
||||
|
||||
if (!GetLogicalProcessorInformation(sysinfo, &length))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
gCpuInfo.socket = 0;
|
||||
length /= sizeof(*sysinfo);
|
||||
|
||||
for (auto i = 0; i < length; i++)
|
||||
{
|
||||
if (sysinfo[i].Relationship == RelationProcessorPackage)
|
||||
{
|
||||
gCpuInfo.socket++;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void SetCpuTopologyNT()
|
||||
{
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION sysinfo[128];
|
||||
DWORD length = AuArraySize(sysinfo) * sizeof(*sysinfo);
|
||||
|
||||
if (IsWindows10OrGreater() || IsWindowsServer() || IsWindowsLTSC())
|
||||
{
|
||||
if (TrySetNtCpuSetInfoSlowExtended())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!GetLogicalProcessorInformation(sysinfo, &length))
|
||||
{
|
||||
SYSTEM_INFO sysinfo;
|
||||
@ -430,15 +526,24 @@ namespace Aurora::HWInfo
|
||||
gCpuInfo.cores = 0;
|
||||
gCpuInfo.threads = 0;
|
||||
|
||||
|
||||
bool sparse = false;
|
||||
for (auto i = 0; i < length; i++)
|
||||
{
|
||||
if (sysinfo[i].Relationship == RelationProcessorCore)
|
||||
{
|
||||
//TODO: fuck it, if some macro fuckery, use popcnt on x86
|
||||
//we just need to count the bits. first it was just two BitScanForwards. discontiguous cores fucked things up so now we have a loop just to count a few bits.
|
||||
gCpuInfo.cores++;
|
||||
|
||||
auto mask = sysinfo[i].ProcessorMask;
|
||||
|
||||
gCpuInfo.cores++;
|
||||
gCpuInfo.threadTopology.push_back(mask);
|
||||
|
||||
CpuBitId serverId;
|
||||
serverId.lower = mask;
|
||||
gCpuInfo.serverTopology.push_back(mask);
|
||||
|
||||
// TODO: fuck it, if some macro fuckery, use popcnt on x86
|
||||
// we just need to count the bits. first it was just two BitScanForwards. discontiguous cores fucked things up so now we have a loop just to count a few bits.
|
||||
int counter {};
|
||||
unsigned long offset {}, tmp;
|
||||
while (offset != (sizeof(offset) * 8))
|
||||
{
|
||||
@ -450,6 +555,8 @@ namespace Aurora::HWInfo
|
||||
BitScanForward(&tmp, ~(mask >> offset));
|
||||
offset += tmp;
|
||||
|
||||
if (counter++) sparse = true;
|
||||
|
||||
// Increment threads by the bits set in
|
||||
gCpuInfo.threads += tmp;
|
||||
}
|
||||
@ -460,6 +567,15 @@ namespace Aurora::HWInfo
|
||||
}
|
||||
}
|
||||
|
||||
gCpuInfo.maskMTContig = !sparse;
|
||||
gCpuInfo.maskMTHalf = sparse;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void SetCpuTopology()
|
||||
{
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
SetCpuTopologyNT();
|
||||
#elif defined(AURORA_IS_BSD_DERIVED)
|
||||
|
||||
auto opt = QueryBsdHwStat(HW_AVAILCPU);
|
||||
@ -472,12 +588,18 @@ namespace Aurora::HWInfo
|
||||
gCpuInfo.cores = 1;
|
||||
gCpuInfo.threads = opt.value_or(1);
|
||||
|
||||
// TODO: parse sysctl kern.sched.topology_spec
|
||||
gCpuInfo.maskMTHalf = true;
|
||||
|
||||
#elif defined(AURORA_IS_LINUX_DERIVED)
|
||||
|
||||
gCpuInfo.socket = 1;
|
||||
gCpuInfo.cores = 1;
|
||||
gCpuInfo.threads = get_nprocs();
|
||||
|
||||
// TODO: parse /proc/cpuinfo
|
||||
gCpuInfo.maskMTHalf = true;
|
||||
|
||||
#elif defined(AURORA_IS_POSIX_DERIVED)
|
||||
|
||||
gCpuInfo.socket = 1;
|
||||
@ -487,10 +609,47 @@ namespace Aurora::HWInfo
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SetFakeTopologyIfMissing()
|
||||
{
|
||||
if (gCpuInfo.threadTopology.size() || gCpuInfo.serverTopology.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool fakeMtHalf = (gCpuInfo.threads & 1) == 0;
|
||||
gCpuInfo.maskMTHalf = true;
|
||||
|
||||
if (fakeMtHalf)
|
||||
{
|
||||
for (int i = 0; i < gCpuInfo.threads / 2; i++)
|
||||
{
|
||||
AuUInt64 shortMask {AuUInt64(1) << AuUInt64(i)}, shortMask2 {AuUInt64(1) << AuUInt64(i + gCpuInfo.threads / 2)};
|
||||
CpuBitId mask;
|
||||
mask.lower = shortMask | shortMask2;
|
||||
gCpuInfo.serverTopology.push_back(mask);
|
||||
gCpuInfo.threadTopology.push_back(shortMask);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < gCpuInfo.threads; i++)
|
||||
{
|
||||
AuUInt64 shortMask {AuUInt64(1) << AuUInt64(i)};
|
||||
CpuBitId mask;
|
||||
mask.lower = shortMask;
|
||||
gCpuInfo.serverTopology.push_back(mask);
|
||||
gCpuInfo.threadTopology.push_back(shortMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InitCpuInfo()
|
||||
{
|
||||
gCpuInfo.maskMTContig = false;
|
||||
gCpuInfo.maskMTHalf = false;
|
||||
gCpuInfo.cpuArch = Aurora::Build::kCurrentArchitecture;
|
||||
SetCpuId();
|
||||
SetCpuTopology();
|
||||
SetFakeTopologyIfMissing();
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,16 @@ namespace Aurora::IO::FS
|
||||
HANDLE fileHandle;
|
||||
|
||||
auto pathex = NormalizePathRet(path);
|
||||
if (!pathex.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto win32Path = Locale::ConvertFromUTF8(pathex);
|
||||
if (!win32Path.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
|
||||
|
||||
@ -109,7 +118,7 @@ namespace Aurora::IO::FS
|
||||
|
||||
if (fileHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
LogWarn("Missing file: {}", path);
|
||||
AuLogWarn("Missing file: {}", path);
|
||||
SysPushErrorIO("Missing file: {}", path);
|
||||
return {};
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ namespace Aurora::IO::FS
|
||||
{
|
||||
if (ENOENT == errno)
|
||||
{
|
||||
LogWarn("Critical IO error, errno = {}", path);
|
||||
AuLogWarn("Critical IO error, errno = {}", path);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -193,7 +193,7 @@ namespace Aurora::IO::FS
|
||||
|
||||
if (!stat.exists)
|
||||
{
|
||||
LogWarn("Missing attribute type of path {}, stat mode {}", path, s.st_mode);
|
||||
AuLogWarn("Missing attribute type of path {}, stat mode {}", path, s.st_mode);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,16 @@ namespace Aurora::IO::FS
|
||||
pathNormalized = NormalizePathRet(path);
|
||||
win32Path = Locale::ConvertFromUTF8(pathNormalized);
|
||||
|
||||
if (!pathNormalized.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!win32Path.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CreateDirectories(pathNormalized, true);
|
||||
|
||||
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
@ -106,6 +116,11 @@ namespace Aurora::IO::FS
|
||||
offset = 0;
|
||||
win32Path = Locale::ConvertFromUTF8(NormalizePathRet(path));
|
||||
|
||||
if (!win32Path.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto fileHandle = CreateFileW(win32Path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (fileHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
@ -133,7 +148,7 @@ namespace Aurora::IO::FS
|
||||
|
||||
if (!::ReadFile(fileHandle, &buffer[offset], blockSize, &read, NULL))
|
||||
{
|
||||
LogWarn("ReadFile IO Error: 0x{:x} {}", GetLastError(), path);
|
||||
AuLogWarn("ReadFile IO Error: 0x{:x} {}", GetLastError(), path);
|
||||
SysPushErrorIO();
|
||||
goto out;
|
||||
}
|
||||
@ -150,38 +165,80 @@ namespace Aurora::IO::FS
|
||||
}
|
||||
|
||||
AUKN_SYM bool FileExists(const AuString &path)
|
||||
{
|
||||
try
|
||||
{
|
||||
DWORD dwAttrib = GetFileAttributesW(Locale::ConvertFromUTF8(NormalizePathRet(path)).c_str());
|
||||
return ((dwAttrib != INVALID_FILE_ATTRIBUTES) &&
|
||||
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
AUKN_SYM bool DirExists(const AuString &path)
|
||||
{
|
||||
try
|
||||
{
|
||||
DWORD dwAttrib = GetFileAttributesW(Locale::ConvertFromUTF8(NormalizePathRet(path)).c_str());
|
||||
return ((dwAttrib != INVALID_FILE_ATTRIBUTES) &&
|
||||
(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
AUKN_SYM bool DirMk(const AuString &path)
|
||||
{
|
||||
try
|
||||
{
|
||||
return CreateDirectories(NormalizePathRet(path), false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
AUKN_SYM bool Remove(const AuString &path)
|
||||
{
|
||||
try
|
||||
{
|
||||
return DeleteFileW(Locale::ConvertFromUTF8(NormalizePathRet(path)).c_str());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
AUKN_SYM bool Relink(const AuString &src, const AuString &dest)
|
||||
{
|
||||
try
|
||||
{
|
||||
return MoveFileW(Locale::ConvertFromUTF8(NormalizePathRet(src)).c_str(), Locale::ConvertFromUTF8(NormalizePathRet(dest)).c_str());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
AUKN_SYM bool Copy(const AuString &src, const AuString &dest)
|
||||
{
|
||||
try
|
||||
{
|
||||
return CopyFileW(Locale::ConvertFromUTF8(NormalizePathRet(src)).c_str(), Locale::ConvertFromUTF8(NormalizePathRet(dest)).c_str(), true);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
AUKN_SYM bool StatFile(const AuString &path, Stat &stat)
|
||||
{
|
||||
|
@ -42,20 +42,36 @@ namespace Aurora::IO::FS
|
||||
void _NormalizePath(AuString &str);
|
||||
|
||||
static void NormalizePath(AuString &str)
|
||||
{
|
||||
try
|
||||
{
|
||||
_NormalizePath(str);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
str = {};
|
||||
}
|
||||
}
|
||||
|
||||
static inline AuString NormalizePathRet(const AuString &str)
|
||||
static auline AuString NormalizePathRet(const AuString &str)
|
||||
{
|
||||
try
|
||||
{
|
||||
AuString ret = str;
|
||||
_NormalizePath(ret);
|
||||
return ret;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
bool _MkDir(const AuString &str);
|
||||
|
||||
static bool CreateDirectories(const AuString &cpath, bool isFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < cpath.size(); i++)
|
||||
{
|
||||
@ -82,6 +98,11 @@ namespace Aurora::IO::FS
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IterateDirEntriesSTL(const AuString &path, bool filesOnly, AuList<AuString> &patches)
|
||||
{
|
||||
|
@ -189,7 +189,7 @@ namespace Aurora::IO::FS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LogWarn("Couldn't flush file stream");
|
||||
AuLogWarn("Couldn't flush file stream");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -39,7 +39,7 @@ namespace Aurora::IO::FS
|
||||
|
||||
if (SetFilePointerEx(handle_, distance, &pos, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
|
||||
{
|
||||
LogWarn("SetFilePointerEx IO Error: 0x{:x}, {}", GetLastError(), path_);
|
||||
AuLogWarn("SetFilePointerEx IO Error: 0x{:x}, {}", GetLastError(), path_);
|
||||
SysPushErrorIO();
|
||||
return 0;
|
||||
}
|
||||
@ -62,7 +62,7 @@ namespace Aurora::IO::FS
|
||||
|
||||
if (SetFilePointerEx(handle_, distance, &pos, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
|
||||
{
|
||||
LogWarn("SetFilePointerEx IO Error: 0x{:x}, {}", GetLastError(), path_);
|
||||
AuLogWarn("SetFilePointerEx IO Error: 0x{:x}, {}", GetLastError(), path_);
|
||||
SysPushErrorIO();
|
||||
return false;
|
||||
}
|
||||
@ -107,7 +107,7 @@ namespace Aurora::IO::FS
|
||||
|
||||
if (!::ReadFile(handle_, reinterpret_cast<char *>(parameters.ptr) + offset, blockSize, &read, NULL))
|
||||
{
|
||||
LogWarn("ReadFile IO Error: 0x{:x}, {}", GetLastError(), path_);
|
||||
AuLogWarn("ReadFile IO Error: 0x{:x}, {}", GetLastError(), path_);
|
||||
SysPushErrorIO();
|
||||
return false;
|
||||
}
|
||||
@ -148,7 +148,7 @@ namespace Aurora::IO::FS
|
||||
|
||||
if (!::WriteFile(handle_, reinterpret_cast<const char *>(parameters.ptr) + offset, blockSize, &written, NULL))
|
||||
{
|
||||
LogWarn("WriteFileEx IO Error: 0x{:x}, {}", GetLastError(), path_);
|
||||
AuLogWarn("WriteFileEx IO Error: 0x{:x}, {}", GetLastError(), path_);
|
||||
SysPushErrorIO();
|
||||
return false;
|
||||
}
|
||||
@ -195,9 +195,20 @@ namespace Aurora::IO::FS
|
||||
}
|
||||
|
||||
static IFileStream *OpenNew(const AuString &path, bool read)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto pathex = NormalizePathRet(path);
|
||||
if (pathex.empty())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto win32Path = Locale::ConvertFromUTF8(pathex);
|
||||
if (win32Path.empty())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HANDLE fileHandle;
|
||||
if (read)
|
||||
@ -212,7 +223,7 @@ namespace Aurora::IO::FS
|
||||
|
||||
if (fileHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
LogWarn("Missing file: {}", path);
|
||||
AuLogWarn("Missing file: {}", path);
|
||||
SysPushErrorIO("Missing file: {}", path);
|
||||
return nullptr;
|
||||
}
|
||||
@ -227,6 +238,11 @@ namespace Aurora::IO::FS
|
||||
stream->Init(fileHandle, pathex);
|
||||
return stream;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
AUKN_SYM IFileStream *OpenReadNew(const AuString &path)
|
||||
{
|
||||
|
@ -61,7 +61,7 @@ namespace Aurora::IO::FS
|
||||
|
||||
if (fileName.find("..") != AuString::npos)
|
||||
{
|
||||
LogWarn("Exploit Attempt? A system resource path may not contain relative directory move tokens: {}", fileName);
|
||||
AuLogWarn("Exploit Attempt? A system resource path may not contain relative directory move tokens: {}", fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -10,3 +10,14 @@
|
||||
#include "Encoding.hpp"
|
||||
#include "EncoderIConv.hpp"
|
||||
|
||||
namespace Aurora::Locale::Encoding
|
||||
{
|
||||
static void SanitizeIConvCharset(AuString &str)
|
||||
{
|
||||
if (AuStartsWith(str, "MS-"))
|
||||
str = "WINDOWS-" + str.substr(3);
|
||||
else if (AuToUpper(str) == AuToUpper("Latin-1"))
|
||||
str = "LATIN1";
|
||||
else str = AuToUpper(str);
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@
|
||||
|
||||
namespace Aurora::Locale::Encoding
|
||||
{
|
||||
AUKN_SYM BOM DecodeBOM(const AuMemoryViewRead & binary)
|
||||
AUKN_SYM BOM DecodeBOM(const AuMemoryViewRead &binary)
|
||||
{
|
||||
#define ADD_PATTERN(str, code) {str, {ECodePage::code, AuArraySize(str) - 1}}
|
||||
AuList<AuTuple<const char *, BOM>> bows =
|
||||
|
@ -31,11 +31,21 @@ namespace Aurora::Locale
|
||||
#endif
|
||||
|
||||
AUKN_SYM AuString ConvertFromWChar(const wchar_t *in)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ConvertFromWChar(in, wcslen(in));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
SysPushErrorMem("ConvertFromWChar failed");
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
AUKN_SYM AuString ConvertFromWChar(const wchar_t *in, AuMach length)
|
||||
{
|
||||
try
|
||||
{
|
||||
#if defined(AU_HAS_MSFT_NATIONALLANGSUPPORT)
|
||||
AuString ret;
|
||||
@ -52,11 +62,21 @@ namespace Aurora::Locale
|
||||
#elif !defined(AU_NO_CPPLOCALE)
|
||||
return gUtf8Conv.to_bytes(std::wstring(in, wcslen(in)));
|
||||
#else
|
||||
return false;
|
||||
SysPushErrorUnimplemented("ConvertFromWChar");
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
SysPushErrorMem("ConvertFromWChar failed");
|
||||
Debug::CheckErrors();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
AUKN_SYM std::wstring ConvertFromUTF8(const AuString &in)
|
||||
{
|
||||
try
|
||||
{
|
||||
#if defined(AU_HAS_MSFT_NATIONALLANGSUPPORT)
|
||||
std::wstring ret;
|
||||
@ -73,9 +93,17 @@ namespace Aurora::Locale
|
||||
#elif !defined(AU_NO_CPPLOCALE)
|
||||
return gUtf8Conv.from_bytes(in);
|
||||
#else
|
||||
return false;
|
||||
SysPushErrorUnimplemented("ConvertFromUTF8");
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
SysPushErrorMem("ConvertFromUTF8 failed");
|
||||
Debug::CheckErrors();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
ECodePage GetInternalCodePage()
|
||||
{
|
||||
@ -214,9 +242,9 @@ namespace Aurora::Locale
|
||||
|
||||
if (locale == "C")
|
||||
{
|
||||
LogWarn("Improperly configured UNIX environment.");
|
||||
LogWarn("This localization detection code was written in 2020, please follow the `language[_territory][.codeset][@modifier]` convention for user/sys locales.");
|
||||
LogWarn("'C' is not a language, country, or anything with which we can discern anything meaningful from. Fix your scuffed unix operating system and try again later...");
|
||||
AuLogWarn("Improperly configured UNIX environment.");
|
||||
AuLogWarn("This localization detection code was written in 2020, please follow the `language[_territory][.codeset][@modifier]` convention for user/sys locales.");
|
||||
AuLogWarn("'C' is not a language, country, or anything with which we can discern anything meaningful from. Fix your scuffed unix operating system and try again later...");
|
||||
SysPanic("You fools");
|
||||
}
|
||||
|
||||
@ -229,8 +257,8 @@ namespace Aurora::Locale
|
||||
}
|
||||
else
|
||||
{
|
||||
LogWarn("Improperly configured UNIX environment.");
|
||||
LogWarn("Couldn't discern language from localization string: {}", locale);
|
||||
AuLogWarn("Improperly configured UNIX environment.");
|
||||
AuLogWarn("Couldn't discern language from localization string: {}", locale);
|
||||
SysPanic("You fools");
|
||||
}
|
||||
|
||||
@ -343,9 +371,9 @@ namespace Aurora::Locale
|
||||
|
||||
gLanguageCode = AuToLower(gLanguageCode);
|
||||
gCountryCode = AuToUpper(gCountryCode);
|
||||
gCodeset = AuToUpper(gCodeset);
|
||||
gCodeset = gCodeset;
|
||||
|
||||
LogDbg("Initialized default localization information (language: {}, country: {}, codeset: {})", gLanguageCode, gCountryCode, gCodeset);
|
||||
AuLogDbg("Initialized default localization information (language: {}, country: {}, codeset: {})", gLanguageCode, gCountryCode, gCodeset);
|
||||
}
|
||||
|
||||
static bool gLockLocale = false;
|
||||
|
183
Source/Locale/LocaleStrings.cpp
Normal file
183
Source/Locale/LocaleStrings.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: LocaleStrings.cpp
|
||||
Date: 2022-1-23
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "LocaleStrings.hpp"
|
||||
|
||||
namespace Aurora::Locale
|
||||
{
|
||||
AUKN_SYM AuString NumbericLocaleGetDecimal()
|
||||
{
|
||||
return "."; //for.now
|
||||
}
|
||||
|
||||
AUKN_SYM AuString TimeLocaleGetDayChar()
|
||||
{
|
||||
return "d"; //for.now
|
||||
}
|
||||
|
||||
AUKN_SYM AuString TimeLocaleS()
|
||||
{
|
||||
return "s";
|
||||
}
|
||||
|
||||
AUKN_SYM AuString TimeLocaleGetMSChar()
|
||||
{
|
||||
return "ms"; //for.now
|
||||
}
|
||||
|
||||
static AuString &_TextPrepadZeroIfOne(AuString &in)
|
||||
{
|
||||
if (in.size() == 1) in.insert(in.begin(), '0');
|
||||
return in;
|
||||
}
|
||||
|
||||
static AuString _TextPrepadZeroIfOne(const AuString &in)
|
||||
{
|
||||
AuString ret = in;
|
||||
if (ret.size() == 1) ret.insert(ret.begin(), '0');
|
||||
return ret;
|
||||
}
|
||||
|
||||
static AuString _TextPrepadZeroMS(const AuString &in)
|
||||
{
|
||||
AuString ret = in;
|
||||
if (ret.size() == 1) ret.insert(0, "000", 3);
|
||||
else if (ret.size() == 2) ret.insert(0, "000", 2);
|
||||
else if (ret.size() == 3) ret.insert(0, "000", 1);
|
||||
while (ret.size() > 1 && ret[ret.size() - 1] == '0')
|
||||
ret.pop_back();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static AuString _TextPrepadZeroNS(const AuString &in)
|
||||
{
|
||||
AuString ret = in;
|
||||
switch (ret.size())
|
||||
{
|
||||
case 1: ret.insert(0, "000000", 6); break;
|
||||
case 2: ret.insert(0, "000000", 5); break;
|
||||
case 3: ret.insert(0, "000000", 4); break;
|
||||
case 4: ret.insert(0, "000000", 3); break;
|
||||
case 5: ret.insert(0, "000000", 2); break;
|
||||
case 6: ret.insert(0, "000000", 1); break;
|
||||
}
|
||||
while (ret.size() > 1 && ret[ret.size() - 1] == '0')
|
||||
ret.pop_back();
|
||||
return ret;
|
||||
}
|
||||
|
||||
AUKN_SYM AuString ConvertMSToTimescale(AuUInt32 ms)
|
||||
{
|
||||
const auto msDiv1000 = ms / 1000; // seconds
|
||||
const auto msDiv1000Mod60 = msDiv1000 % 60; // remaining seconds relative to next whole minute
|
||||
const auto msDiv1000Div60 = msDiv1000 / 60; // total minutes
|
||||
|
||||
try
|
||||
{
|
||||
if (ms < 1000)
|
||||
{
|
||||
return AuToString(ms) + TimeLocaleGetMSChar();
|
||||
}
|
||||
else if (ms < (1000 * 60))
|
||||
{
|
||||
auto s = msDiv1000;
|
||||
auto remMs = ms % 1000;
|
||||
return _TextPrepadZeroIfOne(AuToString(s)) + NumbericLocaleGetDecimal() + _TextPrepadZeroMS(AuToString(remMs)) + TimeLocaleS();
|
||||
}
|
||||
else if (ms < (1000 * 60 * 60))
|
||||
{
|
||||
auto m = msDiv1000Div60;
|
||||
auto remS = msDiv1000Mod60;
|
||||
return _TextPrepadZeroIfOne(AuToString(m)) + ":" + _TextPrepadZeroIfOne(AuToString(remS));
|
||||
}
|
||||
else if (ms < (1000 * 60 * 60 * 24))
|
||||
{
|
||||
auto h = msDiv1000Div60 / 60;
|
||||
auto remM = msDiv1000Div60;
|
||||
auto remS = msDiv1000Mod60;
|
||||
|
||||
return _TextPrepadZeroIfOne(AuToString(h)) + ":" + _TextPrepadZeroIfOne(AuToString(remM)) + ":" + _TextPrepadZeroIfOne(AuToString(remS));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto d = (msDiv1000Div60 / 60 / 24);
|
||||
auto h = (msDiv1000Div60 / 60) - (d * 24);
|
||||
auto remM = msDiv1000Div60;
|
||||
auto remS = msDiv1000Mod60;
|
||||
return AuToString(d) + TimeLocaleGetDayChar() + " " + _TextPrepadZeroIfOne(AuToString(h)) + ":" + _TextPrepadZeroIfOne(AuToString(remM)) + ":" + _TextPrepadZeroIfOne(AuToString(remS));
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
SysPushErrorGeneric("ConvertNSToTimescale failed -> returning empty string");
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
AUKN_SYM AuString ConvertNSToTimescale(AuUInt64 ns)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ns < AuUInt64(1000000000))
|
||||
{
|
||||
const auto ms = ns / 1000000;
|
||||
const auto remNs = ns % 1000000;
|
||||
return _TextPrepadZeroMS(AuToString(ms)) + NumbericLocaleGetDecimal() + _TextPrepadZeroNS(AuToString(remNs)) + TimeLocaleGetMSChar();
|
||||
}
|
||||
else
|
||||
{
|
||||
return ConvertMSToTimescale(ns / AuUInt64(1000000000));
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
SysPushErrorGeneric("ConvertNSToTimescale failed -> returning empty string");
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
AUKN_SYM AuString TimeDateToString(const Time::tm &time)
|
||||
{
|
||||
try
|
||||
{
|
||||
bool simple = time.tm_mday == 0 && time.tm_mon == 0 && time.tm_year == 0;
|
||||
if (simple)
|
||||
{
|
||||
return fmt::format("{:02}-{:02}-{:02}", time.tm_hour, time.tm_min, time.tm_sec);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hard-code ISO-8601 locale because, the larders locale doesn't make any sense whatsoever, and east asia has the right idea
|
||||
// EU users and burgers seethe... we normalize one standard to disambiguate this shit
|
||||
return fmt::format("{:{:04}-{:02}-{:02} {:02}-{:02}-{:02}}", time.tm_year + 1900, time.tm_mon + 1, time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
SysPushErrorGeneric("TimeDateToString failed -> returning empty string");
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
AUKN_SYM AuString TimeDateToISO8601(const Time::tm &time, AuTime::ETimezoneShift shift)
|
||||
{
|
||||
try
|
||||
{
|
||||
AuString tz {};
|
||||
auto tnorm = AuTime::NormalizeCivilTimezone(time, shift);
|
||||
return fmt::format("{:04}-{:02}-{:02}T{:02}-{:02}-{:02}Z",
|
||||
tnorm.tm_year + 1900, tnorm.tm_mon + 1, tnorm.tm_mday,
|
||||
tnorm.tm_hour, tnorm.tm_min, tnorm.tm_sec);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
SysPushErrorGeneric("TimeDateToISO8601 failed -> returning empty string");
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
8
Source/Locale/LocaleStrings.hpp
Normal file
8
Source/Locale/LocaleStrings.hpp
Normal file
@ -0,0 +1,8 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: LocaleStrings.hpp
|
||||
Date: 2022-1-23
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
@ -36,11 +36,6 @@ namespace Aurora::Loop
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!(ret = AuMakeShared<Mutex>(mutex)))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return ret;
|
||||
return AuMakeShared<Mutex>(mutex);
|
||||
}
|
||||
}
|
@ -37,11 +37,6 @@ namespace Aurora::Loop
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!(ret = AuMakeShared<Semaphore>(mutex)))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return ret;
|
||||
return AuMakeShared<Semaphore>(mutex);
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@ namespace Aurora::Loop
|
||||
AuList<HANDLE> handleArray;
|
||||
AuSPtr<ILoopSource> msgSource;
|
||||
|
||||
try
|
||||
{
|
||||
isWinLoop = false;
|
||||
loopSourceExs.reserve(objects.size());
|
||||
handleArray.reserve(objects.size());
|
||||
@ -48,6 +50,11 @@ namespace Aurora::Loop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
for (const auto &source : loopSourceExs)
|
||||
{
|
||||
@ -100,7 +107,7 @@ namespace Aurora::Loop
|
||||
|
||||
if (source->OnTrigger(lastHandle, wasTriggered))
|
||||
{
|
||||
triggered.push_back(source);
|
||||
AuTryInsert(triggered, source);
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,7 +116,7 @@ namespace Aurora::Loop
|
||||
|
||||
if (isPump)
|
||||
{
|
||||
triggered.push_back(msgSource);
|
||||
AuTryInsert(triggered, msgSource);
|
||||
}
|
||||
|
||||
return triggered;
|
||||
|
@ -20,7 +20,7 @@ namespace Aurora::Loop
|
||||
|
||||
if (handles.size() == 1)
|
||||
{
|
||||
return WaitForSingleObject(reinterpret_cast<HANDLE>(handles.at(0)), 0) == WAIT_OBJECT_0;
|
||||
return WaitForSingleObjectEx(reinterpret_cast<HANDLE>(handles.at(0)), 0, true) == WAIT_OBJECT_0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -30,7 +30,7 @@ namespace Aurora::Loop
|
||||
{
|
||||
ntHandles.push_back(reinterpret_cast<HANDLE>(handle));
|
||||
}
|
||||
return WaitForMultipleObjects(ntHandles.size(), ntHandles.data(), false, 0) >= WAIT_OBJECT_0;
|
||||
return WaitForMultipleObjectsEx(ntHandles.size(), ntHandles.data(), false, 0, true) >= WAIT_OBJECT_0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,8 +244,8 @@ namespace Aurora::Memory
|
||||
|
||||
if (count_)
|
||||
{
|
||||
LogWarn("Heap life was less than its allocations, waiting for final free");
|
||||
LogWarn("Reporting using mayday!");
|
||||
AuLogWarn("Heap life was less than its allocations, waiting for final free");
|
||||
AuLogWarn("Reporting using mayday!");
|
||||
Telemetry::Mayday();
|
||||
|
||||
isDangling_ = true;
|
||||
|
@ -23,7 +23,7 @@ namespace Aurora::Parse
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Console::Logging::LogWarn("Decoding error: {}", in);
|
||||
AuLogWarn("Decoding error: {}", in);
|
||||
Debug::PrintError();
|
||||
return false;
|
||||
}
|
||||
@ -41,7 +41,7 @@ namespace Aurora::Parse
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Console::Logging::LogWarn("Encoding error");
|
||||
AuLogWarn("Encoding error");
|
||||
Debug::PrintError();
|
||||
return false;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ namespace Aurora::Parse
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Console::Logging::LogWarn("Decoding error: {}", in);
|
||||
AuLogWarn("Decoding error: {}", in);
|
||||
Debug::PrintError();
|
||||
return false;
|
||||
}
|
||||
@ -61,7 +61,7 @@ namespace Aurora::Parse
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Console::Logging::LogWarn("Encoding error");
|
||||
AuLogWarn("Encoding error");
|
||||
Debug::PrintError();
|
||||
return false;
|
||||
}
|
||||
|
@ -196,11 +196,11 @@ namespace Aurora::Parse
|
||||
//SysAssert(!stringLevel, "Parsed tag of string type must end with \", got {}", out);
|
||||
if (stringLevel)
|
||||
{
|
||||
LogWarn("Parsed tag of string type must end with \", got {}", out);
|
||||
AuLogWarn("Parsed tag of string type must end with \", got {}", out);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Aurora::Console::Logging::LogDbg("returned {} {}", out, count != 0);
|
||||
//AuLogDbg("returned {} {}", out, count != 0);
|
||||
return out.size() != 0;
|
||||
}
|
||||
|
||||
@ -369,7 +369,7 @@ namespace Aurora::Parse
|
||||
uuid = uuids::uuid::from_string(str);
|
||||
if (!uuid.has_value())
|
||||
{
|
||||
LogWarn("Parse Error: invalid UUID {}", str);
|
||||
AuLogWarn("Parse Error: invalid UUID {}", str);
|
||||
return false;
|
||||
}
|
||||
out.UUID = uuid.value();
|
||||
@ -387,7 +387,7 @@ namespace Aurora::Parse
|
||||
}
|
||||
else
|
||||
{
|
||||
Aurora::Console::Logging::LogWarn("Parsed tag of boolean type wasn't parsable given the English string {}", str);
|
||||
AuLogWarn("Parsed tag of boolean type wasn't parsable given the English string {}", str);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@ -457,7 +457,7 @@ namespace Aurora::Parse
|
||||
|
||||
if (!ConsumeToken(state, context, ParsableTag::kParseUInt, arrayLengthBit))
|
||||
{
|
||||
Aurora::Console::Logging::LogWarn("Couldn't consume array length, label: {}, tag {}", parseBit.label, parseBit.tag);
|
||||
AuLogWarn("Couldn't consume array length, label: {}, tag {}", parseBit.label, parseBit.tag);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -505,7 +505,7 @@ namespace Aurora::Parse
|
||||
break;
|
||||
}
|
||||
|
||||
Aurora::Console::Logging::LogWarn("Syntax error around: label: {}, tag {}", parseBit.label, parseBit.tag);
|
||||
AuLogWarn("Syntax error around: label: {}, tag {}", parseBit.label, parseBit.tag);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ namespace Aurora::Process
|
||||
|
||||
for (const auto &name : procFsPaths)
|
||||
{
|
||||
if (Aurora::IO::FS::ReadString(name, path))
|
||||
if (AuIOFS::ReadString(name, path))
|
||||
{
|
||||
splitter = '/';
|
||||
return true;
|
||||
@ -138,8 +138,11 @@ namespace Aurora::Process
|
||||
{
|
||||
static AuString cachedModule, cachedPartialPath, cachedFullPath;
|
||||
static bool init = false;
|
||||
static AuThreadPrimitives::SpinLock spinlock;
|
||||
char spitter;
|
||||
|
||||
AU_TRY_LOCK_GUARD_RET_DEF(spinlock);
|
||||
|
||||
if (AuExchange(init, true))
|
||||
{
|
||||
if (!cachedModule.size())
|
||||
@ -178,12 +181,19 @@ namespace Aurora::Process
|
||||
{
|
||||
AuString module, partial, full;
|
||||
|
||||
try
|
||||
{
|
||||
if (!GetModulePath(module, partial, full))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
executable = module;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -192,6 +202,8 @@ namespace Aurora::Process
|
||||
{
|
||||
AuString module, partial, full;
|
||||
|
||||
try
|
||||
{
|
||||
if (!GetModulePath(module, partial, full))
|
||||
{
|
||||
return false;
|
||||
@ -203,6 +215,11 @@ namespace Aurora::Process
|
||||
{
|
||||
return GetWorkingDirectory(path);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -211,12 +228,19 @@ namespace Aurora::Process
|
||||
{
|
||||
AuString module, partial, full;
|
||||
|
||||
try
|
||||
{
|
||||
if (!GetModulePath(module, partial, full))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
path = full;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include <Source/IO/FS/FS.hpp>
|
||||
#include <Source/IO/FS/Resources.hpp>
|
||||
|
||||
#include "ProcessMap.hpp"
|
||||
|
||||
namespace Aurora::Process
|
||||
{
|
||||
static AuThreadPrimitives::SpinLock gSpinLock;
|
||||
@ -265,7 +267,7 @@ namespace Aurora::Process
|
||||
{
|
||||
fail = false;
|
||||
|
||||
auto pathNrml = IO::FS::NormalizePathRet(path);
|
||||
auto pathNrml = AuIOFS::NormalizePathRet(path);
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
auto widePath = Locale::ConvertFromUTF8(pathNrml);
|
||||
@ -278,7 +280,7 @@ namespace Aurora::Process
|
||||
return false;
|
||||
}
|
||||
|
||||
auto absPath = IO::FS::NormalizePathRet(abs);
|
||||
auto absPath = AuIOFS::NormalizePathRet(abs);
|
||||
#endif
|
||||
|
||||
if (request.verify || (kIsMainSigned || request.enableMitigations))
|
||||
@ -292,7 +294,7 @@ namespace Aurora::Process
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
LogWarn("Can't verify {} on this platform", path);
|
||||
AuLogWarn("Can't verify {} on this platform", path);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -342,7 +344,7 @@ namespace Aurora::Process
|
||||
AuString bAbs = path + "/" + genericDll + ".";
|
||||
#endif
|
||||
|
||||
if (Aurora::IO::FS::FileExists(a))
|
||||
if (AuIOFS::FileExists(a))
|
||||
{
|
||||
return TryLoadModule(a,
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
@ -353,7 +355,7 @@ namespace Aurora::Process
|
||||
);
|
||||
}
|
||||
|
||||
if (Aurora::IO::FS::FileExists(b))
|
||||
if (AuIOFS::FileExists(b))
|
||||
{
|
||||
return TryLoadModule(b,
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
@ -382,15 +384,15 @@ namespace Aurora::Process
|
||||
|
||||
break;
|
||||
case EModulePath::eModulePathSystemDir:
|
||||
pathA = IO::FS::GetSystemLibPath().value_or(AuString {});
|
||||
pathB = IO::FS::GetSystemLibPath2().value_or(AuString {});
|
||||
pathA = AuIOFS::GetSystemLibPath().value_or(AuString {});
|
||||
pathB = AuIOFS::GetSystemLibPath2().value_or(AuString {});
|
||||
|
||||
if (pathA.empty()) return false;
|
||||
|
||||
break;
|
||||
case EModulePath::eModulePathUserDir:
|
||||
pathA = IO::FS::GetUserLibPath().value_or(AuString {});
|
||||
pathB = IO::FS::GetUserLibPath2().value_or(AuString {});
|
||||
pathA = AuIOFS::GetUserLibPath().value_or(AuString {});
|
||||
pathB = AuIOFS::GetUserLibPath2().value_or(AuString {});
|
||||
|
||||
if (pathA.empty()) return false;
|
||||
|
||||
@ -532,6 +534,16 @@ namespace Aurora::Process
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO (reece): init, deinit
|
||||
// TODO (reece): test if self is signed
|
||||
|
||||
void InitProcess()
|
||||
{
|
||||
// TODO (reece): test if self is signed -> xref kIsMainSigned
|
||||
|
||||
InitProcessMap();
|
||||
}
|
||||
|
||||
void DeinitProcess()
|
||||
{
|
||||
DeinitProcessMap();
|
||||
}
|
||||
}
|
@ -9,5 +9,6 @@
|
||||
|
||||
namespace Aurora::Process
|
||||
{
|
||||
|
||||
void InitProcess();
|
||||
void DeinitProcess();
|
||||
}
|
306
Source/Process/ProcessMap.NT.cpp
Normal file
306
Source/Process/ProcessMap.NT.cpp
Normal file
@ -0,0 +1,306 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: UtilProcessMap.NT.cpp
|
||||
Date: 2022-1-24
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "ProcessMap.NT.hpp"
|
||||
#include "ProcessMap.hpp"
|
||||
|
||||
namespace Aurora::Process
|
||||
{
|
||||
static AuThreadPrimitives::MutexUnique_t gMutex;
|
||||
static AuBST<AuUInt, AuString> gPathCache;
|
||||
static AuBST<AuUInt, AuString> gModNameCache;
|
||||
|
||||
AuString ModuleToSomething(HMODULE handle, bool path)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::wstring file;
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
if (gMutex)
|
||||
{
|
||||
AU_LOCK_GUARD(gMutex);
|
||||
if (path)
|
||||
{
|
||||
auto itr = gPathCache.find(reinterpret_cast<AuUInt>(handle));
|
||||
if (itr != gPathCache.end()) return itr->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto itr = gModNameCache.find(reinterpret_cast<AuUInt>(handle));
|
||||
if (itr != gModNameCache.end()) return itr->second;
|
||||
}
|
||||
}
|
||||
|
||||
if (!AuTryResize(file, 16 * 1024))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
auto length = GetModuleFileNameW(handle, &file[0], file.size());
|
||||
if (!length)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
file.resize(length);
|
||||
|
||||
if (!path)
|
||||
{
|
||||
auto idx = file.find_last_of('\\');
|
||||
if (idx != std::wstring::npos)
|
||||
{
|
||||
file = file.substr(idx + 1);
|
||||
}
|
||||
}
|
||||
|
||||
auto ret = Locale::ConvertFromWChar(file.c_str(), file.length());
|
||||
|
||||
if (gMutex)
|
||||
{
|
||||
AU_LOCK_GUARD(gMutex);
|
||||
if (path)
|
||||
{
|
||||
AuTryInsert(gPathCache, AuMakePair(reinterpret_cast<AuUInt>(handle), ret));
|
||||
}
|
||||
else
|
||||
{
|
||||
AuTryInsert(gModNameCache, AuMakePair(reinterpret_cast<AuUInt>(handle), ret));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
AuString ModuleToName(HMODULE handle)
|
||||
{
|
||||
return ModuleToSomething(handle, false);
|
||||
}
|
||||
|
||||
AuString ModuleToPath(HMODULE handle)
|
||||
{
|
||||
return ModuleToSomething(handle, true);
|
||||
}
|
||||
|
||||
static AuUInt GetModuleBaseAddressFromPathGrossYesThisIsCached(HMODULE mod, const AuString &path)
|
||||
{
|
||||
if (path.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(mod);
|
||||
auto nt = &(reinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<AuUInt>(mod) + dosHeader->e_lfanew)->OptionalHeader.ImageBase);
|
||||
|
||||
auto offset = static_cast<AuUInt32>(reinterpret_cast<const AuUInt8 *>(nt) - reinterpret_cast<const AuUInt8 *>(mod));
|
||||
using Value_t = AuRemovePointer_t<decltype(nt)>;
|
||||
Value_t value {};
|
||||
|
||||
auto handle = CreateFileW(Locale::ConvertFromUTF8(path).c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE) return 0;
|
||||
|
||||
DWORD bytesRead {};
|
||||
|
||||
if (!SetFilePointer(handle, offset, NULL, 0))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!ReadFile(handle, &value, sizeof(Value_t), &bytesRead, NULL))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
if (bytesRead != sizeof(Value_t))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
return value;
|
||||
}
|
||||
|
||||
static void FetchModuleSegments(Segments &segments, AuUInt offset, HMODULE mod)
|
||||
{
|
||||
auto dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(mod);
|
||||
auto nt = reinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<AuUInt>(mod) + dosHeader->e_lfanew);
|
||||
|
||||
auto pSection = IMAGE_FIRST_SECTION(nt);
|
||||
auto pSectionCur = pSection;
|
||||
|
||||
for (auto i = 0; i < nt->FileHeader.NumberOfSections; i++)
|
||||
{
|
||||
auto cur = pSectionCur++;
|
||||
Segment seg;
|
||||
|
||||
seg.origVa = cur->VirtualAddress - reinterpret_cast<AuUInt>(mod) + offset;
|
||||
seg.baseVa = cur->VirtualAddress;
|
||||
seg.size = cur->SizeOfRawData;
|
||||
seg.fsOff = cur->PointerToRawData;
|
||||
|
||||
seg.pt.readable = cur->Characteristics & (IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE);
|
||||
seg.pt.NX = !(cur->Characteristics & IMAGE_SCN_MEM_EXECUTE);
|
||||
seg.pt.writable = cur->Characteristics & IMAGE_SCN_MEM_WRITE;
|
||||
|
||||
seg.name = AuString(cur->Name, cur->Name + strnlen(reinterpret_cast<const char *>(cur->Name), sizeof(cur->Name)));
|
||||
|
||||
AuTryInsert(segments, seg);
|
||||
}
|
||||
}
|
||||
|
||||
static AuSPtr<PublicModule> HandleToPublicModule(HMODULE h)
|
||||
{
|
||||
auto pub = AuMakeShared<PublicModule>();
|
||||
if (!pub) return {};
|
||||
pub->moduleMeta = AuMakeShared<ModuleMeta>();
|
||||
if (!pub->moduleMeta) return {};
|
||||
|
||||
pub->moduleMeta->moduleBase = AuUInt(h);
|
||||
pub->moduleMeta->moduleName = ModuleToName(h);
|
||||
pub->moduleMeta->modulePath = ModuleToPath(h);
|
||||
pub->moduleMeta->origVa = GetModuleBaseAddressFromPathGrossYesThisIsCached(h, pub->moduleMeta->modulePath);
|
||||
FetchModuleSegments(pub->segments, pub->moduleMeta->origVa, h);
|
||||
return pub;
|
||||
}
|
||||
|
||||
void InvaildateModule(HMODULE hmod)
|
||||
{
|
||||
if (!gMutex)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// acquire gmutex
|
||||
{
|
||||
AU_LOCK_GUARD(gMutex);
|
||||
auto itr1 = gPathCache.find(reinterpret_cast<AuUInt>(hmod));
|
||||
if (itr1 != gPathCache.end()) gPathCache.erase(itr1);
|
||||
|
||||
auto itr2 = gModNameCache.find(reinterpret_cast<AuUInt>(hmod));
|
||||
if (itr2 != gModNameCache.end()) gModNameCache.erase(itr2);
|
||||
}
|
||||
|
||||
// release lock
|
||||
{
|
||||
RemoveModuleCache({"", reinterpret_cast<AuUInt>(hmod)});
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool MakeAwarePtr(AuUInt pointer)
|
||||
{
|
||||
HMODULE handle;
|
||||
if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, reinterpret_cast<LPCWSTR>(pointer), &handle))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
MakeAware(handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
AuOptional<Segment> LookupArbitrarySegment(AuUInt address)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
Segment segment;
|
||||
|
||||
if (!VirtualQuery((LPCVOID)address, &info, sizeof(info)))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
segment.baseVa = reinterpret_cast<AuUInt>(info.BaseAddress);
|
||||
segment.size = info.RegionSize;
|
||||
segment.pt.NX = (info.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ)) == 0;
|
||||
segment.pt.writable = (info.Protect & (PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_WRITECOPY)) != 0;
|
||||
segment.pt.readable = (!segment.pt.NX) && ((info.Protect & (PAGE_NOACCESS)) != 0);
|
||||
segment.pt.acSanity = info.Protect == PAGE_EXECUTE_WRITECOPY;
|
||||
return segment;
|
||||
}
|
||||
|
||||
void MakeAware(HMODULE hmod)
|
||||
{
|
||||
ModuleBasePair handle {"", reinterpret_cast<AuUInt>(hmod)};
|
||||
|
||||
if (!gMutex)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (hmod == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
SysPushErrorArg();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hmod)
|
||||
{
|
||||
SysPushErrorArg();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (IsInModuleCache(handle))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto ptr = HandleToPublicModule(hmod);
|
||||
if (!ptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
InsertModuleCache(handle, ptr);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
PublicModule GetExecutableRoot()
|
||||
{
|
||||
try
|
||||
{
|
||||
auto handle = GetModuleHandleW(NULL);
|
||||
MakeAware(handle);
|
||||
return GetFromModuleCache(reinterpret_cast<AuUInt>(handle));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void InitProcessMapNt()
|
||||
{
|
||||
gMutex = AuThreadPrimitives::MutexUnique();
|
||||
}
|
||||
|
||||
void DeinitProcessMapNt()
|
||||
{
|
||||
gMutex.reset();
|
||||
}
|
||||
}
|
25
Source/Process/ProcessMap.NT.hpp
Normal file
25
Source/Process/ProcessMap.NT.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: UtilProcessMap.NT.hpp
|
||||
Date: 2022-1-24
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Process
|
||||
{
|
||||
void DeinitProcessMapNt();
|
||||
void InitProcessMapNt();
|
||||
|
||||
AuOptional<Segment> LookupArbitrarySegment(AuUInt address);
|
||||
|
||||
void InvaildateModule(HMODULE hmod);
|
||||
void MakeAware(HMODULE hmod);
|
||||
bool MakeAwarePtr(AuUInt pointer);
|
||||
|
||||
PublicModule GetExecutableRoot();
|
||||
|
||||
AuString ModuleToName(HMODULE handle);
|
||||
AuString ModuleToPath(HMODULE handle);
|
||||
}
|
@ -7,47 +7,39 @@
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "ProcessMap.Win32.hpp"
|
||||
#include "ProcessMap.NT.hpp"
|
||||
#include <tlhelp32.h>
|
||||
|
||||
namespace Aurora::Process
|
||||
{
|
||||
static AuString ModuleToSomething(HMODULE handle, bool path)
|
||||
void MakeToolHelp32Snapshot()
|
||||
{
|
||||
std::wstring file;
|
||||
file.resize(16 * 1024);
|
||||
MODULEENTRY32 me32;
|
||||
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
|
||||
|
||||
// HMODULE arent handles, they're COFF pointers
|
||||
if (!handle)
|
||||
hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
|
||||
if (hModuleSnap == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return {};
|
||||
SysPushErrorGen("CreateToolhelp32Snapshot");
|
||||
return;
|
||||
}
|
||||
me32.dwSize = sizeof(MODULEENTRY32);
|
||||
|
||||
if (!Module32First(hModuleSnap, &me32))
|
||||
{
|
||||
SysPushErrorGen("Module32First failed");
|
||||
CloseHandle(hModuleSnap);
|
||||
return;
|
||||
}
|
||||
|
||||
auto length = GetModuleFileNameW(handle, &file[0], file.size());
|
||||
if (!length)
|
||||
do
|
||||
{
|
||||
return {};
|
||||
auto h = reinterpret_cast<HMODULE>(me32.modBaseAddr);
|
||||
InvaildateModule(h);
|
||||
MakeAware(h);
|
||||
}
|
||||
while (Module32Next(hModuleSnap, &me32));
|
||||
|
||||
file.resize(length);
|
||||
|
||||
if (!path)
|
||||
{
|
||||
auto idx = file.find_last_of('\\');
|
||||
if (idx != std::wstring::npos)
|
||||
{
|
||||
file = file.substr(idx + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return Locale::ConvertFromWChar(file.c_str(), file.length());
|
||||
}
|
||||
|
||||
AuString ModuleToName(HMODULE handle)
|
||||
{
|
||||
return ModuleToSomething(handle, false);
|
||||
}
|
||||
|
||||
AuString ModuleToPath(HMODULE handle)
|
||||
{
|
||||
return ModuleToSomething(handle, true);
|
||||
CloseHandle(hModuleSnap);
|
||||
}
|
||||
}
|
@ -9,6 +9,8 @@
|
||||
|
||||
namespace Aurora::Process
|
||||
{
|
||||
void MakeToolHelp32Snapshot();
|
||||
|
||||
AuString ModuleToName(HMODULE handle);
|
||||
AuString ModuleToPath(HMODULE handle);
|
||||
}
|
225
Source/Process/ProcessMap.cpp
Normal file
225
Source/Process/ProcessMap.cpp
Normal file
@ -0,0 +1,225 @@
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "ProcessMap.hpp"
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
#include "ProcessMap.Win32.hpp"
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
#include "ProcessMap.NT.hpp"
|
||||
#endif
|
||||
|
||||
namespace Aurora::Process
|
||||
{
|
||||
struct ModuleBasePairUtil
|
||||
{
|
||||
AuUInt operator()(const ModuleBasePair &in) const
|
||||
{
|
||||
return in.modBase;
|
||||
}
|
||||
|
||||
constexpr bool operator()(const ModuleBasePair &lhs, const AuString &rhs) const
|
||||
{
|
||||
return lhs.module == rhs;
|
||||
}
|
||||
|
||||
constexpr bool operator()(const ModuleBasePair &lhs, const AuUInt &rhs) const
|
||||
{
|
||||
return lhs.modBase == rhs;
|
||||
}
|
||||
|
||||
constexpr bool operator()(const ModuleBasePair &lhs, const ModuleBasePair &rhs) const
|
||||
{
|
||||
return rhs.modBase ? lhs.modBase == rhs.modBase : (rhs.module.size() ? rhs.module == rhs.module : false);
|
||||
}
|
||||
};
|
||||
|
||||
struct ModuleLookup : Segment
|
||||
{
|
||||
ModuleLookup()
|
||||
{}
|
||||
|
||||
ModuleLookup(const Segment &s) : Segment(s)
|
||||
{}
|
||||
};
|
||||
|
||||
static AuBST<AuUInt, ModuleLookup> gModulePtrMap;
|
||||
|
||||
static const auto kMinPageAlignment = 4096;
|
||||
static const auto kPageBufferPad = 20;
|
||||
|
||||
static AuThreadPrimitives::MutexUnique_t gMutexUnique;
|
||||
static AuHashMapEx<ModuleBasePair, AuSPtr<PublicModule>, ModuleBasePairUtil> gModuleMap;
|
||||
|
||||
static AuUInt ToLowestPageAlignment(AuUInt in)
|
||||
{
|
||||
return in & ~(kMinPageAlignment - 1);
|
||||
}
|
||||
|
||||
static AuSPtr<PublicModule> GetModuleFromSegmentCache(AuUInt pointer)
|
||||
{
|
||||
AU_LOCK_GUARD(gMutexUnique);
|
||||
auto itr = gModulePtrMap.find(pointer);
|
||||
if (itr == gModulePtrMap.end()) return {};
|
||||
return itr->second.moduleMeta.lock();
|
||||
}
|
||||
|
||||
static AuOptional<Segment> GetSegmentCache(AuUInt pointer)
|
||||
{
|
||||
AU_LOCK_GUARD(gMutexUnique);
|
||||
auto itr = gModulePtrMap.find(pointer);
|
||||
if (itr == gModulePtrMap.end()) return {};
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
bool IsInModuleCache(const ModuleBasePair &pair)
|
||||
{
|
||||
AU_LOCK_GUARD(gMutexUnique);
|
||||
return gModuleMap.find(pair) != gModuleMap.end();
|
||||
}
|
||||
|
||||
void InsertModuleCache(const ModuleBasePair &pair, const AuSPtr<PublicModule> &mod)
|
||||
{
|
||||
for (auto &segment : mod->segments)
|
||||
{
|
||||
AU_LOCK_GUARD(gMutexUnique);
|
||||
segment.moduleMeta = mod;
|
||||
|
||||
for (AuUInt i = segment.baseVa; i < segment.baseVa + segment.size; i += (kMinPageAlignment * kPageBufferPad))
|
||||
{
|
||||
ModuleLookup a(segment);
|
||||
gModulePtrMap[i] = a;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
AU_LOCK_GUARD(gMutexUnique);
|
||||
gModuleMap[pair] = mod;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveModuleCache(const ModuleBasePair &eitherOr)
|
||||
{
|
||||
AU_LOCK_GUARD(gMutexUnique);
|
||||
auto itr = gModuleMap.find(eitherOr);
|
||||
if (itr == gModuleMap.end()) return;
|
||||
auto mod = itr->second;
|
||||
|
||||
for (const auto &segment : mod->segments)
|
||||
{
|
||||
for (AuUInt i = segment.baseVa; i < segment.baseVa + segment.size; i += (kMinPageAlignment * kPageBufferPad))
|
||||
{
|
||||
auto itr = gModulePtrMap.find(i);
|
||||
if (itr != gModulePtrMap.end())
|
||||
{
|
||||
gModulePtrMap.erase(itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gModuleMap.erase(itr);
|
||||
}
|
||||
|
||||
PublicModule GetFromModuleCache(AuUInt handle)
|
||||
{
|
||||
AU_LOCK_GUARD(gMutexUnique);
|
||||
auto itr = gModuleMap.find({"", handle});
|
||||
if (itr == gModuleMap.end()) return {};
|
||||
return *itr->second;
|
||||
}
|
||||
|
||||
static AuOptional<Segment> FindInCache(AuUInt pointer)
|
||||
{
|
||||
AU_LOCK_GUARD(gMutexUnique);
|
||||
|
||||
auto curPtr = ToLowestPageAlignment(pointer);
|
||||
auto temp = GetSegmentCache(curPtr);
|
||||
if (temp.has_value()) return temp;
|
||||
|
||||
for (int i = 0; i < kPageBufferPad; i++)
|
||||
{
|
||||
curPtr -= kMinPageAlignment;
|
||||
temp = GetSegmentCache(curPtr); // TODO: i dont want to start from the top of the tree, thats stupid
|
||||
if (temp.has_value()) return temp;
|
||||
}
|
||||
|
||||
return AuOptional<Segment>{};
|
||||
}
|
||||
|
||||
void InitProcessMap()
|
||||
{
|
||||
gMutexUnique = AuThreadPrimitives::MutexUnique();
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
InitProcessMapNt();
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
MakeToolHelp32Snapshot();
|
||||
#endif
|
||||
}
|
||||
|
||||
void DeinitProcessMap()
|
||||
{
|
||||
gMutexUnique.reset();
|
||||
DeinitProcessMapNt();
|
||||
}
|
||||
|
||||
AUKN_SYM AuOptional<Segment> GetSegment(AuUInt pointer)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto ceg = FindInCache(pointer);
|
||||
if (ceg.has_value())
|
||||
{
|
||||
return ceg;
|
||||
}
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
if (MakeAwarePtr(pointer))
|
||||
{
|
||||
return FindInCache(pointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
return LookupArbitrarySegment(pointer);
|
||||
}
|
||||
#endif
|
||||
|
||||
return {};
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
AUKN_SYM PublicModule DumpExecutableRoot()
|
||||
{
|
||||
try
|
||||
{
|
||||
return GetExecutableRoot();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
AUKN_SYM Segments DumpExecutableAll()
|
||||
{
|
||||
try
|
||||
{
|
||||
Segments ret;
|
||||
for (const auto &[meta, ptr] : gModuleMap)
|
||||
{
|
||||
ret.insert(ret.end(), ptr->segments.begin(), ptr->segments.end());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
18
Source/Process/ProcessMap.hpp
Normal file
18
Source/Process/ProcessMap.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Process
|
||||
{
|
||||
struct ModuleBasePair
|
||||
{
|
||||
AuString module;
|
||||
AuUInt modBase;
|
||||
};
|
||||
|
||||
PublicModule GetFromModuleCache(AuUInt handle);
|
||||
void InsertModuleCache(const ModuleBasePair &pair, const AuSPtr<PublicModule> &mod);
|
||||
void RemoveModuleCache(const ModuleBasePair &eitherOr);
|
||||
bool IsInModuleCache(const ModuleBasePair &pair);
|
||||
|
||||
void InitProcessMap();
|
||||
void DeinitProcessMap();
|
||||
}
|
@ -33,7 +33,7 @@ namespace Aurora::Processes
|
||||
{
|
||||
for (const auto &open : gOpenItems)
|
||||
{
|
||||
ShellExecuteW(NULL, IO::FS::DirExists(open) ? L"explore" : NULL, Locale::ConvertFromUTF8(open).c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||
ShellExecuteW(NULL, AuIOFS::DirExists(open) ? L"explore" : NULL, Locale::ConvertFromUTF8(open).c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||
}
|
||||
gOpenItems.clear();
|
||||
gCondVariable->WaitForSignal();
|
||||
@ -41,7 +41,7 @@ namespace Aurora::Processes
|
||||
catch (...)
|
||||
{
|
||||
Debug::PrintError();
|
||||
LogWarn("An error occurred while dispatching a ShellExecute runner frame");
|
||||
AuLogWarn("An error occurred while dispatching a ShellExecute runner frame");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -56,12 +56,18 @@ namespace Aurora::Processes
|
||||
void InitWin32Opener()
|
||||
{
|
||||
gCondMutex = AuThreadPrimitives::ConditionMutexUnique();
|
||||
SysAssert(gCondMutex);
|
||||
|
||||
gCondVariable = AuThreadPrimitives::ConditionVariableUnique(AuUnsafeRaiiToShared(gCondMutex));
|
||||
SysAssert(gCondVariable);
|
||||
|
||||
gOpenerThread = AuThreads::ThreadUnique(AuThreads::ThreadInfo(
|
||||
AuMakeShared<AuThreads::IThreadVectorsFunctional>(AuThreads::IThreadVectorsFunctional::OnEntry_t(std::bind(OpenerThread)),
|
||||
AuThreads::IThreadVectorsFunctional::OnExit_t{}),
|
||||
"COM ShellExecute Runner"
|
||||
));
|
||||
SysAssert(gOpenerThread);
|
||||
|
||||
gOpenerThread->Run();
|
||||
}
|
||||
|
||||
@ -83,6 +89,6 @@ namespace Aurora::Processes
|
||||
|
||||
AUKN_SYM void OpenFile(const AuString &file)
|
||||
{
|
||||
OpenUri(IO::FS::NormalizePathRet(file));
|
||||
OpenUri(AuIOFS::NormalizePathRet(file));
|
||||
}
|
||||
}
|
14
Source/Processes/UtilRun.cpp
Normal file
14
Source/Processes/UtilRun.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: UtilRun.cpp
|
||||
Date:
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "UtilRun.hpp"
|
||||
|
||||
namespace Aurora::Processes
|
||||
{
|
||||
|
||||
}
|
12
Source/Processes/UtilRun.hpp
Normal file
12
Source/Processes/UtilRun.hpp
Normal file
@ -0,0 +1,12 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: UtilRun.hpp
|
||||
Date:
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Processes
|
||||
{
|
||||
}
|
@ -104,9 +104,9 @@ namespace Aurora::Registry
|
||||
cacheDocument_ = {};
|
||||
}
|
||||
|
||||
if (!IO::FS::ReadString(path, file))
|
||||
if (!AuIOFS::ReadString(path, file))
|
||||
{
|
||||
return IO::FS::WriteString(path, "{}");
|
||||
return AuIOFS::WriteString(path, "{}");
|
||||
}
|
||||
|
||||
currentStreamDocument_ = json::parse(file);
|
||||
@ -294,7 +294,6 @@ namespace Aurora::Registry
|
||||
CloseSave();
|
||||
}
|
||||
|
||||
|
||||
void FSRegistry::OpenRead(const AuString &path)
|
||||
{
|
||||
Read(path, EReadType::eClearCacheAndStore);
|
||||
@ -349,7 +348,7 @@ namespace Aurora::Registry
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IO::FS::WriteString(lastPath_.value(), currentStreamDocument_.dump(4)))
|
||||
if (!AuIOFS::WriteString(lastPath_.value(), currentStreamDocument_.dump(4)))
|
||||
{
|
||||
SysPushErrorIO("Couldn't write registry to {}", lastPath_.value());
|
||||
return false;
|
||||
|
@ -13,18 +13,18 @@
|
||||
#include "TLSView.hpp"
|
||||
|
||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||
#include <sys/resource.h>
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_HAS_PTHREADS)
|
||||
#include <sched.h>
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
#include <process.h>
|
||||
#include <Aux_ulib.h>
|
||||
#include <Aux_ulib.h>
|
||||
#endif
|
||||
|
||||
#include "SpawnThread.hpp"
|
||||
|
||||
namespace Aurora::Threading::Threads
|
||||
{
|
||||
@ -231,11 +231,11 @@ namespace Aurora::Threading::Threads
|
||||
// The thread must've requested suicide and got stuck in a lengthy clean up effort
|
||||
if (!exitOnlyOnce_->TryLock())
|
||||
{
|
||||
LogWarn("Watchdog error - OS thread context didn't finish in 15 seconds, but he should exiting now.");
|
||||
AuLogWarn("Watchdog error - OS thread context didn't finish in 15 seconds, but he should exiting now.");
|
||||
return false;
|
||||
}
|
||||
|
||||
LogWarn("Watchdog error - OS thread context didn't finish in 15 seconds, forcefully terminating without a watchdog overlooking onExit");
|
||||
AuLogWarn("Watchdog error - OS thread context didn't finish in 15 seconds, forcefully terminating without a watchdog overlooking onExit");
|
||||
|
||||
// Kill the current OS thread instance
|
||||
TeminateOSContext(false);
|
||||
@ -266,7 +266,7 @@ namespace Aurora::Threading::Threads
|
||||
return prio_;
|
||||
}
|
||||
|
||||
AuUInt32 OSThread::GetMask()
|
||||
AuUInt64 OSThread::GetMask()
|
||||
{
|
||||
return affinityProcessMask_;
|
||||
}
|
||||
@ -276,9 +276,9 @@ namespace Aurora::Threading::Threads
|
||||
return name_;
|
||||
}
|
||||
|
||||
void OSThread::SetAffinity(AuUInt32 mask)
|
||||
void OSThread::SetAffinity(AuUInt64 mask)
|
||||
{
|
||||
if (mask == 0) mask = 0xFFFFFFFF;
|
||||
if (mask == 0) mask = 0xFFFFFFFFFFFFFFFF;
|
||||
affinityProcessMask_ = mask;
|
||||
UpdateAffinity(mask);
|
||||
}
|
||||
@ -303,102 +303,17 @@ namespace Aurora::Threading::Threads
|
||||
{
|
||||
task_ = task;
|
||||
|
||||
// https://github.com/webrtc-uwp/chromium-base/blob/master/threading/platform_thread_win.cc#L129-L136
|
||||
// Do we care yet?
|
||||
// When targeting older CRTs, _beginthreadex
|
||||
// When targeting at least UWP, CreateThread but _beginthreadex is fine
|
||||
// https://web.archive.org/web/20110928122401/http://www.microsoft.com/msj/1099/win32/win321099.aspx
|
||||
// Even in 1999 it sounded like _tiddata was setup for all modules that may come across our thread
|
||||
// It wasn't until 2005, 6 years later, it became less of a requirement.
|
||||
// Does the modern CRT need it for anything estoeric or evil?
|
||||
// I think so long as we're targeting modern windows its fine to call _beginthreadex for all CRT users
|
||||
// Userland icds, plugins, software not in our build chain, it makes sense for them to have a _fully_ initialized crt
|
||||
// I think I switched it from CreateThread to _beginthreadex at somepoint and i don't remember why
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
auto ret = SpawnThread([this]()
|
||||
{
|
||||
this->_ThreadEP();
|
||||
}, GetName(), info_.stackSize);
|
||||
|
||||
unsigned(WINAPI * OSEP_f)(void *) = [](void *that) -> unsigned
|
||||
if (ret.first)
|
||||
{
|
||||
auto thiz = reinterpret_cast<OSThread *>(that);
|
||||
thiz->_ThreadEP();
|
||||
return 0;
|
||||
};
|
||||
|
||||
DWORD(WINAPI * OSCreateThreadEP_f)(void *) = [](void *that) -> DWORD
|
||||
{
|
||||
auto thiz = reinterpret_cast<OSThread *>(that);
|
||||
thiz->_ThreadEP();
|
||||
return 0;
|
||||
};
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
BOOL a {};
|
||||
if (AuxUlibIsDLLSynchronizationHeld(&a))
|
||||
{
|
||||
if (a)
|
||||
{
|
||||
handle_ = CreateThread(NULL, info_.stackSize, OSCreateThreadEP_f, reinterpret_cast<LPVOID>(this), NULL, NULL);
|
||||
if (!handle_)
|
||||
{
|
||||
handle_ = INVALID_HANDLE_VALUE;
|
||||
SysPushErrorGen("Couldn't create locked thread: {}", GetName());
|
||||
return false;
|
||||
handle_ = (decltype(handle_))ret.second;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
auto ok = _beginthreadex(nullptr, info_.stackSize, OSEP_f, this, 0, 0);
|
||||
if (ok == -1L)
|
||||
{
|
||||
SysPushErrorGen("Couldn't initialize thread: {}", GetName());
|
||||
return false;
|
||||
}
|
||||
|
||||
handle_ = reinterpret_cast<HANDLE>(ok);
|
||||
|
||||
#elif defined(AURORA_HAS_PTHREADS)
|
||||
pthread_attr_t tattr;
|
||||
|
||||
void *(*OSEP_f)(void *) = [](void *that) -> void *
|
||||
{
|
||||
auto thiz = reinterpret_cast<OSThread *>(that);
|
||||
thiz->_ThreadEP();
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
auto ret = pthread_attr_init(&tattr);
|
||||
if (ret != 0)
|
||||
{
|
||||
SysPushErrorGen("Couldn't create thread: {}", GetName());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (info_.stackSize)
|
||||
{
|
||||
ret = pthread_attr_setstacksize(&tattr, AuMin(AuUInt32(PTHREAD_STACK_MIN), info_.stackSize));
|
||||
if (ret != 0)
|
||||
{
|
||||
SysPushErrorGen("Couldn't create thread: {}", GetName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ret = pthread_create(&handle_, &tattr, OSEP_f, this);
|
||||
if (ret != 0)
|
||||
{
|
||||
SysPushErrorGen("Couldn't create thread: {}", GetName());
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
SysPanic("Not implemented");
|
||||
|
||||
#endif
|
||||
|
||||
return true;
|
||||
return ret.first;
|
||||
}
|
||||
|
||||
void OSThread::_ThreadEP()
|
||||
@ -627,7 +542,7 @@ namespace Aurora::Threading::Threads
|
||||
prio_ = prio;
|
||||
}
|
||||
|
||||
void OSThread::UpdateAffinity(AuUInt32 mask)
|
||||
void OSThread::UpdateAffinity(AuUInt64 mask)
|
||||
{
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
if (handle_ == INVALID_HANDLE_VALUE)
|
||||
@ -669,10 +584,10 @@ namespace Aurora::Threading::Threads
|
||||
catch (...)
|
||||
{
|
||||
Debug::PrintError();
|
||||
LogWarn("Couldn't deinitialize thread");
|
||||
LogWarn("The smart thing to do at this point would be to panic");
|
||||
LogWarn("...but we could continue");
|
||||
LogWarn("Carrying on despite the potential for data integrity loss and memory leaks");
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -23,11 +23,11 @@ namespace Aurora::Threading::Threads
|
||||
void SendExitSignal() override;
|
||||
|
||||
void SetPrio(EThreadPrio prio) override;
|
||||
void SetAffinity(AuUInt32 mask) override;
|
||||
void SetAffinity(AuUInt64 mask) override;
|
||||
void SetName(const AuString &name) override;
|
||||
|
||||
EThreadPrio GetPrio() override;
|
||||
AuUInt32 GetMask() override;
|
||||
AuUInt64 GetMask() override;
|
||||
AuString GetName() override;
|
||||
|
||||
AuSPtr<TLSView> GetTlsView() override;
|
||||
@ -48,7 +48,7 @@ namespace Aurora::Threading::Threads
|
||||
bool Exit(bool willReturnToOS);
|
||||
bool ExecuteNewOSContext(AuFunction<void()> task);
|
||||
void UpdatePrio(EThreadPrio prio);
|
||||
void UpdateAffinity(AuUInt32 mask);
|
||||
void UpdateAffinity(AuUInt64 mask);
|
||||
void UpdateName();
|
||||
void OSAttach();
|
||||
void OSDeatach();
|
||||
@ -65,7 +65,7 @@ namespace Aurora::Threading::Threads
|
||||
OSThread * tlsReferenceThread_ {};
|
||||
AuString name_;
|
||||
ThreadInfo info_;
|
||||
AuUInt32 affinityProcessMask_ = 0xFFFFFFFF;
|
||||
AuUInt64 affinityProcessMask_ = 0xFFFFFFFFFFFFFFFF;
|
||||
EThreadPrio prio_ = EThreadPrio::ePrioNormal;
|
||||
|
||||
bool exiting_{};
|
||||
@ -84,7 +84,7 @@ namespace Aurora::Threading::Threads
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
HANDLE handle_ = INVALID_HANDLE_VALUE;
|
||||
#elif defined(AURORA_HAS_PTHREADS)
|
||||
pthread_t handle_;
|
||||
pthread_t handle_ {};
|
||||
#endif
|
||||
|
||||
AuUInt64 unixThreadId_ = 0;
|
||||
|
93
Source/Threading/Threads/SpawnThread.NT.cpp
Normal file
93
Source/Threading/Threads/SpawnThread.NT.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: SpawnThread.NT.cpp
|
||||
Date:
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "Threads.hpp"
|
||||
#include "SpawnThread.hpp"
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
#include <process.h>
|
||||
#include <Aux_ulib.h>
|
||||
#endif
|
||||
|
||||
namespace Aurora::Threading::Threads
|
||||
{
|
||||
AuPair<bool, AuUInt> /*success, oshandle*/ SpawnThread(const AuFunction<void()> &entrypoint, const AuString &debugString, AuUInt32 staskSize)
|
||||
{
|
||||
// https://github.com/webrtc-uwp/chromium-base/blob/master/threading/platform_thread_win.cc#L129-L136
|
||||
// Do we care yet?
|
||||
// When targeting older CRTs, _beginthreadex
|
||||
// When targeting at least UWP, CreateThread but _beginthreadex is fine
|
||||
// https://web.archive.org/web/20110928122401/http://www.microsoft.com/msj/1099/win32/win321099.aspx
|
||||
// Even in 1999 it sounded like _tiddata was setup for all modules that may come across our thread
|
||||
// It wasn't until 2005, 6 years later, it became less of a requirement.
|
||||
// Does the modern CRT need it for anything estoeric or evil?
|
||||
// I think so long as we're targeting modern windows its fine to call _beginthreadex for all CRT users
|
||||
// Userland icds, plugins, software not in our build chain, it makes sense for them to have a _fully_ initialized crt
|
||||
// I think I switched it from CreateThread to _beginthreadex at somepoint and i don't remember why
|
||||
|
||||
if (!entrypoint)
|
||||
{
|
||||
return {false, 0};
|
||||
}
|
||||
|
||||
// i dont like this allocate
|
||||
auto callbackClone = _new AuFunction<void()>(entrypoint);
|
||||
if (!callbackClone)
|
||||
{
|
||||
return {false, 0};
|
||||
}
|
||||
|
||||
static auto callVoidPtr_f = [](void *that) -> void
|
||||
{
|
||||
auto handle = reinterpret_cast<AuFunction<void()> *>(that);
|
||||
auto callMe = *handle;
|
||||
delete handle;
|
||||
callMe();
|
||||
};
|
||||
|
||||
unsigned(WINAPI * OSEP_f)(void *) = [](void *that) -> unsigned
|
||||
{
|
||||
callVoidPtr_f(that);
|
||||
return 0;
|
||||
};
|
||||
|
||||
DWORD(WINAPI * OSCreateThreadEP_f)(void *) = [](void *that) -> DWORD
|
||||
{
|
||||
callVoidPtr_f(that);
|
||||
return 0;
|
||||
};
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
BOOL a {};
|
||||
if (AuxUlibIsDLLSynchronizationHeld(&a))
|
||||
{
|
||||
if (a)
|
||||
{
|
||||
auto handle = CreateThread(NULL, staskSize, OSCreateThreadEP_f, reinterpret_cast<LPVOID>(callbackClone), NULL, NULL);
|
||||
if (!handle)
|
||||
{
|
||||
handle = INVALID_HANDLE_VALUE;
|
||||
SysPushErrorGen("Couldn't create locked thread: {}", debugString);
|
||||
return {false, 0};
|
||||
}
|
||||
|
||||
return {true, reinterpret_cast<AuUInt>(handle)};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
auto ok = _beginthreadex(nullptr, staskSize, OSEP_f, callbackClone, 0, 0);
|
||||
if (ok == -1L)
|
||||
{
|
||||
SysPushErrorGen("Couldn't initialize thread: {}", debugString);
|
||||
return {false, 0};
|
||||
}
|
||||
|
||||
return {true, ok};
|
||||
}
|
||||
}
|
13
Source/Threading/Threads/SpawnThread.NT.hpp
Normal file
13
Source/Threading/Threads/SpawnThread.NT.hpp
Normal file
@ -0,0 +1,13 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: SpawnThread.NT.hpp
|
||||
Date:
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Threading::Threads
|
||||
{
|
||||
// ...
|
||||
}
|
76
Source/Threading/Threads/SpawnThread.Unix.cpp
Normal file
76
Source/Threading/Threads/SpawnThread.Unix.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: SpawnThread.Unix.cpp
|
||||
Date:
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "Threads.hpp"
|
||||
#include "SpawnThread.hpp"
|
||||
|
||||
#if defined(AURORA_HAS_PTHREADS)
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
||||
namespace Aurora::Threading::Threads
|
||||
{
|
||||
AuPair<bool, AuUInt> /*success, oshandle*/ SpawnThread(const AuFunction<void()> &entrypoint, const AuString &debugString, AuUInt32 staskSize)
|
||||
{
|
||||
pthread_attr_t tattr;
|
||||
pthread_t handle;
|
||||
|
||||
if (!entrypoint)
|
||||
{
|
||||
return {false, 0};
|
||||
}
|
||||
|
||||
// i dont like this allocate
|
||||
auto callbackClone = _new AuFunction<void()>(entrypoint);
|
||||
if (!callbackClone)
|
||||
{
|
||||
return {false, 0};
|
||||
}
|
||||
|
||||
static auto callVoidPtr_f = [](void *that) -> void
|
||||
{
|
||||
auto handle = reinterpret_cast<AuFunction<void()> *>(that);
|
||||
auto callMe = *handle;
|
||||
delete handle;
|
||||
callMe();
|
||||
};
|
||||
|
||||
void *(*OSEP_f)(void *) = [](void *that) -> void *
|
||||
{
|
||||
auto thiz = reinterpret_cast<OSThread *>(that);
|
||||
thiz->_ThreadEP();
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
auto ret = pthread_attr_init(&tattr);
|
||||
if (ret != 0)
|
||||
{
|
||||
SysPushErrorGen("Couldn't create thread: {}", debugString);
|
||||
return {false, 0};
|
||||
}
|
||||
|
||||
if (info_.stackSize)
|
||||
{
|
||||
ret = pthread_attr_setstacksize(&tattr, AuMin(AuUInt32(PTHREAD_STACK_MIN), info_.stackSize));
|
||||
if (ret != 0)
|
||||
{
|
||||
SysPushErrorGen("Couldn't create thread: {}", debugString);
|
||||
return {false, 0};
|
||||
}
|
||||
}
|
||||
|
||||
ret = pthread_create(&handle, &tattr, OSEP_f, callbackClone);
|
||||
if (ret != 0)
|
||||
{
|
||||
SysPushErrorGen("Couldn't create thread: {}", debugString);
|
||||
return {false, 0};
|
||||
}
|
||||
|
||||
return {true, handle};
|
||||
}
|
||||
}
|
20
Source/Threading/Threads/SpawnThread.hpp
Normal file
20
Source/Threading/Threads/SpawnThread.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: SpawnThread.hpp
|
||||
Date:
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
|
||||
namespace Aurora::Threading::Threads
|
||||
{
|
||||
AuPair<bool, AuUInt> /*success, oshandle*/ SpawnThread(const AuFunction<void()> &entrypoint, const AuString &debugString, AuUInt32 staskSize = 0);
|
||||
}
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
#include "SpawnThread.NT.hpp"
|
||||
#elif defined(AURORA_IS_UNIX_DERIVED)
|
||||
#include "SpawnThread.Unix.hpp"
|
||||
#endif
|
@ -219,7 +219,7 @@ namespace Aurora::Time
|
||||
if (!localtime_r(&timet, &ret))
|
||||
#endif
|
||||
{
|
||||
LogWarn("Couldn't convert local civil time");
|
||||
AuLogWarn("Couldn't convert local civil time");
|
||||
return ToCivilTime(time, true);
|
||||
}
|
||||
}
|
||||
@ -253,4 +253,14 @@ namespace Aurora::Time
|
||||
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(NormalizeEpoch(std::chrono::system_clock::from_time_t(timet).time_since_epoch())).count();
|
||||
}
|
||||
|
||||
AUKN_SYM tm NormalizeCivilTimezone(const Time::tm &time, ETimezoneShift shift)
|
||||
{
|
||||
if ((time.tm_isdst == 0) && (shift == ETimezoneShift::eUTC))
|
||||
{
|
||||
return time;
|
||||
}
|
||||
|
||||
return ToCivilTime(FromCivilTime(time, shift == ETimezoneShift::eUTC));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user