/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuRamInfo.cpp Date: 2021-6-12 Author: Reece ***/ #include #include "AuHWInfo.hpp" #include "AuRamInfo.hpp" #if defined(AURORA_IS_BSD_DERIVED) #include #include #include #include #endif #if defined(AURORA_IS_LINUX_DERIVED) #include #include #endif #if defined(AURORA_IS_MODERNNT_DERIVED) #include #include #endif namespace Aurora::HWInfo { static AuOptional gMemStartup; AUKN_SYM AuOptional 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(&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(&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 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(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(&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 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(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 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(cmd); auto vmInfo = GetVMInfo(); auto freeMem = AuUInt64(vmInfo.t_free) * AuUInt64(QueryBsdHwStat(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 GetMemStatStartup() { return gMemStartup; } AUKN_SYM AuUInt32 GetPageSize() { return gPageSize; } AUKN_SYM AuOptional GetSwapSize() { static AuOptional 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 GetPhysicalSize() { static AuOptional 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(); } }