1.1 --- a/src/os/linux/vm/os_linux.cpp Tue Jul 10 18:31:51 2018 +0100 1.2 +++ b/src/os/linux/vm/os_linux.cpp Fri Jul 06 18:50:13 2018 +0000 1.3 @@ -37,6 +37,7 @@ 1.4 #include "mutex_linux.inline.hpp" 1.5 #include "oops/oop.inline.hpp" 1.6 #include "os_share_linux.hpp" 1.7 +#include "osContainer_linux.hpp" 1.8 #include "prims/jniFastGetField.hpp" 1.9 #include "prims/jvm.h" 1.10 #include "prims/jvm_misc.hpp" 1.11 @@ -179,13 +180,62 @@ 1.12 julong os::Linux::available_memory() { 1.13 // values in struct sysinfo are "unsigned long" 1.14 struct sysinfo si; 1.15 + julong avail_mem; 1.16 + 1.17 + if (OSContainer::is_containerized()) { 1.18 + jlong mem_limit, mem_usage; 1.19 + if ((mem_limit = OSContainer::memory_limit_in_bytes()) < 1) { 1.20 + if (PrintContainerInfo) { 1.21 + tty->print_cr("container memory limit %s: " JLONG_FORMAT ", using host value", 1.22 + mem_limit == OSCONTAINER_ERROR ? "failed" : "unlimited", mem_limit); 1.23 + } 1.24 + } 1.25 + 1.26 + if (mem_limit > 0 && (mem_usage = OSContainer::memory_usage_in_bytes()) < 1) { 1.27 + if (PrintContainerInfo) { 1.28 + tty->print_cr("container memory usage failed: " JLONG_FORMAT ", using host value", mem_usage); 1.29 + } 1.30 + } 1.31 + 1.32 + if (mem_limit > 0 && mem_usage > 0 ) { 1.33 + avail_mem = mem_limit > mem_usage ? (julong)mem_limit - (julong)mem_usage : 0; 1.34 + if (PrintContainerInfo) { 1.35 + tty->print_cr("available container memory: " JULONG_FORMAT, avail_mem); 1.36 + } 1.37 + return avail_mem; 1.38 + } 1.39 + } 1.40 + 1.41 sysinfo(&si); 1.42 - 1.43 - return (julong)si.freeram * si.mem_unit; 1.44 + avail_mem = (julong)si.freeram * si.mem_unit; 1.45 + if (Verbose) { 1.46 + tty->print_cr("available memory: " JULONG_FORMAT, avail_mem); 1.47 + } 1.48 + return avail_mem; 1.49 } 1.50 1.51 julong os::physical_memory() { 1.52 - return Linux::physical_memory(); 1.53 + jlong phys_mem = 0; 1.54 + if (OSContainer::is_containerized()) { 1.55 + jlong mem_limit; 1.56 + if ((mem_limit = OSContainer::memory_limit_in_bytes()) > 0) { 1.57 + if (PrintContainerInfo) { 1.58 + tty->print_cr("total container memory: " JLONG_FORMAT, mem_limit); 1.59 + } 1.60 + return mem_limit; 1.61 + } 1.62 + 1.63 + if (PrintContainerInfo) { 1.64 + tty->print_cr("container memory limit %s: " JLONG_FORMAT ", using host value", 1.65 + mem_limit == OSCONTAINER_ERROR ? "failed" : "unlimited", mem_limit); 1.66 + } 1.67 + } 1.68 + 1.69 + phys_mem = Linux::physical_memory(); 1.70 + if (Verbose) { 1.71 + tty->print_cr("total system memory: " JLONG_FORMAT, phys_mem); 1.72 + } 1.73 + return phys_mem; 1.74 } 1.75 1.76 //////////////////////////////////////////////////////////////////////////////// 1.77 @@ -2114,6 +2164,8 @@ 1.78 os::Posix::print_load_average(st); 1.79 1.80 os::Linux::print_full_memory_info(st); 1.81 + 1.82 + os::Linux::print_container_info(st); 1.83 } 1.84 1.85 // Try to identify popular distros. 1.86 @@ -2179,6 +2231,57 @@ 1.87 st->cr(); 1.88 } 1.89 1.90 +void os::Linux::print_container_info(outputStream* st) { 1.91 +if (!OSContainer::is_containerized()) { 1.92 + return; 1.93 + } 1.94 + 1.95 + st->print("container (cgroup) information:\n"); 1.96 + 1.97 + const char *p_ct = OSContainer::container_type(); 1.98 + st->print("container_type: %s\n", p_ct != NULL ? p_ct : "failed"); 1.99 + 1.100 + char *p = OSContainer::cpu_cpuset_cpus(); 1.101 + st->print("cpu_cpuset_cpus: %s\n", p != NULL ? p : "failed"); 1.102 + free(p); 1.103 + 1.104 + p = OSContainer::cpu_cpuset_memory_nodes(); 1.105 + st->print("cpu_memory_nodes: %s\n", p != NULL ? p : "failed"); 1.106 + free(p); 1.107 + 1.108 + int i = OSContainer::active_processor_count(); 1.109 + if (i > 0) { 1.110 + st->print("active_processor_count: %d\n", i); 1.111 + } else { 1.112 + st->print("active_processor_count: failed\n"); 1.113 + } 1.114 + 1.115 + i = OSContainer::cpu_quota(); 1.116 + st->print("cpu_quota: %d\n", i); 1.117 + 1.118 + i = OSContainer::cpu_period(); 1.119 + st->print("cpu_period: %d\n", i); 1.120 + 1.121 + i = OSContainer::cpu_shares(); 1.122 + st->print("cpu_shares: %d\n", i); 1.123 + 1.124 + jlong j = OSContainer::memory_limit_in_bytes(); 1.125 + st->print("memory_limit_in_bytes: " JLONG_FORMAT "\n", j); 1.126 + 1.127 + j = OSContainer::memory_and_swap_limit_in_bytes(); 1.128 + st->print("memory_and_swap_limit_in_bytes: " JLONG_FORMAT "\n", j); 1.129 + 1.130 + j = OSContainer::memory_soft_limit_in_bytes(); 1.131 + st->print("memory_soft_limit_in_bytes: " JLONG_FORMAT "\n", j); 1.132 + 1.133 + j = OSContainer::OSContainer::memory_usage_in_bytes(); 1.134 + st->print("memory_usage_in_bytes: " JLONG_FORMAT "\n", j); 1.135 + 1.136 + j = OSContainer::OSContainer::memory_max_usage_in_bytes(); 1.137 + st->print("memory_max_usage_in_bytes: " JLONG_FORMAT "\n", j); 1.138 + st->cr(); 1.139 +} 1.140 + 1.141 void os::print_memory_info(outputStream* st) { 1.142 1.143 st->print("Memory:"); 1.144 @@ -4951,6 +5054,10 @@ 1.145 } 1.146 } 1.147 1.148 +void os::pd_init_container_support() { 1.149 + OSContainer::init(); 1.150 +} 1.151 + 1.152 // this is called _after_ the global arguments have been parsed 1.153 jint os::init_2(void) 1.154 { 1.155 @@ -5131,7 +5238,7 @@ 1.156 // sched_getaffinity gives an accurate answer as it accounts for cpusets. 1.157 // If anything goes wrong we fallback to returning the number of online 1.158 // processors - which can be greater than the number available to the process. 1.159 -int os::active_processor_count() { 1.160 +int os::Linux::active_processor_count() { 1.161 cpu_set_t cpus; // can represent at most 1024 (CPU_SETSIZE) processors 1.162 int cpus_size = sizeof(cpu_set_t); 1.163 int cpu_count = 0; 1.164 @@ -5149,10 +5256,48 @@ 1.165 "which may exceed available processors", strerror(errno), cpu_count); 1.166 } 1.167 1.168 - assert(cpu_count > 0 && cpu_count <= processor_count(), "sanity check"); 1.169 + assert(cpu_count > 0 && cpu_count <= os::processor_count(), "sanity check"); 1.170 return cpu_count; 1.171 } 1.172 1.173 +// Determine the active processor count from one of 1.174 +// three different sources: 1.175 +// 1.176 +// 1. User option -XX:ActiveProcessorCount 1.177 +// 2. kernel os calls (sched_getaffinity or sysconf(_SC_NPROCESSORS_ONLN) 1.178 +// 3. extracted from cgroup cpu subsystem (shares and quotas) 1.179 +// 1.180 +// Option 1, if specified, will always override. 1.181 +// If the cgroup subsystem is active and configured, we 1.182 +// will return the min of the cgroup and option 2 results. 1.183 +// This is required since tools, such as numactl, that 1.184 +// alter cpu affinity do not update cgroup subsystem 1.185 +// cpuset configuration files. 1.186 +int os::active_processor_count() { 1.187 + // User has overridden the number of active processors 1.188 + if (ActiveProcessorCount > 0) { 1.189 + if (PrintActiveCpus) { 1.190 + tty->print_cr("active_processor_count: " 1.191 + "active processor count set by user : %d", 1.192 + ActiveProcessorCount); 1.193 + } 1.194 + return ActiveProcessorCount; 1.195 + } 1.196 + 1.197 + int active_cpus; 1.198 + if (OSContainer::is_containerized()) { 1.199 + active_cpus = OSContainer::active_processor_count(); 1.200 + if (PrintActiveCpus) { 1.201 + tty->print_cr("active_processor_count: determined by OSContainer: %d", 1.202 + active_cpus); 1.203 + } 1.204 + } else { 1.205 + active_cpus = os::Linux::active_processor_count(); 1.206 + } 1.207 + 1.208 + return active_cpus; 1.209 +} 1.210 + 1.211 void os::set_native_thread_name(const char *name) { 1.212 // Not yet implemented. 1.213 return;