From 5252262349cccb09f693ebd431fe2987ec0917f0 Mon Sep 17 00:00:00 2001 From: Casper Norrbin Date: Thu, 2 Oct 2025 13:38:41 +0000 Subject: [PATCH] 8292984: Refactor internal container-related interfaces for clarity Reviewed-by: sgehwolf, eosterlund --- .../os/linux/cgroupSubsystem_linux.cpp | 28 ++++------- .../os/linux/cgroupSubsystem_linux.hpp | 16 +++---- .../os/linux/cgroupV1Subsystem_linux.cpp | 46 +++++++++---------- .../os/linux/cgroupV1Subsystem_linux.hpp | 10 ++-- .../os/linux/cgroupV2Subsystem_linux.cpp | 24 +++++----- .../os/linux/cgroupV2Subsystem_linux.hpp | 6 +-- src/hotspot/os/linux/osContainer_linux.cpp | 38 ++++++++++++--- src/hotspot/os/linux/osContainer_linux.hpp | 1 + src/hotspot/os/linux/os_linux.cpp | 44 +++++++----------- 9 files changed, 109 insertions(+), 104 deletions(-) diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp index f935e2cbb9c..f5c4abeb4ca 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp @@ -665,15 +665,13 @@ int CgroupSubsystem::active_processor_count() { * -1 for unlimited * OSCONTAINER_ERROR for not supported */ -jlong CgroupSubsystem::memory_limit_in_bytes() { +jlong CgroupSubsystem::memory_limit_in_bytes(julong upper_bound) { CachingCgroupController* contrl = memory_controller(); CachedMetric* memory_limit = contrl->metrics_cache(); if (!memory_limit->should_check_metric()) { return memory_limit->value(); } - julong phys_mem = static_cast(os::Linux::physical_memory()); - log_trace(os, container)("total physical memory: " JULONG_FORMAT, phys_mem); - jlong mem_limit = contrl->controller()->read_memory_limit_in_bytes(phys_mem); + jlong mem_limit = contrl->controller()->read_memory_limit_in_bytes(upper_bound); // Update cached metric to avoid re-reading container settings too often memory_limit->set_value(mem_limit, OSCONTAINER_CACHE_TIMEOUT); return mem_limit; @@ -841,21 +839,16 @@ jlong CgroupController::limit_from_str(char* limit_str) { // CgroupSubsystem implementations -jlong CgroupSubsystem::memory_and_swap_limit_in_bytes() { - julong phys_mem = static_cast(os::Linux::physical_memory()); - julong host_swap = os::Linux::host_swap(); - return memory_controller()->controller()->memory_and_swap_limit_in_bytes(phys_mem, host_swap); +jlong CgroupSubsystem::memory_and_swap_limit_in_bytes(julong upper_mem_bound, julong upper_swap_bound) { + return memory_controller()->controller()->memory_and_swap_limit_in_bytes(upper_mem_bound, upper_swap_bound); } -jlong CgroupSubsystem::memory_and_swap_usage_in_bytes() { - julong phys_mem = static_cast(os::Linux::physical_memory()); - julong host_swap = os::Linux::host_swap(); - return memory_controller()->controller()->memory_and_swap_usage_in_bytes(phys_mem, host_swap); +jlong CgroupSubsystem::memory_and_swap_usage_in_bytes(julong upper_mem_bound, julong upper_swap_bound) { + return memory_controller()->controller()->memory_and_swap_usage_in_bytes(upper_mem_bound, upper_swap_bound); } -jlong CgroupSubsystem::memory_soft_limit_in_bytes() { - julong phys_mem = static_cast(os::Linux::physical_memory()); - return memory_controller()->controller()->memory_soft_limit_in_bytes(phys_mem); +jlong CgroupSubsystem::memory_soft_limit_in_bytes(julong upper_bound) { + return memory_controller()->controller()->memory_soft_limit_in_bytes(upper_bound); } jlong CgroupSubsystem::memory_throttle_limit_in_bytes() { @@ -894,7 +887,6 @@ jlong CgroupSubsystem::cpu_usage_in_micros() { return cpuacct_controller()->cpu_usage_in_micros(); } -void CgroupSubsystem::print_version_specific_info(outputStream* st) { - julong phys_mem = static_cast(os::Linux::physical_memory()); - memory_controller()->controller()->print_version_specific_info(st, phys_mem); +void CgroupSubsystem::print_version_specific_info(outputStream* st, julong upper_mem_bound) { + memory_controller()->controller()->print_version_specific_info(st, upper_mem_bound); } diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp index 22e57d56c93..62a61432665 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp @@ -233,14 +233,14 @@ class CgroupMemoryController: public CHeapObj { public: virtual jlong read_memory_limit_in_bytes(julong upper_bound) = 0; virtual jlong memory_usage_in_bytes() = 0; - virtual jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) = 0; - virtual jlong memory_and_swap_usage_in_bytes(julong host_mem, julong host_swap) = 0; + virtual jlong memory_and_swap_limit_in_bytes(julong upper_mem_bound, julong upper_swap_bound) = 0; + virtual jlong memory_and_swap_usage_in_bytes(julong upper_mem_bound, julong upper_swap_bound) = 0; virtual jlong memory_soft_limit_in_bytes(julong upper_bound) = 0; virtual jlong memory_throttle_limit_in_bytes() = 0; virtual jlong memory_max_usage_in_bytes() = 0; virtual jlong rss_usage_in_bytes() = 0; virtual jlong cache_usage_in_bytes() = 0; - virtual void print_version_specific_info(outputStream* st, julong host_mem) = 0; + virtual void print_version_specific_info(outputStream* st, julong upper_mem_bound) = 0; virtual bool needs_hierarchy_adjustment() = 0; virtual bool is_read_only() = 0; virtual const char* subsystem_path() = 0; @@ -251,7 +251,7 @@ class CgroupMemoryController: public CHeapObj { class CgroupSubsystem: public CHeapObj { public: - jlong memory_limit_in_bytes(); + jlong memory_limit_in_bytes(julong upper_bound); int active_processor_count(); virtual jlong pids_max() = 0; @@ -272,14 +272,14 @@ class CgroupSubsystem: public CHeapObj { jlong cpu_usage_in_micros(); jlong memory_usage_in_bytes(); - jlong memory_and_swap_limit_in_bytes(); - jlong memory_and_swap_usage_in_bytes(); - jlong memory_soft_limit_in_bytes(); + jlong memory_and_swap_limit_in_bytes(julong upper_mem_bound, julong upper_swap_bound); + jlong memory_and_swap_usage_in_bytes(julong upper_mem_bound, julong upper_swap_bound); + jlong memory_soft_limit_in_bytes(julong upper_bound); jlong memory_throttle_limit_in_bytes(); jlong memory_max_usage_in_bytes(); jlong rss_usage_in_bytes(); jlong cache_usage_in_bytes(); - void print_version_specific_info(outputStream* st); + void print_version_specific_info(outputStream* st, julong upper_mem_bound); }; // Utility class for storing info retrieved from /proc/cgroups, diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp index 64cb53eda28..90f01565b84 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp @@ -136,35 +136,35 @@ bool CgroupV1Controller::needs_hierarchy_adjustment() { } static inline -void verbose_log(julong read_mem_limit, julong host_mem) { +void verbose_log(julong read_mem_limit, julong upper_mem_bound) { if (log_is_enabled(Debug, os, container)) { jlong mem_limit = (jlong)read_mem_limit; // account for negative values - if (mem_limit < 0 || read_mem_limit >= host_mem) { + if (mem_limit < 0 || read_mem_limit >= upper_mem_bound) { const char *reason; if (mem_limit == OSCONTAINER_ERROR) { reason = "failed"; } else if (mem_limit == -1) { reason = "unlimited"; } else { - assert(read_mem_limit >= host_mem, "Expected read value exceeding host_mem"); + assert(read_mem_limit >= upper_mem_bound, "Expected read value exceeding upper memory bound"); // Exceeding physical memory is treated as unlimited. This implementation // caps it at host_mem since Cg v1 has no value to represent 'max'. reason = "ignored"; } - log_debug(os, container)("container memory limit %s: " JLONG_FORMAT ", using host value " JLONG_FORMAT, - reason, mem_limit, host_mem); + log_debug(os, container)("container memory limit %s: " JLONG_FORMAT ", upper bound is " JLONG_FORMAT, + reason, mem_limit, upper_mem_bound); } } } -jlong CgroupV1MemoryController::read_memory_limit_in_bytes(julong phys_mem) { +jlong CgroupV1MemoryController::read_memory_limit_in_bytes(julong upper_bound) { julong memlimit; CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.limit_in_bytes", "Memory Limit", memlimit); - if (memlimit >= phys_mem) { - verbose_log(memlimit, phys_mem); + if (memlimit >= upper_bound) { + verbose_log(memlimit, upper_bound); return (jlong)-1; } else { - verbose_log(memlimit, phys_mem); + verbose_log(memlimit, upper_bound); return (jlong)memlimit; } } @@ -181,10 +181,10 @@ jlong CgroupV1MemoryController::read_memory_limit_in_bytes(julong phys_mem) { * * -1 if there isn't any limit in place (note: includes values which exceed a physical * upper bound) */ -jlong CgroupV1MemoryController::read_mem_swap(julong host_total_memsw) { +jlong CgroupV1MemoryController::read_mem_swap(julong upper_memsw_bound) { julong memswlimit; CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.memsw.limit_in_bytes", "Memory and Swap Limit", memswlimit); - if (memswlimit >= host_total_memsw) { + if (memswlimit >= upper_memsw_bound) { log_trace(os, container)("Memory and Swap Limit is: Unlimited"); return (jlong)-1; } else { @@ -192,8 +192,8 @@ jlong CgroupV1MemoryController::read_mem_swap(julong host_total_memsw) { } } -jlong CgroupV1MemoryController::memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) { - jlong memory_swap = read_mem_swap(host_mem + host_swap); +jlong CgroupV1MemoryController::memory_and_swap_limit_in_bytes(julong upper_mem_bound, julong upper_swap_bound) { + jlong memory_swap = read_mem_swap(upper_mem_bound + upper_swap_bound); if (memory_swap == -1) { return memory_swap; } @@ -202,7 +202,7 @@ jlong CgroupV1MemoryController::memory_and_swap_limit_in_bytes(julong host_mem, // supported. jlong swappiness = read_mem_swappiness(); if (swappiness == 0 || memory_swap == OSCONTAINER_ERROR) { - jlong memlimit = read_memory_limit_in_bytes(host_mem); + jlong memlimit = read_memory_limit_in_bytes(upper_mem_bound); if (memory_swap == OSCONTAINER_ERROR) { log_trace(os, container)("Memory and Swap Limit has been reset to " JLONG_FORMAT " because swap is not supported", memlimit); } else { @@ -220,9 +220,9 @@ jlong memory_swap_usage_impl(CgroupController* ctrl) { return (jlong)memory_swap_usage; } -jlong CgroupV1MemoryController::memory_and_swap_usage_in_bytes(julong phys_mem, julong host_swap) { - jlong memory_sw_limit = memory_and_swap_limit_in_bytes(phys_mem, host_swap); - jlong memory_limit = read_memory_limit_in_bytes(phys_mem); +jlong CgroupV1MemoryController::memory_and_swap_usage_in_bytes(julong upper_mem_bound, julong upper_swap_bound) { + jlong memory_sw_limit = memory_and_swap_limit_in_bytes(upper_mem_bound, upper_swap_bound); + jlong memory_limit = read_memory_limit_in_bytes(upper_mem_bound); if (memory_sw_limit > 0 && memory_limit > 0) { jlong delta_swap = memory_sw_limit - memory_limit; if (delta_swap > 0) { @@ -238,10 +238,10 @@ jlong CgroupV1MemoryController::read_mem_swappiness() { return (jlong)swappiness; } -jlong CgroupV1MemoryController::memory_soft_limit_in_bytes(julong phys_mem) { +jlong CgroupV1MemoryController::memory_soft_limit_in_bytes(julong upper_bound) { julong memsoftlimit; CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.soft_limit_in_bytes", "Memory Soft Limit", memsoftlimit); - if (memsoftlimit >= phys_mem) { + if (memsoftlimit >= upper_bound) { log_trace(os, container)("Memory Soft Limit is: Unlimited"); return (jlong)-1; } else { @@ -336,10 +336,10 @@ jlong CgroupV1MemoryController::kernel_memory_usage_in_bytes() { return (jlong)kmem_usage; } -jlong CgroupV1MemoryController::kernel_memory_limit_in_bytes(julong phys_mem) { +jlong CgroupV1MemoryController::kernel_memory_limit_in_bytes(julong upper_bound) { julong kmem_limit; CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.kmem.limit_in_bytes", "Kernel Memory Limit", kmem_limit); - if (kmem_limit >= phys_mem) { + if (kmem_limit >= upper_bound) { return (jlong)-1; } return (jlong)kmem_limit; @@ -351,9 +351,9 @@ jlong CgroupV1MemoryController::kernel_memory_max_usage_in_bytes() { return (jlong)kmem_max_usage; } -void CgroupV1MemoryController::print_version_specific_info(outputStream* st, julong phys_mem) { +void CgroupV1MemoryController::print_version_specific_info(outputStream* st, julong mem_bound) { jlong kmem_usage = kernel_memory_usage_in_bytes(); - jlong kmem_limit = kernel_memory_limit_in_bytes(phys_mem); + jlong kmem_limit = kernel_memory_limit_in_bytes(mem_bound); jlong kmem_max_usage = kernel_memory_max_usage_in_bytes(); OSContainer::print_container_helper(st, kmem_limit, "kernel_memory_limit_in_bytes"); diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp index 33bf2ed6e55..02b2c6a9fce 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp @@ -79,17 +79,17 @@ class CgroupV1MemoryController final : public CgroupMemoryController { } jlong read_memory_limit_in_bytes(julong upper_bound) override; jlong memory_usage_in_bytes() override; - jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) override; - jlong memory_and_swap_usage_in_bytes(julong host_mem, julong host_swap) override; + jlong memory_and_swap_limit_in_bytes(julong upper_mem_bound, julong upper_swap_bound) override; + jlong memory_and_swap_usage_in_bytes(julong upper_mem_bound, julong upper_swap_bound) override; jlong memory_soft_limit_in_bytes(julong upper_bound) override; jlong memory_throttle_limit_in_bytes() override; jlong memory_max_usage_in_bytes() override; jlong rss_usage_in_bytes() override; jlong cache_usage_in_bytes() override; jlong kernel_memory_usage_in_bytes(); - jlong kernel_memory_limit_in_bytes(julong host_mem); + jlong kernel_memory_limit_in_bytes(julong upper_bound); jlong kernel_memory_max_usage_in_bytes(); - void print_version_specific_info(outputStream* st, julong host_mem) override; + void print_version_specific_info(outputStream* st, julong upper_mem_bound) override; bool needs_hierarchy_adjustment() override { return reader()->needs_hierarchy_adjustment(); } @@ -101,7 +101,7 @@ class CgroupV1MemoryController final : public CgroupMemoryController { const char* cgroup_path() override { return reader()->cgroup_path(); } private: jlong read_mem_swappiness(); - jlong read_mem_swap(julong host_total_memsw); + jlong read_mem_swap(julong upper_memsw_bound); public: CgroupV1MemoryController(const CgroupV1Controller& reader) diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp index 661f7e909b5..38258a1f049 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp @@ -181,7 +181,7 @@ jlong CgroupV2MemoryController::memory_usage_in_bytes() { return (jlong)memusage; } -jlong CgroupV2MemoryController::memory_soft_limit_in_bytes(julong phys_mem) { +jlong CgroupV2MemoryController::memory_soft_limit_in_bytes(julong upper_bound) { jlong mem_soft_limit; CONTAINER_READ_NUMBER_CHECKED_MAX(reader(), "/memory.low", "Memory Soft Limit", mem_soft_limit); return mem_soft_limit; @@ -224,19 +224,19 @@ jlong CgroupV2MemoryController::cache_usage_in_bytes() { // respectively. In order to properly report a cgroup v1 like // compound value we need to sum the two values. Setting a swap limit // without also setting a memory limit is not allowed. -jlong CgroupV2MemoryController::memory_and_swap_limit_in_bytes(julong phys_mem, - julong host_swap /* unused in cg v2 */) { +jlong CgroupV2MemoryController::memory_and_swap_limit_in_bytes(julong upper_mem_bound, + julong upper_swap_bound /* unused in cg v2 */) { jlong swap_limit; bool is_ok = reader()->read_number_handle_max("/memory.swap.max", &swap_limit); if (!is_ok) { // Some container tests rely on this trace logging to happen. log_trace(os, container)("Swap Limit failed: %d", OSCONTAINER_ERROR); // swap disabled at kernel level, treat it as no swap - return read_memory_limit_in_bytes(phys_mem); + return read_memory_limit_in_bytes(upper_mem_bound); } log_trace(os, container)("Swap Limit is: " JLONG_FORMAT, swap_limit); if (swap_limit >= 0) { - jlong memory_limit = read_memory_limit_in_bytes(phys_mem); + jlong memory_limit = read_memory_limit_in_bytes(upper_mem_bound); assert(memory_limit >= 0, "swap limit without memory limit?"); return memory_limit + swap_limit; } @@ -252,7 +252,7 @@ jlong memory_swap_current_value(CgroupV2Controller* ctrl) { return (jlong)swap_current; } -jlong CgroupV2MemoryController::memory_and_swap_usage_in_bytes(julong host_mem, julong host_swap) { +jlong CgroupV2MemoryController::memory_and_swap_usage_in_bytes(julong upper_mem_bound, julong upper_swap_bound) { jlong memory_usage = memory_usage_in_bytes(); if (memory_usage >= 0) { jlong swap_current = memory_swap_current_value(reader()); @@ -276,7 +276,7 @@ jlong memory_limit_value(CgroupV2Controller* ctrl) { * memory limit in bytes or * -1 for unlimited, OSCONTAINER_ERROR for an error */ -jlong CgroupV2MemoryController::read_memory_limit_in_bytes(julong phys_mem) { +jlong CgroupV2MemoryController::read_memory_limit_in_bytes(julong upper_bound) { jlong limit = memory_limit_value(reader()); if (log_is_enabled(Trace, os, container)) { if (limit == -1) { @@ -287,18 +287,18 @@ jlong CgroupV2MemoryController::read_memory_limit_in_bytes(julong phys_mem) { } if (log_is_enabled(Debug, os, container)) { julong read_limit = (julong)limit; // avoid signed/unsigned compare - if (limit < 0 || read_limit >= phys_mem) { + if (limit < 0 || read_limit >= upper_bound) { const char* reason; if (limit == -1) { reason = "unlimited"; } else if (limit == OSCONTAINER_ERROR) { reason = "failed"; } else { - assert(read_limit >= phys_mem, "Expected mem limit to exceed host memory"); + assert(read_limit >= upper_bound, "Expected mem limit to exceed upper memory bound"); reason = "ignored"; } - log_debug(os, container)("container memory limit %s: " JLONG_FORMAT ", using host value " JLONG_FORMAT, - reason, limit, phys_mem); + log_debug(os, container)("container memory limit %s: " JLONG_FORMAT ", upper bound is " JLONG_FORMAT, + reason, limit, upper_bound); } } return limit; @@ -327,7 +327,7 @@ bool CgroupV2Controller::needs_hierarchy_adjustment() { return strcmp(_cgroup_path, "/") != 0; } -void CgroupV2MemoryController::print_version_specific_info(outputStream* st, julong phys_mem) { +void CgroupV2MemoryController::print_version_specific_info(outputStream* st, julong upper_mem_bound) { jlong swap_current = memory_swap_current_value(reader()); jlong swap_limit = memory_swap_limit_value(reader()); diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp index e26f37925ca..07db126ce90 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp @@ -115,15 +115,15 @@ class CgroupV2MemoryController final: public CgroupMemoryController { } jlong read_memory_limit_in_bytes(julong upper_bound) override; - jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swp) override; - jlong memory_and_swap_usage_in_bytes(julong host_mem, julong host_swp) override; + jlong memory_and_swap_limit_in_bytes(julong upper_mem_bound, julong upper_swap_bound) override; + jlong memory_and_swap_usage_in_bytes(julong upper_mem_bound, julong upper_swap_bound) override; jlong memory_soft_limit_in_bytes(julong upper_bound) override; jlong memory_throttle_limit_in_bytes() override; jlong memory_usage_in_bytes() override; jlong memory_max_usage_in_bytes() override; jlong rss_usage_in_bytes() override; jlong cache_usage_in_bytes() override; - void print_version_specific_info(outputStream* st, julong host_mem) override; + void print_version_specific_info(outputStream* st, julong upper_mem_bound) override; bool is_read_only() override { return reader()->is_read_only(); } diff --git a/src/hotspot/os/linux/osContainer_linux.cpp b/src/hotspot/os/linux/osContainer_linux.cpp index 899e7535fde..561f2d4926c 100644 --- a/src/hotspot/os/linux/osContainer_linux.cpp +++ b/src/hotspot/os/linux/osContainer_linux.cpp @@ -84,8 +84,8 @@ void OSContainer::init() { // We can be in one of two cases: // 1.) On a physical Linux system without any limit // 2.) On a physical Linux system with a limit enforced by other means (like systemd slice) - any_mem_cpu_limit_present = cgroup_subsystem->memory_limit_in_bytes() > 0 || - os::Linux::active_processor_count() != cgroup_subsystem->active_processor_count(); + any_mem_cpu_limit_present = memory_limit_in_bytes() > 0 || + os::Linux::active_processor_count() != active_processor_count(); if (any_mem_cpu_limit_present) { reason = " because either a cpu or a memory limit is present"; } else { @@ -103,24 +103,47 @@ const char * OSContainer::container_type() { return cgroup_subsystem->container_type(); } +bool OSContainer::available_memory_in_container(julong& value) { + jlong mem_limit = memory_limit_in_bytes(); + jlong mem_usage = memory_usage_in_bytes(); + + if (mem_limit > 0 && mem_usage <= 0) { + log_debug(os, container)("container memory usage failed: " JLONG_FORMAT, mem_usage); + } + + if (mem_limit <= 0 || mem_usage <= 0) { + return false; + } + + value = mem_limit > mem_usage ? static_cast(mem_limit - mem_usage) : 0; + + return true; +} + jlong OSContainer::memory_limit_in_bytes() { assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); - return cgroup_subsystem->memory_limit_in_bytes(); + julong phys_mem = static_cast(os::Linux::physical_memory()); + return cgroup_subsystem->memory_limit_in_bytes(phys_mem); } jlong OSContainer::memory_and_swap_limit_in_bytes() { assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); - return cgroup_subsystem->memory_and_swap_limit_in_bytes(); + julong phys_mem = static_cast(os::Linux::physical_memory()); + julong host_swap = os::Linux::host_swap(); + return cgroup_subsystem->memory_and_swap_limit_in_bytes(phys_mem, host_swap); } jlong OSContainer::memory_and_swap_usage_in_bytes() { assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); - return cgroup_subsystem->memory_and_swap_usage_in_bytes(); + julong phys_mem = static_cast(os::Linux::physical_memory()); + julong host_swap = os::Linux::host_swap(); + return cgroup_subsystem->memory_and_swap_usage_in_bytes(phys_mem, host_swap); } jlong OSContainer::memory_soft_limit_in_bytes() { assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); - return cgroup_subsystem->memory_soft_limit_in_bytes(); + julong phys_mem = static_cast(os::Linux::physical_memory()); + return cgroup_subsystem->memory_soft_limit_in_bytes(phys_mem); } jlong OSContainer::memory_throttle_limit_in_bytes() { @@ -150,7 +173,8 @@ jlong OSContainer::cache_usage_in_bytes() { void OSContainer::print_version_specific_info(outputStream* st) { assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); - cgroup_subsystem->print_version_specific_info(st); + julong phys_mem = static_cast(os::Linux::physical_memory()); + cgroup_subsystem->print_version_specific_info(st, phys_mem); } char * OSContainer::cpu_cpuset_cpus() { diff --git a/src/hotspot/os/linux/osContainer_linux.hpp b/src/hotspot/os/linux/osContainer_linux.hpp index d9b024dbbb5..6258714c48b 100644 --- a/src/hotspot/os/linux/osContainer_linux.hpp +++ b/src/hotspot/os/linux/osContainer_linux.hpp @@ -50,6 +50,7 @@ class OSContainer: AllStatic { static inline bool is_containerized(); static const char * container_type(); + static bool available_memory_in_container(julong& value); static jlong memory_limit_in_bytes(); static jlong memory_and_swap_limit_in_bytes(); static jlong memory_and_swap_usage_in_bytes(); diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 7159b2a78c4..772b170d11c 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -213,33 +213,20 @@ static bool suppress_primordial_thread_resolution = false; // utility functions -julong os::Linux::available_memory_in_container() { - julong avail_mem = static_cast(-1L); - if (OSContainer::is_containerized()) { - jlong mem_limit = OSContainer::memory_limit_in_bytes(); - jlong mem_usage; - if (mem_limit > 0 && (mem_usage = OSContainer::memory_usage_in_bytes()) < 1) { - log_debug(os, container)("container memory usage failed: " JLONG_FORMAT ", using host value", mem_usage); - } - if (mem_limit > 0 && mem_usage > 0) { - avail_mem = mem_limit > mem_usage ? (julong)mem_limit - (julong)mem_usage : 0; - } - } - return avail_mem; -} - bool os::available_memory(physical_memory_size_type& value) { - return Linux::available_memory(value); -} - -bool os::Linux::available_memory(physical_memory_size_type& value) { - julong avail_mem = available_memory_in_container(); - if (avail_mem != static_cast(-1L)) { + julong avail_mem = 0; + if (OSContainer::is_containerized() && OSContainer::available_memory_in_container(avail_mem)) { log_trace(os)("available container memory: " JULONG_FORMAT, avail_mem); value = static_cast(avail_mem); return true; } + return Linux::available_memory(value); +} + +bool os::Linux::available_memory(physical_memory_size_type& value) { + julong avail_mem = static_cast(-1L); + FILE *fp = os::fopen("/proc/meminfo", "r"); if (fp != nullptr) { char buf[80]; @@ -264,24 +251,25 @@ bool os::Linux::available_memory(physical_memory_size_type& value) { } bool os::free_memory(physical_memory_size_type& value) { + julong free_mem = 0; + if (OSContainer::is_containerized() && OSContainer::available_memory_in_container(free_mem)) { + log_trace(os)("free container memory: " JULONG_FORMAT, free_mem); + value = static_cast(free_mem); + return true; + } + return Linux::free_memory(value); } bool os::Linux::free_memory(physical_memory_size_type& value) { // values in struct sysinfo are "unsigned long" struct sysinfo si; - julong free_mem = available_memory_in_container(); - if (free_mem != static_cast(-1L)) { - log_trace(os)("free container memory: " JULONG_FORMAT, free_mem); - value = static_cast(free_mem); - return true; - } int ret = sysinfo(&si); if (ret != 0) { return false; } - free_mem = (julong)si.freeram * si.mem_unit; + julong free_mem = (julong)si.freeram * si.mem_unit; log_trace(os)("free memory: " JULONG_FORMAT, free_mem); value = static_cast(free_mem); return true;