move os::linux calls out of cgroups

This commit is contained in:
Casper Norrbin 2026-01-13 10:45:17 +00:00
parent 8402891889
commit b635c7a7db
8 changed files with 37 additions and 33 deletions

View File

@ -28,7 +28,6 @@
#include "cgroupV2Subsystem_linux.hpp" #include "cgroupV2Subsystem_linux.hpp"
#include "logging/log.hpp" #include "logging/log.hpp"
#include "memory/allocation.hpp" #include "memory/allocation.hpp"
#include "os_linux.hpp"
#include "runtime/globals.hpp" #include "runtime/globals.hpp"
#include "runtime/os.hpp" #include "runtime/os.hpp"
#include "utilities/globalDefinitions.hpp" #include "utilities/globalDefinitions.hpp"
@ -605,6 +604,11 @@ void CgroupSubsystemFactory::cleanup(CgroupInfo* cg_infos) {
} }
} }
void CgroupSubsystem::adjust_controllers(physical_memory_size_type upper_mem_bound, int upper_cpu_bound) {
CgroupUtil::adjust_controller(memory_controller()->controller(), upper_mem_bound);
CgroupUtil::adjust_controller(cpu_controller()->controller(), upper_cpu_bound);
}
/* active_processor_count /* active_processor_count
* *
* Calculate an appropriate number of active processors for the * Calculate an appropriate number of active processors for the
@ -631,7 +635,7 @@ void CgroupSubsystemFactory::cleanup(CgroupInfo* cg_infos) {
* return: * return:
* true if there were no errors. false otherwise. * true if there were no errors. false otherwise.
*/ */
bool CgroupSubsystem::active_processor_count(int& value) { bool CgroupSubsystem::active_processor_count(int (*cpu_bound_func)(), int& value) {
int cpu_count; int cpu_count;
int result = -1; int result = -1;
@ -646,7 +650,7 @@ bool CgroupSubsystem::active_processor_count(int& value) {
return true; return true;
} }
cpu_count = os::Linux::active_processor_count(); cpu_count = cpu_bound_func();
if (!CgroupUtil::processor_count(contrl->controller(), cpu_count, result)) { if (!CgroupUtil::processor_count(contrl->controller(), cpu_count, result)) {
return false; return false;
} }

View File

@ -277,7 +277,7 @@ class CgroupMemoryController: public CHeapObj<mtInternal> {
class CgroupSubsystem: public CHeapObj<mtInternal> { class CgroupSubsystem: public CHeapObj<mtInternal> {
public: public:
bool memory_limit_in_bytes(physical_memory_size_type upper_bound, physical_memory_size_type& value); bool memory_limit_in_bytes(physical_memory_size_type upper_bound, physical_memory_size_type& value);
bool active_processor_count(int& value); bool active_processor_count(int (*cpu_bound_func)(), int& value);
virtual bool pids_max(uint64_t& value) = 0; virtual bool pids_max(uint64_t& value) = 0;
virtual bool pids_current(uint64_t& value) = 0; virtual bool pids_current(uint64_t& value) = 0;
@ -290,6 +290,8 @@ class CgroupSubsystem: public CHeapObj<mtInternal> {
virtual CachingCgroupController<CgroupCpuController>* cpu_controller() = 0; virtual CachingCgroupController<CgroupCpuController>* cpu_controller() = 0;
virtual CgroupCpuacctController* cpuacct_controller() = 0; virtual CgroupCpuacctController* cpuacct_controller() = 0;
void adjust_controllers(physical_memory_size_type upper_mem_bound, int upper_cpu_bound);
bool cpu_quota(int& value); bool cpu_quota(int& value);
bool cpu_period(int& value); bool cpu_period(int& value);
bool cpu_shares(int& value); bool cpu_shares(int& value);

View File

@ -23,7 +23,6 @@
*/ */
#include "cgroupUtil_linux.hpp" #include "cgroupUtil_linux.hpp"
#include "os_linux.hpp"
bool CgroupUtil::processor_count(CgroupCpuController* cpu_ctrl, int upper_bound, int& value) { bool CgroupUtil::processor_count(CgroupCpuController* cpu_ctrl, int upper_bound, int& value) {
assert(upper_bound > 0, "upper bound of cpus must be positive"); assert(upper_bound > 0, "upper bound of cpus must be positive");
@ -87,7 +86,7 @@ int CgroupUtil::get_updated_cpu_limit(CgroupCpuController* cpu,
return lowest; return lowest;
} }
void CgroupUtil::adjust_controller(CgroupMemoryController* mem) { void CgroupUtil::adjust_controller(CgroupMemoryController* mem, physical_memory_size_type upper_bound) {
assert(mem->cgroup_path() != nullptr, "invariant"); assert(mem->cgroup_path() != nullptr, "invariant");
if (strstr(mem->cgroup_path(), "../") != nullptr) { if (strstr(mem->cgroup_path(), "../") != nullptr) {
log_warning(os, container)("Cgroup memory controller path at '%s' seems to have moved " log_warning(os, container)("Cgroup memory controller path at '%s' seems to have moved "
@ -105,17 +104,16 @@ void CgroupUtil::adjust_controller(CgroupMemoryController* mem) {
char* cg_path = os::strdup(orig); char* cg_path = os::strdup(orig);
char* last_slash; char* last_slash;
assert(cg_path[0] == '/', "cgroup path must start with '/'"); assert(cg_path[0] == '/', "cgroup path must start with '/'");
physical_memory_size_type phys_mem = os::Linux::physical_memory();
char* limit_cg_path = nullptr; char* limit_cg_path = nullptr;
physical_memory_size_type limit = value_unlimited; physical_memory_size_type limit = value_unlimited;
physical_memory_size_type lowest_limit = phys_mem; physical_memory_size_type lowest_limit = upper_bound;
lowest_limit = get_updated_mem_limit(mem, lowest_limit, phys_mem); lowest_limit = get_updated_mem_limit(mem, lowest_limit, upper_bound);
physical_memory_size_type orig_limit = lowest_limit != phys_mem ? lowest_limit : phys_mem; physical_memory_size_type orig_limit = lowest_limit != upper_bound ? lowest_limit : upper_bound;
while ((last_slash = strrchr(cg_path, '/')) != cg_path) { while ((last_slash = strrchr(cg_path, '/')) != cg_path) {
*last_slash = '\0'; // strip path *last_slash = '\0'; // strip path
// update to shortened path and try again // update to shortened path and try again
mem->set_subsystem_path(cg_path); mem->set_subsystem_path(cg_path);
limit = get_updated_mem_limit(mem, lowest_limit, phys_mem); limit = get_updated_mem_limit(mem, lowest_limit, upper_bound);
if (limit < lowest_limit) { if (limit < lowest_limit) {
lowest_limit = limit; lowest_limit = limit;
os::free(limit_cg_path); // handles nullptr os::free(limit_cg_path); // handles nullptr
@ -124,13 +122,13 @@ void CgroupUtil::adjust_controller(CgroupMemoryController* mem) {
} }
// need to check limit at mount point // need to check limit at mount point
mem->set_subsystem_path("/"); mem->set_subsystem_path("/");
limit = get_updated_mem_limit(mem, lowest_limit, phys_mem); limit = get_updated_mem_limit(mem, lowest_limit, upper_bound);
if (limit < lowest_limit) { if (limit < lowest_limit) {
lowest_limit = limit; lowest_limit = limit;
os::free(limit_cg_path); // handles nullptr os::free(limit_cg_path); // handles nullptr
limit_cg_path = os::strdup("/"); limit_cg_path = os::strdup("/");
} }
assert(lowest_limit <= phys_mem, "limit must not exceed host memory"); assert(lowest_limit <= upper_bound, "limit must not exceed upper bound");
if (lowest_limit != orig_limit) { if (lowest_limit != orig_limit) {
// we've found a lower limit anywhere in the hierarchy, // we've found a lower limit anywhere in the hierarchy,
// set the path to the limit path // set the path to the limit path
@ -152,7 +150,7 @@ void CgroupUtil::adjust_controller(CgroupMemoryController* mem) {
os::free(limit_cg_path); os::free(limit_cg_path);
} }
void CgroupUtil::adjust_controller(CgroupCpuController* cpu) { void CgroupUtil::adjust_controller(CgroupCpuController* cpu, int upper_bound) {
assert(cpu->cgroup_path() != nullptr, "invariant"); assert(cpu->cgroup_path() != nullptr, "invariant");
if (strstr(cpu->cgroup_path(), "../") != nullptr) { if (strstr(cpu->cgroup_path(), "../") != nullptr) {
log_warning(os, container)("Cgroup cpu controller path at '%s' seems to have moved " log_warning(os, container)("Cgroup cpu controller path at '%s' seems to have moved "
@ -170,17 +168,16 @@ void CgroupUtil::adjust_controller(CgroupCpuController* cpu) {
char* cg_path = os::strdup(orig); char* cg_path = os::strdup(orig);
char* last_slash; char* last_slash;
assert(cg_path[0] == '/', "cgroup path must start with '/'"); assert(cg_path[0] == '/', "cgroup path must start with '/'");
int host_cpus = os::Linux::active_processor_count(); int lowest_limit = upper_bound;
int lowest_limit = host_cpus; int cpus = get_updated_cpu_limit(cpu, lowest_limit, upper_bound);
int cpus = get_updated_cpu_limit(cpu, lowest_limit, host_cpus); int orig_limit = lowest_limit != upper_bound ? lowest_limit : upper_bound;
int orig_limit = lowest_limit != host_cpus ? lowest_limit : host_cpus;
char* limit_cg_path = nullptr; char* limit_cg_path = nullptr;
while ((last_slash = strrchr(cg_path, '/')) != cg_path) { while ((last_slash = strrchr(cg_path, '/')) != cg_path) {
*last_slash = '\0'; // strip path *last_slash = '\0'; // strip path
// update to shortened path and try again // update to shortened path and try again
cpu->set_subsystem_path(cg_path); cpu->set_subsystem_path(cg_path);
cpus = get_updated_cpu_limit(cpu, lowest_limit, host_cpus); cpus = get_updated_cpu_limit(cpu, lowest_limit, upper_bound);
if (cpus != host_cpus && cpus < lowest_limit) { if (cpus != upper_bound && cpus < lowest_limit) {
lowest_limit = cpus; lowest_limit = cpus;
os::free(limit_cg_path); // handles nullptr os::free(limit_cg_path); // handles nullptr
limit_cg_path = os::strdup(cg_path); limit_cg_path = os::strdup(cg_path);
@ -188,8 +185,8 @@ void CgroupUtil::adjust_controller(CgroupCpuController* cpu) {
} }
// need to check limit at mount point // need to check limit at mount point
cpu->set_subsystem_path("/"); cpu->set_subsystem_path("/");
cpus = get_updated_cpu_limit(cpu, lowest_limit, host_cpus); cpus = get_updated_cpu_limit(cpu, lowest_limit, upper_bound);
if (cpus != host_cpus && cpus < lowest_limit) { if (cpus != upper_bound && cpus < lowest_limit) {
lowest_limit = cpus; lowest_limit = cpus;
os::free(limit_cg_path); // handles nullptr os::free(limit_cg_path); // handles nullptr
limit_cg_path = os::strdup(cg_path); limit_cg_path = os::strdup(cg_path);

View File

@ -34,10 +34,10 @@ class CgroupUtil: AllStatic {
static bool processor_count(CgroupCpuController* cpu, int upper_bound, int& value); static bool processor_count(CgroupCpuController* cpu, int upper_bound, int& value);
// Given a memory controller, adjust its path to a point in the hierarchy // Given a memory controller, adjust its path to a point in the hierarchy
// that represents the closest memory limit. // that represents the closest memory limit.
static void adjust_controller(CgroupMemoryController* m); static void adjust_controller(CgroupMemoryController* m, physical_memory_size_type upper_bound);
// Given a cpu controller, adjust its path to a point in the hierarchy // Given a cpu controller, adjust its path to a point in the hierarchy
// that represents the closest cpu limit. // that represents the closest cpu limit.
static void adjust_controller(CgroupCpuController* c); static void adjust_controller(CgroupCpuController* c, int upper_bound);
private: private:
static physical_memory_size_type get_updated_mem_limit(CgroupMemoryController* m, static physical_memory_size_type get_updated_mem_limit(CgroupMemoryController* m,
physical_memory_size_type lowest, physical_memory_size_type lowest,

View File

@ -326,8 +326,6 @@ CgroupV1Subsystem::CgroupV1Subsystem(CgroupV1Controller* cpuset,
_cpuset(cpuset), _cpuset(cpuset),
_cpuacct(cpuacct), _cpuacct(cpuacct),
_pids(pids) { _pids(pids) {
CgroupUtil::adjust_controller(memory);
CgroupUtil::adjust_controller(cpu);
_memory = new CachingCgroupController<CgroupMemoryController>(memory); _memory = new CachingCgroupController<CgroupMemoryController>(memory);
_cpu = new CachingCgroupController<CgroupCpuController>(cpu); _cpu = new CachingCgroupController<CgroupCpuController>(cpu);
} }

View File

@ -154,8 +154,6 @@ CgroupV2Subsystem::CgroupV2Subsystem(CgroupV2MemoryController * memory,
CgroupV2CpuacctController* cpuacct, CgroupV2CpuacctController* cpuacct,
CgroupV2Controller unified) : CgroupV2Controller unified) :
_unified(unified) { _unified(unified) {
CgroupUtil::adjust_controller(memory);
CgroupUtil::adjust_controller(cpu);
_memory = new CachingCgroupController<CgroupMemoryController>(memory); _memory = new CachingCgroupController<CgroupMemoryController>(memory);
_cpu = new CachingCgroupController<CgroupCpuController>(cpu); _cpu = new CachingCgroupController<CgroupCpuController>(cpu);
_cpuacct = cpuacct; _cpuacct = cpuacct;

View File

@ -59,6 +59,11 @@ void OSContainer::init() {
if (cgroup_subsystem == nullptr) { if (cgroup_subsystem == nullptr) {
return; // Required subsystem files not found or other error return; // Required subsystem files not found or other error
} }
// Adjust controller paths once subsystem is initialized
physical_memory_size_type phys_mem = os::Linux::physical_memory();
int host_cpus = os::Linux::active_processor_count();
cgroup_subsystem->adjust_controllers(phys_mem, host_cpus);
/* /*
* In order to avoid a false positive on is_containerized() on * In order to avoid a false positive on is_containerized() on
* Linux systems outside a container *and* to ensure compatibility * Linux systems outside a container *and* to ensure compatibility
@ -254,7 +259,7 @@ char * OSContainer::cpu_cpuset_memory_nodes() {
bool OSContainer::active_processor_count(int& value) { bool OSContainer::active_processor_count(int& value) {
assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); assert(cgroup_subsystem != nullptr, "cgroup subsystem not available");
return cgroup_subsystem->active_processor_count(value); return cgroup_subsystem->active_processor_count(&os::Linux::active_processor_count, value);
} }
bool OSContainer::cpu_quota(int& value) { bool OSContainer::cpu_quota(int& value) {

View File

@ -479,7 +479,7 @@ TEST(cgroupTest, set_cgroupv1_subsystem_path_adjusted) {
ccc->set_subsystem_path((char*)cpu.cgroup_path); ccc->set_subsystem_path((char*)cpu.cgroup_path);
EXPECT_TRUE(ccc->needs_hierarchy_adjustment()); EXPECT_TRUE(ccc->needs_hierarchy_adjustment());
CgroupUtil::adjust_controller(ccc); CgroupUtil::adjust_controller(ccc, 1);
ASSERT_STREQ(cpu.expected_path, ccc->subsystem_path()); ASSERT_STREQ(cpu.expected_path, ccc->subsystem_path());
EXPECT_FALSE(ccc->needs_hierarchy_adjustment()); EXPECT_FALSE(ccc->needs_hierarchy_adjustment());
@ -489,7 +489,7 @@ TEST(cgroupTest, set_cgroupv1_subsystem_path_adjusted) {
cmc->set_subsystem_path((char*)memory.cgroup_path); cmc->set_subsystem_path((char*)memory.cgroup_path);
EXPECT_TRUE(cmc->needs_hierarchy_adjustment()); EXPECT_TRUE(cmc->needs_hierarchy_adjustment());
CgroupUtil::adjust_controller(cmc); CgroupUtil::adjust_controller(cmc, (physical_memory_size_type)1024);
ASSERT_STREQ(memory.expected_path, cmc->subsystem_path()); ASSERT_STREQ(memory.expected_path, cmc->subsystem_path());
EXPECT_FALSE(cmc->needs_hierarchy_adjustment()); EXPECT_FALSE(cmc->needs_hierarchy_adjustment());
} }
@ -512,7 +512,7 @@ TEST(cgroupTest, set_cgroupv2_subsystem_path_adjusted) {
true /* read-only mount */)); true /* read-only mount */));
EXPECT_TRUE(ccc->needs_hierarchy_adjustment()); EXPECT_TRUE(ccc->needs_hierarchy_adjustment());
CgroupUtil::adjust_controller(ccc); CgroupUtil::adjust_controller(ccc, 1);
ASSERT_STREQ(cpu.expected_path, ccc->subsystem_path()); ASSERT_STREQ(cpu.expected_path, ccc->subsystem_path());
EXPECT_FALSE(ccc->needs_hierarchy_adjustment()); EXPECT_FALSE(ccc->needs_hierarchy_adjustment());
@ -521,7 +521,7 @@ TEST(cgroupTest, set_cgroupv2_subsystem_path_adjusted) {
true /* read-only mount */)); true /* read-only mount */));
EXPECT_TRUE(cmc->needs_hierarchy_adjustment()); EXPECT_TRUE(cmc->needs_hierarchy_adjustment());
CgroupUtil::adjust_controller(cmc); CgroupUtil::adjust_controller(cmc, (physical_memory_size_type)1024);
ASSERT_STREQ(memory.expected_path, cmc->subsystem_path()); ASSERT_STREQ(memory.expected_path, cmc->subsystem_path());
EXPECT_FALSE(cmc->needs_hierarchy_adjustment()); EXPECT_FALSE(cmc->needs_hierarchy_adjustment());
} }