Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Commit

Permalink
fixes for standalone gc & more
Browse files Browse the repository at this point in the history
  • Loading branch information
rahul committed Mar 10, 2017
1 parent c2b59fe commit e766e7f
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 149 deletions.
120 changes: 69 additions & 51 deletions src/gc/unix/cgroup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,50 +11,64 @@ Module Name:
Abstract:
Read memory limits for the current process
--*/

#include <cstdint>
#include <cstddef>
#include <cassert>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
#include <errno.h>
#include "cgroup.h"

#define SIZE_T_MAX (~(size_t)0)
#define PROC_MOUNTINFO_FILENAME "/proc/self/mountinfo"
#define PROC_CGROUP_FILENAME "/proc/self/cgroup"
#define PROC_STATM_FILENAME "/proc/self/statm"
#define MEM_LIMIT_FILENAME "/memory.limit_in_bytes"
#define MEM_SWAP_LIMIT_FILENAME "/memory.memsw.limit_in_bytes"

CGroup::CGroup()
{
if(!findMemoryHierarchyMount(_memory_cgroup_path, MAX_PATH))
if(!FindMemoryHierarchyMount(m_memory_cgroup_path))
{
_memory_cgroup_path[0] = '\0';
m_memory_cgroup_path[0] = '\0';
return;
}
char cgroup_path_relative_to_mount[MAX_PATH];
if(!findCGroupPathForMemorySubsystem(cgroup_path_relative_to_mount, MAX_PATH))
if(!FindCGroupPathForMemorySubsystem(cgroup_path_relative_to_mount))
{
_memory_cgroup_path[0] = '\0';
m_memory_cgroup_path[0] = '\0';
return;
}
strcat_s(_memory_cgroup_path, MAX_PATH, cgroup_path_relative_to_mount);
strcat(m_memory_cgroup_path, cgroup_path_relative_to_mount);
}

bool CGroup::physicalMemoryLimit(size_t &val)
bool CGroup::GetPhysicalMemoryLimit(size_t *val)
{
char mem_limit_filename[MAX_PATH];

if(_memory_cgroup_path[0] == 0)
if(m_memory_cgroup_path[0] == 0)
return false;

strcpy_s(mem_limit_filename, MAX_PATH, _memory_cgroup_path);
strcat_s(mem_limit_filename, MAX_PATH, MEM_LIMIT_FILENAME);
return readMemoryValueFromFile(mem_limit_filename, val);
strcpy(mem_limit_filename, m_memory_cgroup_path);
strcat(mem_limit_filename, MEM_LIMIT_FILENAME);
return ReadMemoryValueFromFile(mem_limit_filename, val);
}

bool CGroup::swapMemoryLimit(size_t &val)
bool CGroup::GetSwapMemoryLimit(size_t *val)
{
char memsw_limit_filename[MAX_PATH];

if(_memory_cgroup_path[0] == 0)
if(m_memory_cgroup_path[0] == 0)
return false;

strcpy_s(memsw_limit_filename, MAX_PATH, _memory_cgroup_path);
strcat_s(memsw_limit_filename, MAX_PATH, MEM_SWAP_LIMIT_FILENAME);
return readMemoryValueFromFile(memsw_limit_filename, val);
strcpy(memsw_limit_filename, m_memory_cgroup_path);
strcat(memsw_limit_filename, MEM_SWAP_LIMIT_FILENAME);
return ReadMemoryValueFromFile(memsw_limit_filename, val);
}

bool CGroup::findMemoryHierarchyMount(char* mountpath, size_t mountpathsize)
bool CGroup::FindMemoryHierarchyMount(char* mountpath)
{
bool retval = false;
char *line = nullptr;
Expand All @@ -71,36 +85,36 @@ bool CGroup::findMemoryHierarchyMount(char* mountpath, size_t mountpathsize)
char* separatorChar = strchr(line, '-');

// See man page of proc to get format for /proc/self/mountinfo file
int sscanfRet = sscanf_s(separatorChar,
"- %s %*s %s",
filesystemType, (unsigned)_countof(filesystemType),
options, (unsigned)_countof(options));
int sscanfRet = sscanf(separatorChar,
"- %s %*s %s",
filesystemType,
options);
if (sscanfRet != 2)
{
_ASSERTE(!"Failed to parse mount info file contents with sscanf_s.");
assert(!"Failed to parse mount info file contents with sscanf.");
goto done;
}

if(strncmp(filesystemType, "cgroup", 6) == 0)
{
char* context = NULL;
char* strTok = strtok_s(options, ",", &context);
char* strTok = strtok_r(options, ",", &context);
while(strTok != NULL)
{
if(strncmp("memory", strTok, 6) == 0)
{
sscanfRet = sscanf_s(line,
"%*d %*d %*s %*s %s ",
mountpath, mountpathsize);
sscanfRet = sscanf(line,
"%*d %*d %*s %*s %s ",
mountpath);
if (sscanfRet != 1)
{
_ASSERTE(!"Failed to parse mount info file contents with sscanf_s.");
assert(!"Failed to parse mount info file contents with sscanf.");
goto done;
}
retval = true;
break;
}
strTok = strtok_s(NULL, ",", &context);
strTok = strtok_r(NULL, ",", &context);
}
}
}
Expand All @@ -112,7 +126,7 @@ bool CGroup::findMemoryHierarchyMount(char* mountpath, size_t mountpathsize)
return retval;
}

bool CGroup::findCGroupPathForMemorySubsystem(char* cgrouppath, size_t cgrouppathsize)
bool CGroup::FindCGroupPathForMemorySubsystem(char* cgrouppath)
{
bool retval = false;
char *line = nullptr;
Expand All @@ -127,27 +141,27 @@ bool CGroup::findCGroupPathForMemorySubsystem(char* cgrouppath, size_t cgrouppat
char cgroup_path[MAX_PATH];

// See man page of proc to get format for /proc/self/cgroup file
int sscanfRet = sscanf_s(line,
"%*[^:]:%[^:]:%s",
subsystem_list, (unsigned)_countof(subsystem_list),
cgroup_path, (unsigned)_countof(cgroup_path));
int sscanfRet = sscanf(line,
"%*[^:]:%[^:]:%s",
subsystem_list,
cgroup_path);
if (sscanfRet != 2)
{
_ASSERTE(!"Failed to parse cgroup info file contents with sscanf_s.");
assert(!"Failed to parse cgroup info file contents with sscanf.");
goto done;
}

char* context = NULL;
char* strTok = strtok_s(subsystem_list, ",", &context);
char* strTok = strtok_r(subsystem_list, ",", &context);
while(strTok != NULL)
{
if(strncmp("memory", strTok, 6) == 0)
{
strcpy_s(cgrouppath, cgrouppathsize, cgroup_path);
strcpy(cgrouppath, cgroup_path);
retval = true;
break;
}
strTok = strtok_s(NULL, ",", &context);
strTok = strtok_r(NULL, ",", &context);
}
}
done:
Expand All @@ -158,15 +172,19 @@ bool CGroup::findCGroupPathForMemorySubsystem(char* cgrouppath, size_t cgrouppat
return retval;
}

bool CGroup::readMemoryValueFromFile(const char* filename, size_t& val)
bool CGroup::ReadMemoryValueFromFile(const char* filename, size_t* val)
{
bool result = false;
char *line = nullptr;
size_t lineLen = 0;
char* endptr = NULL;
size_t num = 0, l, multiplier;
FILE* file = NULL;

FILE* file = fopen(filename, "r");
if(val == NULL)
goto done;

file = fopen(filename, "r");
if(file == NULL)
goto done;

Expand All @@ -184,14 +202,14 @@ bool CGroup::readMemoryValueFromFile(const char* filename, size_t& val)
case 'g':
case 'G': multiplier = 1024;
case 'm':
case 'M': multiplier = result*1024;
case 'M': multiplier = multiplier*1024;
case 'k':
case 'K': multiplier = result*1024;
case 'K': multiplier = multiplier*1024;
}

val = num * multiplier;
*val = num * multiplier;
result = true;
if(val/multiplier != num)
if(*val/multiplier != num)
result = false;
done:
if(file)
Expand All @@ -208,11 +226,11 @@ size_t GetRestrictedPhysicalMemoryLimit()
size_t physical_memory_limit;
size_t swap_memory_limit;

if(!cgroup.physicalMemoryLimit(physical_memory_limit))
physical_memory_limit = MAX_SIZE_T;
if(cgroup.swapMemoryLimit(swap_memory_limit))
if(!cgroup.GetPhysicalMemoryLimit(&physical_memory_limit))
physical_memory_limit = SIZE_T_MAX;
if(cgroup.GetSwapMemoryLimit(&swap_memory_limit))
{
_ASSERTE(swap_memory_limit >= physical_memory_limit);
assert(swap_memory_limit >= physical_memory_limit);
result = swap_memory_limit;
}
else
Expand All @@ -223,20 +241,20 @@ size_t GetRestrictedPhysicalMemoryLimit()
{
rlimit_soft_limit = curr_rlimit.rlim_cur;
}
result = min(result, rlimit_soft_limit);
result = (result < rlimit_soft_limit) ? result : rlimit_soft_limit;
return result;
}

BOOL GetWorkingSetSize(size_t* val)
bool GetWorkingSetSize(size_t* val)
{
BOOL result = false;
bool result = false;
size_t linelen;
char* line = NULL;

FILE* file = fopen(PROC_STATM_FILENAME, "r");
if(file != NULL && getline(&line, &linelen, file) != -1)
{
if(sscanf_s(line, "%*s %zu %*s %*s %*s %*s %*s", val) == 1)
if(sscanf(line, "%*s %zu %*s %*s %*s %*s %*s", val) == 1)
result = true;
}

Expand Down
21 changes: 8 additions & 13 deletions src/gc/unix/cgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,20 @@ Module Name:
Read memory limits for the current process
--*/

#define MAX_SIZE_T (~(SIZE_T)0)
#define PROC_MOUNTINFO_FILENAME "/proc/self/mountinfo"
#define PROC_CGROUP_FILENAME "/proc/self/cgroup"
#define PROC_STATM_FILENAME "/proc/self/statm"
#define MEM_LIMIT_FILENAME "/memory.limit_in_bytes"
#define MEM_SWAP_LIMIT_FILENAME "/memory.memsw.limit_in_bytes"
#define MAX_PATH 1024

class CGroup
{
char _memory_cgroup_path[MAX_PATH];
char m_memory_cgroup_path[MAX_PATH];
public:
CGroup();
bool physicalMemoryLimit(size_t &val);
bool swapMemoryLimit(size_t &val);
bool GetPhysicalMemoryLimit(size_t* val);
bool GetSwapMemoryLimit(size_t* val);
private:
bool findMemoryHierarchyMount(char* mountpath, size_t mountpathsize);
bool findCGroupPathForMemorySubsystem(char* cgrouppath, size_t cgrouppathsize);
bool readMemoryValueFromFile(const char* filename, size_t& val);
bool FindMemoryHierarchyMount(char* mountpath);
bool FindCGroupPathForMemorySubsystem(char* cgrouppath);
bool ReadMemoryValueFromFile(const char* filename, size_t* val);
};

size_t GetRestrictedPhysicalMemoryLimit();
BOOL GetWorkingSetSize(size_t* val);
bool GetWorkingSetSize(size_t* val);
8 changes: 4 additions & 4 deletions src/gc/unix/gcenv.unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,17 +79,17 @@ static uint8_t g_helperPage[OS_PAGE_SIZE] __attribute__((aligned(OS_PAGE_SIZE)))
// Mutex to make the FlushProcessWriteBuffersMutex thread safe
static pthread_mutex_t g_flushProcessWriteBuffersMutex;

static size_t g_RestrictedPhysicalMemoryLimit = (size_t)MAX_PTR;
static size_t g_RestrictedPhysicalMemoryLimit = 0;

static size_t GetRestrictedPhysicalMemoryLimit()
{
LIMITED_METHOD_CONTRACT;

// The limit was cached already
if (g_RestrictedPhysicalMemoryLimit != (size_t)MAX_PTR)
if (g_RestrictedPhysicalMemoryLimit != 0)
return g_RestrictedPhysicalMemoryLimit;

size_t memory_limit = PAL_GetRestrictedPhysicalMemoryLimit();
size_t memory_limit = GetRestrictedPhysicalMemoryLimit();

VolatileStore(&g_RestrictedPhysicalMemoryLimit, memory_limit);
return g_RestrictedPhysicalMemoryLimit;
Expand Down Expand Up @@ -460,7 +460,7 @@ size_t GCToOSInterface::GetVirtualMemoryLimit()
uint64_t GCToOSInterface::GetPhysicalMemoryLimit()
{
size_t restricted_limit = GetRestrictedPhysicalMemoryLimit();
if (restricted_limit != 0 && restricted_limit != (size_t)MAX_PTR)
if (restricted_limit != 0 && restricted_limit != SIZE_T_MAX)
return restricted_limit;

long pages = sysconf(_SC_PHYS_PAGES);
Expand Down
Loading

0 comments on commit e766e7f

Please sign in to comment.