AuroraRuntime/Source/HWInfo/AuRamInfo.cpp

334 lines
8.4 KiB
C++

/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuRamInfo.cpp
Date: 2021-6-12
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "AuHWInfo.hpp"
#include "AuRamInfo.hpp"
#if defined(AURORA_IS_BSD_DERIVED)
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
#include <sys/limits.h>
#include <vm/vm_param.h>
#endif
#if defined(AURORA_IS_LINUX_DERIVED)
#include <sys/sysinfo.h>
#include <sys/resource.h>
#endif
#if defined(AURORA_IS_MODERNNT_DERIVED)
#include <psapi.h>
#include <winternl.h>
#endif
namespace Aurora::HWInfo
{
static AuOptional<RamStat> gMemStartup;
AUKN_SYM AuOptional<RamStat> GetMemStatProcess()
{
auto max = GetMemStatSystem().value_or(RamStat {}).qwAvailable;
#if defined(AURORA_IS_MODERNNT_DERIVED)
PROCESS_MEMORY_COUNTERS_EX pmc;
PROCESS_MEMORY_COUNTERS pm;
if (pGetProcessMemoryInfo)
{
if (pGetProcessMemoryInfo(GetCurrentProcess(),
reinterpret_cast<PPROCESS_MEMORY_COUNTERS>(&pmc),
sizeof(PROCESS_MEMORY_COUNTERS_EX)))
{
if (pmc.PagefileUsage)
{
return RamStat { pmc.PagefileUsage, max };
}
else
{
return RamStat { pmc.PrivateUsage, max };
}
}
if (pGetProcessMemoryInfo(GetCurrentProcess(),
reinterpret_cast<PPROCESS_MEMORY_COUNTERS>(&pm),
sizeof(PROCESS_MEMORY_COUNTERS)))
{
if (pm.PagefileUsage)
{
return RamStat { pm.PagefileUsage, max };
}
else
{
return RamStat { pm.WorkingSetSize, max };
}
}
}
return RamStat {0, max};
#elif defined(AURORA_IS_POSIX_DERIVED)
struct rusage usage;
getrusage(RUSAGE_SELF, &usage);
auto used = AuUInt64(usage.ru_maxrss)
#if !defined(AURORA_IS_XNU_DERIVED)
* 1024
#endif
;
return RamStat {used, max};
#else
return {};
#endif
}
AUKN_SYM AuOptional<RamStat> GetMemStatProcessBlamed()
{
#if defined(AURORA_IS_MODERNNT_DERIVED)
auto max = GetMemStatSystem().value_or(RamStat {}).qwAvailable;
#if defined(AURORA_PLATFORM_WIN32)
if (pNtQueryInformationProcess &&
AuSwInfo::IsWindows10OrGreater())
{
struct VM_COUNTERS_EX
{
SIZE_T PeakVirtualSize;
SIZE_T VirtualSize;
ULONG PageFaultCount;
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
SIZE_T QuotaPeakPagedPoolUsage;
SIZE_T QuotaPagedPoolUsage;
SIZE_T QuotaPeakNonPagedPoolUsage;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
SIZE_T PrivateUsage;
};
struct VM_COUNTERS_EX2
{
VM_COUNTERS_EX CountersEx;
SIZE_T PrivateWorkingSetSize;
ULONGLONG SharedCommitUsage;
} vm;
static const PROCESSINFOCLASS kProcessVmCounters = static_cast<PROCESSINFOCLASS>(3);
if (pNtQueryInformationProcess(GetCurrentProcess(),
kProcessVmCounters,
&vm,
sizeof(vm),
0))
{
// I WILL NOT USE A BLOATED OS THAT LIES TO US
// I WILL NOT USE A BLOATED OS THAT LIES TO US
// I WILL NOT USE A BLOATED OS THAT LIES TO US
// I WILL NOT USE A BLOATED OS THAT LIES TO US
// I WILL NOT USE A BLOATED OS THAT LIES TO US
// I WILL NOT USE A BLOATED OS THAT LIES TO US
return RamStat {vm.PrivateWorkingSetSize, max};
}
}
#endif
PROCESS_MEMORY_COUNTERS pm;
if (pGetProcessMemoryInfo(GetCurrentProcess(),
reinterpret_cast<PPROCESS_MEMORY_COUNTERS>(&pm),
sizeof(PROCESS_MEMORY_COUNTERS)))
{
return RamStat { pm.WorkingSetSize, max };
}
return RamStat {};
#else
return GetMemStatProcess();
#endif
}
#if defined(AURORA_IS_BSD_DERIVED)
struct vmtotal GetVMInfo()
{
struct vmtotal info;
int mib[2];
mib[0] = CTL_VM;
mib[1] = VM_TOTAL;
size_t len = sizeof(info);
sysctl(mib, 2, &info, &len, NULL, 0);
return info; // TODO: consider polling VM_UVMEXP
}
#endif
AUKN_SYM AuOptional<RamStat> GetMemStatSystem()
{
#if defined(AURORA_IS_MODERNNT_DERIVED)
MEMORYSTATUSEX statex;
statex.dwLength = sizeof(statex);
if (!GlobalMemoryStatusEx(&statex))
{
return {};
}
return RamStat {statex.ullTotalPageFile - statex.ullAvailPageFile, statex.ullTotalPageFile};
#elif defined(AURORA_IS_BSD_DERIVED)
auto vmInfo = GetVMInfo();
auto pageSize = AuUInt64(QueryBsdHwStat<unsigned int>(HW_PAGESIZE).value_or(4096));
auto totalMem = AuUInt64(vmInfo.t_vm) * pageSize;
auto freeMem = AuUInt64(vmInfo.t_free) * pageSize;
return RamStat {freeMem - totalMem, totalMem};
#elif defined(AURORA_IS_LINUX_DERIVED)
struct sysinfo info;
if (sysinfo(&info) != 0)
{
return {};
}
return RamStat {(info.totalram - info.freeram) + (info.totalswap - info.freeswap), info.totalram + info.totalswap};
#else
return GetMemStatPhysical();
#endif
}
AUKN_SYM AuOptional<RamStat> GetMemStatPhysical()
{
#if defined(AURORA_IS_MODERNNT_DERIVED)
MEMORYSTATUSEX statex;
statex.dwLength = sizeof(statex);
if (!GlobalMemoryStatusEx(&statex))
{
return {};
}
return RamStat {statex.ullTotalPhys - statex.ullAvailPhys, statex.ullTotalPhys};
#elif defined(AURORA_IS_BSD_DERIVED)
#if defined(HW_PHYSMEM64)
uint64_t stat;
auto cmd = HW_PHYSMEM64;
#else
unsigned int stat;
auto cmd = HW_PHYSMEM;
#endif
auto maxMem = QueryBsdHwStat<decltype(stat)>(cmd);
auto vmInfo = GetVMInfo();
auto freeMem = AuUInt64(vmInfo.t_free) * AuUInt64(QueryBsdHwStat<unsigned int>(HW_PAGESIZE).value_or(4096));
return RamStat {vmInfo.t_rm, maxMem.value_or(freeMem)};
#elif defined(AURORA_IS_LINUX_DERIVED)
struct sysinfo info;
if (sysinfo(&info) != 0)
{
return {};
}
return RamStat {info.totalram - info.freeram, info.totalram};
#else
return {};
#endif
}
AUKN_SYM AuOptional<RamStat> GetMemStatStartup()
{
return gMemStartup;
}
AUKN_SYM AuUInt32 GetPageSize()
{
return gPageSize;
}
AUKN_SYM AuOptional<AuUInt64> GetSwapSize()
{
static AuOptional<AuUInt64> gCached;
if (gCached)
{
return gCached;
}
if (auto opt = GetMemStatSystem())
{
if (auto optPhys = GetMemStatPhysical())
{
return gCached = AuUInt64(opt.value().qwAvailable - optPhys.value().qwAvailable);
}
}
return {};
}
AUKN_SYM AuOptional<AuUInt64> GetPhysicalSize()
{
static AuOptional<AuUInt64> gCached;
if (gCached)
{
return gCached;
}
if (auto optPhys = GetMemStatPhysical())
{
return gCached = optPhys.value().qwAvailable;
}
return {};
}
static void SetPageSize()
{
#if defined(AURORA_IS_MODERNNT_DERIVED)
SYSTEM_INFO info;
GetSystemInfo(&info);
gPageSize = info.dwPageSize;
#elif defined(AURORA_IS_POSIX_DERIVED)
gPageSize = getpagesize();
#else
gPageSize = 4096;
#endif
}
void InitRamInfo()
{
gMemStartup = GetMemStatSystem();
SetPageSize();
}
}