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 (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
Debug::PrintError();
|
Debug::PrintError();
|
||||||
Shutdown();
|
ShutdownNoLock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +172,7 @@ namespace Aurora::Async
|
|||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
Debug::PrintError();
|
Debug::PrintError();
|
||||||
Shutdown();
|
ShutdownNoLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ namespace Aurora::Console
|
|||||||
/// Writes a log message to the console subscribers and telemetry outputs
|
/// Writes a log message to the console subscribers and telemetry outputs
|
||||||
AUKN_SYM void WriteLine(AuUInt8 level, const ConsoleMessage &msg);
|
AUKN_SYM void WriteLine(AuUInt8 level, const ConsoleMessage &msg);
|
||||||
AUKN_SYM void SetGlobalLogger(const AuSPtr<Logging::ILogger> &defaultGlobalLogger);
|
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 -
|
/// Consider using the following function for asynchronous utf-8 processed line based input -
|
||||||
/// Hooks::SetCallbackAndDisableCmdProcessing(...)
|
/// Hooks::SetCallbackAndDisableCmdProcessing(...)
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
namespace Aurora::Console::Logging
|
namespace Aurora::Console::Logging
|
||||||
{
|
{
|
||||||
AUKN_INTERFACE(IBasicSink,
|
AUKN_INTERFACE(IBasicSink,
|
||||||
AUI_METHOD(void, OnMessageBlocking, (const ConsoleMessage &, msg)),
|
AUI_METHOD(void, OnMessageBlocking, (AuUInt8, level, const ConsoleMessage &, msg)),
|
||||||
AUI_METHOD(void, OnMessageNonblocking, (const ConsoleMessage &, msg)),
|
AUI_METHOD(void, OnMessageNonblocking, (AuUInt8, level, const ConsoleMessage &, msg)),
|
||||||
AUI_METHOD(void, OnFlush, ())
|
AUI_METHOD(void, OnFlush, ())
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -14,7 +14,8 @@ namespace Aurora
|
|||||||
|
|
||||||
namespace Aurora::Console::Logging
|
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(NewFileSink, IBasicSink, const AuString &path, bool binary = false);
|
||||||
AUKN_SHARED_API(NewIPCSink, IBasicSink, const SocketConsole &console);
|
AUKN_SHARED_API(NewIPCSink, IBasicSink, const SocketConsole &console);
|
||||||
AUKN_SHARED_API(NewRingLogger, IBasicSinkRB, AuUInt32 approxMaxBytes);
|
AUKN_SHARED_API(NewRingLogger, IBasicSinkRB, AuUInt32 approxMaxBytes);
|
||||||
|
@ -47,6 +47,9 @@ namespace Aurora::Debug
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
AUKN_SYM void PrintError();
|
AUKN_SYM void PrintError();
|
||||||
|
|
||||||
|
|
||||||
|
AUKN_SYM void CheckErrors();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Immediately terminates the process.
|
Immediately terminates the process.
|
||||||
|
@ -33,6 +33,7 @@ namespace Aurora::Debug
|
|||||||
kFailureSyntaxError,
|
kFailureSyntaxError,
|
||||||
kFailureDisconnected,
|
kFailureDisconnected,
|
||||||
kFailureUninitialized,
|
kFailureUninitialized,
|
||||||
|
kFailureUnimplemented,
|
||||||
|
|
||||||
kFailureUserBegin = 256
|
kFailureUserBegin = 256
|
||||||
};
|
};
|
||||||
|
@ -13,6 +13,7 @@ namespace Aurora::Debug
|
|||||||
{
|
{
|
||||||
AuOptional<AuString> label;
|
AuOptional<AuString> label;
|
||||||
AuUInt64 address;
|
AuUInt64 address;
|
||||||
|
AuUInt64 relAddress;
|
||||||
AuOptional<AuString> module;
|
AuOptional<AuString> module;
|
||||||
AuOptional<AuTuple<AuString, int, int>> file; // file, line, offset
|
AuOptional<AuTuple<AuString, int, int>> file; // file, line, offset
|
||||||
|
|
||||||
|
@ -108,6 +108,7 @@ namespace Aurora::Debug
|
|||||||
#define SysPushErrorSyntaxError(...) SysPushErrorError(kFailureSyntaxError, ## __VA_ARGS__)
|
#define SysPushErrorSyntaxError(...) SysPushErrorError(kFailureSyntaxError, ## __VA_ARGS__)
|
||||||
#define SysPushErrorDisconnected(...) SysPushErrorError(kFailureDisconnected, ## __VA_ARGS__)
|
#define SysPushErrorDisconnected(...) SysPushErrorError(kFailureDisconnected, ## __VA_ARGS__)
|
||||||
#define SysPushErrorUninitialized(...) SysPushErrorError(kFailureUninitialized, ## __VA_ARGS__)
|
#define SysPushErrorUninitialized(...) SysPushErrorError(kFailureUninitialized, ## __VA_ARGS__)
|
||||||
|
#define SysPushErrorUnimplemented(...) SysPushErrorError(kFailureUnimplemented, ## __VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
#if defined(DEBUG) || defined(STAGING)
|
#if defined(DEBUG) || defined(STAGING)
|
||||||
@ -142,6 +143,7 @@ namespace Aurora::Debug
|
|||||||
#define SysPushErrorSyntaxErrorDbg SysPushErrorSyntaxError
|
#define SysPushErrorSyntaxErrorDbg SysPushErrorSyntaxError
|
||||||
#define SysPushErrorDisconnectedDbg SysPushErrorDisconnected
|
#define SysPushErrorDisconnectedDbg SysPushErrorDisconnected
|
||||||
#define SysPushErrorUninitializedDbg SysPushErrorUninitialized
|
#define SysPushErrorUninitializedDbg SysPushErrorUninitialized
|
||||||
|
#define SysPushErrorUnimplementedDbg SysPushErrorUnimplemented
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -174,5 +176,6 @@ namespace Aurora::Debug
|
|||||||
#define SysPushErrorSyntaxErrorDbg(...)
|
#define SysPushErrorSyntaxErrorDbg(...)
|
||||||
#define SysPushErrorDisconnectedDbg(...)
|
#define SysPushErrorDisconnectedDbg(...)
|
||||||
#define SysPushErrorUninitializedDbg(...)
|
#define SysPushErrorUninitializedDbg(...)
|
||||||
|
#define SysPushErrorUnimplementedDbg(...)
|
||||||
|
|
||||||
#endif
|
#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
|
#pragma once
|
||||||
|
|
||||||
|
#include "CpuBitId.hpp"
|
||||||
|
#include "CpuId.hpp"
|
||||||
|
|
||||||
namespace Aurora::HWInfo
|
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
|
struct CpuInfo
|
||||||
{
|
{
|
||||||
Aurora::Build::EArchitecture cpuArch;
|
Aurora::Build::EArchitecture cpuArch;
|
||||||
@ -88,7 +19,14 @@ namespace Aurora::HWInfo
|
|||||||
AuUInt8 socket;
|
AuUInt8 socket;
|
||||||
AuUInt8 cores;
|
AuUInt8 cores;
|
||||||
AuUInt8 threads;
|
AuUInt8 threads;
|
||||||
|
|
||||||
|
AuList<AuInt64> threadTopology;
|
||||||
|
AuList<CpuBitId> serverTopology;
|
||||||
|
CpuBitId maskECores;
|
||||||
|
|
||||||
|
bool maskMTContig;
|
||||||
|
bool maskMTHalf;
|
||||||
|
|
||||||
CpuId cpuId;
|
CpuId cpuId;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "ECodePage.hpp"
|
#include "ECodePage.hpp"
|
||||||
#include "Encoding/Encoding.hpp"
|
#include "Encoding/Encoding.hpp"
|
||||||
|
#include "LocaleStrings.hpp"
|
||||||
|
|
||||||
namespace Aurora::Locale
|
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
|
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
|
struct Segment
|
||||||
{
|
{
|
||||||
AuUInt base;
|
AuUInt baseVa;
|
||||||
|
AuUInt origVa;
|
||||||
|
AuUInt fsOff;
|
||||||
AuUInt size;
|
AuUInt size;
|
||||||
char perms[6];
|
PageTable pt;
|
||||||
AuString module;
|
AuString name;
|
||||||
|
AuWPtr<PublicModule> moduleMeta;
|
||||||
};
|
};
|
||||||
|
|
||||||
using Segments = AuList<Segment>;
|
using Segments = AuList<Segment>;
|
||||||
|
|
||||||
|
struct PublicModule
|
||||||
|
{
|
||||||
|
AuList<Segment> segments;
|
||||||
|
AuSPtr<ModuleMeta> moduleMeta;
|
||||||
|
};
|
||||||
|
|
||||||
AUKN_SYM AuOptional<Segment> GetSegment(AuUInt pointer);
|
AUKN_SYM AuOptional<Segment> GetSegment(AuUInt pointer);
|
||||||
AUKN_SYM Segments DumpExecutableRoot();
|
AUKN_SYM PublicModule DumpExecutableRoot();
|
||||||
AUKN_SYM Segments DumpExecutableAll();
|
AUKN_SYM Segments DumpExecutableAll();
|
||||||
}
|
}
|
@ -10,5 +10,6 @@
|
|||||||
#include "ESpawnType.hpp"
|
#include "ESpawnType.hpp"
|
||||||
#include "IProcess.hpp"
|
#include "IProcess.hpp"
|
||||||
#include "Spawn.hpp"
|
#include "Spawn.hpp"
|
||||||
|
#include "UtilRun.hpp"
|
||||||
|
|
||||||
#include "Open.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 "Hashing/Hashing.hpp"
|
||||||
#include "HWInfo/HWInfo.hpp"
|
#include "HWInfo/HWInfo.hpp"
|
||||||
#include "IO/IO.hpp"
|
#include "IO/IO.hpp"
|
||||||
|
#include "Time/Time.hpp"
|
||||||
#include "Locale/Locale.hpp"
|
#include "Locale/Locale.hpp"
|
||||||
#include "Parse/Parse.hpp"
|
#include "Parse/Parse.hpp"
|
||||||
#include "Process/Process.hpp"
|
#include "Process/Process.hpp"
|
||||||
#include "Processes/Processes.hpp"
|
|
||||||
#include "Registry/Registry.hpp"
|
#include "Registry/Registry.hpp"
|
||||||
#include "RNG/RNG.hpp"
|
#include "RNG/RNG.hpp"
|
||||||
#include "Telemetry/Telemetery.hpp"
|
#include "Telemetry/Telemetery.hpp"
|
||||||
#include "Threading/Threading.hpp"
|
#include "Threading/Threading.hpp"
|
||||||
#include "Async/Async.hpp"
|
#include "Async/Async.hpp"
|
||||||
#include "Time/Time.hpp"
|
#include "Processes/Processes.hpp"
|
||||||
#include "Loop/Loop.hpp"
|
#include "Loop/Loop.hpp"
|
||||||
|
|
||||||
#include "Memory/_ByteBuffer.hpp"
|
#include "Memory/_ByteBuffer.hpp"
|
||||||
@ -109,8 +109,6 @@ using AuMemoryViewWrite = AuMemory::MemoryViewWrite;
|
|||||||
using AuMemoryViewStreamRead = AuMemory::MemoryViewStreamRead;
|
using AuMemoryViewStreamRead = AuMemory::MemoryViewStreamRead;
|
||||||
using AuMemoryViewStreamWrite = AuMemory::MemoryViewStreamWrite;
|
using AuMemoryViewStreamWrite = AuMemory::MemoryViewStreamWrite;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static bool AuIsThreadRunning()
|
static bool AuIsThreadRunning()
|
||||||
{
|
{
|
||||||
return !AuThreads::GetThread()->Exiting();
|
return !AuThreads::GetThread()->Exiting();
|
||||||
@ -195,6 +193,9 @@ namespace Aurora
|
|||||||
|
|
||||||
/// Use WxWidgets when possible
|
/// Use WxWidgets when possible
|
||||||
bool enableWxWidgets {true};
|
bool enableWxWidgets {true};
|
||||||
|
|
||||||
|
/// Delegate stdout writes to loops -> recommended for servers
|
||||||
|
bool asyncWrite {false};
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
/// FIO config
|
/// FIO config
|
||||||
|
@ -24,10 +24,10 @@ namespace Aurora::Threading::Threads
|
|||||||
/// A common worker thread semantic:
|
/// A common worker thread semantic:
|
||||||
/// EndWorker()
|
/// EndWorker()
|
||||||
/// m_Worker->SendExitSignal(); // sets the exiting flag
|
/// 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()
|
/// WorkerMain()
|
||||||
/// while (!this->Exiting()) {}
|
/// while (AuIsThreadRunning()) {}
|
||||||
///
|
///
|
||||||
/// It's similar to Java
|
/// It's similar to Java
|
||||||
/// -> think while (Thread.currentThread().isAlive()) { doWork() }
|
/// -> think while (Thread.currentThread().isAlive()) { doWork() }
|
||||||
@ -42,11 +42,11 @@ namespace Aurora::Threading::Threads
|
|||||||
virtual void SendExitSignal() = 0;
|
virtual void SendExitSignal() = 0;
|
||||||
|
|
||||||
virtual void SetPrio(EThreadPrio prio) = 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 void SetName(const AuString &name) = 0;
|
||||||
|
|
||||||
virtual EThreadPrio GetPrio() = 0;
|
virtual EThreadPrio GetPrio() = 0;
|
||||||
virtual AuUInt32 GetMask() = 0;
|
virtual AuUInt64 GetMask() = 0;
|
||||||
virtual AuString GetName() = 0;
|
virtual AuString GetName() = 0;
|
||||||
|
|
||||||
/// Registers a thread feature _not_ calling on init
|
/// Registers a thread feature _not_ calling on init
|
||||||
|
@ -7,49 +7,11 @@
|
|||||||
***/
|
***/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "ETimezoneShift.hpp"
|
||||||
|
#include "TM.hpp"
|
||||||
|
|
||||||
namespace Aurora::Time
|
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
|
Converts milliseconds from the Aurora epoch to a civil timestamp structure
|
||||||
similar to or of std::tm
|
similar to or of std::tm
|
||||||
@ -65,6 +27,12 @@ namespace Aurora::Time
|
|||||||
*/
|
*/
|
||||||
AUKN_SYM AuInt64 FromCivilTime(const tm &time, bool UTC = true);
|
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
|
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
|
#pragma once
|
||||||
|
|
||||||
|
#include <Aurora/Time/ETimezoneShift.hpp>
|
||||||
|
#include <Aurora/Locale/LocaleStrings.hpp>
|
||||||
|
|
||||||
namespace Aurora::Time
|
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"
|
#include "Clock.hpp"
|
||||||
|
@ -83,8 +83,8 @@ namespace Aurora::Async
|
|||||||
{
|
{
|
||||||
if (entry.pool->ToThreadPool()->InRunnerMode())
|
if (entry.pool->ToThreadPool()->InRunnerMode())
|
||||||
{
|
{
|
||||||
LogWarn("Dropped scheduled task! Expect a leaky counter!");
|
AuLogWarn("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("Would you rather `Why u no exit?!` or `WHY DID U JUST CRASH REEEE` in production?");
|
||||||
}
|
}
|
||||||
Debug::PrintError();
|
Debug::PrintError();
|
||||||
}
|
}
|
||||||
@ -103,7 +103,7 @@ namespace Aurora::Async
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
LogWarn("Dropped SysRuntimePump");
|
AuLogWarn("Dropped SysRuntimePump");
|
||||||
Debug::PrintError();
|
Debug::PrintError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1002,7 +1002,7 @@ namespace Aurora::Async
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
LogWarn("Couldn't clean up thread feature!");
|
AuLogWarn("Couldn't clean up thread feature!");
|
||||||
Debug::PrintError();
|
Debug::PrintError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ namespace Aurora::Console::Commands
|
|||||||
auto cmdItr = gCommands.find(tag);
|
auto cmdItr = gCommands.find(tag);
|
||||||
if (cmdItr == gCommands.end())
|
if (cmdItr == gCommands.end())
|
||||||
{
|
{
|
||||||
LogWarn("Command {} does not exist", tag);
|
AuLogWarn("Command {} does not exist", tag);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ namespace Aurora::Console::Commands
|
|||||||
|
|
||||||
if (!status)
|
if (!status)
|
||||||
{
|
{
|
||||||
LogWarn("Couldn't parse command {}", string);
|
AuLogWarn("Couldn't parse command {}", string);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,8 +192,7 @@ namespace Aurora::Console::Commands
|
|||||||
AuMakeShared<Async::BasicWorkStdFunc>([&commands]()
|
AuMakeShared<Async::BasicWorkStdFunc>([&commands]()
|
||||||
{
|
{
|
||||||
DispatchCommandsFromThis(commands);
|
DispatchCommandsFromThis(commands);
|
||||||
}),
|
}), true)->Dispatch()->BlockUntilComplete();
|
||||||
true)->Dispatch()->BlockUntilComplete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gMutex->Unlock();
|
gMutex->Unlock();
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "Console.hpp"
|
#include "Console.hpp"
|
||||||
#include "Commands/Commands.hpp"
|
#include "Commands/Commands.hpp"
|
||||||
#include "Hooks/Hooks.hpp"
|
#include "Hooks/Hooks.hpp"
|
||||||
|
#include "Logging/Logger.hpp"
|
||||||
#include "ConsoleStd/ConsoleStd.hpp"
|
#include "ConsoleStd/ConsoleStd.hpp"
|
||||||
#include "ConsoleWxWidgets/ConsoleWxWidgets.hpp"
|
#include "ConsoleWxWidgets/ConsoleWxWidgets.hpp"
|
||||||
#include "ConsoleFIO/ConsoleFIO.hpp"
|
#include "ConsoleFIO/ConsoleFIO.hpp"
|
||||||
@ -22,7 +23,7 @@ namespace Aurora::Console
|
|||||||
|
|
||||||
static AuSPtr<ILogger> CreateDefaultLogger()
|
static AuSPtr<ILogger> CreateDefaultLogger()
|
||||||
{
|
{
|
||||||
return {};
|
return Logging::NewLoggerShared(gDefaultSinks);
|
||||||
}
|
}
|
||||||
|
|
||||||
AUKN_SYM void WriteLine(AuUInt8 level, const ConsoleMessage &msg)
|
AUKN_SYM void WriteLine(AuUInt8 level, const ConsoleMessage &msg)
|
||||||
@ -56,6 +57,16 @@ namespace Aurora::Console
|
|||||||
gDefaultLogger = CreateDefaultLogger();
|
gDefaultLogger = CreateDefaultLogger();
|
||||||
//gDefaultSinks.clear();
|
//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)
|
AUKN_SYM AuUInt32 ReadStdIn(void *buffer, AuUInt32 length)
|
||||||
{
|
{
|
||||||
@ -90,6 +101,7 @@ namespace Aurora::Console
|
|||||||
ConsoleFIO::Init();
|
ConsoleFIO::Init();
|
||||||
InitFlusher();
|
InitFlusher();
|
||||||
FinailizeDefaultLogger();
|
FinailizeDefaultLogger();
|
||||||
|
Logging::InitLoggers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pump()
|
void Pump()
|
||||||
@ -102,10 +114,15 @@ namespace Aurora::Console
|
|||||||
|
|
||||||
void Exit()
|
void Exit()
|
||||||
{
|
{
|
||||||
|
gDefaultSinks.clear();
|
||||||
|
gDefaultLogger.reset();
|
||||||
|
gUserLogger.reset();
|
||||||
|
|
||||||
DeinitFlusher();
|
DeinitFlusher();
|
||||||
ConsoleStd::Exit();
|
Logging::DeinitLoggers();
|
||||||
ConsoleWxWidgets::Exit();
|
|
||||||
ConsoleFIO::Exit();
|
ConsoleFIO::Exit();
|
||||||
|
ConsoleWxWidgets::Exit();
|
||||||
|
ConsoleStd::Exit();
|
||||||
Hooks::Deinit();
|
Hooks::Deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
namespace Aurora::Console
|
namespace Aurora::Console
|
||||||
{
|
{
|
||||||
|
|
||||||
void AddDefaultLogger(const AuSPtr<IBasicSink> &logger);
|
void AddDefaultLogger(const AuSPtr<IBasicSink> &logger);
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
|
@ -7,12 +7,12 @@
|
|||||||
***/
|
***/
|
||||||
#include <Source/RuntimeInternal.hpp>
|
#include <Source/RuntimeInternal.hpp>
|
||||||
#include "ConsoleFIO.hpp"
|
#include "ConsoleFIO.hpp"
|
||||||
|
#include "FileSink.hpp"
|
||||||
|
#include "../Console.hpp"
|
||||||
|
|
||||||
namespace Aurora::Console::ConsoleFIO
|
namespace Aurora::Console::ConsoleFIO
|
||||||
{
|
{
|
||||||
static AuList<AuUInt8> gLogBuffer;
|
static IBasicSink * gFileSink;
|
||||||
static AuThreadPrimitives::RWLockUnique_t gLogMutex;
|
|
||||||
static AuIOFS::OpenWriteUnique_t gFileHandle;
|
|
||||||
|
|
||||||
static const auto &gLogConfig = gRuntimeConfig.console.fio;
|
static const auto &gLogConfig = gRuntimeConfig.console.fio;
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ namespace Aurora::Console::ConsoleFIO
|
|||||||
AuString path;
|
AuString path;
|
||||||
AuString procName;
|
AuString procName;
|
||||||
|
|
||||||
if ((gLogConfig.writeLogsToUserDir) || (!IO::FS::GetProfileDomain(path)))
|
if ((!gLogConfig.writeLogsToUserDir) || (!AuIOFS::GetProfileDomain(path)))
|
||||||
{
|
{
|
||||||
path = ".";
|
path = ".";
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ namespace Aurora::Console::ConsoleFIO
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (IO::FS::Remove(path + "/" + files[i]))
|
if (AuIOFS::Remove(path + "/" + files[i]))
|
||||||
{
|
{
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
@ -68,17 +68,17 @@ namespace Aurora::Console::ConsoleFIO
|
|||||||
static void CleanupOldLogs()
|
static void CleanupOldLogs()
|
||||||
{
|
{
|
||||||
AuList<AuString> files;
|
AuList<AuString> files;
|
||||||
AuBST<AuString, IO::FS::Stat> fileMeta;
|
AuBST<AuString, AuIOFS::Stat> fileMeta;
|
||||||
AuUInt32 size {};
|
AuUInt32 size {};
|
||||||
|
|
||||||
auto baseLogPath = GetLogDirectory();
|
auto baseLogPath = GetLogDirectory();
|
||||||
|
|
||||||
IO::FS::FilesInDirectory(baseLogPath, files);
|
AuIOFS::FilesInDirectory(baseLogPath, files);
|
||||||
|
|
||||||
for (const auto &file : files)
|
for (const auto &file : files)
|
||||||
{
|
{
|
||||||
IO::FS::Stat stat;
|
AuIOFS::Stat stat;
|
||||||
IO::FS::StatFile(baseLogPath + "/" + file, stat);
|
AuIOFS::StatFile(baseLogPath + "/" + file, stat);
|
||||||
fileMeta[file] = stat;
|
fileMeta[file] = stat;
|
||||||
size += stat.size;
|
size += stat.size;
|
||||||
}
|
}
|
||||||
@ -94,20 +94,8 @@ namespace Aurora::Console::ConsoleFIO
|
|||||||
|
|
||||||
void Flush()
|
void Flush()
|
||||||
{
|
{
|
||||||
/// It should be expected that the TLS teardown emergency flush to dispatch after deinit
|
if (!gFileSink) return;
|
||||||
if (!gLogMutex)
|
gFileSink->OnFlush();
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AU_LOCK_GUARD(gLogMutex->AsReadable());
|
|
||||||
|
|
||||||
if (gFileHandle)
|
|
||||||
{
|
|
||||||
gFileHandle->Write(Aurora::Memory::MemoryViewStreamRead(gLogBuffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
gLogBuffer.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool OpenLogFile()
|
static bool OpenLogFile()
|
||||||
@ -121,8 +109,8 @@ namespace Aurora::Console::ConsoleFIO
|
|||||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||||
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||||
|
|
||||||
gFileHandle = IO::FS::OpenWriteUnique(path);
|
gFileSink = NewFileSinkNew(path);
|
||||||
return static_cast<bool>(gFileHandle);
|
return gFileSink;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FIOCleanup()
|
void FIOCleanup()
|
||||||
@ -142,27 +130,8 @@ namespace Aurora::Console::ConsoleFIO
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gLogMutex = AuThreadPrimitives::RWLockUnique();
|
Console::AddDefaultLogger(AuUnsafeRaiiToShared(gFileSink));
|
||||||
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'));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pump()
|
void Pump()
|
||||||
@ -173,7 +142,10 @@ namespace Aurora::Console::ConsoleFIO
|
|||||||
void Exit()
|
void Exit()
|
||||||
{
|
{
|
||||||
Flush();
|
Flush();
|
||||||
gLogMutex.reset();
|
if (gFileSink)
|
||||||
gFileHandle.reset();
|
{
|
||||||
|
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);
|
||||||
|
}
|
@ -30,17 +30,24 @@ namespace Aurora::Console
|
|||||||
|
|
||||||
AuString ConsoleMessage::StringifyTime(bool simple) const
|
AuString ConsoleMessage::StringifyTime(bool simple) const
|
||||||
{
|
{
|
||||||
std::tm localized;
|
try
|
||||||
|
|
||||||
Aurora::Time::ToCivilTime(time, false).CopyTo(localized);
|
|
||||||
|
|
||||||
if (simple)
|
|
||||||
{
|
{
|
||||||
return fmt::format("{:%H:%M:%S}", localized);
|
std::tm localized;
|
||||||
|
|
||||||
|
Aurora::Time::ToCivilTime(time, false).CopyTo(localized);
|
||||||
|
|
||||||
|
if (simple)
|
||||||
|
{
|
||||||
|
return fmt::format("{:%H:%M:%S}", localized);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return fmt::format("{:%Y-%m-%d %H:%M:%S}", localized);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
catch (...)
|
||||||
{
|
{
|
||||||
return fmt::format("{:%Y-%m-%d %H:%M:%S}", localized);
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,11 +58,33 @@ namespace Aurora::Console
|
|||||||
|
|
||||||
AuString ConsoleMessage::ToConsole() const
|
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
|
AuString ConsoleMessage::ToSimplified() const
|
||||||
{
|
{
|
||||||
return fmt::format("{:<9} {:<7} | {}", StringifyTime(true), GetWrappedTag(), line);
|
try
|
||||||
|
{
|
||||||
|
return fmt::format("{:<9} {:<7} | {}", StringifyTime(true), GetWrappedTag(), line);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,7 +7,8 @@
|
|||||||
***/
|
***/
|
||||||
#include <Source/RuntimeInternal.hpp>
|
#include <Source/RuntimeInternal.hpp>
|
||||||
#include "ConsoleStd.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)
|
#if defined(AURORA_IS_MODERNNT_DERIVED) || defined(AURORA_IS_POSIX_DERIVED)
|
||||||
|
|
||||||
@ -77,6 +78,43 @@ namespace Aurora::Console::ConsoleStd
|
|||||||
}
|
}
|
||||||
#endif
|
#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()
|
static void StartLogger()
|
||||||
{
|
{
|
||||||
if (gRuntimeConfig.console.enableStdPassthrough && gRuntimeConfig.console.enableStdOut)
|
if (gRuntimeConfig.console.enableStdPassthrough && gRuntimeConfig.console.enableStdOut)
|
||||||
@ -84,51 +122,12 @@ namespace Aurora::Console::ConsoleStd
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Console::Hooks::AddFunctionalHook([](const Aurora::Console::ConsoleMessage &string) -> void
|
if (!gRuntimeConfig.console.enableStdOut)
|
||||||
{
|
{
|
||||||
#if (defined(DEBUG) || defined(STAGING)) && defined(AURORA_IS_MODERNNT_DERIVED)
|
return;
|
||||||
auto debugLine = string.ToSimplified() + "\r\n";
|
}
|
||||||
OutputDebugStringW(Locale::ConvertFromUTF8(debugLine).c_str());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!gRuntimeConfig.console.enableStdOut)
|
Console::AddDefaultLogger(AuUnsafeRaiiToShared(&gStdConsoleSink));
|
||||||
{
|
|
||||||
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
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
@ -287,7 +286,47 @@ namespace Aurora::Console::ConsoleStd
|
|||||||
|
|
||||||
return written;
|
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()
|
static bool InputStreamAvailable()
|
||||||
{
|
{
|
||||||
#if defined(IO_POSIX_STREAMS)
|
#if defined(IO_POSIX_STREAMS)
|
||||||
|
@ -15,6 +15,10 @@ namespace Aurora::Console::ConsoleStd
|
|||||||
|
|
||||||
void Start();
|
void Start();
|
||||||
|
|
||||||
|
|
||||||
|
IBasicSink *NewStdSinkNew();
|
||||||
|
void NewStdSinkRelease(IBasicSink *registry);
|
||||||
|
|
||||||
AuUInt32 ReadStdIn(void *data, AuUInt32 length);
|
AuUInt32 ReadStdIn(void *data, AuUInt32 length);
|
||||||
AuUInt32 WriteStdOut(const 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)
|
void ConsoleFrame::OnHello(wxCommandEvent &event)
|
||||||
{
|
{
|
||||||
LogGame("nani?!");
|
AuLogGame("nani?!");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleFrame::OnBugWrite(wxCommandEvent &event)
|
void ConsoleFrame::OnBugWrite(wxCommandEvent &event)
|
||||||
|
@ -9,10 +9,13 @@
|
|||||||
#include "Flusher.hpp"
|
#include "Flusher.hpp"
|
||||||
|
|
||||||
#include "ConsoleFIO/ConsoleFIO.hpp"
|
#include "ConsoleFIO/ConsoleFIO.hpp"
|
||||||
|
#include "Logging/Logger.hpp"
|
||||||
|
|
||||||
namespace Aurora::Console
|
namespace Aurora::Console
|
||||||
{
|
{
|
||||||
static AuThreads::ThreadUnique_t gWriterThread;
|
static AuThreads::ThreadUnique_t gWriterThread;
|
||||||
|
static AuThreadPrimitives::ConditionVariableUnique_t gCondVar;
|
||||||
|
static AuThreadPrimitives::ConditionMutexUnique_t gMutex;
|
||||||
|
|
||||||
class ShutdownFlushHook : public AuThreads::IThreadFeature
|
class ShutdownFlushHook : public AuThreads::IThreadFeature
|
||||||
{
|
{
|
||||||
@ -38,13 +41,13 @@ namespace Aurora::Console
|
|||||||
|
|
||||||
static void LogThreadEP()
|
static void LogThreadEP()
|
||||||
{
|
{
|
||||||
auto thread = AuThreads::GetThread();
|
|
||||||
|
|
||||||
SlowStartupTasks();
|
SlowStartupTasks();
|
||||||
|
|
||||||
while (!thread->Exiting())
|
AU_LOCK_GUARD(gMutex);
|
||||||
|
|
||||||
|
while (AuIsThreadRunning())
|
||||||
{
|
{
|
||||||
Threading::Sleep(500);
|
gCondVar->WaitForSignal(500);
|
||||||
ForceFlush();
|
ForceFlush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,16 +60,17 @@ namespace Aurora::Console
|
|||||||
static void InitFlushThread()
|
static void InitFlushThread()
|
||||||
{
|
{
|
||||||
// Startup a runner thread that will take care of all the stress inducing IO every so often on a remote thread
|
// 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(
|
gWriterThread = AuThreads::ThreadUnique(AuThreads::ThreadInfo(
|
||||||
AuMakeShared<AuThreads::IThreadVectorsFunctional>(AuThreads::IThreadVectorsFunctional::OnEntry_t(std::bind(LogThreadEP)),
|
AuMakeShared<AuThreads::IThreadVectorsFunctional>(AuThreads::IThreadVectorsFunctional::OnEntry_t(std::bind(LogThreadEP)),
|
||||||
AuThreads::IThreadVectorsFunctional::OnExit_t{}),
|
AuThreads::IThreadVectorsFunctional::OnExit_t{}),
|
||||||
"CasualConsoleAsyncWritter"
|
"CasualConsoleAsyncWritter"
|
||||||
));
|
));
|
||||||
|
|
||||||
if (!gWriterThread)
|
if (!gWriterThread)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gWriterThread->Run();
|
gWriterThread->Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,9 +79,23 @@ namespace Aurora::Console
|
|||||||
// Add a 'ShutdownFlushHook' object to the main threads TLS hook
|
// Add a 'ShutdownFlushHook' object to the main threads TLS hook
|
||||||
AuThreads::GetThread()->AddLastHopeTlsHook(AuMakeShared<ShutdownFlushHook>());
|
AuThreads::GetThread()->AddLastHopeTlsHook(AuMakeShared<ShutdownFlushHook>());
|
||||||
|
|
||||||
|
gMutex = AuThreadPrimitives::ConditionMutexUnique();
|
||||||
|
SysAssert(gMutex);
|
||||||
|
|
||||||
|
gCondVar = AuThreadPrimitives::ConditionVariableUnique(AuUnsafeRaiiToShared(gMutex));
|
||||||
|
SysAssert(gCondVar);
|
||||||
|
|
||||||
InitFlushThread();
|
InitFlushThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PingFlushers()
|
||||||
|
{
|
||||||
|
if (gCondVar)
|
||||||
|
{
|
||||||
|
gCondVar->Signal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DeinitFlusher()
|
void DeinitFlusher()
|
||||||
{
|
{
|
||||||
DestroyFlushThread();
|
DestroyFlushThread();
|
||||||
@ -85,6 +103,7 @@ namespace Aurora::Console
|
|||||||
|
|
||||||
void ForceFlush()
|
void ForceFlush()
|
||||||
{
|
{
|
||||||
|
Logging::ForceFlushLoggers();
|
||||||
ConsoleFIO::Flush();
|
ConsoleFIO::Flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
namespace Aurora::Console
|
namespace Aurora::Console
|
||||||
{
|
{
|
||||||
|
void PingFlushers();
|
||||||
|
|
||||||
void ForceFlush();
|
void ForceFlush();
|
||||||
void InitFlusher();
|
void InitFlusher();
|
||||||
void DeinitFlusher();
|
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
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -15,13 +15,13 @@
|
|||||||
|
|
||||||
namespace Aurora::Debug
|
namespace Aurora::Debug
|
||||||
{
|
{
|
||||||
static thread_local AuUInt32 tlsLastBackTrace = 0xFFFFFFFF;
|
static thread_local AuUInt32 tlsLastBackTrace = 0xFFFFFFFF;
|
||||||
|
static thread_local StackTrace tlsLastStackTrace;
|
||||||
|
static thread_local AuString tlsLastExceptionMessage;
|
||||||
|
|
||||||
static StackTrace gLastStackTrace;
|
|
||||||
static AuUInt32 gStackTraceFence;
|
static AuUInt32 gStackTraceFence;
|
||||||
static AuUInt32 gFenceId;
|
static AuUInt32 gFenceId;
|
||||||
static AuThreadPrimitives::SpinLock gLock;
|
static AuThreadPrimitives::SpinLock gLock;
|
||||||
static AuString gLastExceptionMessage;
|
|
||||||
static AuUInt32 gFenceOSError = -1;
|
static AuUInt32 gFenceOSError = -1;
|
||||||
|
|
||||||
AuUInt32 GetOSErrorFence()
|
AuUInt32 GetOSErrorFence()
|
||||||
@ -175,8 +175,8 @@ namespace Aurora::Debug
|
|||||||
AuUInt32 ReportStackTrace(const StackTrace& trace, const AuString& message)
|
AuUInt32 ReportStackTrace(const StackTrace& trace, const AuString& message)
|
||||||
{
|
{
|
||||||
AU_LOCK_GUARD(gLock);
|
AU_LOCK_GUARD(gLock);
|
||||||
gLastStackTrace = trace;
|
tlsLastStackTrace = trace;
|
||||||
gLastExceptionMessage = message;
|
tlsLastExceptionMessage = message;
|
||||||
tlsLastBackTrace = gStackTraceFence++;
|
tlsLastBackTrace = gStackTraceFence++;
|
||||||
gFenceId++;
|
gFenceId++;
|
||||||
return tlsLastBackTrace;
|
return tlsLastBackTrace;
|
||||||
@ -195,13 +195,13 @@ namespace Aurora::Debug
|
|||||||
AUKN_SYM StackTrace GetLastStackTrace()
|
AUKN_SYM StackTrace GetLastStackTrace()
|
||||||
{
|
{
|
||||||
AU_LOCK_GUARD(gLock);
|
AU_LOCK_GUARD(gLock);
|
||||||
return gLastStackTrace;
|
return tlsLastStackTrace;
|
||||||
}
|
}
|
||||||
|
|
||||||
AUKN_SYM AuString GetLastException()
|
AUKN_SYM AuString GetLastException()
|
||||||
{
|
{
|
||||||
AU_LOCK_GUARD(gLock);
|
AU_LOCK_GUARD(gLock);
|
||||||
return gLastExceptionMessage;
|
return tlsLastExceptionMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
AUKN_SYM OSError_t GetLastSystemMessage()
|
AUKN_SYM OSError_t GetLastSystemMessage()
|
||||||
@ -223,7 +223,7 @@ namespace Aurora::Debug
|
|||||||
auto cError = TryGetOrFetchCError();
|
auto cError = TryGetOrFetchCError();
|
||||||
if ((cError) && (cFence != cLastFence))
|
if ((cError) && (cFence != cLastFence))
|
||||||
{
|
{
|
||||||
LogWarn("Language Error: {} ({})", strerror(*cError), *cError);
|
AuLogWarn("Language Error: {} ({})", strerror(*cError), *cError);
|
||||||
cLastFence = cFence;
|
cLastFence = cFence;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +232,7 @@ namespace Aurora::Debug
|
|||||||
auto osError = TryGetOrFetchOSError();
|
auto osError = TryGetOrFetchOSError();
|
||||||
if ((osError) && (osFence != osLastFence))
|
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;
|
osLastFence = osFence;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,7 +245,7 @@ namespace Aurora::Debug
|
|||||||
Telemetry::EndBlock();
|
Telemetry::EndBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckErrors()
|
AUKN_SYM void CheckErrors()
|
||||||
{
|
{
|
||||||
AuUInt32 rng = GetFenceId();
|
AuUInt32 rng = GetFenceId();
|
||||||
Telemetry::BeginBlock();
|
Telemetry::BeginBlock();
|
||||||
@ -301,7 +301,7 @@ namespace Aurora::Debug
|
|||||||
|
|
||||||
#if defined(DEBUG) || defined(STAGING)
|
#if defined(DEBUG) || defined(STAGING)
|
||||||
PrintError();
|
PrintError();
|
||||||
LogWarn("ERROR: {}", error.dbg);
|
AuLogWarn("ERROR: {}", error.dbg);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,64 +310,78 @@ namespace Aurora::Debug
|
|||||||
const auto frame = *this;
|
const auto frame = *this;
|
||||||
AuString backTraceBuffer;
|
AuString backTraceBuffer;
|
||||||
|
|
||||||
backTraceBuffer.reserve(512 - 32); // 512 seems like a nice length minus some overhead for a bucket allocator
|
try
|
||||||
|
|
||||||
backTraceBuffer += fmt::format("\tAddress: {:x}", frame.address);
|
|
||||||
|
|
||||||
if (frame.module)
|
|
||||||
{
|
{
|
||||||
auto modName = frame.module.value();
|
backTraceBuffer.reserve(512 - 32); // 512 seems like a nice length minus some overhead for a bucket allocator
|
||||||
if (modName.size())
|
|
||||||
|
backTraceBuffer += fmt::format("\tAddress: 0x{:x} (0x{:x})", frame.relAddress ? frame.relAddress : frame.address, frame.relAddress ? frame.address : frame.relAddress);
|
||||||
|
|
||||||
|
if (frame.module)
|
||||||
{
|
{
|
||||||
backTraceBuffer += fmt::format(" within {}", modName);
|
auto modName = frame.module.value();
|
||||||
|
if (modName.size())
|
||||||
|
{
|
||||||
|
backTraceBuffer += fmt::format(" within {}", modName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
backTraceBuffer += ", invalid module";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
backTraceBuffer += ", invalid module";
|
backTraceBuffer += ", unknown module";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
backTraceBuffer += ", unknown module";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frame.label)
|
if (frame.label)
|
||||||
{
|
{
|
||||||
backTraceBuffer += fmt::format(" ({}) \n", frame.label.value());
|
backTraceBuffer += fmt::format(" ({}) \n", frame.label.value());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
backTraceBuffer += ", unknown function\n";
|
backTraceBuffer += ", unknown function\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame.file)
|
|
||||||
{
|
|
||||||
const auto &re = frame.file.value();
|
|
||||||
backTraceBuffer += fmt::format("\t\t{}:{} ({}) \n", std::get<0>(re), std::get<1>(re), std::get<2>(re));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
backTraceBuffer += "\t\t[proprietary]\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
return backTraceBuffer;
|
if (frame.file)
|
||||||
|
{
|
||||||
|
const auto &re = frame.file.value();
|
||||||
|
backTraceBuffer += fmt::format("\t\t{}:{} ({}) \n", std::get<0>(re), std::get<1>(re), std::get<2>(re));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
backTraceBuffer += "\t\t[proprietary]\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return backTraceBuffer;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AUKN_SYM AuString StringifyStackTrace(const StackTrace &backtrace)
|
AUKN_SYM AuString StringifyStackTrace(const StackTrace &backtrace)
|
||||||
{
|
{
|
||||||
AuString backTraceBuffer;
|
AuString backTraceBuffer;
|
||||||
|
|
||||||
backTraceBuffer.reserve(2048);
|
try
|
||||||
|
|
||||||
backTraceBuffer += "Unwinding call frame:";
|
|
||||||
|
|
||||||
for (const auto &frame : backtrace)
|
|
||||||
{
|
{
|
||||||
backTraceBuffer += "\n";
|
backTraceBuffer.reserve(2048);
|
||||||
backTraceBuffer += frame.Stringify();
|
|
||||||
}
|
|
||||||
|
|
||||||
return backTraceBuffer;
|
backTraceBuffer += "Unwinding call frame:";
|
||||||
|
|
||||||
|
for (const auto &frame : backtrace)
|
||||||
|
{
|
||||||
|
backTraceBuffer += "\n";
|
||||||
|
backTraceBuffer += frame.Stringify();
|
||||||
|
}
|
||||||
|
|
||||||
|
return backTraceBuffer;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitDebug()
|
void InitDebug()
|
||||||
|
@ -19,10 +19,33 @@
|
|||||||
#include <vcruntime_exception.h>
|
#include <vcruntime_exception.h>
|
||||||
#include <ehdata.h>
|
#include <ehdata.h>
|
||||||
|
|
||||||
static thread_local int gDebugLocked = 0;
|
#include <Source/Process/ProcessMap.hpp>
|
||||||
|
|
||||||
|
static thread_local int gDebugLocked = 0;
|
||||||
|
|
||||||
namespace Aurora::Debug
|
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)
|
static void ParseStack(CONTEXT *ctx, StackTrace &backTrace)
|
||||||
{
|
{
|
||||||
char buffer[sizeof(SYMBOL_INFO) + (MAX_SYM_NAME + 1) * sizeof(char)] = { 0 };
|
char buffer[sizeof(SYMBOL_INFO) + (MAX_SYM_NAME + 1) * sizeof(char)] = { 0 };
|
||||||
@ -80,26 +103,17 @@ namespace Aurora::Debug
|
|||||||
pSymbol->MaxNameLen = MAX_SYM_NAME;
|
pSymbol->MaxNameLen = MAX_SYM_NAME;
|
||||||
|
|
||||||
frameCurrent.address = stack.AddrPC.Offset;
|
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 (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)(stack.AddrPC.Offset), &hModule))
|
||||||
{
|
{
|
||||||
if (hModule != NULL)
|
if (hModule != NULL)
|
||||||
{
|
{
|
||||||
frameCurrent.module = Process::ModuleToPath(hModule);
|
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)
|
#if defined(DEBUG) || defined(STAGING)
|
||||||
IMAGEHLP_LINE64 line;
|
IMAGEHLP_LINE64 line;
|
||||||
DWORD disp;
|
DWORD disp;
|
||||||
@ -336,8 +350,8 @@ namespace Aurora::Debug
|
|||||||
|
|
||||||
if ((isCritical || isInternal) && (minimal == 0))
|
if ((isCritical || isInternal) && (minimal == 0))
|
||||||
{
|
{
|
||||||
LogWarn("NT Exception: 0x{:x}, {}", ExceptionInfo->ExceptionRecord->ExceptionCode, entry.wincxx.str);
|
AuLogWarn("NT Exception: 0x{:x}, {}", ExceptionInfo->ExceptionRecord->ExceptionCode, entry.wincxx.str);
|
||||||
LogWarn("{}", StringifyStackTrace(entry.wincxx.stack.backtrace));
|
AuLogWarn("{}", StringifyStackTrace(entry.wincxx.stack.backtrace));
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#if defined(AURORA_PLATFORM_WIN32)
|
#if defined(AURORA_PLATFORM_WIN32)
|
||||||
#include "Extensions/Win32/DarkTheme.hpp"
|
#include "Extensions/Win32/DarkTheme.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
#include "Process/ProcessMap.hpp"
|
||||||
|
|
||||||
static void Init()
|
static void Init()
|
||||||
{
|
{
|
||||||
@ -44,6 +45,7 @@ static void Init()
|
|||||||
Aurora::Async::InitAsync();
|
Aurora::Async::InitAsync();
|
||||||
Aurora::HWInfo::Init();
|
Aurora::HWInfo::Init();
|
||||||
Aurora::Telemetry::Init();
|
Aurora::Telemetry::Init();
|
||||||
|
Aurora::Process::InitProcessMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Pump()
|
static void Pump()
|
||||||
@ -66,7 +68,14 @@ namespace Aurora
|
|||||||
AUKN_SYM void RuntimeStart(const RuntimeStartInfo &info)
|
AUKN_SYM void RuntimeStart(const RuntimeStartInfo &info)
|
||||||
{
|
{
|
||||||
gRuntimeConfig = info;
|
gRuntimeConfig = info;
|
||||||
Init();
|
try
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
SysPanic("A fatal error occurred during the initialization of Aurora Runtime");
|
||||||
|
}
|
||||||
gRuntimeHasStarted = true;
|
gRuntimeHasStarted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,10 @@
|
|||||||
#include <cpuid.h>
|
#include <cpuid.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||||
|
#include <VersionHelpers.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Aurora::HWInfo
|
namespace Aurora::HWInfo
|
||||||
{
|
{
|
||||||
static CpuInfo gCpuInfo;
|
static CpuInfo gCpuInfo;
|
||||||
@ -348,10 +352,10 @@ namespace Aurora::HWInfo
|
|||||||
}
|
}
|
||||||
|
|
||||||
char vendor[0x20];
|
char vendor[0x20];
|
||||||
memset(vendor, 0, sizeof(vendor));
|
AuMemset(vendor, 0, sizeof(vendor));
|
||||||
*reinterpret_cast<int*>(vendor) = cpuInfo.ebx;
|
*reinterpret_cast<AuUInt32 *>(vendor) = cpuInfo.ebx;
|
||||||
*reinterpret_cast<int*>(vendor + 4) = cpuInfo.edx;
|
*reinterpret_cast<AuUInt32 *>(vendor + 4) = cpuInfo.edx;
|
||||||
*reinterpret_cast<int*>(vendor + 8) = cpuInfo.ecx;
|
*reinterpret_cast<AuUInt32 *>(vendor + 8) = cpuInfo.ecx;
|
||||||
|
|
||||||
gCpuInfo.cpuId.vendor = vendor;
|
gCpuInfo.cpuId.vendor = vendor;
|
||||||
|
|
||||||
@ -383,7 +387,7 @@ namespace Aurora::HWInfo
|
|||||||
auto nExIds = cpui.eax;
|
auto nExIds = cpui.eax;
|
||||||
|
|
||||||
char brand[0x40];
|
char brand[0x40];
|
||||||
memset(brand, 0, sizeof(brand));
|
AuMemset(brand, 0, sizeof(brand));
|
||||||
|
|
||||||
for (int i = 0x80000000; i <= nExIds; ++i)
|
for (int i = 0x80000000; i <= nExIds; ++i)
|
||||||
{
|
{
|
||||||
@ -400,56 +404,159 @@ namespace Aurora::HWInfo
|
|||||||
// Interpret CPU brand string if reported
|
// Interpret CPU brand string if reported
|
||||||
if (nExIds >= 0x80000004)
|
if (nExIds >= 0x80000004)
|
||||||
{
|
{
|
||||||
memcpy(brand, &extdata[2], sizeof(cpui));
|
AuMemcpy(brand, &extdata[2], sizeof(cpui));
|
||||||
memcpy(brand + 16, &extdata[3], sizeof(cpui));
|
AuMemcpy(brand + 16, &extdata[3], sizeof(cpui));
|
||||||
memcpy(brand + 32, &extdata[4], sizeof(cpui));
|
AuMemcpy(brand + 32, &extdata[4], sizeof(cpui));
|
||||||
gCpuInfo.cpuId.brand = brand;
|
gCpuInfo.cpuId.brand = brand;
|
||||||
}
|
}
|
||||||
#endif
|
#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];
|
SYSTEM_LOGICAL_PROCESSOR_INFORMATION sysinfo[128];
|
||||||
DWORD length = AuArraySize(sysinfo) * sizeof(*sysinfo);
|
DWORD length = AuArraySize(sysinfo) * sizeof(*sysinfo);
|
||||||
|
|
||||||
|
if (IsWindows10OrGreater() || IsWindowsServer() || IsWindowsLTSC())
|
||||||
|
{
|
||||||
|
if (TrySetNtCpuSetInfoSlowExtended())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!GetLogicalProcessorInformation(sysinfo, &length))
|
if (!GetLogicalProcessorInformation(sysinfo, &length))
|
||||||
{
|
{
|
||||||
SYSTEM_INFO sysinfo;
|
SYSTEM_INFO sysinfo;
|
||||||
GetSystemInfo(&sysinfo);
|
GetSystemInfo(&sysinfo);
|
||||||
gCpuInfo.socket = 1;
|
gCpuInfo.socket = 1;
|
||||||
gCpuInfo.cores = 1;
|
gCpuInfo.cores = 1;
|
||||||
gCpuInfo.threads = sysinfo.dwNumberOfProcessors;
|
gCpuInfo.threads = sysinfo.dwNumberOfProcessors;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
length /= sizeof(*sysinfo);
|
length /= sizeof(*sysinfo);
|
||||||
|
|
||||||
gCpuInfo.socket = 0;
|
gCpuInfo.socket = 0;
|
||||||
gCpuInfo.cores = 0;
|
gCpuInfo.cores = 0;
|
||||||
gCpuInfo.threads = 0;
|
gCpuInfo.threads = 0;
|
||||||
|
|
||||||
|
|
||||||
|
bool sparse = false;
|
||||||
for (auto i = 0; i < length; i++)
|
for (auto i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
if (sysinfo[i].Relationship == RelationProcessorCore)
|
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;
|
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;
|
unsigned long offset {}, tmp;
|
||||||
while (offset != (sizeof(offset) * 8))
|
while (offset != (sizeof(offset) * 8))
|
||||||
{
|
{
|
||||||
// Count the index to a 1
|
// Count the index to a 1
|
||||||
if (BitScanForward(&tmp, mask >> offset) == 0) break; // mask was zero, end of scan
|
if (BitScanForward(&tmp, mask >> offset) == 0) break; // mask was zero, end of scan
|
||||||
offset += tmp;
|
offset += tmp;
|
||||||
|
|
||||||
// Count the 1's by inverting the bitmap and counting to 1
|
// Count the 1's by inverting the bitmap and counting to 1
|
||||||
BitScanForward(&tmp, ~(mask >> offset));
|
BitScanForward(&tmp, ~(mask >> offset));
|
||||||
offset += tmp;
|
offset += tmp;
|
||||||
|
|
||||||
|
if (counter++) sparse = true;
|
||||||
|
|
||||||
// Increment threads by the bits set in
|
// Increment threads by the bits set in
|
||||||
gCpuInfo.threads += tmp;
|
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)
|
#elif defined(AURORA_IS_BSD_DERIVED)
|
||||||
|
|
||||||
auto opt = QueryBsdHwStat(HW_AVAILCPU);
|
auto opt = QueryBsdHwStat(HW_AVAILCPU);
|
||||||
@ -472,12 +588,18 @@ namespace Aurora::HWInfo
|
|||||||
gCpuInfo.cores = 1;
|
gCpuInfo.cores = 1;
|
||||||
gCpuInfo.threads = opt.value_or(1);
|
gCpuInfo.threads = opt.value_or(1);
|
||||||
|
|
||||||
|
// TODO: parse sysctl kern.sched.topology_spec
|
||||||
|
gCpuInfo.maskMTHalf = true;
|
||||||
|
|
||||||
#elif defined(AURORA_IS_LINUX_DERIVED)
|
#elif defined(AURORA_IS_LINUX_DERIVED)
|
||||||
|
|
||||||
gCpuInfo.socket = 1;
|
gCpuInfo.socket = 1;
|
||||||
gCpuInfo.cores = 1;
|
gCpuInfo.cores = 1;
|
||||||
gCpuInfo.threads = get_nprocs();
|
gCpuInfo.threads = get_nprocs();
|
||||||
|
|
||||||
|
// TODO: parse /proc/cpuinfo
|
||||||
|
gCpuInfo.maskMTHalf = true;
|
||||||
|
|
||||||
#elif defined(AURORA_IS_POSIX_DERIVED)
|
#elif defined(AURORA_IS_POSIX_DERIVED)
|
||||||
|
|
||||||
gCpuInfo.socket = 1;
|
gCpuInfo.socket = 1;
|
||||||
@ -487,10 +609,47 @@ namespace Aurora::HWInfo
|
|||||||
#endif
|
#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()
|
void InitCpuInfo()
|
||||||
{
|
{
|
||||||
|
gCpuInfo.maskMTContig = false;
|
||||||
|
gCpuInfo.maskMTHalf = false;
|
||||||
gCpuInfo.cpuArch = Aurora::Build::kCurrentArchitecture;
|
gCpuInfo.cpuArch = Aurora::Build::kCurrentArchitecture;
|
||||||
SetCpuId();
|
SetCpuId();
|
||||||
SetCpuTopology();
|
SetCpuTopology();
|
||||||
|
SetFakeTopologyIfMissing();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,16 @@ namespace Aurora::IO::FS
|
|||||||
HANDLE fileHandle;
|
HANDLE fileHandle;
|
||||||
|
|
||||||
auto pathex = NormalizePathRet(path);
|
auto pathex = NormalizePathRet(path);
|
||||||
|
if (!pathex.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto win32Path = Locale::ConvertFromUTF8(pathex);
|
auto win32Path = Locale::ConvertFromUTF8(pathex);
|
||||||
|
if (!win32Path.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
|
auto flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
|
||||||
|
|
||||||
@ -109,7 +118,7 @@ namespace Aurora::IO::FS
|
|||||||
|
|
||||||
if (fileHandle == INVALID_HANDLE_VALUE)
|
if (fileHandle == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
LogWarn("Missing file: {}", path);
|
AuLogWarn("Missing file: {}", path);
|
||||||
SysPushErrorIO("Missing file: {}", path);
|
SysPushErrorIO("Missing file: {}", path);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,7 @@ namespace Aurora::IO::FS
|
|||||||
{
|
{
|
||||||
if (ENOENT == errno)
|
if (ENOENT == errno)
|
||||||
{
|
{
|
||||||
LogWarn("Critical IO error, errno = {}", path);
|
AuLogWarn("Critical IO error, errno = {}", path);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -193,7 +193,7 @@ namespace Aurora::IO::FS
|
|||||||
|
|
||||||
if (!stat.exists)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,8 +56,18 @@ namespace Aurora::IO::FS
|
|||||||
pathNormalized = NormalizePathRet(path);
|
pathNormalized = NormalizePathRet(path);
|
||||||
win32Path = Locale::ConvertFromUTF8(pathNormalized);
|
win32Path = Locale::ConvertFromUTF8(pathNormalized);
|
||||||
|
|
||||||
CreateDirectories(pathNormalized, true);
|
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);
|
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
if (fileHandle == INVALID_HANDLE_VALUE)
|
if (fileHandle == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
@ -106,6 +116,11 @@ namespace Aurora::IO::FS
|
|||||||
offset = 0;
|
offset = 0;
|
||||||
win32Path = Locale::ConvertFromUTF8(NormalizePathRet(path));
|
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);
|
auto fileHandle = CreateFileW(win32Path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
if (fileHandle == INVALID_HANDLE_VALUE)
|
if (fileHandle == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
@ -133,7 +148,7 @@ namespace Aurora::IO::FS
|
|||||||
|
|
||||||
if (!::ReadFile(fileHandle, &buffer[offset], blockSize, &read, NULL))
|
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();
|
SysPushErrorIO();
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -151,36 +166,78 @@ namespace Aurora::IO::FS
|
|||||||
|
|
||||||
AUKN_SYM bool FileExists(const AuString &path)
|
AUKN_SYM bool FileExists(const AuString &path)
|
||||||
{
|
{
|
||||||
DWORD dwAttrib = GetFileAttributesW(Locale::ConvertFromUTF8(NormalizePathRet(path)).c_str());
|
try
|
||||||
return ((dwAttrib != INVALID_FILE_ATTRIBUTES) &&
|
{
|
||||||
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
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)
|
AUKN_SYM bool DirExists(const AuString &path)
|
||||||
{
|
{
|
||||||
DWORD dwAttrib = GetFileAttributesW(Locale::ConvertFromUTF8(NormalizePathRet(path)).c_str());
|
try
|
||||||
return ((dwAttrib != INVALID_FILE_ATTRIBUTES) &&
|
{
|
||||||
(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
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)
|
AUKN_SYM bool DirMk(const AuString &path)
|
||||||
{
|
{
|
||||||
return CreateDirectories(NormalizePathRet(path), false);
|
try
|
||||||
|
{
|
||||||
|
return CreateDirectories(NormalizePathRet(path), false);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AUKN_SYM bool Remove(const AuString &path)
|
AUKN_SYM bool Remove(const AuString &path)
|
||||||
{
|
{
|
||||||
return DeleteFileW(Locale::ConvertFromUTF8(NormalizePathRet(path)).c_str());
|
try
|
||||||
|
{
|
||||||
|
return DeleteFileW(Locale::ConvertFromUTF8(NormalizePathRet(path)).c_str());
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AUKN_SYM bool Relink(const AuString &src, const AuString &dest)
|
AUKN_SYM bool Relink(const AuString &src, const AuString &dest)
|
||||||
{
|
{
|
||||||
return MoveFileW(Locale::ConvertFromUTF8(NormalizePathRet(src)).c_str(), Locale::ConvertFromUTF8(NormalizePathRet(dest)).c_str());
|
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)
|
AUKN_SYM bool Copy(const AuString &src, const AuString &dest)
|
||||||
{
|
{
|
||||||
return CopyFileW(Locale::ConvertFromUTF8(NormalizePathRet(src)).c_str(), Locale::ConvertFromUTF8(NormalizePathRet(dest)).c_str(), true);
|
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)
|
AUKN_SYM bool StatFile(const AuString &path, Stat &stat)
|
||||||
|
@ -43,44 +43,65 @@ namespace Aurora::IO::FS
|
|||||||
|
|
||||||
static void NormalizePath(AuString &str)
|
static void NormalizePath(AuString &str)
|
||||||
{
|
{
|
||||||
_NormalizePath(str);
|
try
|
||||||
|
{
|
||||||
|
_NormalizePath(str);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
str = {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline AuString NormalizePathRet(const AuString &str)
|
static auline AuString NormalizePathRet(const AuString &str)
|
||||||
{
|
{
|
||||||
AuString ret = str;
|
try
|
||||||
_NormalizePath(ret);
|
{
|
||||||
return ret;
|
AuString ret = str;
|
||||||
|
_NormalizePath(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _MkDir(const AuString &str);
|
bool _MkDir(const AuString &str);
|
||||||
|
|
||||||
static bool CreateDirectories(const AuString &cpath, bool isFile)
|
static bool CreateDirectories(const AuString &cpath, bool isFile)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < cpath.size(); i++)
|
try
|
||||||
{
|
{
|
||||||
bool end = i == cpath.size() - 1;
|
for (int i = 0; i < cpath.size(); i++)
|
||||||
if ((cpath[i] == kPathSplitter) ||
|
|
||||||
((!isFile) && (end)))
|
|
||||||
{
|
{
|
||||||
auto subpath = end ? cpath : AuString(cpath.begin(), cpath.begin() + i);
|
bool end = i == cpath.size() - 1;
|
||||||
|
if ((cpath[i] == kPathSplitter) ||
|
||||||
if (DirExists(subpath))
|
((!isFile) && (end)))
|
||||||
{
|
{
|
||||||
continue;
|
auto subpath = end ? cpath : AuString(cpath.begin(), cpath.begin() + i);
|
||||||
}
|
|
||||||
|
|
||||||
if (!_MkDir(subpath))
|
if (DirExists(subpath))
|
||||||
{
|
|
||||||
if (!DirExists(subpath)) // copium. im worried :(
|
|
||||||
{
|
{
|
||||||
return false; // ...aw shit
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_MkDir(subpath))
|
||||||
|
{
|
||||||
|
if (!DirExists(subpath)) // copium. im worried :(
|
||||||
|
{
|
||||||
|
return false; // ...aw shit
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IterateDirEntriesSTL(const AuString &path, bool filesOnly, AuList<AuString> &patches)
|
static bool IterateDirEntriesSTL(const AuString &path, bool filesOnly, AuList<AuString> &patches)
|
||||||
|
@ -189,7 +189,7 @@ namespace Aurora::IO::FS
|
|||||||
}
|
}
|
||||||
catch (...)
|
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)
|
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();
|
SysPushErrorIO();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ namespace Aurora::IO::FS
|
|||||||
|
|
||||||
if (SetFilePointerEx(handle_, distance, &pos, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
|
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();
|
SysPushErrorIO();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -107,7 +107,7 @@ namespace Aurora::IO::FS
|
|||||||
|
|
||||||
if (!::ReadFile(handle_, reinterpret_cast<char *>(parameters.ptr) + offset, blockSize, &read, NULL))
|
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();
|
SysPushErrorIO();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -148,7 +148,7 @@ namespace Aurora::IO::FS
|
|||||||
|
|
||||||
if (!::WriteFile(handle_, reinterpret_cast<const char *>(parameters.ptr) + offset, blockSize, &written, NULL))
|
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();
|
SysPushErrorIO();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -196,36 +196,52 @@ namespace Aurora::IO::FS
|
|||||||
|
|
||||||
static IFileStream *OpenNew(const AuString &path, bool read)
|
static IFileStream *OpenNew(const AuString &path, bool read)
|
||||||
{
|
{
|
||||||
auto pathex = NormalizePathRet(path);
|
try
|
||||||
auto win32Path = Locale::ConvertFromUTF8(pathex);
|
{
|
||||||
|
auto pathex = NormalizePathRet(path);
|
||||||
|
if (pathex.empty())
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
HANDLE fileHandle;
|
auto win32Path = Locale::ConvertFromUTF8(pathex);
|
||||||
if (read)
|
if (win32Path.empty())
|
||||||
{
|
{
|
||||||
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
return nullptr;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
CreateDirectories(pathex, true);
|
|
||||||
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fileHandle == INVALID_HANDLE_VALUE)
|
HANDLE fileHandle;
|
||||||
|
if (read)
|
||||||
|
{
|
||||||
|
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CreateDirectories(pathex, true);
|
||||||
|
fileHandle = CreateFileW(win32Path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileHandle == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
AuLogWarn("Missing file: {}", path);
|
||||||
|
SysPushErrorIO("Missing file: {}", path);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto stream = _new WinFileStream();
|
||||||
|
if (!stream)
|
||||||
|
{
|
||||||
|
CloseHandle(fileHandle);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->Init(fileHandle, pathex);
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
{
|
{
|
||||||
LogWarn("Missing file: {}", path);
|
|
||||||
SysPushErrorIO("Missing file: {}", path);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto stream = _new WinFileStream();
|
|
||||||
if (!stream)
|
|
||||||
{
|
|
||||||
CloseHandle(fileHandle);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
stream->Init(fileHandle, pathex);
|
|
||||||
return stream;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AUKN_SYM IFileStream *OpenReadNew(const AuString &path)
|
AUKN_SYM IFileStream *OpenReadNew(const AuString &path)
|
||||||
|
@ -61,7 +61,7 @@ namespace Aurora::IO::FS
|
|||||||
|
|
||||||
if (fileName.find("..") != AuString::npos)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,3 +10,14 @@
|
|||||||
#include "Encoding.hpp"
|
#include "Encoding.hpp"
|
||||||
#include "EncoderIConv.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
|
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}}
|
#define ADD_PATTERN(str, code) {str, {ECodePage::code, AuArraySize(str) - 1}}
|
||||||
AuList<AuTuple<const char *, BOM>> bows =
|
AuList<AuTuple<const char *, BOM>> bows =
|
||||||
|
@ -32,49 +32,77 @@ namespace Aurora::Locale
|
|||||||
|
|
||||||
AUKN_SYM AuString ConvertFromWChar(const wchar_t *in)
|
AUKN_SYM AuString ConvertFromWChar(const wchar_t *in)
|
||||||
{
|
{
|
||||||
return ConvertFromWChar(in, wcslen(in));
|
try
|
||||||
|
{
|
||||||
|
return ConvertFromWChar(in, wcslen(in));
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
SysPushErrorMem("ConvertFromWChar failed");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AUKN_SYM AuString ConvertFromWChar(const wchar_t *in, AuMach length)
|
AUKN_SYM AuString ConvertFromWChar(const wchar_t *in, AuMach length)
|
||||||
{
|
{
|
||||||
#if defined(AU_HAS_MSFT_NATIONALLANGSUPPORT)
|
try
|
||||||
AuString ret;
|
|
||||||
auto chars = WideCharToMultiByte(CP_UTF8, 0, in, length, NULL, 0, NULL, NULL);
|
|
||||||
|
|
||||||
if (!chars)
|
|
||||||
{
|
{
|
||||||
return {};
|
#if defined(AU_HAS_MSFT_NATIONALLANGSUPPORT)
|
||||||
}
|
AuString ret;
|
||||||
|
auto chars = WideCharToMultiByte(CP_UTF8, 0, in, length, NULL, 0, NULL, NULL);
|
||||||
|
|
||||||
ret.resize(chars);
|
if (!chars)
|
||||||
WideCharToMultiByte(CP_UTF8, 0, in, length, ret.data(), ret.size(), NULL, NULL);
|
{
|
||||||
return ret;
|
return {};
|
||||||
#elif !defined(AU_NO_CPPLOCALE)
|
}
|
||||||
return gUtf8Conv.to_bytes(std::wstring(in, wcslen(in)));
|
|
||||||
#else
|
ret.resize(chars);
|
||||||
return false;
|
WideCharToMultiByte(CP_UTF8, 0, in, length, ret.data(), ret.size(), NULL, NULL);
|
||||||
#endif
|
return ret;
|
||||||
|
#elif !defined(AU_NO_CPPLOCALE)
|
||||||
|
return gUtf8Conv.to_bytes(std::wstring(in, wcslen(in)));
|
||||||
|
#else
|
||||||
|
SysPushErrorUnimplemented("ConvertFromWChar");
|
||||||
|
return {};
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
SysPushErrorMem("ConvertFromWChar failed");
|
||||||
|
Debug::CheckErrors();
|
||||||
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
AUKN_SYM std::wstring ConvertFromUTF8(const AuString &in)
|
AUKN_SYM std::wstring ConvertFromUTF8(const AuString &in)
|
||||||
{
|
{
|
||||||
#if defined(AU_HAS_MSFT_NATIONALLANGSUPPORT)
|
try
|
||||||
std::wstring ret;
|
|
||||||
auto chars = MultiByteToWideChar(CP_UTF8, 0, in.c_str(), in.length(), NULL, 0);
|
|
||||||
|
|
||||||
if (!chars)
|
|
||||||
{
|
{
|
||||||
return {};
|
#if defined(AU_HAS_MSFT_NATIONALLANGSUPPORT)
|
||||||
}
|
std::wstring ret;
|
||||||
|
auto chars = MultiByteToWideChar(CP_UTF8, 0, in.c_str(), in.length(), NULL, 0);
|
||||||
|
|
||||||
ret.resize(chars);
|
if (!chars)
|
||||||
MultiByteToWideChar(CP_UTF8, 0, in.c_str(), in.length(), ret.data(), ret.size());
|
{
|
||||||
return ret;
|
return {};
|
||||||
#elif !defined(AU_NO_CPPLOCALE)
|
}
|
||||||
return gUtf8Conv.from_bytes(in);
|
|
||||||
#else
|
ret.resize(chars);
|
||||||
return false;
|
MultiByteToWideChar(CP_UTF8, 0, in.c_str(), in.length(), ret.data(), ret.size());
|
||||||
#endif
|
return ret;
|
||||||
|
#elif !defined(AU_NO_CPPLOCALE)
|
||||||
|
return gUtf8Conv.from_bytes(in);
|
||||||
|
#else
|
||||||
|
SysPushErrorUnimplemented("ConvertFromUTF8");
|
||||||
|
return {};
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
SysPushErrorMem("ConvertFromUTF8 failed");
|
||||||
|
Debug::CheckErrors();
|
||||||
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ECodePage GetInternalCodePage()
|
ECodePage GetInternalCodePage()
|
||||||
@ -214,9 +242,9 @@ namespace Aurora::Locale
|
|||||||
|
|
||||||
if (locale == "C")
|
if (locale == "C")
|
||||||
{
|
{
|
||||||
LogWarn("Improperly configured UNIX environment.");
|
AuLogWarn("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.");
|
AuLogWarn("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("'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");
|
SysPanic("You fools");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,8 +257,8 @@ namespace Aurora::Locale
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogWarn("Improperly configured UNIX environment.");
|
AuLogWarn("Improperly configured UNIX environment.");
|
||||||
LogWarn("Couldn't discern language from localization string: {}", locale);
|
AuLogWarn("Couldn't discern language from localization string: {}", locale);
|
||||||
SysPanic("You fools");
|
SysPanic("You fools");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,9 +371,9 @@ namespace Aurora::Locale
|
|||||||
|
|
||||||
gLanguageCode = AuToLower(gLanguageCode);
|
gLanguageCode = AuToLower(gLanguageCode);
|
||||||
gCountryCode = AuToUpper(gCountryCode);
|
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;
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(ret = AuMakeShared<Mutex>(mutex)))
|
return AuMakeShared<Mutex>(mutex);
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -37,11 +37,6 @@ namespace Aurora::Loop
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(ret = AuMakeShared<Semaphore>(mutex)))
|
return AuMakeShared<Semaphore>(mutex);
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -19,36 +19,43 @@ namespace Aurora::Loop
|
|||||||
AuList<HANDLE> handleArray;
|
AuList<HANDLE> handleArray;
|
||||||
AuSPtr<ILoopSource> msgSource;
|
AuSPtr<ILoopSource> msgSource;
|
||||||
|
|
||||||
isWinLoop = false;
|
try
|
||||||
loopSourceExs.reserve(objects.size());
|
|
||||||
handleArray.reserve(objects.size());
|
|
||||||
triggered.reserve(triggered.size());
|
|
||||||
|
|
||||||
for (const auto &source : objects)
|
|
||||||
{
|
{
|
||||||
if (!source)
|
isWinLoop = false;
|
||||||
{
|
loopSourceExs.reserve(objects.size());
|
||||||
continue;
|
handleArray.reserve(objects.size());
|
||||||
}
|
triggered.reserve(triggered.size());
|
||||||
|
|
||||||
if (source->GetType() == ELoopSource::eSourceWin32)
|
|
||||||
{
|
|
||||||
isWinLoop = true;
|
|
||||||
msgSource = source;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto extended = std::dynamic_pointer_cast<ILoopSourceEx>(source))
|
for (const auto &source : objects)
|
||||||
{
|
{
|
||||||
loopSourceExs.push_back(extended);
|
if (!source)
|
||||||
for (const auto &handle : extended->GetHandles())
|
|
||||||
{
|
{
|
||||||
auto nthandle = reinterpret_cast<HANDLE>(handle);
|
continue;
|
||||||
handleArray.push_back(nthandle);
|
}
|
||||||
|
|
||||||
|
if (source->GetType() == ELoopSource::eSourceWin32)
|
||||||
|
{
|
||||||
|
isWinLoop = true;
|
||||||
|
msgSource = source;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto extended = std::dynamic_pointer_cast<ILoopSourceEx>(source))
|
||||||
|
{
|
||||||
|
loopSourceExs.push_back(extended);
|
||||||
|
for (const auto &handle : extended->GetHandles())
|
||||||
|
{
|
||||||
|
auto nthandle = reinterpret_cast<HANDLE>(handle);
|
||||||
|
handleArray.push_back(nthandle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto &source : loopSourceExs)
|
for (const auto &source : loopSourceExs)
|
||||||
{
|
{
|
||||||
source->OnPresleep();
|
source->OnPresleep();
|
||||||
@ -100,7 +107,7 @@ namespace Aurora::Loop
|
|||||||
|
|
||||||
if (source->OnTrigger(lastHandle, wasTriggered))
|
if (source->OnTrigger(lastHandle, wasTriggered))
|
||||||
{
|
{
|
||||||
triggered.push_back(source);
|
AuTryInsert(triggered, source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +116,7 @@ namespace Aurora::Loop
|
|||||||
|
|
||||||
if (isPump)
|
if (isPump)
|
||||||
{
|
{
|
||||||
triggered.push_back(msgSource);
|
AuTryInsert(triggered, msgSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
return triggered;
|
return triggered;
|
||||||
|
@ -20,7 +20,7 @@ namespace Aurora::Loop
|
|||||||
|
|
||||||
if (handles.size() == 1)
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -30,7 +30,7 @@ namespace Aurora::Loop
|
|||||||
{
|
{
|
||||||
ntHandles.push_back(reinterpret_cast<HANDLE>(handle));
|
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_)
|
if (count_)
|
||||||
{
|
{
|
||||||
LogWarn("Heap life was less than its allocations, waiting for final free");
|
AuLogWarn("Heap life was less than its allocations, waiting for final free");
|
||||||
LogWarn("Reporting using mayday!");
|
AuLogWarn("Reporting using mayday!");
|
||||||
Telemetry::Mayday();
|
Telemetry::Mayday();
|
||||||
|
|
||||||
isDangling_ = true;
|
isDangling_ = true;
|
||||||
|
@ -23,7 +23,7 @@ namespace Aurora::Parse
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
Console::Logging::LogWarn("Decoding error: {}", in);
|
AuLogWarn("Decoding error: {}", in);
|
||||||
Debug::PrintError();
|
Debug::PrintError();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -41,7 +41,7 @@ namespace Aurora::Parse
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
Console::Logging::LogWarn("Encoding error");
|
AuLogWarn("Encoding error");
|
||||||
Debug::PrintError();
|
Debug::PrintError();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ namespace Aurora::Parse
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
Console::Logging::LogWarn("Decoding error: {}", in);
|
AuLogWarn("Decoding error: {}", in);
|
||||||
Debug::PrintError();
|
Debug::PrintError();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ namespace Aurora::Parse
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
Console::Logging::LogWarn("Encoding error");
|
AuLogWarn("Encoding error");
|
||||||
Debug::PrintError();
|
Debug::PrintError();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -196,11 +196,11 @@ namespace Aurora::Parse
|
|||||||
//SysAssert(!stringLevel, "Parsed tag of string type must end with \", got {}", out);
|
//SysAssert(!stringLevel, "Parsed tag of string type must end with \", got {}", out);
|
||||||
if (stringLevel)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Aurora::Console::Logging::LogDbg("returned {} {}", out, count != 0);
|
//AuLogDbg("returned {} {}", out, count != 0);
|
||||||
return out.size() != 0;
|
return out.size() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,7 +369,7 @@ namespace Aurora::Parse
|
|||||||
uuid = uuids::uuid::from_string(str);
|
uuid = uuids::uuid::from_string(str);
|
||||||
if (!uuid.has_value())
|
if (!uuid.has_value())
|
||||||
{
|
{
|
||||||
LogWarn("Parse Error: invalid UUID {}", str);
|
AuLogWarn("Parse Error: invalid UUID {}", str);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
out.UUID = uuid.value();
|
out.UUID = uuid.value();
|
||||||
@ -387,7 +387,7 @@ namespace Aurora::Parse
|
|||||||
}
|
}
|
||||||
else
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -457,7 +457,7 @@ namespace Aurora::Parse
|
|||||||
|
|
||||||
if (!ConsumeToken(state, context, ParsableTag::kParseUInt, arrayLengthBit))
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,7 +505,7 @@ namespace Aurora::Parse
|
|||||||
break;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ namespace Aurora::Process
|
|||||||
|
|
||||||
for (const auto &name : procFsPaths)
|
for (const auto &name : procFsPaths)
|
||||||
{
|
{
|
||||||
if (Aurora::IO::FS::ReadString(name, path))
|
if (AuIOFS::ReadString(name, path))
|
||||||
{
|
{
|
||||||
splitter = '/';
|
splitter = '/';
|
||||||
return true;
|
return true;
|
||||||
@ -138,8 +138,11 @@ namespace Aurora::Process
|
|||||||
{
|
{
|
||||||
static AuString cachedModule, cachedPartialPath, cachedFullPath;
|
static AuString cachedModule, cachedPartialPath, cachedFullPath;
|
||||||
static bool init = false;
|
static bool init = false;
|
||||||
|
static AuThreadPrimitives::SpinLock spinlock;
|
||||||
char spitter;
|
char spitter;
|
||||||
|
|
||||||
|
AU_TRY_LOCK_GUARD_RET_DEF(spinlock);
|
||||||
|
|
||||||
if (AuExchange(init, true))
|
if (AuExchange(init, true))
|
||||||
{
|
{
|
||||||
if (!cachedModule.size())
|
if (!cachedModule.size())
|
||||||
@ -178,13 +181,20 @@ namespace Aurora::Process
|
|||||||
{
|
{
|
||||||
AuString module, partial, full;
|
AuString module, partial, full;
|
||||||
|
|
||||||
if (!GetModulePath(module, partial, full))
|
try
|
||||||
|
{
|
||||||
|
if (!GetModulePath(module, partial, full))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
executable = module;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
executable = module;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,18 +202,25 @@ namespace Aurora::Process
|
|||||||
{
|
{
|
||||||
AuString module, partial, full;
|
AuString module, partial, full;
|
||||||
|
|
||||||
if (!GetModulePath(module, partial, full))
|
try
|
||||||
|
{
|
||||||
|
if (!GetModulePath(module, partial, full))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = partial;
|
||||||
|
|
||||||
|
if (path.empty())
|
||||||
|
{
|
||||||
|
return GetWorkingDirectory(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
path = partial;
|
|
||||||
|
|
||||||
if (path.empty())
|
|
||||||
{
|
|
||||||
return GetWorkingDirectory(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,13 +228,20 @@ namespace Aurora::Process
|
|||||||
{
|
{
|
||||||
AuString module, partial, full;
|
AuString module, partial, full;
|
||||||
|
|
||||||
if (!GetModulePath(module, partial, full))
|
try
|
||||||
|
{
|
||||||
|
if (!GetModulePath(module, partial, full))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = full;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
path = full;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -23,6 +23,8 @@
|
|||||||
#include <Source/IO/FS/FS.hpp>
|
#include <Source/IO/FS/FS.hpp>
|
||||||
#include <Source/IO/FS/Resources.hpp>
|
#include <Source/IO/FS/Resources.hpp>
|
||||||
|
|
||||||
|
#include "ProcessMap.hpp"
|
||||||
|
|
||||||
namespace Aurora::Process
|
namespace Aurora::Process
|
||||||
{
|
{
|
||||||
static AuThreadPrimitives::SpinLock gSpinLock;
|
static AuThreadPrimitives::SpinLock gSpinLock;
|
||||||
@ -265,7 +267,7 @@ namespace Aurora::Process
|
|||||||
{
|
{
|
||||||
fail = false;
|
fail = false;
|
||||||
|
|
||||||
auto pathNrml = IO::FS::NormalizePathRet(path);
|
auto pathNrml = AuIOFS::NormalizePathRet(path);
|
||||||
|
|
||||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||||
auto widePath = Locale::ConvertFromUTF8(pathNrml);
|
auto widePath = Locale::ConvertFromUTF8(pathNrml);
|
||||||
@ -278,7 +280,7 @@ namespace Aurora::Process
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto absPath = IO::FS::NormalizePathRet(abs);
|
auto absPath = AuIOFS::NormalizePathRet(abs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (request.verify || (kIsMainSigned || request.enableMitigations))
|
if (request.verify || (kIsMainSigned || request.enableMitigations))
|
||||||
@ -292,7 +294,7 @@ namespace Aurora::Process
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
LogWarn("Can't verify {} on this platform", path);
|
AuLogWarn("Can't verify {} on this platform", path);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,7 +344,7 @@ namespace Aurora::Process
|
|||||||
AuString bAbs = path + "/" + genericDll + ".";
|
AuString bAbs = path + "/" + genericDll + ".";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (Aurora::IO::FS::FileExists(a))
|
if (AuIOFS::FileExists(a))
|
||||||
{
|
{
|
||||||
return TryLoadModule(a,
|
return TryLoadModule(a,
|
||||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
#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,
|
return TryLoadModule(b,
|
||||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||||
@ -382,15 +384,15 @@ namespace Aurora::Process
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case EModulePath::eModulePathSystemDir:
|
case EModulePath::eModulePathSystemDir:
|
||||||
pathA = IO::FS::GetSystemLibPath().value_or(AuString {});
|
pathA = AuIOFS::GetSystemLibPath().value_or(AuString {});
|
||||||
pathB = IO::FS::GetSystemLibPath2().value_or(AuString {});
|
pathB = AuIOFS::GetSystemLibPath2().value_or(AuString {});
|
||||||
|
|
||||||
if (pathA.empty()) return false;
|
if (pathA.empty()) return false;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case EModulePath::eModulePathUserDir:
|
case EModulePath::eModulePathUserDir:
|
||||||
pathA = IO::FS::GetUserLibPath().value_or(AuString {});
|
pathA = AuIOFS::GetUserLibPath().value_or(AuString {});
|
||||||
pathB = IO::FS::GetUserLibPath2().value_or(AuString {});
|
pathB = AuIOFS::GetUserLibPath2().value_or(AuString {});
|
||||||
|
|
||||||
if (pathA.empty()) return false;
|
if (pathA.empty()) return false;
|
||||||
|
|
||||||
@ -532,6 +534,16 @@ namespace Aurora::Process
|
|||||||
#endif
|
#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
|
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 <Source/RuntimeInternal.hpp>
|
||||||
#include "ProcessMap.Win32.hpp"
|
#include "ProcessMap.Win32.hpp"
|
||||||
|
#include "ProcessMap.NT.hpp"
|
||||||
|
#include <tlhelp32.h>
|
||||||
|
|
||||||
namespace Aurora::Process
|
namespace Aurora::Process
|
||||||
{
|
{
|
||||||
static AuString ModuleToSomething(HMODULE handle, bool path)
|
void MakeToolHelp32Snapshot()
|
||||||
{
|
{
|
||||||
std::wstring file;
|
MODULEENTRY32 me32;
|
||||||
file.resize(16 * 1024);
|
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
// HMODULE arent handles, they're COFF pointers
|
hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
|
||||||
if (!handle)
|
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());
|
do
|
||||||
if (!length)
|
|
||||||
{
|
{
|
||||||
return {};
|
auto h = reinterpret_cast<HMODULE>(me32.modBaseAddr);
|
||||||
|
InvaildateModule(h);
|
||||||
|
MakeAware(h);
|
||||||
}
|
}
|
||||||
|
while (Module32Next(hModuleSnap, &me32));
|
||||||
|
|
||||||
file.resize(length);
|
CloseHandle(hModuleSnap);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
namespace Aurora::Process
|
namespace Aurora::Process
|
||||||
{
|
{
|
||||||
|
void MakeToolHelp32Snapshot();
|
||||||
|
|
||||||
AuString ModuleToName(HMODULE handle);
|
AuString ModuleToName(HMODULE handle);
|
||||||
AuString ModuleToPath(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)
|
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();
|
gOpenItems.clear();
|
||||||
gCondVariable->WaitForSignal();
|
gCondVariable->WaitForSignal();
|
||||||
@ -41,7 +41,7 @@ namespace Aurora::Processes
|
|||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
Debug::PrintError();
|
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()
|
void InitWin32Opener()
|
||||||
{
|
{
|
||||||
gCondMutex = AuThreadPrimitives::ConditionMutexUnique();
|
gCondMutex = AuThreadPrimitives::ConditionMutexUnique();
|
||||||
|
SysAssert(gCondMutex);
|
||||||
|
|
||||||
gCondVariable = AuThreadPrimitives::ConditionVariableUnique(AuUnsafeRaiiToShared(gCondMutex));
|
gCondVariable = AuThreadPrimitives::ConditionVariableUnique(AuUnsafeRaiiToShared(gCondMutex));
|
||||||
|
SysAssert(gCondVariable);
|
||||||
|
|
||||||
gOpenerThread = AuThreads::ThreadUnique(AuThreads::ThreadInfo(
|
gOpenerThread = AuThreads::ThreadUnique(AuThreads::ThreadInfo(
|
||||||
AuMakeShared<AuThreads::IThreadVectorsFunctional>(AuThreads::IThreadVectorsFunctional::OnEntry_t(std::bind(OpenerThread)),
|
AuMakeShared<AuThreads::IThreadVectorsFunctional>(AuThreads::IThreadVectorsFunctional::OnEntry_t(std::bind(OpenerThread)),
|
||||||
AuThreads::IThreadVectorsFunctional::OnExit_t{}),
|
AuThreads::IThreadVectorsFunctional::OnExit_t{}),
|
||||||
"COM ShellExecute Runner"
|
"COM ShellExecute Runner"
|
||||||
));
|
));
|
||||||
|
SysAssert(gOpenerThread);
|
||||||
|
|
||||||
gOpenerThread->Run();
|
gOpenerThread->Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,6 +89,6 @@ namespace Aurora::Processes
|
|||||||
|
|
||||||
AUKN_SYM void OpenFile(const AuString &file)
|
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_ = {};
|
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);
|
currentStreamDocument_ = json::parse(file);
|
||||||
@ -293,7 +293,6 @@ namespace Aurora::Registry
|
|||||||
SaveBuffered();
|
SaveBuffered();
|
||||||
CloseSave();
|
CloseSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FSRegistry::OpenRead(const AuString &path)
|
void FSRegistry::OpenRead(const AuString &path)
|
||||||
{
|
{
|
||||||
@ -349,7 +348,7 @@ namespace Aurora::Registry
|
|||||||
return false;
|
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());
|
SysPushErrorIO("Couldn't write registry to {}", lastPath_.value());
|
||||||
return false;
|
return false;
|
||||||
|
@ -13,18 +13,18 @@
|
|||||||
#include "TLSView.hpp"
|
#include "TLSView.hpp"
|
||||||
|
|
||||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(AURORA_HAS_PTHREADS)
|
#if defined(AURORA_HAS_PTHREADS)
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(AURORA_PLATFORM_WIN32)
|
#if defined(AURORA_PLATFORM_WIN32)
|
||||||
#include <process.h>
|
#include <Aux_ulib.h>
|
||||||
#include <Aux_ulib.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "SpawnThread.hpp"
|
||||||
|
|
||||||
namespace Aurora::Threading::Threads
|
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
|
// The thread must've requested suicide and got stuck in a lengthy clean up effort
|
||||||
if (!exitOnlyOnce_->TryLock())
|
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;
|
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
|
// Kill the current OS thread instance
|
||||||
TeminateOSContext(false);
|
TeminateOSContext(false);
|
||||||
@ -266,7 +266,7 @@ namespace Aurora::Threading::Threads
|
|||||||
return prio_;
|
return prio_;
|
||||||
}
|
}
|
||||||
|
|
||||||
AuUInt32 OSThread::GetMask()
|
AuUInt64 OSThread::GetMask()
|
||||||
{
|
{
|
||||||
return affinityProcessMask_;
|
return affinityProcessMask_;
|
||||||
}
|
}
|
||||||
@ -276,9 +276,9 @@ namespace Aurora::Threading::Threads
|
|||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSThread::SetAffinity(AuUInt32 mask)
|
void OSThread::SetAffinity(AuUInt64 mask)
|
||||||
{
|
{
|
||||||
if (mask == 0) mask = 0xFFFFFFFF;
|
if (mask == 0) mask = 0xFFFFFFFFFFFFFFFF;
|
||||||
affinityProcessMask_ = mask;
|
affinityProcessMask_ = mask;
|
||||||
UpdateAffinity(mask);
|
UpdateAffinity(mask);
|
||||||
}
|
}
|
||||||
@ -303,102 +303,17 @@ namespace Aurora::Threading::Threads
|
|||||||
{
|
{
|
||||||
task_ = task;
|
task_ = task;
|
||||||
|
|
||||||
// https://github.com/webrtc-uwp/chromium-base/blob/master/threading/platform_thread_win.cc#L129-L136
|
auto ret = SpawnThread([this]()
|
||||||
// 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)
|
|
||||||
|
|
||||||
unsigned(WINAPI * OSEP_f)(void *) = [](void *that) -> unsigned
|
|
||||||
{
|
{
|
||||||
auto thiz = reinterpret_cast<OSThread *>(that);
|
this->_ThreadEP();
|
||||||
thiz->_ThreadEP();
|
}, GetName(), info_.stackSize);
|
||||||
return 0;
|
|
||||||
};
|
if (ret.first)
|
||||||
|
|
||||||
DWORD(WINAPI * OSCreateThreadEP_f)(void *) = [](void *that) -> DWORD
|
|
||||||
{
|
{
|
||||||
auto thiz = reinterpret_cast<OSThread *>(that);
|
handle_ = (decltype(handle_))ret.second;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
return ret.first;
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSThread::_ThreadEP()
|
void OSThread::_ThreadEP()
|
||||||
@ -627,7 +542,7 @@ namespace Aurora::Threading::Threads
|
|||||||
prio_ = prio;
|
prio_ = prio;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSThread::UpdateAffinity(AuUInt32 mask)
|
void OSThread::UpdateAffinity(AuUInt64 mask)
|
||||||
{
|
{
|
||||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||||
if (handle_ == INVALID_HANDLE_VALUE)
|
if (handle_ == INVALID_HANDLE_VALUE)
|
||||||
@ -669,10 +584,10 @@ namespace Aurora::Threading::Threads
|
|||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
Debug::PrintError();
|
Debug::PrintError();
|
||||||
LogWarn("Couldn't deinitialize thread");
|
AuLogWarn("Couldn't deinitialize thread");
|
||||||
LogWarn("The smart thing to do at this point would be to panic");
|
AuLogWarn("The smart thing to do at this point would be to panic");
|
||||||
LogWarn("...but we could continue");
|
AuLogWarn("...but we could continue");
|
||||||
LogWarn("Carrying on despite the potential for data integrity loss and memory leaks");
|
AuLogWarn("Carrying on despite the potential for data integrity loss and memory leaks");
|
||||||
Telemetry::Mayday();
|
Telemetry::Mayday();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,11 +23,11 @@ namespace Aurora::Threading::Threads
|
|||||||
void SendExitSignal() override;
|
void SendExitSignal() override;
|
||||||
|
|
||||||
void SetPrio(EThreadPrio prio) override;
|
void SetPrio(EThreadPrio prio) override;
|
||||||
void SetAffinity(AuUInt32 mask) override;
|
void SetAffinity(AuUInt64 mask) override;
|
||||||
void SetName(const AuString &name) override;
|
void SetName(const AuString &name) override;
|
||||||
|
|
||||||
EThreadPrio GetPrio() override;
|
EThreadPrio GetPrio() override;
|
||||||
AuUInt32 GetMask() override;
|
AuUInt64 GetMask() override;
|
||||||
AuString GetName() override;
|
AuString GetName() override;
|
||||||
|
|
||||||
AuSPtr<TLSView> GetTlsView() override;
|
AuSPtr<TLSView> GetTlsView() override;
|
||||||
@ -48,7 +48,7 @@ namespace Aurora::Threading::Threads
|
|||||||
bool Exit(bool willReturnToOS);
|
bool Exit(bool willReturnToOS);
|
||||||
bool ExecuteNewOSContext(AuFunction<void()> task);
|
bool ExecuteNewOSContext(AuFunction<void()> task);
|
||||||
void UpdatePrio(EThreadPrio prio);
|
void UpdatePrio(EThreadPrio prio);
|
||||||
void UpdateAffinity(AuUInt32 mask);
|
void UpdateAffinity(AuUInt64 mask);
|
||||||
void UpdateName();
|
void UpdateName();
|
||||||
void OSAttach();
|
void OSAttach();
|
||||||
void OSDeatach();
|
void OSDeatach();
|
||||||
@ -65,7 +65,7 @@ namespace Aurora::Threading::Threads
|
|||||||
OSThread * tlsReferenceThread_ {};
|
OSThread * tlsReferenceThread_ {};
|
||||||
AuString name_;
|
AuString name_;
|
||||||
ThreadInfo info_;
|
ThreadInfo info_;
|
||||||
AuUInt32 affinityProcessMask_ = 0xFFFFFFFF;
|
AuUInt64 affinityProcessMask_ = 0xFFFFFFFFFFFFFFFF;
|
||||||
EThreadPrio prio_ = EThreadPrio::ePrioNormal;
|
EThreadPrio prio_ = EThreadPrio::ePrioNormal;
|
||||||
|
|
||||||
bool exiting_{};
|
bool exiting_{};
|
||||||
@ -84,7 +84,7 @@ namespace Aurora::Threading::Threads
|
|||||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||||
HANDLE handle_ = INVALID_HANDLE_VALUE;
|
HANDLE handle_ = INVALID_HANDLE_VALUE;
|
||||||
#elif defined(AURORA_HAS_PTHREADS)
|
#elif defined(AURORA_HAS_PTHREADS)
|
||||||
pthread_t handle_;
|
pthread_t handle_ {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
AuUInt64 unixThreadId_ = 0;
|
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))
|
if (!localtime_r(&timet, &ret))
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
LogWarn("Couldn't convert local civil time");
|
AuLogWarn("Couldn't convert local civil time");
|
||||||
return ToCivilTime(time, true);
|
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();
|
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