#include <sys/resource.h>
#include <errno.h>
+#include "cgroup.h"
+
#ifndef SIZE_T_MAX
#define SIZE_T_MAX (~(size_t)0)
#endif
class CGroup
{
- char* m_memory_cgroup_path;
- char* m_cpu_cgroup_path;
+ static char* s_memory_cgroup_path;
+ static char* s_cpu_cgroup_path;
public:
- CGroup()
+ static void Initialize()
{
- m_memory_cgroup_path = FindCgroupPath(&IsMemorySubsystem);
- m_cpu_cgroup_path = FindCgroupPath(&IsCpuSubsystem);
+ s_memory_cgroup_path = FindCgroupPath(&IsMemorySubsystem);
+ s_cpu_cgroup_path = FindCgroupPath(&IsCpuSubsystem);
}
- ~CGroup()
+ static void Cleanup()
{
- free(m_memory_cgroup_path);
- free(m_cpu_cgroup_path);
+ free(s_memory_cgroup_path);
+ free(s_cpu_cgroup_path);
}
- bool GetPhysicalMemoryLimit(size_t *val)
+ static bool GetPhysicalMemoryLimit(size_t *val)
{
char *mem_limit_filename = nullptr;
bool result = false;
- if (m_memory_cgroup_path == nullptr)
+ if (s_memory_cgroup_path == nullptr)
return result;
- size_t len = strlen(m_memory_cgroup_path);
+ size_t len = strlen(s_memory_cgroup_path);
len += strlen(MEM_LIMIT_FILENAME);
mem_limit_filename = (char*)malloc(len+1);
if (mem_limit_filename == nullptr)
return result;
- strcpy(mem_limit_filename, m_memory_cgroup_path);
+ strcpy(mem_limit_filename, s_memory_cgroup_path);
strcat(mem_limit_filename, MEM_LIMIT_FILENAME);
result = ReadMemoryValueFromFile(mem_limit_filename, val);
free(mem_limit_filename);
return result;
}
- bool GetPhysicalMemoryUsage(size_t *val)
+ static bool GetPhysicalMemoryUsage(size_t *val)
{
char *mem_usage_filename = nullptr;
bool result = false;
- if (m_memory_cgroup_path == nullptr)
+ if (s_memory_cgroup_path == nullptr)
return result;
- size_t len = strlen(m_memory_cgroup_path);
+ size_t len = strlen(s_memory_cgroup_path);
len += strlen(MEM_USAGE_FILENAME);
mem_usage_filename = (char*)malloc(len+1);
if (mem_usage_filename == nullptr)
return result;
- strcpy(mem_usage_filename, m_memory_cgroup_path);
+ strcpy(mem_usage_filename, s_memory_cgroup_path);
strcat(mem_usage_filename, MEM_USAGE_FILENAME);
result = ReadMemoryValueFromFile(mem_usage_filename, val);
free(mem_usage_filename);
return result;
}
- bool GetCpuLimit(uint32_t *val)
+ static bool GetCpuLimit(uint32_t *val)
{
long long quota;
long long period;
return cgroup_path;
}
- bool ReadMemoryValueFromFile(const char* filename, size_t* val)
+ static bool ReadMemoryValueFromFile(const char* filename, size_t* val)
{
bool result = false;
char *line = nullptr;
return result;
}
- long long ReadCpuCGroupValue(const char* subsystemFilename){
+ static long long ReadCpuCGroupValue(const char* subsystemFilename){
char *filename = nullptr;
bool result = false;
long long val;
- if (m_cpu_cgroup_path == nullptr)
+ if (s_cpu_cgroup_path == nullptr)
return -1;
- filename = (char*)malloc(strlen(m_cpu_cgroup_path) + strlen(subsystemFilename) + 1);
+ filename = (char*)malloc(strlen(s_cpu_cgroup_path) + strlen(subsystemFilename) + 1);
if (filename == nullptr)
return -1;
- strcpy(filename, m_cpu_cgroup_path);
+ strcpy(filename, s_cpu_cgroup_path);
strcat(filename, subsystemFilename);
result = ReadLongLongValueFromFile(filename, &val);
free(filename);
return val;
}
- bool ReadLongLongValueFromFile(const char* filename, long long* val)
+ static bool ReadLongLongValueFromFile(const char* filename, long long* val)
{
bool result = false;
char *line = nullptr;
}
};
+char *CGroup::s_memory_cgroup_path = nullptr;
+char *CGroup::s_cpu_cgroup_path = nullptr;
+
+void InitializeCGroup()
+{
+ CGroup::Initialize();
+}
+
+void CleanupCGroup()
+{
+ CGroup::Cleanup();
+}
+
size_t GetRestrictedPhysicalMemoryLimit()
{
- CGroup cgroup;
size_t physical_memory_limit;
- if (!cgroup.GetPhysicalMemoryLimit(&physical_memory_limit))
+ if (!CGroup::GetPhysicalMemoryLimit(&physical_memory_limit))
physical_memory_limit = SIZE_T_MAX;
struct rlimit curr_rlimit;
bool result = false;
size_t linelen;
char* line = nullptr;
- CGroup cgroup;
if (val == nullptr)
return false;
// Linux uses cgroup usage to trigger oom kills.
- if (cgroup.GetPhysicalMemoryUsage(val))
+ if (CGroup::GetPhysicalMemoryUsage(val))
return true;
// process resident set size.
bool GetCpuLimit(uint32_t* val)
{
- CGroup cgroup;
-
if (val == nullptr)
return false;
- return cgroup.GetCpuLimit(val);
+ return CGroup::GetCpuLimit(val);
}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+#ifndef __CGROUP_H__
+#define __CGROUP_H__
+
+void InitializeCGroup();
+void CleanupCGroup();
+
+#endif // __CGROUP_H__
+
#include <errno.h>
#include <unistd.h> // sysconf
#include "globals.h"
+#include "cgroup.h"
#if defined(_ARM_) || defined(_ARM64_)
#define SYSCONF_GET_NUMPROCS _SC_NPROCESSORS_CONF
}
#endif // HAVE_MACH_ABSOLUTE_TIME
+ InitializeCGroup();
+
return true;
}
assert(ret == 0);
munmap(g_helperPage, OS_PAGE_SIZE);
+
+ CleanupCGroup();
}
// Get numeric id of the current thread if possible on the
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*++
+
+
+
+Module Name:
+
+ include/pal/cgroup.h
+
+Abstract:
+
+ Header file for the CGroup related functions.
+
+
+
+--*/
+
+#ifndef _PAL_CGROUP_H_
+#define _PAL_CGROUP_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+void InitializeCGroup();
+void CleanupCGroup();
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* _PAL_CGROUP_H_ */
+
#include "pal/init.h"
#include "pal/numa.h"
#include "pal/stackstring.hpp"
+#include "pal/cgroup.h"
#if HAVE_MACH_EXCEPTIONS
#include "../exception/machexception.h"
goto done;
}
+ InitializeCGroup();
+
// Initialize the environment.
if (FALSE == EnvironInitialize())
{
CLEANUP1:
SHMCleanup();
CLEANUP0:
+ CleanupCGroup();
TLSCleanup();
ERROR("PAL_Initialize failed\n");
SetLastError(palError);
#include "pal/palinternal.h"
#include <sys/resource.h>
#include "pal/virtual.h"
+#include "pal/cgroup.h"
#include <algorithm>
#define PROC_MOUNTINFO_FILENAME "/proc/self/mountinfo"
#define CFS_PERIOD_FILENAME "/cpu.cfs_period_us"
class CGroup
{
- char *m_memory_cgroup_path;
- char *m_cpu_cgroup_path;
+ static char *s_memory_cgroup_path;
+ static char *s_cpu_cgroup_path;
public:
- CGroup()
+ static void Initialize()
{
- m_memory_cgroup_path = FindCgroupPath(&IsMemorySubsystem);
- m_cpu_cgroup_path = FindCgroupPath(&IsCpuSubsystem);
+ s_memory_cgroup_path = FindCgroupPath(&IsMemorySubsystem);
+ s_cpu_cgroup_path = FindCgroupPath(&IsCpuSubsystem);
}
- ~CGroup()
+ static void Cleanup()
{
- PAL_free(m_memory_cgroup_path);
- PAL_free(m_cpu_cgroup_path);
+ PAL_free(s_memory_cgroup_path);
+ PAL_free(s_cpu_cgroup_path);
}
- bool GetPhysicalMemoryLimit(size_t *val)
+ static bool GetPhysicalMemoryLimit(size_t *val)
{
char *mem_limit_filename = nullptr;
bool result = false;
- if (m_memory_cgroup_path == nullptr)
+ if (s_memory_cgroup_path == nullptr)
return result;
- size_t len = strlen(m_memory_cgroup_path);
+ size_t len = strlen(s_memory_cgroup_path);
len += strlen(MEM_LIMIT_FILENAME);
mem_limit_filename = (char*)PAL_malloc(len+1);
if (mem_limit_filename == nullptr)
return result;
- strcpy_s(mem_limit_filename, len+1, m_memory_cgroup_path);
+ strcpy_s(mem_limit_filename, len+1, s_memory_cgroup_path);
strcat_s(mem_limit_filename, len+1, MEM_LIMIT_FILENAME);
result = ReadMemoryValueFromFile(mem_limit_filename, val);
PAL_free(mem_limit_filename);
return result;
}
- bool GetPhysicalMemoryUsage(size_t *val)
+ static bool GetPhysicalMemoryUsage(size_t *val)
{
char *mem_usage_filename = nullptr;
bool result = false;
- if (m_memory_cgroup_path == nullptr)
+ if (s_memory_cgroup_path == nullptr)
return result;
- size_t len = strlen(m_memory_cgroup_path);
+ size_t len = strlen(s_memory_cgroup_path);
len += strlen(MEM_USAGE_FILENAME);
mem_usage_filename = (char*)malloc(len+1);
if (mem_usage_filename == nullptr)
return result;
- strcpy(mem_usage_filename, m_memory_cgroup_path);
+ strcpy(mem_usage_filename, s_memory_cgroup_path);
strcat(mem_usage_filename, MEM_USAGE_FILENAME);
result = ReadMemoryValueFromFile(mem_usage_filename, val);
free(mem_usage_filename);
return result;
}
- bool GetCpuLimit(UINT *val)
+ static bool GetCpuLimit(UINT *val)
{
long long quota;
long long period;
return cgroup_path;
}
- bool ReadMemoryValueFromFile(const char* filename, size_t* val)
+ static bool ReadMemoryValueFromFile(const char* filename, size_t* val)
{
return ::ReadMemoryValueFromFile(filename, val);
}
- long long ReadCpuCGroupValue(const char* subsystemFilename){
+ static long long ReadCpuCGroupValue(const char* subsystemFilename){
char *filename = nullptr;
bool result = false;
long long val;
size_t len;
- if (m_cpu_cgroup_path == nullptr)
+ if (s_cpu_cgroup_path == nullptr)
return -1;
- len = strlen(m_cpu_cgroup_path);
+ len = strlen(s_cpu_cgroup_path);
len += strlen(subsystemFilename);
filename = (char*)PAL_malloc(len + 1);
if (filename == nullptr)
return -1;
- strcpy_s(filename, len+1, m_cpu_cgroup_path);
+ strcpy_s(filename, len+1, s_cpu_cgroup_path);
strcat_s(filename, len+1, subsystemFilename);
result = ReadLongLongValueFromFile(filename, &val);
PAL_free(filename);
return val;
}
- bool ReadLongLongValueFromFile(const char* filename, long long* val)
+ static bool ReadLongLongValueFromFile(const char* filename, long long* val)
{
bool result = false;
char *line = nullptr;
}
};
+char *CGroup::s_memory_cgroup_path = nullptr;
+char *CGroup::s_cpu_cgroup_path = nullptr;
+
+void InitializeCGroup()
+{
+ CGroup::Initialize();
+}
+
+void CleanupCGroup()
+{
+ CGroup::Cleanup();
+}
+
size_t
PALAPI
PAL_GetRestrictedPhysicalMemoryLimit()
{
- CGroup cgroup;
size_t physical_memory_limit;
- if (!cgroup.GetPhysicalMemoryLimit(&physical_memory_limit))
+ if (!CGroup::GetPhysicalMemoryLimit(&physical_memory_limit))
physical_memory_limit = SIZE_T_MAX;
struct rlimit curr_rlimit;
BOOL result = false;
size_t linelen;
char* line = nullptr;
- CGroup cgroup;
if (val == nullptr)
return FALSE;
// Linux uses cgroup usage to trigger oom kills.
- if (cgroup.GetPhysicalMemoryUsage(val))
+ if (CGroup::GetPhysicalMemoryUsage(val))
return TRUE;
// process resident set size.
PALAPI
PAL_GetCpuLimit(UINT* val)
{
- CGroup cgroup;
-
if (val == nullptr)
return FALSE;
- return cgroup.GetCpuLimit(val);
+ return CGroup::GetCpuLimit(val);
}