[+] Added VersionHelpers

[*] Detabify
[*] Broke up CpuInfo
[*] I want to rewrite this trashy readme soon
This commit is contained in:
Reece Wilson 2022-01-26 04:22:12 +00:00
parent 7eb6900e9f
commit 0d388dc4e2
19 changed files with 939 additions and 664 deletions

View File

@ -12,7 +12,7 @@ namespace Aurora::Async
struct IWorkItemHandler struct IWorkItemHandler
{ {
enum class EProcessNext enum class EProcessNext
{ {
eInvalid = -1, eInvalid = -1,
eFinished = 0, eFinished = 0,
eRerun, eRerun,

View File

@ -27,9 +27,9 @@ namespace Aurora::HWInfo
AuString CpuBitId::ToString() const AuString CpuBitId::ToString() const
{ {
#if defined(_AU_MASSIVE_CPUID) #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); return fmt::format("{4:#0{0}b} {3:#0{0}b} {2:#0{0}b} {1:#0{0}b}", sizeof(decltype(lower)) * 8, lower, upper, upper2, upper3);
#else #else
return fmt::format("{1:#0{0}b} {2:#0{0}b}", sizeof(decltype(lower)) * 8, lower, upper); return fmt::format("{2:#0{0}b} {1:#0{0}b}", sizeof(decltype(lower)) * 8, lower, upper);
#endif #endif
} }

View File

@ -5,15 +5,15 @@
namespace Aurora::Locale namespace Aurora::Locale
{ {
AUKN_SYM AuString NumbericLocaleGetDecimal(); 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 TimeLocaleGetMSChar();
AUKN_SYM AuString TimeDateToISO8601(const Time::tm &time, Time::ETimezoneShift shift = Time::ETimezoneShift::eUTC); AUKN_SYM AuString TimeLocaleS();
AUKN_SYM AuString TimeLocaleGetDayChar();
AUKN_SYM AuString ConvertMSToTimescale(AuUInt32 ms); AUKN_SYM AuString TimeDateToString(const Time::tm &time);
AUKN_SYM AuString ConvertNSToTimescale(AuUInt64 ns); 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);
} }

View File

@ -9,93 +9,93 @@
namespace Aurora::Memory namespace Aurora::Memory
{ {
template<class TType_t, class Base_t> template<class TType_t, class Base_t>
struct ExSharedPtr : public Base_t struct ExSharedPtr : public Base_t
{ {
bool cached {}; bool cached {};
using element_type = Base_t::element_type; using element_type = Base_t::element_type;
using weak_type = Base_t::weak_type; using weak_type = Base_t::weak_type;
using base_type = Base_t; using base_type = Base_t;
using Base_t::Base_t; using Base_t::Base_t;
ExSharedPtr(Base_t &&in) : Base_t(in) ExSharedPtr(Base_t &&in) : Base_t(in)
{} {}
ExSharedPtr(const Base_t &in) : Base_t(in) ExSharedPtr(const Base_t &in) : Base_t(in)
{} {}
operator Base_t() const noexcept operator Base_t() const noexcept
{ {
return *this; return *this;
} }
ExSharedPtr &operator =(const Base_t &in) noexcept ExSharedPtr &operator =(const Base_t &in) noexcept
{ {
Base_t::operator=(in); Base_t::operator=(in);
return *this; return *this;
} }
TType_t &operator*() const TType_t &operator*() const
{ {
throwif(); throwif();
return Base_t::operator*(); return Base_t::operator*();
} }
TType_t *operator->() const TType_t *operator->() const
{ {
throwif(); throwif();
return Base_t::operator->(); return Base_t::operator->();
} }
TType_t &operator*() TType_t &operator*()
{ {
throwif(); throwif();
return Base_t::operator*(); return Base_t::operator*();
} }
TType_t *operator->() TType_t *operator->()
{ {
throwif(); throwif();
return Base_t::operator->(); return Base_t::operator->();
} }
private: private:
auline void _cache() auline void _cache()
{ {
cached = Base_t::operator bool(); cached = Base_t::operator bool();
} }
auline void throwif() const auline void throwif() const
{ {
if (!cached) [[unlikely]] if (!cached) [[unlikely]]
{ {
if (!Base_t::operator bool()) [[likely]] if (!Base_t::operator bool()) [[likely]]
{ {
AU_THROW_STRING("ExSharedPointer Null Access Violation"); AU_THROW_STRING("ExSharedPointer Null Access Violation");
} }
} }
} }
auline void throwif() auline void throwif()
{ {
if (!cached) [[unlikely]] if (!cached) [[unlikely]]
{ {
cached = Base_t::operator bool(); cached = Base_t::operator bool();
if (!cached) [[likely]] if (!cached) [[likely]]
{ {
AU_THROW_STRING("ExSharedPointer Null Access Violation"); AU_THROW_STRING("ExSharedPointer Null Access Violation");
} }
} }
} }
}; };
template<class TType_t, class Base_t> template<class TType_t, class Base_t>
struct ExSharedFromThis : Base_t struct ExSharedFromThis : Base_t
{ {
ExSharedPtr<TType_t, AURORA_RUNTIME_AU_SHARED_PTR<TType_t>> SharedFromThis() ExSharedPtr<TType_t, AURORA_RUNTIME_AU_SHARED_PTR<TType_t>> SharedFromThis()
{ {
return Base_t::shared_from_this(); return Base_t::shared_from_this();
} }
}; };
} }

View File

@ -49,4 +49,5 @@ namespace Aurora::Process
AUKN_SYM AuOptional<Segment> GetSegment(AuUInt pointer); AUKN_SYM AuOptional<Segment> GetSegment(AuUInt pointer);
AUKN_SYM PublicModule DumpExecutableRoot(); AUKN_SYM PublicModule DumpExecutableRoot();
AUKN_SYM Segments DumpExecutableAll(); AUKN_SYM Segments DumpExecutableAll();
AUKN_SYM void TryRescanSlow();
} }

View File

@ -1,56 +1,71 @@
/*** /***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: SWInfo.hpp File: SWInfo.hpp
Date: 2022-1-25 Date: 2022-1-25
Author: Reece Author: Reece
***/ ***/
#pragma once #pragma once
namespace Aurora::SWInfo namespace Aurora::SWInfo
{ {
struct OSInformation struct OSInformation
{ {
// I tried to make these references, but benji the retard decided that objects and functions should hold constantness, not the data // I tried to make these references, but benji the retard decided that objects and functions should hold constantness, not the data
// Returning a const reference to a struct containing const references, keeping the ability to move, and disabling copy -> impossible // Returning a const reference to a struct containing const references, keeping the ability to move, and disabling copy -> impossible
// Nice tardlang // Nice tardlang
const AuString *kKernelString; // const AuString *kKernelString; //
const AuString *kUserlandBrand; // Windows 10 Pro, Xbox, glibc, Ubuntu, distro name const AuString *kUserlandBrand; // Windows 10 Pro, Xbox, glibc, Ubuntu, distro name
const AuString *kUserlandDesktopEnv; // DWM, CF, [kwin/etc] const AuString *kUserlandDesktopEnv; // DWM, CF, [kwin/etc]
const AuString *kBuildString; // Example: (`Linux version wtf-doxing-lts (no-lts@fingerprinterinos) (some things here) #1 SMP Mon, 69 Apr 2000 13:33:37 +0000`, `??7??.?.amd64???.rs?_release.??-??`) const AuString *kBuildString; // Example: (`Linux version wtf-doxing-lts (no-lts@fingerprinterinos) (some things here) #1 SMP Mon, 69 Apr 2000 13:33:37 +0000`, `??7??.?.amd64???.rs?_release.??-??`)
AuUInt32 uKernelMajor {}; AuUInt32 uKernelMajor {};
AuUInt32 uKernelMinor {}; AuUInt32 uKernelMinor {};
AuUInt32 uKernelPatch {}; AuUInt32 uKernelPatch {};
AuUInt32 uUserlandMajor {}; AuUInt32 uUserlandMajor {};
AuUInt32 uUserlandMinor {}; AuUInt32 uUserlandMinor {};
AuUInt32 uUserlandPatch {}; AuUInt32 uUserlandPatch {};
bool bIsServer {}; bool bIsServer {};
bool bIsEnterprise {}; bool bIsEnterprise {};
Aurora::Build::EPlatform ePlatform = Aurora::Build::EPlatform::eEnumInvalid; Aurora::Build::EPlatform ePlatform = Aurora::Build::EPlatform::eEnumInvalid;
private: private:
static inline AuString _kIgnore {}; static inline AuString _kIgnore {};
public: public:
OSInformation() : kKernelString(&_kIgnore), kUserlandDesktopEnv(&_kIgnore), kUserlandBrand(&_kIgnore), kBuildString(&_kIgnore), ePlatform(Build::EPlatform::eEnumInvalid) OSInformation() : kKernelString(&_kIgnore), kUserlandDesktopEnv(&_kIgnore), kUserlandBrand(&_kIgnore), kBuildString(&_kIgnore), ePlatform(Build::EPlatform::eEnumInvalid)
{} {}
AU_DEFINE_CTOR_VA(OSInformation, ( AU_DEFINE_CTOR_VA(OSInformation, (
kKernelString, kKernelString,
kUserlandBrand, kUserlandBrand,
kUserlandDesktopEnv, kUserlandDesktopEnv,
kBuildString, kBuildString,
ePlatform ePlatform
)) ))
AU_NO_COPY(OSInformation); AU_NO_COPY(OSInformation);
AU_MOVE(OSInformation); AU_MOVE(OSInformation);
}; };
AUKN_SYM const OSInformation & GetPlatformInfo(); AUKN_SYM const OSInformation &GetPlatformInfo();
// VersionHelpers.h, except it doesn't lie to you and wont break NIX land
AUKN_SYM bool IsWindowsXPOrGreater();
AUKN_SYM bool IsWindowsXPSP1OrGreater();
AUKN_SYM bool IsWindowsXPSP2OrGreater();
AUKN_SYM bool IsWindowsXPSP3OrGreater();
AUKN_SYM bool IsWindowsVistaOrGreater();
AUKN_SYM bool IsWindowsVistaSP1OrGreater();
AUKN_SYM bool IsWindowsVistaSP2OrGreater();
AUKN_SYM bool IsWindows7OrGreater();
AUKN_SYM bool IsWindows7SP1OrGreater();
AUKN_SYM bool IsWindows8OrGreater();
AUKN_SYM bool IsWindows8Point1OrGreater();
AUKN_SYM bool IsWindows10OrGreater();
AUKN_SYM bool IsWindows11OrGreater();
} }

View File

@ -44,8 +44,8 @@ static void Init()
Aurora::RNG::Init(); Aurora::RNG::Init();
Aurora::Hashing::InitHashing(); Aurora::Hashing::InitHashing();
Aurora::Async::InitAsync(); Aurora::Async::InitAsync();
Aurora::HWInfo::Init();
Aurora::SWInfo::InitSwInfo(); Aurora::SWInfo::InitSwInfo();
Aurora::HWInfo::Init();
Aurora::Telemetry::Init(); Aurora::Telemetry::Init();
Aurora::Process::InitProcessMap(); Aurora::Process::InitProcessMap();
} }

View File

@ -0,0 +1,40 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: CpuId.BSD.cpp
Date: 2022-1-25
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "HWInfo.hpp"
#include "CpuInfo.hpp"
#include "CpuInfo.BSD.hpp"
#if defined(AURORA_IS_BSD_DERIVED)
#include <sys/types.h>
#include <sys/sysctl.h>
#endif
#if defined(AURORA_IS_POSIX_DERIVED)
#include <stdlib.h>
#include <sys/sysinfo.h>
#endif
namespace Aurora::HWInfo
{
void SetCpuTopologyBSD()
{
auto opt = QueryBsdHwStat(HW_AVAILCPU);
if (opt.value_or(0) < 1)
{
opt = QueryBsdHwStat(HW_NCPU);
}
gCpuInfo.socket = 1;
gCpuInfo.cores = 1;
gCpuInfo.threads = opt.value_or(1);
// TODO: parse sysctl kern.sched.topology_spec
gCpuInfo.maskMTHalf = true;
}
}

View File

@ -0,0 +1,13 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: CpuId.BSD.hpp
Date: 2022-1-25
Author: Reece
***/
#pragma once
namespace Aurora::HWInfo
{
void SetCpuTopologyBSD();
}

View File

@ -0,0 +1,34 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: CpuId.Linux.cpp
Date: 2022-1-25
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "HWInfo.hpp"
#include "CpuInfo.hpp"
#include "CpuInfo.Linux.hpp"
#if defined(AURORA_IS_BSD_DERIVED)
#include <sys/types.h>
#include <sys/sysctl.h>
#endif
#if defined(AURORA_IS_POSIX_DERIVED)
#include <stdlib.h>
#include <sys/sysinfo.h>
#endif
namespace Aurora::HWInfo
{
void SetCpuTopologyLinux()
{
gCpuInfo.socket = 1;
gCpuInfo.cores = 1;
gCpuInfo.threads = get_nprocs();
// TODO: parse /proc/cpuinfo
gCpuInfo.maskMTHalf = true;
}
}

View File

@ -0,0 +1,13 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: CpuId.Linux.hpp
Date: 2022-1-25
Author: Reece
***/
#pragma once
namespace Aurora::HWInfo
{
void SetCpuTopologyLinux();
}

View File

@ -0,0 +1,176 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: CpuId.Nt.cpp
Date: 2022-1-25
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "HWInfo.hpp"
#include "CpuInfo.hpp"
#include "CpuInfo.NT.hpp"
#if defined(AURORA_IS_MODERNNT_DERIVED)
#include <VersionHelpers.h>
#endif
namespace Aurora::HWInfo
{
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;
}
void SetCpuTopologyNT()
{
SYSTEM_LOGICAL_PROCESSOR_INFORMATION sysinfo[128];
DWORD length = AuArraySize(sysinfo) * sizeof(*sysinfo);
if (SWInfo::IsWindows10OrGreater() || IsWindowsServer() || IsWindowsLTSC())
{
if (TrySetNtCpuSetInfoSlowExtended())
{
return;
}
}
if (!GetLogicalProcessorInformation(sysinfo, &length))
{
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
gCpuInfo.socket = 1;
gCpuInfo.cores = 1;
gCpuInfo.threads = sysinfo.dwNumberOfProcessors;
return;
}
length /= sizeof(*sysinfo);
gCpuInfo.socket = 0;
gCpuInfo.cores = 0;
gCpuInfo.threads = 0;
bool sparse = false;
for (auto i = 0; i < length; i++)
{
if (sysinfo[i].Relationship == RelationProcessorCore)
{
auto mask = sysinfo[i].ProcessorMask;
gCpuInfo.cores++;
gCpuInfo.threadTopology.push_back(mask);
CpuBitId serverId;
serverId.lower = mask;
gCpuInfo.serverTopology.push_back(mask);
// TODO: fuck it, if some macro fuckery, use popcnt on x86
// we just need to count the bits. first it was just two BitScanForwards. discontiguous cores fucked things up so now we have a loop just to count a few bits.
int counter {};
unsigned long offset {}, tmp;
while (offset != (sizeof(offset) * 8))
{
// Count the index to a 1
if (BitScanForward(&tmp, mask >> offset) == 0) break; // mask was zero, end of scan
offset += tmp;
// Count the 1's by inverting the bitmap and counting to 1
BitScanForward(&tmp, ~(mask >> offset));
offset += tmp;
if (counter++) sparse = true;
// Increment threads by the bits set in
gCpuInfo.threads += tmp;
}
}
else if (sysinfo[i].Relationship == RelationProcessorPackage)
{
gCpuInfo.socket++;
}
}
gCpuInfo.maskMTContig = !sparse;
gCpuInfo.maskMTHalf = sparse;
}
}

View File

@ -0,0 +1,13 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: CpuId.Nt.hpp
Date: 2022-1-25
Author: Reece
***/
#pragma once
namespace Aurora::HWInfo
{
void SetCpuTopologyNT();
}

View File

@ -10,215 +10,33 @@
#include "CpuInfo.hpp" #include "CpuInfo.hpp"
#include "CpuId.hpp" #include "CpuId.hpp"
#if defined(AURORA_IS_BSD_DERIVED)
#include <sys/types.h>
#include <sys/sysctl.h>
#endif
#if defined(AURORA_IS_POSIX_DERIVED) #if defined(AURORA_IS_POSIX_DERIVED)
#include <stdlib.h> #include <stdlib.h>
#include <sys/sysinfo.h> #include <sys/sysinfo.h>
#endif #endif
#if defined(AURORA_COMPILER_CLANG) || defined(AURORA_IS_POSIX_DERIVED)
#include <cpuid.h>
#endif
#if defined(AURORA_IS_MODERNNT_DERIVED) #if defined(AURORA_IS_MODERNNT_DERIVED)
#include <VersionHelpers.h> #include "CpuInfo.NT.hpp"
#endif #endif
#if defined(AURORA_IS_BSD_DERIVED)
#include "CpuInfo.BSD.hpp"
#endif
#if defined(AURORA_IS_LINUX_DERIVED)
#include "CpuInfo.Linux.hpp"
#endif
namespace Aurora::HWInfo namespace Aurora::HWInfo
{ {
#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()
{
SYSTEM_LOGICAL_PROCESSOR_INFORMATION sysinfo[128];
DWORD length = AuArraySize(sysinfo) * sizeof(*sysinfo);
if (IsWindows10OrGreater() || IsWindowsServer() || IsWindowsLTSC())
{
if (TrySetNtCpuSetInfoSlowExtended())
{
return;
}
}
if (!GetLogicalProcessorInformation(sysinfo, &length))
{
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
gCpuInfo.socket = 1;
gCpuInfo.cores = 1;
gCpuInfo.threads = sysinfo.dwNumberOfProcessors;
return;
}
length /= sizeof(*sysinfo);
gCpuInfo.socket = 0;
gCpuInfo.cores = 0;
gCpuInfo.threads = 0;
bool sparse = false;
for (auto i = 0; i < length; i++)
{
if (sysinfo[i].Relationship == RelationProcessorCore)
{
auto mask = sysinfo[i].ProcessorMask;
gCpuInfo.cores++;
gCpuInfo.threadTopology.push_back(mask);
CpuBitId serverId;
serverId.lower = mask;
gCpuInfo.serverTopology.push_back(mask);
// TODO: fuck it, if some macro fuckery, use popcnt on x86
// we just need to count the bits. first it was just two BitScanForwards. discontiguous cores fucked things up so now we have a loop just to count a few bits.
int counter {};
unsigned long offset {}, tmp;
while (offset != (sizeof(offset) * 8))
{
// Count the index to a 1
if (BitScanForward(&tmp, mask >> offset) == 0) break; // mask was zero, end of scan
offset += tmp;
// Count the 1's by inverting the bitmap and counting to 1
BitScanForward(&tmp, ~(mask >> offset));
offset += tmp;
if (counter++) sparse = true;
// Increment threads by the bits set in
gCpuInfo.threads += tmp;
}
}
else if (sysinfo[i].Relationship == RelationProcessorPackage)
{
gCpuInfo.socket++;
}
}
gCpuInfo.maskMTContig = !sparse;
gCpuInfo.maskMTHalf = sparse;
}
#endif
static void SetCpuTopology() static void SetCpuTopology()
{ {
#if defined(AURORA_IS_MODERNNT_DERIVED) #if defined(AURORA_IS_MODERNNT_DERIVED)
SetCpuTopologyNT(); SetCpuTopologyNT();
#elif defined(AURORA_IS_BSD_DERIVED) #elif defined(AURORA_IS_BSD_DERIVED)
SetCpuTopologyBSD();
auto opt = QueryBsdHwStat(HW_AVAILCPU);
if (opt.value_or(0) < 1)
{
opt = QueryBsdHwStat(HW_NCPU);
}
gCpuInfo.socket = 1;
gCpuInfo.cores = 1;
gCpuInfo.threads = opt.value_or(1);
// TODO: parse sysctl kern.sched.topology_spec
gCpuInfo.maskMTHalf = true;
#elif defined(AURORA_IS_LINUX_DERIVED) #elif defined(AURORA_IS_LINUX_DERIVED)
SetCpuTopologyLinux();
gCpuInfo.socket = 1;
gCpuInfo.cores = 1;
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;
@ -236,7 +54,7 @@ namespace Aurora::HWInfo
} }
bool fakeMtHalf = (gCpuInfo.threads & 1) == 0; bool fakeMtHalf = (gCpuInfo.threads & 1) == 0;
gCpuInfo.maskMTHalf = true; gCpuInfo.maskMTHalf = fakeMtHalf;
if (fakeMtHalf) if (fakeMtHalf)
{ {

View File

@ -82,7 +82,7 @@ namespace Aurora::Locale
// This is completely arbitrary // This is completely arbitrary
// I feel as though this would do juststice to large and small timescales; with sane formatting, without being too autistic on resolution, and without returning excessively long (^ and localized) strings // I feel as though this would do juststice to large and small timescales; with sane formatting, without being too autistic on resolution, and without returning excessively long (^ and localized) strings
// We probably don't need to keep the MS around for more than a minute // We probably don't need to keep the MS around for more than a minute
// We can use the lengthy the MS padding to pad out seconds more into the ballpark of HH:MM:SS // We can use the lengthy MS padding to pad out seconds more into the ballpark of HH:MM:SS
// We can measure months, perhaps years, using mere days. We, and most normies, can comprehend 30/60/90/360/720 without much problem // We can measure months, perhaps years, using mere days. We, and most normies, can comprehend 30/60/90/360/720 without much problem
// //
// ! = pad // ! = pad

View File

@ -1,230 +1,235 @@
/*** /***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: ProcessMap.cpp File: ProcessMap.cpp
Date: 2022-1-23 Date: 2022-1-23
Author: Reece Author: Reece
***/ ***/
#include <Source/RuntimeInternal.hpp> #include <Source/RuntimeInternal.hpp>
#include "ProcessMap.hpp" #include "ProcessMap.hpp"
#if defined(AURORA_PLATFORM_WIN32) #if defined(AURORA_PLATFORM_WIN32)
#include "ProcessMap.Win32.hpp" #include "ProcessMap.Win32.hpp"
#endif #endif
#if defined(AURORA_IS_MODERNNT_DERIVED) #if defined(AURORA_IS_MODERNNT_DERIVED)
#include "ProcessMap.NT.hpp" #include "ProcessMap.NT.hpp"
#endif #endif
namespace Aurora::Process namespace Aurora::Process
{ {
struct ModuleBasePairUtil struct ModuleBasePairUtil
{ {
AuUInt operator()(const ModuleBasePair &in) const AuUInt operator()(const ModuleBasePair &in) const
{ {
return in.modBase; return in.modBase;
} }
constexpr bool operator()(const ModuleBasePair &lhs, const AuString &rhs) const constexpr bool operator()(const ModuleBasePair &lhs, const AuString &rhs) const
{ {
return lhs.module == rhs; return lhs.module == rhs;
} }
constexpr bool operator()(const ModuleBasePair &lhs, const AuUInt &rhs) const constexpr bool operator()(const ModuleBasePair &lhs, const AuUInt &rhs) const
{ {
return lhs.modBase == rhs; return lhs.modBase == rhs;
} }
constexpr bool operator()(const ModuleBasePair &lhs, const ModuleBasePair &rhs) const 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); return rhs.modBase ? lhs.modBase == rhs.modBase : (rhs.module.size() ? rhs.module == rhs.module : false);
} }
}; };
struct ModuleLookup : Segment struct ModuleLookup : Segment
{ {
ModuleLookup() ModuleLookup()
{} {}
ModuleLookup(const Segment &s) : Segment(s) ModuleLookup(const Segment &s) : Segment(s)
{} {}
}; };
static AuBST<AuUInt, ModuleLookup> gModulePtrMap; static AuBST<AuUInt, ModuleLookup> gModulePtrMap;
static const auto kMinPageAlignment = 4096; static const auto kMinPageAlignment = 4096;
static const auto kPageBufferPad = 20; static const auto kPageBufferPad = 20;
static AuThreadPrimitives::MutexUnique_t gMutexUnique; static AuThreadPrimitives::MutexUnique_t gMutexUnique;
static AuHashMapEx<ModuleBasePair, AuSPtr<PublicModule>, ModuleBasePairUtil> gModuleMap; static AuHashMapEx<ModuleBasePair, AuSPtr<PublicModule>, ModuleBasePairUtil> gModuleMap;
static AuUInt ToLowestPageAlignment(AuUInt in) static AuUInt ToLowestPageAlignment(AuUInt in)
{ {
return in & ~(kMinPageAlignment - 1); return in & ~(kMinPageAlignment - 1);
} }
static AuSPtr<PublicModule> GetModuleFromSegmentCache(AuUInt pointer) static AuSPtr<PublicModule> GetModuleFromSegmentCache(AuUInt pointer)
{ {
AU_LOCK_GUARD(gMutexUnique); AU_LOCK_GUARD(gMutexUnique);
auto itr = gModulePtrMap.find(pointer); auto itr = gModulePtrMap.find(pointer);
if (itr == gModulePtrMap.end()) return {}; if (itr == gModulePtrMap.end()) return {};
return itr->second.moduleMeta.lock(); return itr->second.moduleMeta.lock();
} }
static AuOptional<Segment> GetSegmentCache(AuUInt pointer) static AuOptional<Segment> GetSegmentCache(AuUInt pointer)
{ {
AU_LOCK_GUARD(gMutexUnique); AU_LOCK_GUARD(gMutexUnique);
auto itr = gModulePtrMap.find(pointer); auto itr = gModulePtrMap.find(pointer);
if (itr == gModulePtrMap.end()) return {}; if (itr == gModulePtrMap.end()) return {};
return itr->second; return itr->second;
} }
bool IsInModuleCache(const ModuleBasePair &pair) bool IsInModuleCache(const ModuleBasePair &pair)
{ {
AU_LOCK_GUARD(gMutexUnique); AU_LOCK_GUARD(gMutexUnique);
return gModuleMap.find(pair) != gModuleMap.end(); return gModuleMap.find(pair) != gModuleMap.end();
} }
void InsertModuleCache(const ModuleBasePair &pair, const AuSPtr<PublicModule> &mod) void InsertModuleCache(const ModuleBasePair &pair, const AuSPtr<PublicModule> &mod)
{ {
for (auto &segment : mod->segments) for (auto &segment : mod->segments)
{ {
AU_LOCK_GUARD(gMutexUnique); AU_LOCK_GUARD(gMutexUnique);
segment.moduleMeta = mod; segment.moduleMeta = mod;
for (AuUInt i = segment.baseVa; i < segment.baseVa + segment.size; i += (kMinPageAlignment * kPageBufferPad)) for (AuUInt i = segment.baseVa; i < segment.baseVa + segment.size; i += (kMinPageAlignment * kPageBufferPad))
{ {
ModuleLookup a(segment); ModuleLookup a(segment);
gModulePtrMap[i] = a; gModulePtrMap[i] = a;
} }
} }
{ {
AU_LOCK_GUARD(gMutexUnique); AU_LOCK_GUARD(gMutexUnique);
gModuleMap[pair] = mod; gModuleMap[pair] = mod;
} }
} }
void RemoveModuleCache(const ModuleBasePair &eitherOr) void RemoveModuleCache(const ModuleBasePair &eitherOr)
{ {
AU_LOCK_GUARD(gMutexUnique); AU_LOCK_GUARD(gMutexUnique);
auto itr = gModuleMap.find(eitherOr); auto itr = gModuleMap.find(eitherOr);
if (itr == gModuleMap.end()) return; if (itr == gModuleMap.end()) return;
auto mod = itr->second; auto mod = itr->second;
for (const auto &segment : mod->segments) for (const auto &segment : mod->segments)
{ {
for (AuUInt i = segment.baseVa; i < segment.baseVa + segment.size; i += (kMinPageAlignment * kPageBufferPad)) for (AuUInt i = segment.baseVa; i < segment.baseVa + segment.size; i += (kMinPageAlignment * kPageBufferPad))
{ {
auto itr = gModulePtrMap.find(i); auto itr = gModulePtrMap.find(i);
if (itr != gModulePtrMap.end()) if (itr != gModulePtrMap.end())
{ {
gModulePtrMap.erase(itr); gModulePtrMap.erase(itr);
} }
} }
} }
gModuleMap.erase(itr); gModuleMap.erase(itr);
} }
PublicModule GetFromModuleCache(AuUInt handle) PublicModule GetFromModuleCache(AuUInt handle)
{ {
AU_LOCK_GUARD(gMutexUnique); AU_LOCK_GUARD(gMutexUnique);
auto itr = gModuleMap.find({"", handle}); auto itr = gModuleMap.find({"", handle});
if (itr == gModuleMap.end()) return {}; if (itr == gModuleMap.end()) return {};
return *itr->second; return *itr->second;
} }
static AuOptional<Segment> FindInCache(AuUInt pointer) static AuOptional<Segment> FindInCache(AuUInt pointer)
{ {
auto curPtr = ToLowestPageAlignment(pointer); auto curPtr = ToLowestPageAlignment(pointer);
auto temp = GetSegmentCache(curPtr); auto temp = GetSegmentCache(curPtr);
if (temp.has_value()) return temp; if (temp.has_value()) return temp;
for (int i = 0; i < kPageBufferPad + 1; i++) for (int i = 0; i < kPageBufferPad + 1; i++)
{ {
curPtr -= kMinPageAlignment; curPtr -= kMinPageAlignment;
temp = GetSegmentCache(curPtr); // TODO: i dont want to start from the top of the tree, thats stupid temp = GetSegmentCache(curPtr); // TODO: i dont want to start from the top of the tree, thats stupid
if (temp.has_value()) return temp; if (temp.has_value()) return temp;
} }
return AuOptional<Segment>{}; return AuOptional<Segment>{};
} }
void InitProcessMap() void InitProcessMap()
{ {
gMutexUnique = AuThreadPrimitives::MutexUnique(); gMutexUnique = AuThreadPrimitives::MutexUnique();
#if defined(AURORA_IS_MODERNNT_DERIVED) #if defined(AURORA_IS_MODERNNT_DERIVED)
InitProcessMapNt(); InitProcessMapNt();
#endif #endif
#if defined(AURORA_PLATFORM_WIN32) TryRescanSlow();
MakeToolHelp32Snapshot(); }
#endif
}
void DeinitProcessMap() AUKN_SYM void TryRescanSlow()
{ {
gMutexUnique.reset(); #if defined(AURORA_PLATFORM_WIN32)
DeinitProcessMapNt(); MakeToolHelp32Snapshot();
} #endif
}
AUKN_SYM AuOptional<Segment> GetSegment(AuUInt pointer) void DeinitProcessMap()
{ {
try gMutexUnique.reset();
{ DeinitProcessMapNt();
auto ceg = FindInCache(pointer); }
if (ceg.has_value())
{
return ceg;
}
#if defined(AURORA_IS_MODERNNT_DERIVED) AUKN_SYM AuOptional<Segment> GetSegment(AuUInt pointer)
if (MakeAwarePtr(pointer)) {
{ try
return FindInCache(pointer); {
} auto ceg = FindInCache(pointer);
else if (ceg.has_value())
{ {
return LookupArbitrarySegment(pointer); return ceg;
} }
#endif
return {}; #if defined(AURORA_IS_MODERNNT_DERIVED)
} if (MakeAwarePtr(pointer))
catch (...) {
{ return FindInCache(pointer);
return {}; }
} else
} {
return LookupArbitrarySegment(pointer);
}
#endif
AUKN_SYM PublicModule DumpExecutableRoot() return {};
{ }
try catch (...)
{ {
return GetExecutableRoot(); return {};
} }
catch (...) }
{
return {};
}
}
AUKN_SYM Segments DumpExecutableAll() AUKN_SYM PublicModule DumpExecutableRoot()
{ {
try try
{ {
Segments ret; return GetExecutableRoot();
for (const auto &[meta, ptr] : gModuleMap) }
{ catch (...)
ret.insert(ret.end(), ptr->segments.begin(), ptr->segments.end()); {
} return {};
return ret; }
} }
catch (...)
{ AUKN_SYM Segments DumpExecutableAll()
return {}; {
} try
} {
Segments ret;
for (const auto &[meta, ptr] : gModuleMap)
{
ret.insert(ret.end(), ptr->segments.begin(), ptr->segments.end());
}
return ret;
}
catch (...)
{
return {};
}
}
} }

View File

@ -1,25 +1,25 @@
/*** /***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: ProcessMap.hpp File: ProcessMap.hpp
Date: 2022-1-23 Date: 2022-1-23
Author: Reece Author: Reece
***/ ***/
#pragma once #pragma once
namespace Aurora::Process namespace Aurora::Process
{ {
struct ModuleBasePair struct ModuleBasePair
{ {
AuString module; AuString module;
AuUInt modBase; AuUInt modBase;
}; };
PublicModule GetFromModuleCache(AuUInt handle); PublicModule GetFromModuleCache(AuUInt handle);
void InsertModuleCache(const ModuleBasePair &pair, const AuSPtr<PublicModule> &mod); void InsertModuleCache(const ModuleBasePair &pair, const AuSPtr<PublicModule> &mod);
void RemoveModuleCache(const ModuleBasePair &eitherOr); void RemoveModuleCache(const ModuleBasePair &eitherOr);
bool IsInModuleCache(const ModuleBasePair &pair); bool IsInModuleCache(const ModuleBasePair &pair);
void InitProcessMap(); void InitProcessMap();
void DeinitProcessMap(); void DeinitProcessMap();
} }

View File

@ -1,163 +1,241 @@
/*** /***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: SWInfo.cpp File: SWInfo.cpp
Date: 2022-1-25 Date: 2022-1-25
Author: Reece Author: Reece
***/ ***/
#include <Source/RuntimeInternal.hpp> #include <Source/RuntimeInternal.hpp>
#include "SWInfo.hpp" #include "SWInfo.hpp"
#if defined(AURORA_PLATFORM_WIN32) #if defined(AURORA_PLATFORM_WIN32)
#include <VersionHelpers.h> #include <VersionHelpers.h>
#include <winternl.h>
#include <winternl.h>
NTSYSAPI NTSTATUS RtlGetVersion(
PRTL_OSVERSIONINFOW lpVersionInformation
);
#endif #endif
namespace Aurora::SWInfo namespace Aurora::SWInfo
{ {
static const AuString kDefaultStr; static AuUInt8 kWinVerNT4 = 0x0400;
static const OSInformation kDefaultInfo; static AuUInt8 kWinVerWIN2K = 0x0500;
static OSInformation const *gInfo = &kDefaultInfo; static AuUInt8 kWinVerWINXP = 0x0501;
static AuUInt8 kWinVerWS03 = 0x0502;
static AuUInt8 kWinVerWIN6 = 0x0600;
static AuUInt8 kWinVerVISTA = 0x0600;
static AuUInt8 kWinVerWS08 = 0x0600;
static AuUInt8 kWinVerLONGHORN = 0x0600;
static AuUInt8 kWinVerWIN7 = 0x0601;
static AuUInt8 kWinVerWIN8 = 0x0602;
static AuUInt8 kWinVerWINBLUE = 0x0603;
static AuUInt8 kWinVerWIN10 = 0x0A00;
static AuString gKernelString; static AuUInt8 kWinVerWIN10 = 0x0A00;
static AuString gUserlandBrand; static const AuString kDefaultStr;
static AuString gUserlandDesktopEnv; static const OSInformation kDefaultInfo;
static AuString gBuildString; static OSInformation const *gInfo = &kDefaultInfo;
static OSInformation gTempInfo;
static void Reset() static AuString gKernelString;
{ static AuString gUserlandBrand;
gInfo = &kDefaultInfo; static AuString gUserlandDesktopEnv;
} static AuString gBuildString;
static OSInformation gTempInfo;
AUKN_SYM const OSInformation & GetPlatformInfo() static void Reset()
{ {
return *gInfo; gInfo = &kDefaultInfo;
} }
AUKN_SYM const OSInformation &GetPlatformInfo()
{
return *gInfo;
}
#if defined(AURORA_PLATFORM_WIN32) #if defined(AURORA_PLATFORM_WIN32)
static bool IsWindowsEnterpriseBranch() static bool IsWindowsEnterpriseBranch()
{ {
OSVERSIONINFOEXW osvi = {sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0, VER_SUITE_ENTERPRISE, 0}; OSVERSIONINFOEXW osvi = {sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0, VER_SUITE_ENTERPRISE, 0};
DWORDLONG const dwlConditionMask = VerSetConditionMask(0, VER_SUITENAME, VER_EQUAL); DWORDLONG const dwlConditionMask = VerSetConditionMask(0, VER_SUITENAME, VER_EQUAL);
return !VerifyVersionInfoW(&osvi, VER_SUITENAME, dwlConditionMask); return !VerifyVersionInfoW(&osvi, VER_SUITENAME, dwlConditionMask);
} }
auline bool Win32ReadRegistry(HKEY hKey, const wchar_t *key, AuString &strValue) auline bool Win32ReadRegistry(HKEY hKey, const wchar_t *key, AuString &strValue)
{ {
DWORD dwBufferSize {}; DWORD dwBufferSize {};
if (RegQueryValueExW(hKey, key, 0, NULL, NULL, &dwBufferSize) != ERROR_SUCCESS) if (RegQueryValueExW(hKey, key, 0, NULL, NULL, &dwBufferSize) != ERROR_SUCCESS)
{ {
SysPushErrorUnavailableError("Couldn't access registery key"); SysPushErrorUnavailableError("Couldn't access registery key");
return false; return false;
} }
std::wstring in; std::wstring in;
if (!AuTryResize(in, dwBufferSize)) if (!AuTryResize(in, dwBufferSize))
{ {
return false; return false;
} }
if (RegQueryValueExW(hKey, key, 0, NULL, reinterpret_cast<LPBYTE>(in.data()), &dwBufferSize) != ERROR_SUCCESS) if (RegQueryValueExW(hKey, key, 0, NULL, reinterpret_cast<LPBYTE>(in.data()), &dwBufferSize) != ERROR_SUCCESS)
{ {
SysPushErrorUnavailableError("Couldn't access registery key"); SysPushErrorUnavailableError("Couldn't access registery key");
return false; return false;
} }
strValue = Locale::ConvertFromWChar(in.data(), in.size()); strValue = Locale::ConvertFromWChar(in.data(), in.size());
return strValue.size() == in.size(); return strValue.size() == in.size();
} }
#endif #endif
void InitSwInfo() void InitSwInfo()
{ {
Reset(); Reset();
gTempInfo = AuMove(OSInformation(&gKernelString, &gUserlandBrand, &gUserlandDesktopEnv, &gBuildString, Aurora::Build::EPlatform::eEnumInvalid)); gTempInfo = AuMove(OSInformation(&gKernelString, &gUserlandBrand, &gUserlandDesktopEnv, &gBuildString, Aurora::Build::EPlatform::eEnumInvalid));
#if defined(AURORA_IS_MODERNNT_DERIVED) #if defined(AURORA_IS_MODERNNT_DERIVED)
OSVERSIONINFOEX info {}; OSVERSIONINFOEX info {};
info.dwOSVersionInfoSize = sizeof(info); info.dwOSVersionInfoSize = sizeof(info);
#if defined(AURORA_PLATFORM_WIN32) #if defined(AURORA_PLATFORM_WIN32)
gTempInfo.bIsServer = IsWindowsServer(); gTempInfo.bIsServer = IsWindowsServer();
gTempInfo.bIsEnterprise = IsWindowsEnterpriseBranch(); gTempInfo.bIsEnterprise = IsWindowsEnterpriseBranch();
#else #else
gTempInfo.bIsServer = false; gTempInfo.bIsServer = false;
gTempInfo.bIsEnterprise = false; gTempInfo.bIsEnterprise = false;
#endif #endif
gUserlandDesktopEnv = "Desktop Window Manager"; gUserlandDesktopEnv = "Desktop Window Manager";
if (GetVersionExA(reinterpret_cast<LPOSVERSIONINFOA>(&info))) if (GetVersionExA(reinterpret_cast<LPOSVERSIONINFOA>(&info)))
{ {
gTempInfo.uKernelPatch = info.dwBuildNumber; gTempInfo.uKernelPatch = info.dwBuildNumber;
gTempInfo.uKernelMinor = info.dwMinorVersion; gTempInfo.uKernelMinor = info.dwMinorVersion;
gTempInfo.uKernelMajor = info.dwMajorVersion; gTempInfo.uKernelMajor = info.dwMajorVersion;
gTempInfo.uUserlandMajor = gTempInfo.uKernelMajor; gTempInfo.uUserlandMajor = gTempInfo.uKernelMajor;
gTempInfo.uUserlandMinor = info.wServicePackMajor; gTempInfo.uUserlandMinor = info.wServicePackMajor;
gTempInfo.uUserlandPatch = info.wServicePackMinor; gTempInfo.uUserlandPatch = info.wServicePackMinor;
} }
#if defined(AURORA_PLATFORM_WIN32) #if defined(AURORA_PLATFORM_WIN32)
{ {
RTL_OSVERSIONINFOEXW ovi {}; RTL_OSVERSIONINFOEXW ovi {};
ovi.dwOSVersionInfoSize = sizeof(ovi); ovi.dwOSVersionInfoSize = sizeof(ovi);
NTSTATUS(CALLBACK *pRtlGetVersion) (PRTL_OSVERSIONINFOW lpVersionInformation); NTSTATUS(CALLBACK *pRtlGetVersion) (PRTL_OSVERSIONINFOW lpVersionInformation);
pRtlGetVersion = (decltype(pRtlGetVersion))GetProcAddress(LoadLibrary(TEXT("Ntdll.dll")), "RtlGetVersion"); pRtlGetVersion = (decltype(pRtlGetVersion))GetProcAddress(LoadLibrary(TEXT("Ntdll.dll")), "RtlGetVersion");
if (pRtlGetVersion && pRtlGetVersion(reinterpret_cast<PRTL_OSVERSIONINFOW>(&ovi)) == 0) if (pRtlGetVersion && pRtlGetVersion(reinterpret_cast<PRTL_OSVERSIONINFOW>(&ovi)) == 0)
{ {
gTempInfo.uKernelPatch = ovi.dwBuildNumber; gTempInfo.uKernelPatch = ovi.dwBuildNumber;
gTempInfo.uKernelMinor = ovi.dwMinorVersion; gTempInfo.uKernelMinor = ovi.dwMinorVersion;
gTempInfo.uKernelMajor = ovi.dwMajorVersion; gTempInfo.uKernelMajor = ovi.dwMajorVersion;
gTempInfo.uUserlandMajor = gTempInfo.uKernelMajor; gTempInfo.uUserlandMajor = gTempInfo.uKernelMajor;
gTempInfo.uUserlandMinor = ovi.wServicePackMajor; gTempInfo.uUserlandMinor = ovi.wServicePackMajor;
gTempInfo.uUserlandPatch = ovi.wServicePackMinor; gTempInfo.uUserlandPatch = ovi.wServicePackMinor;
} }
} }
HKEY hKey; HKEY hKey;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &hKey) == ERROR_SUCCESS) if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{ {
if (!Win32ReadRegistry(hKey, L"BuildLabEx", gBuildString)) if (!Win32ReadRegistry(hKey, L"BuildLabEx", gBuildString))
{ {
Win32ReadRegistry(hKey, L"BuildLab", gBuildString); Win32ReadRegistry(hKey, L"BuildLab", gBuildString);
} }
Win32ReadRegistry(hKey, L"ProductName", gUserlandBrand); Win32ReadRegistry(hKey, L"ProductName", gUserlandBrand);
RegCloseKey(hKey); RegCloseKey(hKey);
} }
#endif #endif
if (gKernelString.empty()) if (gKernelString.empty())
{ {
gKernelString = fmt::format("Microsoft NT {}.{}.{}", gTempInfo.uKernelMajor, gTempInfo.uKernelMinor, gTempInfo.uKernelPatch); gKernelString = fmt::format("Microsoft NT {}.{}.{}", gTempInfo.uKernelMajor, gTempInfo.uKernelMinor, gTempInfo.uKernelPatch);
} }
if (gUserlandBrand.empty()) if (gUserlandBrand.empty())
{ {
gUserlandBrand = fmt::format("NT Userland {}.{}.{}", gTempInfo.uUserlandMajor, gTempInfo.uUserlandMinor, gTempInfo.uUserlandPatch); gUserlandBrand = fmt::format("NT Userland {}.{}.{}", gTempInfo.uUserlandMajor, gTempInfo.uUserlandMinor, gTempInfo.uUserlandPatch);
} }
#endif #endif
gTempInfo.ePlatform = Build::kCurrentPlatform; gTempInfo.ePlatform = Build::kCurrentPlatform;
gInfo = &gTempInfo; gInfo = &gTempInfo;
} }
static bool IsWindowsVersionOrGreater(AuUInt8 major, AuUInt8 ignored, AuUInt8 sp)
{
return gInfo->ePlatform == Build::EPlatform::ePlatformWin32 && gInfo->uKernelMajor >= major && gInfo->uUserlandMinor >= sp;
}
AUKN_SYM bool IsWindowsXPOrGreater()
{
return IsWindowsVersionOrGreater(kWinVerWINXP, kWinVerWINXP, 0);
}
AUKN_SYM bool IsWindowsXPSP1OrGreater()
{
return IsWindowsVersionOrGreater(kWinVerWINXP, kWinVerWINXP, 1);
}
AUKN_SYM bool IsWindowsXPSP2OrGreater()
{
return IsWindowsVersionOrGreater(kWinVerWINXP, kWinVerWINXP, 2);
}
AUKN_SYM bool IsWindowsXPSP3OrGreater()
{
return IsWindowsVersionOrGreater(kWinVerWINXP, kWinVerWINXP, 3);
}
AUKN_SYM bool IsWindowsVistaOrGreater()
{
return IsWindowsVersionOrGreater(kWinVerVISTA, kWinVerVISTA, 0);
}
AUKN_SYM bool IsWindowsVistaSP1OrGreater()
{
return IsWindowsVersionOrGreater(kWinVerVISTA, kWinVerVISTA, 1);
}
AUKN_SYM bool IsWindowsVistaSP2OrGreater()
{
return IsWindowsVersionOrGreater(kWinVerVISTA, kWinVerVISTA, 2);
}
AUKN_SYM bool IsWindows7OrGreater()
{
return IsWindowsVersionOrGreater(kWinVerWIN7, kWinVerWIN7, 0);
}
AUKN_SYM bool IsWindows7SP1OrGreater()
{
return IsWindowsVersionOrGreater(kWinVerWIN7, kWinVerWIN7, 1);
}
AUKN_SYM bool IsWindows8OrGreater()
{
return IsWindowsVersionOrGreater(kWinVerWIN8, kWinVerWIN8, 0);
}
AUKN_SYM bool IsWindows8Point1OrGreater()
{
return IsWindowsVersionOrGreater(kWinVerWINBLUE, kWinVerWINBLUE, 0);
}
AUKN_SYM bool IsWindows10OrGreater()
{
return IsWindowsVersionOrGreater(kWinVerWIN10, kWinVerWIN10, 0);
}
AUKN_SYM bool IsWindows11OrGreater()
{
return IsWindowsVersionOrGreater(kWinVerWIN10, kWinVerWIN10, 0) && gInfo->uKernelPatch >= 22000;
}
} }

115
readme.md
View File

@ -4,12 +4,14 @@
The Aurora Runtime is an platform abstraction layer for cross-platform C++ development targeting<br> The Aurora Runtime is an platform abstraction layer for cross-platform C++ development targeting<br>
embedded and PC systems. Simply fetch a binary package for your toolchain or integrate the build<br> embedded and PC systems. Simply fetch a binary package for your toolchain or integrate the build<br>
scripts into your applications build pipeline to get started. scripts into your applications build pipeline to get started. <br>
View this raw file for improved formatting
## Features ## Features
- Lightweight threading and synchronization primitives - Lightweight threading and synchronization primitives
- Async threading primitives, including WaitMultipleObjects paradigm [WIP] - Async threading primitives, including WaitMultipleObjects paradigm
- Asynchronous and synchronous IO abstraction - Asynchronous and synchronous IO abstraction
- Optional event driven async programming paradigm - Optional event driven async programming paradigm
- Console; graphical and standard; binary and UTF-8 logger - Console; graphical and standard; binary and UTF-8 logger
@ -32,7 +34,7 @@ Doxygen: <br>
Examples: <br> Examples: <br>
Tests: <br> Tests: <br>
Cmake-stable:<br> Cmake-stable:<br>
Build Pipeline: Build Pipeline: https://git.reece.sx/AuroraPipeline/Build
## Utilities ## Utilities
@ -43,16 +45,35 @@ Aurora Overloadable Type Declerations: https://git.reece.sx/AuroraSupport/Aurora
## Logging ## Logging
Aurora Runtime does not attempt to implement your favourite production logger. We instead ~~Aurora Runtime does not attempt to implement your favourite production logger. We instead <br>
implement a subscription based log message dispatcher with some default backends including implement a subscription based log message dispatcher with some default backends including <br>
a file logger, Windows debug logging, Windows conhost stdin/out using UTF-8, UNIX stdin/out a file logger, Windows debug logging, Windows conhost stdin/out using UTF-8, UNIX stdin/out <br>
respecting the applications codepage, a wxWidgets toolkit GUI, and hopefully more to come. respecting the applications codepage, a wxWidgets toolkit GUI, and hopefully more to come. ~~ <br>
Additionally, consoles that provide an input stream can be used in conjunction with the parse
subsystem to provide basic command-based deserialization, tokenization, and dispatch of UTF-8
Additionally, consoles that provide an input stream can be used in conjunction with the parse <br>
subsystem to provide basic command-based deserialization, tokenization, and dispatch of UTF-8 <br>
translated strings regardless of the system locale translated strings regardless of the system locale
## Exceptions
## Loop [WIP] Through the use of compiler internal overloads, ELF hooking, and Win32 `AddVectoredExceptionHandler`, Aurora <br>
Runtime hooks exceptions at the time of throw, including *some* out of ecosystem exceptions, providing detailed <br>
telemetry of the object type, object string, and backtrace. In addition, the `AuDebug` namespace provides TLS based <br>
last-error and last-backtrace methods. <br>
EXCEPTIONS ARE NOT CONTROL FLOW...<br>
- Aurora Runtime WILL attempt to mitigate exceptions in internal logic
- Aurora Runtime WILL NOT abuse exceptions to communicate failure
- Aurora Runtime WILL try to decouple internal exceptions from the API
- Aurora Runtime WILL NOT use anything that automatically crashes on exception catch (no-nothrow)
- Aurora Runtime WILL provide extended exception information to telemetry backends and through the `AuDebug` namespace
- Aurora Runtime WILL NOT make any guarantees of being globally-nothrow; however, it should be a safe assumption in non-critical environments
`SysPanic` can be used to format a `std::terminate`-like exit condition, complete with telemetry data and safe cleanup.
## Loop
Aurora Runtime offers a main loop that connects multiple input sources into one delegate. <br> Aurora Runtime offers a main loop that connects multiple input sources into one delegate. <br>
Timers, semaphores, mutexes, events, X11, FDs, Win32 msg loop, macos, IPC, file aio handles, and<br> Timers, semaphores, mutexes, events, X11, FDs, Win32 msg loop, macos, IPC, file aio handles, and<br>
@ -117,9 +138,6 @@ represents a binary blob of UTF-8. Looking to switch to `tiny-utf8` for UTF-8 sa
## Memory ## Memory
User-overloadable type declerations and generic access utilities are defined under [utilities](#utilities)<br>
Aurora provides a bring your own container and shared pointer model overloadable in your configuration header.
``` ```
Types: Types:
AuSPtr<Type_t> AuSPtr<Type_t>
@ -135,9 +153,45 @@ Macros:
AuFunction<...> AuBindThis(This_t *::?, ...) AuFunction<...> AuBindThis(This_t *::?, ...)
``` ```
Most Aurora Runtime APIs provide generic new and release functions should you not need the overhead of reference counting or unique ptrs <br> By default, AuSPtr is backed by `std::shared_ptr`, extended by `#include <Aurora/Memory/ExtendStlLikeSharedPtr>` <br>
However, strict C codebases would need to shim to C, perhaps using AuUnsafeRaiiToShared to convert T\*s to unsafe `AuSPtr<T>`s, the namespaced C++ functions <br> Using this class, undefined behaviour on dereference and operator pointer is altered to guarantee an AU_THROW_STRING <br>
It would be 'nice' to live in a world without C++ exceptions; however, nothrow and attempts to mitigate them and their <br>
basis tend to result in `std::terminate` being called sooner or later. Defer to [exceptions](#exceptions) on how we log<br>
and treat them. Those who live in nothrow land can eat the exception, turning it into a terminate condition. Smarter <br>
applications may be able to catch the null dereference and continue operation without brining the whole kingdom down with it.
### Note
Aurora provides a bring your own container and shared pointer model overloadable in your configuration header.<br>
User-overloadable type declerations and generic access utilities are defined under [utilities](#utilities)<br>
## Binding
Aurora Runtime provides C++ APIs; however, it should be noted that two libraries are used to extend interfaces and enums <br>
to help with porting and internal utility access. One, AuroraEnums, wraps basic enumerations and provides value vectors; <br>
value strings; look up; iteration; and more. The other, AuroraInterfaces, provides *TWO* class types for each virtual interface. <br>
Each interface can be backed by a; C++ class method overriding a superclass's `virtual ...(...) = 0;` method, or a `AuFunctional`<br>
-based structure. <br>
It should be noted that most language bindings and generator libraries (^swig, v8pp, nbind, luabind) work with shared pointers. <br> It should be noted that most language bindings and generator libraries (^swig, v8pp, nbind, luabind) work with shared pointers. <br>
Other user code may wish to stuff pointers into a machineword-sized space, whether its a C library, a FFI, or a size constraint. <br>
One handle or abstraction layer will be required to integrate the C++ API into the destination platform, and assuming we have a <br>
C++ language frontend parsing our API, we can use `AuSPtr` for all caller-to-method constant reference scanerios. <br>
Furthermore, `AuSPtrs` can be created, without a deletor, using `AuUnsafeRaiiToShared(unique/raw pointer)`. To solve the raw <br>
pointer issue, `AuSPtrs` are created in the public headers with the help of exported/default visibility interface create and <br>
destroy functions. These APIs provide raw pointers to public C++ interfaces, and as such, can be binded using virtually any <br>
shim generator. Method and API mapping will likely involve manual work from the library developer to reimplement AU concepts <br>
under their language runtime instead of using the C++ platform, or at least require manual effort to shim or map each runtime <br>
prototype into something more sane across the language barrier. <br>
Memory is generally viewed through a `std::span` like concept called MemoryViews. `MemoryViewRead` and `MemoryViewWrite` <br>
provide windows into a defined address range. `MemoryViewStreamRead` and `MemoryViewStreamWrite` expand upon this concept by <br>
accepting an additional offset (`AuUInt &: reference`) that is used by internal APIs to indicate how many bytes were written or <br>
read from a given input region. Such requirement came about from so many APIs, networking, compression, encoding, doing the exact <br>
same thing in different not-so-portable ways. Unifying memory access to 4 class types should aid with SWIG prototyping.
Unrelated note, structure interfacing with questionable C++ ABI reimplementations is somewhat sketchy in FFI projects (^ CppSharp)<br>
can lead to some memory leaks. <br>
## IO ## IO
@ -157,7 +211,7 @@ The networking stack supports a handful of architectural paradigms<br>
- read with an all-or-nothing flag and an async flag<br> - read with an all-or-nothing flag and an async flag<br>
- read with an asynchronous stream callback - read with an asynchronous stream callback
- peaking<br> - peaking<br>
- async read/write pump whenever or all - async read/write pump whenever and/or all
## FIO ## FIO
@ -177,7 +231,11 @@ Path tokens include:<br>
[0] == '?' = ., !, or ~<br> [0] == '?' = ., !, or ~<br>
.. = go back<br> .. = go back<br>
/ = splitter<br> / = splitter<br>
\ = splitter \ = splitter<br>
<br>
[TODO] Aurora Branding <br>
[TODO] Aurora IO Resources <br>
## Aurora Async ## Aurora Async
@ -201,24 +259,35 @@ system configuration, the unix locale env variable, and/or the provided overload
## Philosophies ## Philosophies
- Assume C++17 language support in the language driver - Assume C++17 language support in the language driver
- Solve the large issues nobody is tackling. To avoid reinventing the wheel accept third party <br>
solutions when the pros (developer time) weighted against the negatives (legal, bulk) makes
sense.
- Use AuXXX type bindings for std types, allow customers to overload the std namespace - Use AuXXX type bindings for std types, allow customers to overload the std namespace
We assume *some* containers and utility APIs exist, but where they come from is up to you
- Keep the code and build chain simple such that any C++ developer could maintain - Keep the code and build chain simple such that any C++ developer could maintain
their own software stack built around aurora components. their own software stack built around aurora components.
- Dependencies should be cross-platform friendly
- Dependencies and concepts should be cross-platform, cross-architecture, cross-ring friendly
It is recommended to fork and replace any legacy OS specific code with equivalent It is recommended to fork and replace any legacy OS specific code with equivalent
AuroraRuntime concepts AuroraRuntime concepts, introducing a circular dependency with the Aurora Runtime
APIs shouldn't be designed around userland, mobile computing, or desktop computing;
AuroraRuntime must provide a common backbone for all applications.
Locale and user-info APIs will be limited due to the assumption userland is not a
concept
- Dependencies, excluding core reference algorithms (eg compression), must be rewritten - Dependencies, excluding core reference algorithms (eg compression), must be rewritten
and phased out over time. and phased out over time.
- Dependencies should not be added if most platforms provide some degree of native support<br> - Dependencies should not be added if most platforms provide some degree of native support<br>
Examples:<br> Examples:<br>
-> Don't depend on a pthread shim for windows; implement the best thread <br> -> Don't depend on a pthread shim for windows; implement the best thread <br>
primitives that lie on the best possible api for them <br> primitives that lie on the best possible api for them <br>
Don't depend on ICU when POSIX's iconv and Win32's multibyte apis cover<br> -> Don't depend on ICU when POSIX's iconv and Win32's multibyte apis cover<br>
everything a conservative developer cares about; chinese, utf-16, utf-8,<br> everything a conservative developer cares about; chinese, utf-16, utf-8,<br>
utf-32 conversion, on top of all the ancient windows codepages utf-32 conversion, on top of all the ancient windows codepages
- Dependencies should only be added conservatively when it saves development time and - Dependencies should only be added conservatively when it saves development time and
provides production hardening <br> provides production hardening <br>
Examples:<br> Examples:<br>