129 private: |
129 private: |
130 /* Some container runtimes set limits via cgroup |
130 /* Some container runtimes set limits via cgroup |
131 * hierarchy. If set to true consider also memory.stat |
131 * hierarchy. If set to true consider also memory.stat |
132 * file if everything else seems unlimited */ |
132 * file if everything else seems unlimited */ |
133 bool _uses_mem_hierarchy; |
133 bool _uses_mem_hierarchy; |
|
134 volatile jlong _memory_limit_in_bytes; |
|
135 volatile jlong _next_check_counter; |
134 |
136 |
135 public: |
137 public: |
136 CgroupMemorySubsystem(char *root, char *mountpoint) : CgroupSubsystem::CgroupSubsystem(root, mountpoint) { |
138 CgroupMemorySubsystem(char *root, char *mountpoint) : CgroupSubsystem::CgroupSubsystem(root, mountpoint) { |
137 _uses_mem_hierarchy = false; |
139 _uses_mem_hierarchy = false; |
|
140 _memory_limit_in_bytes = -1; |
|
141 _next_check_counter = min_jlong; |
|
142 |
138 } |
143 } |
139 |
144 |
140 bool is_hierarchical() { return _uses_mem_hierarchy; } |
145 bool is_hierarchical() { return _uses_mem_hierarchy; } |
141 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 |
142 }; |
162 }; |
143 |
163 |
144 CgroupMemorySubsystem* memory = NULL; |
164 CgroupMemorySubsystem* memory = NULL; |
145 CgroupSubsystem* cpuset = NULL; |
165 CgroupSubsystem* cpuset = NULL; |
146 CgroupSubsystem* cpu = NULL; |
166 CgroupSubsystem* cpu = NULL; |
459 * memory limit in bytes or |
479 * memory limit in bytes or |
460 * -1 for unlimited |
480 * -1 for unlimited |
461 * OSCONTAINER_ERROR for not supported |
481 * OSCONTAINER_ERROR for not supported |
462 */ |
482 */ |
463 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() { |
464 GET_CONTAINER_INFO(julong, memory, "/memory.limit_in_bytes", |
494 GET_CONTAINER_INFO(julong, memory, "/memory.limit_in_bytes", |
465 "Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, memlimit); |
495 "Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, memlimit); |
466 |
496 |
467 if (memlimit >= _unlimited_memory) { |
497 if (memlimit >= _unlimited_memory) { |
468 log_trace(os, container)("Non-Hierarchical Memory Limit is: Unlimited"); |
498 log_trace(os, container)("Non-Hierarchical Memory Limit is: Unlimited"); |