[+] 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

@ -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

@ -6,7 +6,7 @@
namespace Aurora::Locale namespace Aurora::Locale
{ {
AUKN_SYM AuString NumbericLocaleGetDecimal(); AUKN_SYM AuString NumbericLocaleGetDecimal();
#
AUKN_SYM AuString TimeLocaleGetMSChar(); AUKN_SYM AuString TimeLocaleGetMSChar();
AUKN_SYM AuString TimeLocaleS(); AUKN_SYM AuString TimeLocaleS();
AUKN_SYM AuString TimeLocaleGetDayChar(); AUKN_SYM AuString TimeLocaleGetDayChar();

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

@ -53,4 +53,19 @@ namespace Aurora::SWInfo
}; };
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

@ -159,6 +159,11 @@ namespace Aurora::Process
InitProcessMapNt(); InitProcessMapNt();
#endif #endif
TryRescanSlow();
}
AUKN_SYM void TryRescanSlow()
{
#if defined(AURORA_PLATFORM_WIN32) #if defined(AURORA_PLATFORM_WIN32)
MakeToolHelp32Snapshot(); MakeToolHelp32Snapshot();
#endif #endif

View File

@ -10,17 +10,25 @@
#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 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 AuUInt8 kWinVerWIN10 = 0x0A00;
static const AuString kDefaultStr; static const AuString kDefaultStr;
static const OSInformation kDefaultInfo; static const OSInformation kDefaultInfo;
static OSInformation const *gInfo = &kDefaultInfo; static OSInformation const *gInfo = &kDefaultInfo;
@ -160,4 +168,74 @@ namespace Aurora::SWInfo
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>