25 #include <string.h> |
25 #include <string.h> |
26 #include <math.h> |
26 #include <math.h> |
27 #include <errno.h> |
27 #include <errno.h> |
28 #include "utilities/globalDefinitions.hpp" |
28 #include "utilities/globalDefinitions.hpp" |
29 #include "memory/allocation.hpp" |
29 #include "memory/allocation.hpp" |
|
30 #include "runtime/globals.hpp" |
30 #include "runtime/os.hpp" |
31 #include "runtime/os.hpp" |
31 #include "logging/log.hpp" |
32 #include "logging/log.hpp" |
32 #include "osContainer_linux.hpp" |
33 #include "osContainer_linux.hpp" |
33 |
34 |
34 /* |
35 /* |
128 private: |
129 private: |
129 /* Some container runtimes set limits via cgroup |
130 /* Some container runtimes set limits via cgroup |
130 * hierarchy. If set to true consider also memory.stat |
131 * hierarchy. If set to true consider also memory.stat |
131 * file if everything else seems unlimited */ |
132 * file if everything else seems unlimited */ |
132 bool _uses_mem_hierarchy; |
133 bool _uses_mem_hierarchy; |
|
134 volatile jlong _memory_limit_in_bytes; |
|
135 volatile jlong _next_check_counter; |
133 |
136 |
134 public: |
137 public: |
135 CgroupMemorySubsystem(char *root, char *mountpoint) : CgroupSubsystem::CgroupSubsystem(root, mountpoint) { |
138 CgroupMemorySubsystem(char *root, char *mountpoint) : CgroupSubsystem::CgroupSubsystem(root, mountpoint) { |
136 _uses_mem_hierarchy = false; |
139 _uses_mem_hierarchy = false; |
|
140 _memory_limit_in_bytes = -1; |
|
141 _next_check_counter = min_jlong; |
|
142 |
137 } |
143 } |
138 |
144 |
139 bool is_hierarchical() { return _uses_mem_hierarchy; } |
145 bool is_hierarchical() { return _uses_mem_hierarchy; } |
140 void set_hierarchical(bool value) { _uses_mem_hierarchy = value; } |
146 void set_hierarchical(bool value) { _uses_mem_hierarchy = value; } |
|
147 |
|
148 bool should_check_memory_limit() { |
|
149 return os::elapsed_counter() > _next_check_counter; |
|
150 } |
|
151 jlong memory_limit_in_bytes() { return _memory_limit_in_bytes; } |
|
152 void set_memory_limit_in_bytes(jlong value) { |
|
153 _memory_limit_in_bytes = value; |
|
154 // max memory limit is unlikely to change, but we want to remain |
|
155 // responsive to configuration changes. A very short (20ms) grace time |
|
156 // between re-read avoids excessive overhead during startup without |
|
157 // significantly reducing the VMs ability to promptly react to reduced |
|
158 // memory availability |
|
159 _next_check_counter = os::elapsed_counter() + (NANOSECS_PER_SEC/50); |
|
160 } |
|
161 |
141 }; |
162 }; |
142 |
163 |
143 CgroupMemorySubsystem* memory = NULL; |
164 CgroupMemorySubsystem* memory = NULL; |
144 CgroupSubsystem* cpuset = NULL; |
165 CgroupSubsystem* cpuset = NULL; |
145 CgroupSubsystem* cpu = NULL; |
166 CgroupSubsystem* cpu = NULL; |
458 * memory limit in bytes or |
479 * memory limit in bytes or |
459 * -1 for unlimited |
480 * -1 for unlimited |
460 * OSCONTAINER_ERROR for not supported |
481 * OSCONTAINER_ERROR for not supported |
461 */ |
482 */ |
462 jlong OSContainer::memory_limit_in_bytes() { |
483 jlong OSContainer::memory_limit_in_bytes() { |
|
484 if (!memory->should_check_memory_limit()) { |
|
485 return memory->memory_limit_in_bytes(); |
|
486 } |
|
487 jlong memory_limit = read_memory_limit_in_bytes(); |
|
488 // Update CgroupMemorySubsystem to avoid re-reading container settings too often |
|
489 memory->set_memory_limit_in_bytes(memory_limit); |
|
490 return memory_limit; |
|
491 } |
|
492 |
|
493 jlong OSContainer::read_memory_limit_in_bytes() { |
463 GET_CONTAINER_INFO(julong, memory, "/memory.limit_in_bytes", |
494 GET_CONTAINER_INFO(julong, memory, "/memory.limit_in_bytes", |
464 "Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, memlimit); |
495 "Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, memlimit); |
465 |
496 |
466 if (memlimit >= _unlimited_memory) { |
497 if (memlimit >= _unlimited_memory) { |
467 log_trace(os, container)("Non-Hierarchical Memory Limit is: Unlimited"); |
498 log_trace(os, container)("Non-Hierarchical Memory Limit is: Unlimited"); |