52 */ |
52 */ |
53 #define PER_CPU_SHARES 1024 |
53 #define PER_CPU_SHARES 1024 |
54 |
54 |
55 bool OSContainer::_is_initialized = false; |
55 bool OSContainer::_is_initialized = false; |
56 bool OSContainer::_is_containerized = false; |
56 bool OSContainer::_is_containerized = false; |
|
57 int OSContainer::_active_processor_count = 1; |
57 julong _unlimited_memory; |
58 julong _unlimited_memory; |
58 |
59 |
59 class CgroupSubsystem: CHeapObj<mtInternal> { |
60 class CgroupSubsystem: CHeapObj<mtInternal> { |
60 friend class OSContainer; |
61 friend class OSContainer; |
61 |
62 |
|
63 |
62 private: |
64 private: |
|
65 volatile jlong _next_check_counter; |
|
66 |
63 /* mountinfo contents */ |
67 /* mountinfo contents */ |
64 char *_root; |
68 char *_root; |
65 char *_mount_point; |
69 char *_mount_point; |
66 |
70 |
67 /* Constructed subsystem directory */ |
71 /* Constructed subsystem directory */ |
70 public: |
74 public: |
71 CgroupSubsystem(char *root, char *mountpoint) { |
75 CgroupSubsystem(char *root, char *mountpoint) { |
72 _root = os::strdup(root); |
76 _root = os::strdup(root); |
73 _mount_point = os::strdup(mountpoint); |
77 _mount_point = os::strdup(mountpoint); |
74 _path = NULL; |
78 _path = NULL; |
|
79 _next_check_counter = min_jlong; |
75 } |
80 } |
76 |
81 |
77 /* |
82 /* |
78 * Set directory to subsystem specific files based |
83 * Set directory to subsystem specific files based |
79 * on the contents of the mountinfo and cgroup files. |
84 * on the contents of the mountinfo and cgroup files. |
130 /* Some container runtimes set limits via cgroup |
143 /* Some container runtimes set limits via cgroup |
131 * hierarchy. If set to true consider also memory.stat |
144 * hierarchy. If set to true consider also memory.stat |
132 * file if everything else seems unlimited */ |
145 * file if everything else seems unlimited */ |
133 bool _uses_mem_hierarchy; |
146 bool _uses_mem_hierarchy; |
134 volatile jlong _memory_limit_in_bytes; |
147 volatile jlong _memory_limit_in_bytes; |
135 volatile jlong _next_check_counter; |
|
136 |
148 |
137 public: |
149 public: |
138 CgroupMemorySubsystem(char *root, char *mountpoint) : CgroupSubsystem::CgroupSubsystem(root, mountpoint) { |
150 CgroupMemorySubsystem(char *root, char *mountpoint) : CgroupSubsystem::CgroupSubsystem(root, mountpoint) { |
139 _uses_mem_hierarchy = false; |
151 _uses_mem_hierarchy = false; |
140 _memory_limit_in_bytes = -1; |
152 _memory_limit_in_bytes = -1; |
141 _next_check_counter = min_jlong; |
|
142 |
153 |
143 } |
154 } |
144 |
155 |
145 bool is_hierarchical() { return _uses_mem_hierarchy; } |
156 bool is_hierarchical() { return _uses_mem_hierarchy; } |
146 void set_hierarchical(bool value) { _uses_mem_hierarchy = value; } |
157 void set_hierarchical(bool value) { _uses_mem_hierarchy = value; } |
147 |
158 |
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; } |
159 jlong memory_limit_in_bytes() { return _memory_limit_in_bytes; } |
152 void set_memory_limit_in_bytes(jlong value) { |
160 void set_memory_limit_in_bytes(jlong value) { |
153 _memory_limit_in_bytes = value; |
161 _memory_limit_in_bytes = value; |
154 // max memory limit is unlikely to change, but we want to remain |
162 // max memory limit is unlikely to change, but we want to remain |
155 // responsive to configuration changes. A very short (20ms) grace time |
163 // responsive to configuration changes. A very short grace time |
156 // between re-read avoids excessive overhead during startup without |
164 // between re-read avoids excessive overhead during startup without |
157 // significantly reducing the VMs ability to promptly react to reduced |
165 // significantly reducing the VMs ability to promptly react to reduced |
158 // memory availability |
166 // memory availability |
159 _next_check_counter = os::elapsed_counter() + (NANOSECS_PER_SEC/50); |
167 set_cache_expiry_time(OSCONTAINER_CACHE_TIMEOUT); |
160 } |
168 } |
161 |
169 |
162 }; |
170 }; |
163 |
171 |
164 CgroupMemorySubsystem* memory = NULL; |
172 CgroupMemorySubsystem* memory = NULL; |
479 * memory limit in bytes or |
487 * memory limit in bytes or |
480 * -1 for unlimited |
488 * -1 for unlimited |
481 * OSCONTAINER_ERROR for not supported |
489 * OSCONTAINER_ERROR for not supported |
482 */ |
490 */ |
483 jlong OSContainer::memory_limit_in_bytes() { |
491 jlong OSContainer::memory_limit_in_bytes() { |
484 if (!memory->should_check_memory_limit()) { |
492 if (!memory->cache_has_expired()) { |
485 return memory->memory_limit_in_bytes(); |
493 return memory->memory_limit_in_bytes(); |
486 } |
494 } |
487 jlong memory_limit = read_memory_limit_in_bytes(); |
495 jlong memory_limit = read_memory_limit_in_bytes(); |
488 // Update CgroupMemorySubsystem to avoid re-reading container settings too often |
496 // Update CgroupMemorySubsystem to avoid re-reading container settings too often |
489 memory->set_memory_limit_in_bytes(memory_limit); |
497 memory->set_memory_limit_in_bytes(memory_limit); |
615 int OSContainer::active_processor_count() { |
623 int OSContainer::active_processor_count() { |
616 int quota_count = 0, share_count = 0; |
624 int quota_count = 0, share_count = 0; |
617 int cpu_count, limit_count; |
625 int cpu_count, limit_count; |
618 int result; |
626 int result; |
619 |
627 |
|
628 // We use a cache with a timeout to avoid performing expensive |
|
629 // computations in the event this function is called frequently. |
|
630 // [See 8227006]. |
|
631 if (!cpu->cache_has_expired()) { |
|
632 log_trace(os, container)("OSContainer::active_processor_count (cached): %d", OSContainer::_active_processor_count); |
|
633 return OSContainer::_active_processor_count; |
|
634 } |
|
635 |
620 cpu_count = limit_count = os::Linux::active_processor_count(); |
636 cpu_count = limit_count = os::Linux::active_processor_count(); |
621 int quota = cpu_quota(); |
637 int quota = cpu_quota(); |
622 int period = cpu_period(); |
638 int period = cpu_period(); |
623 int share = cpu_shares(); |
639 int share = cpu_shares(); |
624 |
640 |
647 limit_count = share_count; |
663 limit_count = share_count; |
648 } |
664 } |
649 |
665 |
650 result = MIN2(cpu_count, limit_count); |
666 result = MIN2(cpu_count, limit_count); |
651 log_trace(os, container)("OSContainer::active_processor_count: %d", result); |
667 log_trace(os, container)("OSContainer::active_processor_count: %d", result); |
|
668 |
|
669 // Update the value and reset the cache timeout |
|
670 OSContainer::_active_processor_count = result; |
|
671 cpu->set_cache_expiry_time(OSCONTAINER_CACHE_TIMEOUT); |
|
672 |
652 return result; |
673 return result; |
653 } |
674 } |
654 |
675 |
655 char * OSContainer::cpu_cpuset_cpus() { |
676 char * OSContainer::cpu_cpuset_cpus() { |
656 GET_CONTAINER_INFO_CPTR(cptr, cpuset, "/cpuset.cpus", |
677 GET_CONTAINER_INFO_CPTR(cptr, cpuset, "/cpuset.cpus", |