2424#include < string>
2525#include < sys/mman.h>
2626#include < sys/statvfs.h>
27+ #if defined(__APPLE__)
28+ #include < mach/mach.h>
29+ #include < sys/sysctl.h>
30+ #elif defined(__linux__)
31+ #include < sys/sysinfo.h>
32+ #endif
2733#include < system_error>
2834#include < unordered_map>
2935#include < vector>
@@ -42,6 +48,71 @@ constexpr ATOM kMaxIntegerAtom = 0xBFFF;
4248constexpr ATOM kMinStringAtom = 0xC000 ;
4349constexpr ATOM kMaxStringAtom = 0xFFFF ;
4450
51+ SIZE_T clampToSizeT (uint64_t value) {
52+ constexpr uint64_t kMaxSizeT = static_cast <uint64_t >(std::numeric_limits<SIZE_T>::max ());
53+ return value > kMaxSizeT ? static_cast <SIZE_T>(kMaxSizeT ) : static_cast <SIZE_T>(value);
54+ }
55+
56+ struct MemorySnapshot {
57+ uint64_t totalPhys = 0 ;
58+ uint64_t availPhys = 0 ;
59+ uint64_t totalPageFile = 0 ;
60+ uint64_t availPageFile = 0 ;
61+ };
62+
63+ bool queryHostMemory (MemorySnapshot &out) {
64+ #if defined(__linux__)
65+ struct sysinfo info {};
66+ if (sysinfo (&info) != 0 ) {
67+ return false ;
68+ }
69+ const uint64_t unit = info.mem_unit ? static_cast <uint64_t >(info.mem_unit ) : 1 ;
70+ out.totalPhys = static_cast <uint64_t >(info.totalram ) * unit;
71+ out.availPhys = static_cast <uint64_t >(info.freeram ) * unit;
72+ out.totalPageFile = (static_cast <uint64_t >(info.totalram ) + static_cast <uint64_t >(info.totalswap )) * unit;
73+ out.availPageFile = (static_cast <uint64_t >(info.freeram ) + static_cast <uint64_t >(info.freeswap )) * unit;
74+ if (info.bufferram > 0 ) {
75+ uint64_t buffers = static_cast <uint64_t >(info.bufferram ) * unit;
76+ out.availPhys += buffers;
77+ out.availPageFile += buffers;
78+ }
79+ return true ;
80+ #elif defined(__APPLE__)
81+ uint64_t totalPhys = 0 ;
82+ size_t totalPhysSize = sizeof (totalPhys);
83+ if (sysctlbyname (" hw.memsize" , &totalPhys, &totalPhysSize, nullptr , 0 ) != 0 ) {
84+ return false ;
85+ }
86+ vm_size_t pageSize = 0 ;
87+ if (host_page_size (mach_host_self (), &pageSize) != KERN_SUCCESS || pageSize == 0 ) {
88+ return false ;
89+ }
90+ vm_statistics64_data_t vmstat {};
91+ mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
92+ if (host_statistics64 (mach_host_self (), HOST_VM_INFO64, reinterpret_cast <host_info64_t >(&vmstat), &count) !=
93+ KERN_SUCCESS) {
94+ return false ;
95+ }
96+ uint64_t freePages = static_cast <uint64_t >(vmstat.free_count ) + static_cast <uint64_t >(vmstat.inactive_count ) +
97+ static_cast <uint64_t >(vmstat.speculative_count );
98+ out.totalPhys = totalPhys;
99+ out.availPhys = freePages * static_cast <uint64_t >(pageSize);
100+
101+ struct xsw_usage swap {};
102+ size_t swapSize = sizeof (swap);
103+ if (sysctlbyname (" vm.swapusage" , &swap, &swapSize, nullptr , 0 ) == 0 && swapSize == sizeof (swap)) {
104+ out.totalPageFile = swap.xsu_total ;
105+ out.availPageFile = swap.xsu_avail ;
106+ } else {
107+ out.totalPageFile = totalPhys;
108+ out.availPageFile = out.availPhys ;
109+ }
110+ return true ;
111+ #else
112+ return false ;
113+ #endif
114+ }
115+
45116struct AtomData {
46117 uint16_t refCount = 0 ;
47118 std::string original;
@@ -780,6 +851,54 @@ UINT WINAPI GlobalFlags(HGLOBAL hMem) {
780851 return 0 ;
781852}
782853
854+ void WINAPI GlobalMemoryStatus (LPMEMORYSTATUS lpBuffer) {
855+ HOST_CONTEXT_GUARD ();
856+ DEBUG_LOG (" GlobalMemoryStatus(%p)\n " , lpBuffer);
857+ if (!lpBuffer) {
858+ return ;
859+ }
860+
861+ std::memset (lpBuffer, 0 , sizeof (*lpBuffer));
862+ lpBuffer->dwLength = sizeof (*lpBuffer);
863+
864+ MemorySnapshot snapshot;
865+ if (!queryHostMemory (snapshot)) {
866+ return ;
867+ }
868+
869+ uint64_t totalPhys = snapshot.totalPhys ;
870+ uint64_t availPhys = snapshot.availPhys ;
871+ uint64_t totalPageFile = snapshot.totalPageFile ;
872+ uint64_t availPageFile = snapshot.availPageFile ;
873+
874+ constexpr uint64_t kMinAppAddr = 0x00010000ULL ;
875+ constexpr uint64_t kMaxAppAddr = 0x7FFEFFFFULL ;
876+ uint64_t totalVirtual = kMaxAppAddr - kMinAppAddr + 1 ;
877+ uint64_t availVirtual = totalVirtual;
878+
879+ constexpr uint64_t kMaxLegacy = static_cast <uint64_t >(std::numeric_limits<LONG>::max ());
880+ totalPhys = std::min (totalPhys, kMaxLegacy );
881+ availPhys = std::min (availPhys, kMaxLegacy );
882+ totalVirtual = std::min (totalVirtual, kMaxLegacy );
883+ availVirtual = std::min (availVirtual, kMaxLegacy );
884+ availPhys = std::min (availPhys, totalPhys);
885+ availPageFile = std::min (availPageFile, totalPageFile);
886+ availVirtual = std::min (availVirtual, totalVirtual);
887+
888+ if (totalPhys > 0 ) {
889+ uint64_t used = totalPhys > availPhys ? totalPhys - availPhys : 0 ;
890+ uint64_t load = (used * 100 ) / totalPhys;
891+ lpBuffer->dwMemoryLoad = static_cast <DWORD>(std::min<uint64_t >(load, 100 ));
892+ }
893+
894+ lpBuffer->dwTotalPhys = clampToSizeT (totalPhys);
895+ lpBuffer->dwAvailPhys = clampToSizeT (availPhys);
896+ lpBuffer->dwTotalPageFile = clampToSizeT (totalPageFile);
897+ lpBuffer->dwAvailPageFile = clampToSizeT (availPageFile);
898+ lpBuffer->dwTotalVirtual = clampToSizeT (totalVirtual);
899+ lpBuffer->dwAvailVirtual = clampToSizeT (availVirtual);
900+ }
901+
783902HLOCAL WINAPI LocalAlloc (UINT uFlags, SIZE_T uBytes) {
784903 HOST_CONTEXT_GUARD ();
785904 VERBOSE_LOG (" LocalAlloc(%x, %zu)\n " , uFlags, static_cast <size_t >(uBytes));
0 commit comments