Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix computing available memory on OSX for GC #97102

Merged
merged 2 commits into from
Jan 25, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 65 additions & 41 deletions src/coreclr/gc/unix/gcenv.unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,13 @@ AffinitySet g_processAffinitySet;
extern "C" int g_highestNumaNode;
extern "C" bool g_numaAvailable;

static int64_t g_totalPhysicalMemSize = 0;

#ifdef TARGET_APPLE
static int *g_kern_memorystatus_level_mib = NULL;
static size_t g_kern_memorystatus_level_mib_length = 0;
#endif

// Initialize the interface implementation
// Return:
// true if it has succeeded, false if it has failed
Expand Down Expand Up @@ -317,6 +324,55 @@ bool GCToOSInterface::Initialize()

NUMASupportInitialize();

#ifdef TARGET_APPLE
const char* mem_free_name = "kern.memorystatus_level";
int rc = sysctlnametomib(mem_free_name, NULL, &g_kern_memorystatus_level_mib_length);
if (rc != 0)
{
return false;
}

g_kern_memorystatus_level_mib = (int*)malloc(g_kern_memorystatus_level_mib_length * sizeof(int));
if (g_kern_memorystatus_level_mib == NULL)
{
return false;
}

rc = sysctlnametomib(mem_free_name, g_kern_memorystatus_level_mib, &g_kern_memorystatus_level_mib_length);
if (rc != 0)
{
free(g_kern_memorystatus_level_mib);
g_kern_memorystatus_level_mib = NULL;
g_kern_memorystatus_level_mib_length = 0;
return false;
}
#endif

// Get the physical memory size
#if HAVE_SYSCONF && HAVE__SC_PHYS_PAGES
long pages = sysconf(_SC_PHYS_PAGES);
if (pages == -1)
{
return false;
}

g_totalPhysicalMemSize = (uint64_t)pages * (uint64_t)g_pageSizeUnixInl;
#elif HAVE_SYSCTL
int mib[2];
mib[0] = CTL_HW;
mib[1] = HW_MEMSIZE;
size_t length = sizeof(INT64);
int rc = sysctl(mib, 2, &g_totalPhysicalMemSize, &length, NULL, 0);
if (rc == 0)
{
return false;
}
#else // HAVE_SYSCTL
#error "Don't know how to get total physical memory on this platform"
#endif // HAVE_SYSCTL

assert(g_totalPhysicalMemSize != 0);

return true;
}

Expand Down Expand Up @@ -1211,34 +1267,7 @@ uint64_t GCToOSInterface::GetPhysicalMemoryLimit(bool* is_restricted)
return restricted_limit;
}

// Get the physical memory size
#if HAVE_SYSCONF && HAVE__SC_PHYS_PAGES
long pages = sysconf(_SC_PHYS_PAGES);
if (pages == -1)
{
return 0;
}

long pageSize = sysconf(_SC_PAGE_SIZE);
if (pageSize == -1)
{
return 0;
}

return (uint64_t)pages * (uint64_t)pageSize;
#elif HAVE_SYSCTL
int mib[3];
mib[0] = CTL_HW;
mib[1] = HW_MEMSIZE;
int64_t physical_memory = 0;
size_t length = sizeof(INT64);
int rc = sysctl(mib, 2, &physical_memory, &length, NULL, 0);
assert(rc == 0);

return physical_memory;
#else // HAVE_SYSCTL
#error "Don't know how to get total physical memory on this platform"
#endif // HAVE_SYSCTL
return g_totalPhysicalMemSize;
}

// Get amount of physical memory available for use in the system
Expand All @@ -1248,20 +1277,15 @@ uint64_t GetAvailablePhysicalMemory()

// Get the physical memory available.
#if defined(__APPLE__)
vm_size_t page_size;
mach_port_t mach_port;
mach_msg_type_number_t count;
vm_statistics_data_t vm_stats;
mach_port = mach_host_self();
count = sizeof(vm_stats) / sizeof(natural_t);
if (KERN_SUCCESS == host_page_size(mach_port, &page_size))
uint32_t mem_free = 0;
size_t mem_free_length = sizeof(uint32_t);
assert(g_kern_memorystatus_level_mib != NULL);
int rc = sysctl(g_kern_memorystatus_level_mib, g_kern_memorystatus_level_mib_length, &mem_free, &mem_free_length, NULL, 0);
assert(rc == 0);
if (rc == 0)
{
if (KERN_SUCCESS == host_statistics(mach_port, HOST_VM_INFO, (host_info_t)&vm_stats, &count))
{
available = (int64_t)vm_stats.free_count * (int64_t)page_size;
}
available = (int64_t)mem_free * g_totalPhysicalMemSize / 100;
}
mach_port_deallocate(mach_task_self(), mach_port);
#elif defined(__FreeBSD__)
size_t inactive_count = 0, laundry_count = 0, free_count = 0;
size_t sz = sizeof(inactive_count);
Expand All @@ -1279,7 +1303,7 @@ uint64_t GetAvailablePhysicalMemory()

if (tryReadMemInfo)
{
// Ensure that we don't try to read the /proc/meminfo in successive calls to the GlobalMemoryStatusEx
// Ensure that we don't try to read the /proc/meminfo in successive calls to the GetAvailablePhysicalMemory
// if we have failed to access the file or the file didn't contain the MemAvailable value.
tryReadMemInfo = ReadMemAvailable(&available);
}
Expand Down
Loading