[+] Added VersionHelpers
[*] Detabify [*] Broke up CpuInfo [*] I want to rewrite this trashy readme soon
This commit is contained in:
parent
7eb6900e9f
commit
0d388dc4e2
@ -12,7 +12,7 @@ namespace Aurora::Async
|
||||
struct IWorkItemHandler
|
||||
{
|
||||
enum class EProcessNext
|
||||
{
|
||||
{
|
||||
eInvalid = -1,
|
||||
eFinished = 0,
|
||||
eRerun,
|
||||
|
@ -27,9 +27,9 @@ namespace Aurora::HWInfo
|
||||
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);
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -5,15 +5,15 @@
|
||||
|
||||
namespace Aurora::Locale
|
||||
{
|
||||
AUKN_SYM AuString NumbericLocaleGetDecimal();
|
||||
#
|
||||
AUKN_SYM AuString TimeLocaleGetMSChar();
|
||||
AUKN_SYM AuString TimeLocaleS();
|
||||
AUKN_SYM AuString TimeLocaleGetDayChar();
|
||||
AUKN_SYM AuString NumbericLocaleGetDecimal();
|
||||
|
||||
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 TimeLocaleGetMSChar();
|
||||
AUKN_SYM AuString TimeLocaleS();
|
||||
AUKN_SYM AuString TimeLocaleGetDayChar();
|
||||
|
||||
AUKN_SYM AuString ConvertMSToTimescale(AuUInt32 ms);
|
||||
AUKN_SYM AuString ConvertNSToTimescale(AuUInt64 ns);
|
||||
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,93 +9,93 @@
|
||||
|
||||
namespace Aurora::Memory
|
||||
{
|
||||
template<class TType_t, class Base_t>
|
||||
struct ExSharedPtr : public Base_t
|
||||
{
|
||||
bool cached {};
|
||||
template<class TType_t, class Base_t>
|
||||
struct ExSharedPtr : public Base_t
|
||||
{
|
||||
bool cached {};
|
||||
|
||||
using element_type = Base_t::element_type;
|
||||
using weak_type = Base_t::weak_type;
|
||||
using base_type = Base_t;
|
||||
using Base_t::Base_t;
|
||||
using element_type = Base_t::element_type;
|
||||
using weak_type = Base_t::weak_type;
|
||||
using base_type = Base_t;
|
||||
using Base_t::Base_t;
|
||||
|
||||
ExSharedPtr(Base_t &&in) : Base_t(in)
|
||||
{}
|
||||
ExSharedPtr(const Base_t &in) : Base_t(in)
|
||||
{}
|
||||
ExSharedPtr(Base_t &&in) : Base_t(in)
|
||||
{}
|
||||
ExSharedPtr(const Base_t &in) : Base_t(in)
|
||||
{}
|
||||
|
||||
operator Base_t() const noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
operator Base_t() const noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
ExSharedPtr &operator =(const Base_t &in) noexcept
|
||||
{
|
||||
Base_t::operator=(in);
|
||||
return *this;
|
||||
}
|
||||
ExSharedPtr &operator =(const Base_t &in) noexcept
|
||||
{
|
||||
Base_t::operator=(in);
|
||||
return *this;
|
||||
}
|
||||
|
||||
TType_t &operator*() const
|
||||
{
|
||||
throwif();
|
||||
return Base_t::operator*();
|
||||
}
|
||||
TType_t &operator*() const
|
||||
{
|
||||
throwif();
|
||||
return Base_t::operator*();
|
||||
}
|
||||
|
||||
TType_t *operator->() const
|
||||
{
|
||||
throwif();
|
||||
return Base_t::operator->();
|
||||
}
|
||||
TType_t *operator->() const
|
||||
{
|
||||
throwif();
|
||||
return Base_t::operator->();
|
||||
}
|
||||
|
||||
TType_t &operator*()
|
||||
{
|
||||
throwif();
|
||||
return Base_t::operator*();
|
||||
}
|
||||
TType_t &operator*()
|
||||
{
|
||||
throwif();
|
||||
return Base_t::operator*();
|
||||
}
|
||||
|
||||
TType_t *operator->()
|
||||
{
|
||||
throwif();
|
||||
return Base_t::operator->();
|
||||
}
|
||||
TType_t *operator->()
|
||||
{
|
||||
throwif();
|
||||
return Base_t::operator->();
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
|
||||
auline void _cache()
|
||||
{
|
||||
cached = Base_t::operator bool();
|
||||
}
|
||||
auline void _cache()
|
||||
{
|
||||
cached = Base_t::operator bool();
|
||||
}
|
||||
|
||||
auline void throwif() const
|
||||
{
|
||||
if (!cached) [[unlikely]]
|
||||
{
|
||||
if (!Base_t::operator bool()) [[likely]]
|
||||
{
|
||||
AU_THROW_STRING("ExSharedPointer Null Access Violation");
|
||||
}
|
||||
}
|
||||
}
|
||||
auline void throwif() const
|
||||
{
|
||||
if (!cached) [[unlikely]]
|
||||
{
|
||||
if (!Base_t::operator bool()) [[likely]]
|
||||
{
|
||||
AU_THROW_STRING("ExSharedPointer Null Access Violation");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auline void throwif()
|
||||
{
|
||||
if (!cached) [[unlikely]]
|
||||
{
|
||||
cached = Base_t::operator bool();
|
||||
if (!cached) [[likely]]
|
||||
{
|
||||
AU_THROW_STRING("ExSharedPointer Null Access Violation");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
auline void throwif()
|
||||
{
|
||||
if (!cached) [[unlikely]]
|
||||
{
|
||||
cached = Base_t::operator bool();
|
||||
if (!cached) [[likely]]
|
||||
{
|
||||
AU_THROW_STRING("ExSharedPointer Null Access Violation");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<class TType_t, class Base_t>
|
||||
struct ExSharedFromThis : Base_t
|
||||
{
|
||||
ExSharedPtr<TType_t, AURORA_RUNTIME_AU_SHARED_PTR<TType_t>> SharedFromThis()
|
||||
{
|
||||
return Base_t::shared_from_this();
|
||||
}
|
||||
};
|
||||
template<class TType_t, class Base_t>
|
||||
struct ExSharedFromThis : Base_t
|
||||
{
|
||||
ExSharedPtr<TType_t, AURORA_RUNTIME_AU_SHARED_PTR<TType_t>> SharedFromThis()
|
||||
{
|
||||
return Base_t::shared_from_this();
|
||||
}
|
||||
};
|
||||
}
|
@ -49,4 +49,5 @@ namespace Aurora::Process
|
||||
AUKN_SYM AuOptional<Segment> GetSegment(AuUInt pointer);
|
||||
AUKN_SYM PublicModule DumpExecutableRoot();
|
||||
AUKN_SYM Segments DumpExecutableAll();
|
||||
AUKN_SYM void TryRescanSlow();
|
||||
}
|
@ -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
|
||||
Date: 2022-1-25
|
||||
Author: Reece
|
||||
File: SWInfo.hpp
|
||||
Date: 2022-1-25
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::SWInfo
|
||||
{
|
||||
struct OSInformation
|
||||
{
|
||||
// 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
|
||||
// Nice tardlang
|
||||
struct OSInformation
|
||||
{
|
||||
// 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
|
||||
// Nice tardlang
|
||||
|
||||
const AuString *kKernelString; //
|
||||
const AuString *kUserlandBrand; // Windows 10 Pro, Xbox, glibc, Ubuntu, distro name
|
||||
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 *kKernelString; //
|
||||
const AuString *kUserlandBrand; // Windows 10 Pro, Xbox, glibc, Ubuntu, distro name
|
||||
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.??-??`)
|
||||
|
||||
AuUInt32 uKernelMajor {};
|
||||
AuUInt32 uKernelMinor {};
|
||||
AuUInt32 uKernelPatch {};
|
||||
AuUInt32 uKernelMajor {};
|
||||
AuUInt32 uKernelMinor {};
|
||||
AuUInt32 uKernelPatch {};
|
||||
|
||||
AuUInt32 uUserlandMajor {};
|
||||
AuUInt32 uUserlandMinor {};
|
||||
AuUInt32 uUserlandPatch {};
|
||||
AuUInt32 uUserlandMajor {};
|
||||
AuUInt32 uUserlandMinor {};
|
||||
AuUInt32 uUserlandPatch {};
|
||||
|
||||
bool bIsServer {};
|
||||
bool bIsEnterprise {};
|
||||
bool bIsServer {};
|
||||
bool bIsEnterprise {};
|
||||
|
||||
Aurora::Build::EPlatform ePlatform = Aurora::Build::EPlatform::eEnumInvalid;
|
||||
Aurora::Build::EPlatform ePlatform = Aurora::Build::EPlatform::eEnumInvalid;
|
||||
|
||||
private:
|
||||
static inline AuString _kIgnore {};
|
||||
private:
|
||||
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, (
|
||||
kKernelString,
|
||||
kUserlandBrand,
|
||||
kUserlandDesktopEnv,
|
||||
kBuildString,
|
||||
ePlatform
|
||||
))
|
||||
AU_NO_COPY(OSInformation);
|
||||
AU_MOVE(OSInformation);
|
||||
};
|
||||
AU_DEFINE_CTOR_VA(OSInformation, (
|
||||
kKernelString,
|
||||
kUserlandBrand,
|
||||
kUserlandDesktopEnv,
|
||||
kBuildString,
|
||||
ePlatform
|
||||
))
|
||||
AU_NO_COPY(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();
|
||||
}
|
@ -44,8 +44,8 @@ static void Init()
|
||||
Aurora::RNG::Init();
|
||||
Aurora::Hashing::InitHashing();
|
||||
Aurora::Async::InitAsync();
|
||||
Aurora::HWInfo::Init();
|
||||
Aurora::SWInfo::InitSwInfo();
|
||||
Aurora::HWInfo::Init();
|
||||
Aurora::Telemetry::Init();
|
||||
Aurora::Process::InitProcessMap();
|
||||
}
|
||||
|
40
Source/HWInfo/CpuInfo.BSD.cpp
Normal file
40
Source/HWInfo/CpuInfo.BSD.cpp
Normal 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;
|
||||
}
|
||||
}
|
13
Source/HWInfo/CpuInfo.BSD.hpp
Normal file
13
Source/HWInfo/CpuInfo.BSD.hpp
Normal 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();
|
||||
}
|
34
Source/HWInfo/CpuInfo.Linux.cpp
Normal file
34
Source/HWInfo/CpuInfo.Linux.cpp
Normal 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;
|
||||
}
|
||||
}
|
13
Source/HWInfo/CpuInfo.Linux.hpp
Normal file
13
Source/HWInfo/CpuInfo.Linux.hpp
Normal 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();
|
||||
}
|
176
Source/HWInfo/CpuInfo.NT.cpp
Normal file
176
Source/HWInfo/CpuInfo.NT.cpp
Normal 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;
|
||||
}
|
||||
}
|
13
Source/HWInfo/CpuInfo.NT.hpp
Normal file
13
Source/HWInfo/CpuInfo.NT.hpp
Normal 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();
|
||||
}
|
@ -10,215 +10,33 @@
|
||||
#include "CpuInfo.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)
|
||||
#include <stdlib.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_COMPILER_CLANG) || defined(AURORA_IS_POSIX_DERIVED)
|
||||
#include <cpuid.h>
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
#include <VersionHelpers.h>
|
||||
#include "CpuInfo.NT.hpp"
|
||||
#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
|
||||
{
|
||||
#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()
|
||||
{
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
SetCpuTopologyNT();
|
||||
#elif defined(AURORA_IS_BSD_DERIVED)
|
||||
|
||||
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;
|
||||
|
||||
SetCpuTopologyBSD();
|
||||
#elif defined(AURORA_IS_LINUX_DERIVED)
|
||||
|
||||
gCpuInfo.socket = 1;
|
||||
gCpuInfo.cores = 1;
|
||||
gCpuInfo.threads = get_nprocs();
|
||||
|
||||
// TODO: parse /proc/cpuinfo
|
||||
gCpuInfo.maskMTHalf = true;
|
||||
|
||||
SetCpuTopologyLinux();
|
||||
#elif defined(AURORA_IS_POSIX_DERIVED)
|
||||
|
||||
gCpuInfo.socket = 1;
|
||||
@ -236,7 +54,7 @@ namespace Aurora::HWInfo
|
||||
}
|
||||
|
||||
bool fakeMtHalf = (gCpuInfo.threads & 1) == 0;
|
||||
gCpuInfo.maskMTHalf = true;
|
||||
gCpuInfo.maskMTHalf = fakeMtHalf;
|
||||
|
||||
if (fakeMtHalf)
|
||||
{
|
||||
|
@ -82,7 +82,7 @@ namespace Aurora::Locale
|
||||
// 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
|
||||
// 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
|
||||
//
|
||||
// ! = pad
|
||||
|
@ -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
|
||||
Date: 2022-1-23
|
||||
Author: Reece
|
||||
File: ProcessMap.cpp
|
||||
Date: 2022-1-23
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "ProcessMap.hpp"
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
#include "ProcessMap.Win32.hpp"
|
||||
#include "ProcessMap.Win32.hpp"
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
#include "ProcessMap.NT.hpp"
|
||||
#include "ProcessMap.NT.hpp"
|
||||
#endif
|
||||
|
||||
namespace Aurora::Process
|
||||
{
|
||||
struct ModuleBasePairUtil
|
||||
{
|
||||
AuUInt operator()(const ModuleBasePair &in) const
|
||||
{
|
||||
return in.modBase;
|
||||
}
|
||||
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 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 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()
|
||||
{}
|
||||
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)
|
||||
{}
|
||||
};
|
||||
ModuleLookup(const Segment &s) : Segment(s)
|
||||
{}
|
||||
};
|
||||
|
||||
static AuBST<AuUInt, ModuleLookup> gModulePtrMap;
|
||||
static AuBST<AuUInt, ModuleLookup> gModulePtrMap;
|
||||
|
||||
static const auto kMinPageAlignment = 4096;
|
||||
static const auto kPageBufferPad = 20;
|
||||
static const auto kMinPageAlignment = 4096;
|
||||
static const auto kPageBufferPad = 20;
|
||||
|
||||
static AuThreadPrimitives::MutexUnique_t gMutexUnique;
|
||||
static AuHashMapEx<ModuleBasePair, AuSPtr<PublicModule>, ModuleBasePairUtil> gModuleMap;
|
||||
static AuThreadPrimitives::MutexUnique_t gMutexUnique;
|
||||
static AuHashMapEx<ModuleBasePair, AuSPtr<PublicModule>, ModuleBasePairUtil> gModuleMap;
|
||||
|
||||
static AuUInt ToLowestPageAlignment(AuUInt in)
|
||||
{
|
||||
return in & ~(kMinPageAlignment - 1);
|
||||
}
|
||||
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 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;
|
||||
}
|
||||
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();
|
||||
}
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
{
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
gModuleMap.erase(itr);
|
||||
}
|
||||
|
||||
PublicModule GetFromModuleCache(AuUInt handle)
|
||||
{
|
||||
AU_LOCK_GUARD(gMutexUnique);
|
||||
auto itr = gModuleMap.find({"", handle});
|
||||
if (itr == gModuleMap.end()) return {};
|
||||
return *itr->second;
|
||||
}
|
||||
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)
|
||||
{
|
||||
auto curPtr = ToLowestPageAlignment(pointer);
|
||||
auto temp = GetSegmentCache(curPtr);
|
||||
if (temp.has_value()) return temp;
|
||||
static AuOptional<Segment> FindInCache(AuUInt pointer)
|
||||
{
|
||||
auto curPtr = ToLowestPageAlignment(pointer);
|
||||
auto temp = GetSegmentCache(curPtr);
|
||||
if (temp.has_value()) return temp;
|
||||
|
||||
for (int i = 0; i < kPageBufferPad + 1; 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;
|
||||
}
|
||||
for (int i = 0; i < kPageBufferPad + 1; 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>{};
|
||||
}
|
||||
return AuOptional<Segment>{};
|
||||
}
|
||||
|
||||
void InitProcessMap()
|
||||
{
|
||||
gMutexUnique = AuThreadPrimitives::MutexUnique();
|
||||
void InitProcessMap()
|
||||
{
|
||||
gMutexUnique = AuThreadPrimitives::MutexUnique();
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
InitProcessMapNt();
|
||||
#endif
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
InitProcessMapNt();
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
MakeToolHelp32Snapshot();
|
||||
#endif
|
||||
}
|
||||
TryRescanSlow();
|
||||
}
|
||||
|
||||
void DeinitProcessMap()
|
||||
{
|
||||
gMutexUnique.reset();
|
||||
DeinitProcessMapNt();
|
||||
}
|
||||
AUKN_SYM void TryRescanSlow()
|
||||
{
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
MakeToolHelp32Snapshot();
|
||||
#endif
|
||||
}
|
||||
|
||||
AUKN_SYM AuOptional<Segment> GetSegment(AuUInt pointer)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto ceg = FindInCache(pointer);
|
||||
if (ceg.has_value())
|
||||
{
|
||||
return ceg;
|
||||
}
|
||||
void DeinitProcessMap()
|
||||
{
|
||||
gMutexUnique.reset();
|
||||
DeinitProcessMapNt();
|
||||
}
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
if (MakeAwarePtr(pointer))
|
||||
{
|
||||
return FindInCache(pointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
return LookupArbitrarySegment(pointer);
|
||||
}
|
||||
#endif
|
||||
AUKN_SYM AuOptional<Segment> GetSegment(AuUInt pointer)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto ceg = FindInCache(pointer);
|
||||
if (ceg.has_value())
|
||||
{
|
||||
return ceg;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
if (MakeAwarePtr(pointer))
|
||||
{
|
||||
return FindInCache(pointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
return LookupArbitrarySegment(pointer);
|
||||
}
|
||||
#endif
|
||||
|
||||
AUKN_SYM PublicModule DumpExecutableRoot()
|
||||
{
|
||||
try
|
||||
{
|
||||
return GetExecutableRoot();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
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 (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
AUKN_SYM PublicModule DumpExecutableRoot()
|
||||
{
|
||||
try
|
||||
{
|
||||
return GetExecutableRoot();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
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 (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
Date: 2022-1-23
|
||||
Author: Reece
|
||||
File: ProcessMap.hpp
|
||||
Date: 2022-1-23
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Process
|
||||
{
|
||||
struct ModuleBasePair
|
||||
{
|
||||
AuString module;
|
||||
AuUInt modBase;
|
||||
};
|
||||
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();
|
||||
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();
|
||||
}
|
@ -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
|
||||
Date: 2022-1-25
|
||||
Author: Reece
|
||||
File: SWInfo.cpp
|
||||
Date: 2022-1-25
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "SWInfo.hpp"
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
#include <VersionHelpers.h>
|
||||
|
||||
#include <winternl.h>
|
||||
|
||||
NTSYSAPI NTSTATUS RtlGetVersion(
|
||||
PRTL_OSVERSIONINFOW lpVersionInformation
|
||||
);
|
||||
#include <VersionHelpers.h>
|
||||
#include <winternl.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace Aurora::SWInfo
|
||||
{
|
||||
static const AuString kDefaultStr;
|
||||
static const OSInformation kDefaultInfo;
|
||||
static OSInformation const *gInfo = &kDefaultInfo;
|
||||
static AuUInt8 kWinVerNT4 = 0x0400;
|
||||
static AuUInt8 kWinVerWIN2K = 0x0500;
|
||||
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 AuString gUserlandBrand;
|
||||
static AuString gUserlandDesktopEnv;
|
||||
static AuString gBuildString;
|
||||
static OSInformation gTempInfo;
|
||||
static AuUInt8 kWinVerWIN10 = 0x0A00;
|
||||
static const AuString kDefaultStr;
|
||||
static const OSInformation kDefaultInfo;
|
||||
static OSInformation const *gInfo = &kDefaultInfo;
|
||||
|
||||
static void Reset()
|
||||
{
|
||||
gInfo = &kDefaultInfo;
|
||||
}
|
||||
static AuString gKernelString;
|
||||
static AuString gUserlandBrand;
|
||||
static AuString gUserlandDesktopEnv;
|
||||
static AuString gBuildString;
|
||||
static OSInformation gTempInfo;
|
||||
|
||||
AUKN_SYM const OSInformation & GetPlatformInfo()
|
||||
{
|
||||
return *gInfo;
|
||||
}
|
||||
static void Reset()
|
||||
{
|
||||
gInfo = &kDefaultInfo;
|
||||
}
|
||||
|
||||
AUKN_SYM const OSInformation &GetPlatformInfo()
|
||||
{
|
||||
return *gInfo;
|
||||
}
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
|
||||
static bool IsWindowsEnterpriseBranch()
|
||||
{
|
||||
OSVERSIONINFOEXW osvi = {sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0, VER_SUITE_ENTERPRISE, 0};
|
||||
DWORDLONG const dwlConditionMask = VerSetConditionMask(0, VER_SUITENAME, VER_EQUAL);
|
||||
static bool IsWindowsEnterpriseBranch()
|
||||
{
|
||||
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);
|
||||
}
|
||||
return !VerifyVersionInfoW(&osvi, VER_SUITENAME, dwlConditionMask);
|
||||
}
|
||||
|
||||
auline bool Win32ReadRegistry(HKEY hKey, const wchar_t *key, AuString &strValue)
|
||||
{
|
||||
DWORD dwBufferSize {};
|
||||
auline bool Win32ReadRegistry(HKEY hKey, const wchar_t *key, AuString &strValue)
|
||||
{
|
||||
DWORD dwBufferSize {};
|
||||
|
||||
if (RegQueryValueExW(hKey, key, 0, NULL, NULL, &dwBufferSize) != ERROR_SUCCESS)
|
||||
{
|
||||
SysPushErrorUnavailableError("Couldn't access registery key");
|
||||
return false;
|
||||
}
|
||||
if (RegQueryValueExW(hKey, key, 0, NULL, NULL, &dwBufferSize) != ERROR_SUCCESS)
|
||||
{
|
||||
SysPushErrorUnavailableError("Couldn't access registery key");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring in;
|
||||
std::wstring in;
|
||||
|
||||
if (!AuTryResize(in, dwBufferSize))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!AuTryResize(in, dwBufferSize))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (RegQueryValueExW(hKey, key, 0, NULL, reinterpret_cast<LPBYTE>(in.data()), &dwBufferSize) != ERROR_SUCCESS)
|
||||
{
|
||||
SysPushErrorUnavailableError("Couldn't access registery key");
|
||||
return false;
|
||||
}
|
||||
if (RegQueryValueExW(hKey, key, 0, NULL, reinterpret_cast<LPBYTE>(in.data()), &dwBufferSize) != ERROR_SUCCESS)
|
||||
{
|
||||
SysPushErrorUnavailableError("Couldn't access registery key");
|
||||
return false;
|
||||
}
|
||||
|
||||
strValue = Locale::ConvertFromWChar(in.data(), in.size());
|
||||
return strValue.size() == in.size();
|
||||
}
|
||||
strValue = Locale::ConvertFromWChar(in.data(), in.size());
|
||||
return strValue.size() == in.size();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void InitSwInfo()
|
||||
{
|
||||
Reset();
|
||||
void InitSwInfo()
|
||||
{
|
||||
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)
|
||||
OSVERSIONINFOEX info {};
|
||||
info.dwOSVersionInfoSize = sizeof(info);
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
OSVERSIONINFOEX info {};
|
||||
info.dwOSVersionInfoSize = sizeof(info);
|
||||
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
gTempInfo.bIsServer = IsWindowsServer();
|
||||
gTempInfo.bIsEnterprise = IsWindowsEnterpriseBranch();
|
||||
#else
|
||||
gTempInfo.bIsServer = false;
|
||||
gTempInfo.bIsEnterprise = false;
|
||||
#endif
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
gTempInfo.bIsServer = IsWindowsServer();
|
||||
gTempInfo.bIsEnterprise = IsWindowsEnterpriseBranch();
|
||||
#else
|
||||
gTempInfo.bIsServer = false;
|
||||
gTempInfo.bIsEnterprise = false;
|
||||
#endif
|
||||
|
||||
gUserlandDesktopEnv = "Desktop Window Manager";
|
||||
gUserlandDesktopEnv = "Desktop Window Manager";
|
||||
|
||||
if (GetVersionExA(reinterpret_cast<LPOSVERSIONINFOA>(&info)))
|
||||
{
|
||||
gTempInfo.uKernelPatch = info.dwBuildNumber;
|
||||
gTempInfo.uKernelMinor = info.dwMinorVersion;
|
||||
gTempInfo.uKernelMajor = info.dwMajorVersion;
|
||||
if (GetVersionExA(reinterpret_cast<LPOSVERSIONINFOA>(&info)))
|
||||
{
|
||||
gTempInfo.uKernelPatch = info.dwBuildNumber;
|
||||
gTempInfo.uKernelMinor = info.dwMinorVersion;
|
||||
gTempInfo.uKernelMajor = info.dwMajorVersion;
|
||||
|
||||
gTempInfo.uUserlandMajor = gTempInfo.uKernelMajor;
|
||||
gTempInfo.uUserlandMinor = info.wServicePackMajor;
|
||||
gTempInfo.uUserlandPatch = info.wServicePackMinor;
|
||||
}
|
||||
gTempInfo.uUserlandMajor = gTempInfo.uKernelMajor;
|
||||
gTempInfo.uUserlandMinor = info.wServicePackMajor;
|
||||
gTempInfo.uUserlandPatch = info.wServicePackMinor;
|
||||
}
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
{
|
||||
RTL_OSVERSIONINFOEXW ovi {};
|
||||
ovi.dwOSVersionInfoSize = sizeof(ovi);
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
{
|
||||
RTL_OSVERSIONINFOEXW ovi {};
|
||||
ovi.dwOSVersionInfoSize = sizeof(ovi);
|
||||
|
||||
NTSTATUS(CALLBACK *pRtlGetVersion) (PRTL_OSVERSIONINFOW lpVersionInformation);
|
||||
pRtlGetVersion = (decltype(pRtlGetVersion))GetProcAddress(LoadLibrary(TEXT("Ntdll.dll")), "RtlGetVersion");
|
||||
NTSTATUS(CALLBACK *pRtlGetVersion) (PRTL_OSVERSIONINFOW lpVersionInformation);
|
||||
pRtlGetVersion = (decltype(pRtlGetVersion))GetProcAddress(LoadLibrary(TEXT("Ntdll.dll")), "RtlGetVersion");
|
||||
|
||||
if (pRtlGetVersion && pRtlGetVersion(reinterpret_cast<PRTL_OSVERSIONINFOW>(&ovi)) == 0)
|
||||
{
|
||||
gTempInfo.uKernelPatch = ovi.dwBuildNumber;
|
||||
gTempInfo.uKernelMinor = ovi.dwMinorVersion;
|
||||
gTempInfo.uKernelMajor = ovi.dwMajorVersion;
|
||||
if (pRtlGetVersion && pRtlGetVersion(reinterpret_cast<PRTL_OSVERSIONINFOW>(&ovi)) == 0)
|
||||
{
|
||||
gTempInfo.uKernelPatch = ovi.dwBuildNumber;
|
||||
gTempInfo.uKernelMinor = ovi.dwMinorVersion;
|
||||
gTempInfo.uKernelMajor = ovi.dwMajorVersion;
|
||||
|
||||
gTempInfo.uUserlandMajor = gTempInfo.uKernelMajor;
|
||||
gTempInfo.uUserlandMinor = ovi.wServicePackMajor;
|
||||
gTempInfo.uUserlandPatch = ovi.wServicePackMinor;
|
||||
}
|
||||
}
|
||||
|
||||
HKEY hKey;
|
||||
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
||||
{
|
||||
if (!Win32ReadRegistry(hKey, L"BuildLabEx", gBuildString))
|
||||
{
|
||||
Win32ReadRegistry(hKey, L"BuildLab", gBuildString);
|
||||
}
|
||||
Win32ReadRegistry(hKey, L"ProductName", gUserlandBrand);
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
#endif
|
||||
gTempInfo.uUserlandMajor = gTempInfo.uKernelMajor;
|
||||
gTempInfo.uUserlandMinor = ovi.wServicePackMajor;
|
||||
gTempInfo.uUserlandPatch = ovi.wServicePackMinor;
|
||||
}
|
||||
}
|
||||
|
||||
HKEY hKey;
|
||||
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
||||
{
|
||||
if (!Win32ReadRegistry(hKey, L"BuildLabEx", gBuildString))
|
||||
{
|
||||
Win32ReadRegistry(hKey, L"BuildLab", gBuildString);
|
||||
}
|
||||
Win32ReadRegistry(hKey, L"ProductName", gUserlandBrand);
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (gKernelString.empty())
|
||||
{
|
||||
gKernelString = fmt::format("Microsoft NT {}.{}.{}", gTempInfo.uKernelMajor, gTempInfo.uKernelMinor, gTempInfo.uKernelPatch);
|
||||
}
|
||||
if (gKernelString.empty())
|
||||
{
|
||||
gKernelString = fmt::format("Microsoft NT {}.{}.{}", gTempInfo.uKernelMajor, gTempInfo.uKernelMinor, gTempInfo.uKernelPatch);
|
||||
}
|
||||
|
||||
if (gUserlandBrand.empty())
|
||||
{
|
||||
gUserlandBrand = fmt::format("NT Userland {}.{}.{}", gTempInfo.uUserlandMajor, gTempInfo.uUserlandMinor, gTempInfo.uUserlandPatch);
|
||||
}
|
||||
if (gUserlandBrand.empty())
|
||||
{
|
||||
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
115
readme.md
@ -4,12 +4,14 @@
|
||||
|
||||
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>
|
||||
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
|
||||
|
||||
- Lightweight threading and synchronization primitives
|
||||
- Async threading primitives, including WaitMultipleObjects paradigm [WIP]
|
||||
- Async threading primitives, including WaitMultipleObjects paradigm
|
||||
- Asynchronous and synchronous IO abstraction
|
||||
- Optional event driven async programming paradigm
|
||||
- Console; graphical and standard; binary and UTF-8 logger
|
||||
@ -32,7 +34,7 @@ Doxygen: <br>
|
||||
Examples: <br>
|
||||
Tests: <br>
|
||||
Cmake-stable:<br>
|
||||
Build Pipeline:
|
||||
Build Pipeline: https://git.reece.sx/AuroraPipeline/Build
|
||||
|
||||
## Utilities
|
||||
|
||||
@ -43,16 +45,35 @@ Aurora Overloadable Type Declerations: https://git.reece.sx/AuroraSupport/Aurora
|
||||
|
||||
## Logging
|
||||
|
||||
Aurora Runtime does not attempt to implement your favourite production logger. We instead
|
||||
implement a subscription based log message dispatcher with some default backends including
|
||||
a file logger, Windows debug logging, Windows conhost stdin/out using UTF-8, UNIX stdin/out
|
||||
respecting the applications codepage, a wxWidgets toolkit GUI, and hopefully more to come.
|
||||
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
|
||||
~~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 <br>
|
||||
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. ~~ <br>
|
||||
|
||||
|
||||
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
|
||||
|
||||
## 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>
|
||||
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
|
||||
|
||||
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:
|
||||
AuSPtr<Type_t>
|
||||
@ -135,9 +153,45 @@ Macros:
|
||||
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>
|
||||
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>
|
||||
By default, AuSPtr is backed by `std::shared_ptr`, extended by `#include <Aurora/Memory/ExtendStlLikeSharedPtr>` <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>
|
||||
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
|
||||
@ -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 asynchronous stream callback
|
||||
- peaking<br>
|
||||
- async read/write pump whenever or all
|
||||
- async read/write pump whenever and/or all
|
||||
|
||||
## FIO
|
||||
|
||||
@ -177,7 +231,11 @@ Path tokens include:<br>
|
||||
[0] == '?' = ., !, or ~<br>
|
||||
.. = go back<br>
|
||||
/ = splitter<br>
|
||||
\ = splitter
|
||||
\ = splitter<br>
|
||||
|
||||
<br>
|
||||
[TODO] Aurora Branding <br>
|
||||
[TODO] Aurora IO Resources <br>
|
||||
|
||||
## Aurora Async
|
||||
|
||||
@ -201,24 +259,35 @@ system configuration, the unix locale env variable, and/or the provided overload
|
||||
## Philosophies
|
||||
|
||||
- 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
|
||||
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
|
||||
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
|
||||
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
|
||||
and phased out over time.
|
||||
|
||||
- Dependencies should not be added if most platforms provide some degree of native support<br>
|
||||
Examples:<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>
|
||||
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>
|
||||
utf-32 conversion, on top of all the ancient windows codepages
|
||||
|
||||
- Dependencies should only be added conservatively when it saves development time and
|
||||
provides production hardening <br>
|
||||
Examples:<br>
|
||||
|
Loading…
Reference in New Issue
Block a user