Mon, 09 Jul 2018 15:45:22 +0000
Merge
1.1 --- a/.hgtags Mon Jul 09 05:53:08 2018 -0700 1.2 +++ b/.hgtags Mon Jul 09 15:45:22 2018 +0000 1.3 @@ -1157,3 +1157,4 @@ 1.4 083a9d6562100353708e4b73656282b21a78f714 jdk8u172-b11 1.5 c19c5b73704e3d188bedfe52a473b408ca39009f jdk8u182-b00 1.6 0341fa6dbb363ee4dc5dbf5bfc4f820523400a72 jdk8u192-b00 1.7 +5792d995ed26eec0417d96a2423446bbcd6951a9 jdk8u192-b01
2.1 --- a/make/linux/makefiles/jsig.make Mon Jul 09 05:53:08 2018 -0700 2.2 +++ b/make/linux/makefiles/jsig.make Mon Jul 09 15:45:22 2018 +0000 2.3 @@ -57,14 +57,15 @@ 2.4 $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) $(EXTRA_CFLAGS) -o $@ $< -ldl 2.5 ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) 2.6 $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJSIG_DEBUGINFO) 2.7 + ifeq ($(STRIP_POLICY),all_strip) 2.8 $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJSIG_DEBUGINFO) $@ 2.9 - ifeq ($(STRIP_POLICY),all_strip) 2.10 $(QUIETLY) $(STRIP) $@ 2.11 else 2.12 ifeq ($(STRIP_POLICY),min_strip) 2.13 + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJSIG_DEBUGINFO) $@ 2.14 $(QUIETLY) $(STRIP) -g $@ 2.15 + endif 2.16 # implied else here is no stripping at all 2.17 - endif 2.18 endif 2.19 ifeq ($(ZIP_DEBUGINFO_FILES),1) 2.20 $(ZIPEXE) -q -y $(LIBJSIG_DIZ) $(LIBJSIG_DEBUGINFO)
3.1 --- a/make/linux/makefiles/saproc.make Mon Jul 09 05:53:08 2018 -0700 3.2 +++ b/make/linux/makefiles/saproc.make Mon Jul 09 15:45:22 2018 +0000 3.3 @@ -100,14 +100,15 @@ 3.4 -lthread_db 3.5 ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) 3.6 $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBSAPROC_DEBUGINFO) 3.7 + ifeq ($(STRIP_POLICY),all_strip) 3.8 $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBSAPROC_DEBUGINFO) $@ 3.9 - ifeq ($(STRIP_POLICY),all_strip) 3.10 $(QUIETLY) $(STRIP) $@ 3.11 else 3.12 ifeq ($(STRIP_POLICY),min_strip) 3.13 + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBSAPROC_DEBUGINFO) $@ 3.14 $(QUIETLY) $(STRIP) -g $@ 3.15 + endif 3.16 # implied else here is no stripping at all 3.17 - endif 3.18 endif 3.19 ifeq ($(ZIP_DEBUGINFO_FILES),1) 3.20 $(ZIPEXE) -q -y $(LIBSAPROC_DIZ) $(LIBSAPROC_DEBUGINFO)
4.1 --- a/make/linux/makefiles/vm.make Mon Jul 09 05:53:08 2018 -0700 4.2 +++ b/make/linux/makefiles/vm.make Mon Jul 09 15:45:22 2018 +0000 4.3 @@ -358,14 +358,15 @@ 4.4 4.5 ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) 4.6 $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJVM_DEBUGINFO) 4.7 + ifeq ($(STRIP_POLICY),all_strip) 4.8 $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJVM_DEBUGINFO) $@ 4.9 - ifeq ($(STRIP_POLICY),all_strip) 4.10 $(QUIETLY) $(STRIP) $@ 4.11 else 4.12 ifeq ($(STRIP_POLICY),min_strip) 4.13 + $(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJVM_DEBUGINFO) $@ 4.14 $(QUIETLY) $(STRIP) -g $@ 4.15 + endif 4.16 # implied else here is no stripping at all 4.17 - endif 4.18 endif 4.19 ifeq ($(ZIP_DEBUGINFO_FILES),1) 4.20 $(ZIPEXE) -q -y $(LIBJVM_DIZ) $(LIBJVM_DEBUGINFO)
5.1 --- a/src/os/aix/vm/os_aix.cpp Mon Jul 09 05:53:08 2018 -0700 5.2 +++ b/src/os/aix/vm/os_aix.cpp Mon Jul 09 15:45:22 2018 +0000 5.3 @@ -4008,6 +4008,16 @@ 5.4 }; 5.5 5.6 int os::active_processor_count() { 5.7 + // User has overridden the number of active processors 5.8 + if (ActiveProcessorCount > 0) { 5.9 + if (PrintActiveCpus) { 5.10 + tty->print_cr("active_processor_count: " 5.11 + "active processor count set by user : %d", 5.12 + ActiveProcessorCount); 5.13 + } 5.14 + return ActiveProcessorCount; 5.15 + } 5.16 + 5.17 int online_cpus = ::sysconf(_SC_NPROCESSORS_ONLN); 5.18 assert(online_cpus > 0 && online_cpus <= processor_count(), "sanity check"); 5.19 return online_cpus;
6.1 --- a/src/os/bsd/vm/os_bsd.cpp Mon Jul 09 05:53:08 2018 -0700 6.2 +++ b/src/os/bsd/vm/os_bsd.cpp Mon Jul 09 15:45:22 2018 +0000 6.3 @@ -3765,6 +3765,16 @@ 6.4 }; 6.5 6.6 int os::active_processor_count() { 6.7 + // User has overridden the number of active processors 6.8 + if (ActiveProcessorCount > 0) { 6.9 + if (PrintActiveCpus) { 6.10 + tty->print_cr("active_processor_count: " 6.11 + "active processor count set by user : %d", 6.12 + ActiveProcessorCount); 6.13 + } 6.14 + return ActiveProcessorCount; 6.15 + } 6.16 + 6.17 return _processor_count; 6.18 } 6.19
7.1 --- a/src/os/linux/vm/globals_linux.hpp Mon Jul 09 05:53:08 2018 -0700 7.2 +++ b/src/os/linux/vm/globals_linux.hpp Mon Jul 09 15:45:22 2018 +0000 7.3 @@ -1,5 +1,5 @@ 7.4 /* 7.5 - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. 7.6 + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. 7.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7.8 * 7.9 * This code is free software; you can redistribute it and/or modify it 7.10 @@ -49,8 +49,13 @@ 7.11 product(bool, UseSHM, false, \ 7.12 "Use SYSV shared memory for large pages") \ 7.13 \ 7.14 - diagnostic(bool, PrintActiveCpus, false, \ 7.15 - "Print the number of CPUs detected in os::active_processor_count") 7.16 + product(bool, UseContainerSupport, true, \ 7.17 + "Enable detection and runtime container configuration support") \ 7.18 + \ 7.19 + product(bool, PreferContainerQuotaForCPUCount, true, \ 7.20 + "Calculate the container CPU availability based on the value" \ 7.21 + " of quotas (if set), when true. Otherwise, use the CPU" \ 7.22 + " shares value, provided it is less than quota.") 7.23 7.24 // 7.25 // Defines Linux-specific default values. The flags are available on all
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/os/linux/vm/osContainer_linux.cpp Mon Jul 09 15:45:22 2018 +0000 8.3 @@ -0,0 +1,680 @@ 8.4 +/* 8.5 + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. 8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.7 + * 8.8 + * This code is free software; you can redistribute it and/or modify it 8.9 + * under the terms of the GNU General Public License version 2 only, as 8.10 + * published by the Free Software Foundation. 8.11 + * 8.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 8.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 8.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 8.15 + * version 2 for more details (a copy is included in the LICENSE file that 8.16 + * accompanied this code). 8.17 + * 8.18 + * You should have received a copy of the GNU General Public License version 8.19 + * 2 along with this work; if not, write to the Free Software Foundation, 8.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 8.21 + * 8.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 8.23 + * or visit www.oracle.com if you need additional information or have any 8.24 + * questions. 8.25 + * 8.26 + */ 8.27 + 8.28 +#include <string.h> 8.29 +#include <math.h> 8.30 +#include <errno.h> 8.31 +#include "utilities/globalDefinitions.hpp" 8.32 +#include "memory/allocation.hpp" 8.33 +#include "runtime/os.hpp" 8.34 +#include "osContainer_linux.hpp" 8.35 + 8.36 +#define PER_CPU_SHARES 1024 8.37 + 8.38 +bool OSContainer::_is_initialized = false; 8.39 +bool OSContainer::_is_containerized = false; 8.40 +julong _unlimited_memory; 8.41 + 8.42 +class CgroupSubsystem: CHeapObj<mtInternal> { 8.43 + friend class OSContainer; 8.44 + 8.45 + private: 8.46 + /* mountinfo contents */ 8.47 + char *_root; 8.48 + char *_mount_point; 8.49 + 8.50 + /* Constructed subsystem directory */ 8.51 + char *_path; 8.52 + 8.53 + public: 8.54 + CgroupSubsystem(char *root, char *mountpoint) { 8.55 + _root = os::strdup(root); 8.56 + _mount_point = os::strdup(mountpoint); 8.57 + _path = NULL; 8.58 + } 8.59 + 8.60 + /* 8.61 + * Set directory to subsystem specific files based 8.62 + * on the contents of the mountinfo and cgroup files. 8.63 + */ 8.64 + void set_subsystem_path(char *cgroup_path) { 8.65 + char buf[MAXPATHLEN+1]; 8.66 + if (_root != NULL && cgroup_path != NULL) { 8.67 + if (strcmp(_root, "/") == 0) { 8.68 + int buflen; 8.69 + strncpy(buf, _mount_point, MAXPATHLEN); 8.70 + buf[MAXPATHLEN-1] = '\0'; 8.71 + if (strcmp(cgroup_path,"/") != 0) { 8.72 + buflen = strlen(buf); 8.73 + if ((buflen + strlen(cgroup_path)) > (MAXPATHLEN-1)) { 8.74 + return; 8.75 + } 8.76 + strncat(buf, cgroup_path, MAXPATHLEN-buflen); 8.77 + buf[MAXPATHLEN-1] = '\0'; 8.78 + } 8.79 + _path = os::strdup(buf); 8.80 + } else { 8.81 + if (strcmp(_root, cgroup_path) == 0) { 8.82 + strncpy(buf, _mount_point, MAXPATHLEN); 8.83 + buf[MAXPATHLEN-1] = '\0'; 8.84 + _path = os::strdup(buf); 8.85 + } else { 8.86 + char *p = strstr(_root, cgroup_path); 8.87 + if (p != NULL && p == _root) { 8.88 + if (strlen(cgroup_path) > strlen(_root)) { 8.89 + int buflen; 8.90 + strncpy(buf, _mount_point, MAXPATHLEN); 8.91 + buf[MAXPATHLEN-1] = '\0'; 8.92 + buflen = strlen(buf); 8.93 + if ((buflen + strlen(cgroup_path)) > (MAXPATHLEN-1)) { 8.94 + return; 8.95 + } 8.96 + strncat(buf, cgroup_path + strlen(_root), MAXPATHLEN-buflen); 8.97 + buf[MAXPATHLEN-1] = '\0'; 8.98 + _path = os::strdup(buf); 8.99 + } 8.100 + } 8.101 + } 8.102 + } 8.103 + } 8.104 + } 8.105 + 8.106 + char *subsystem_path() { return _path; } 8.107 +}; 8.108 + 8.109 +CgroupSubsystem* memory = NULL; 8.110 +CgroupSubsystem* cpuset = NULL; 8.111 +CgroupSubsystem* cpu = NULL; 8.112 +CgroupSubsystem* cpuacct = NULL; 8.113 + 8.114 +typedef char * cptr; 8.115 + 8.116 +PRAGMA_DIAG_PUSH 8.117 +PRAGMA_FORMAT_NONLITERAL_IGNORED 8.118 +template <typename T> int subsystem_file_contents(CgroupSubsystem* c, 8.119 + const char *filename, 8.120 + const char *scan_fmt, 8.121 + T returnval) { 8.122 + FILE *fp = NULL; 8.123 + char *p; 8.124 + char file[MAXPATHLEN+1]; 8.125 + char buf[MAXPATHLEN+1]; 8.126 + 8.127 + if (c == NULL) { 8.128 + if (PrintContainerInfo) { 8.129 + tty->print_cr("subsystem_file_contents: CgroupSubsytem* is NULL"); 8.130 + } 8.131 + return OSCONTAINER_ERROR; 8.132 + } 8.133 + if (c->subsystem_path() == NULL) { 8.134 + if (PrintContainerInfo) { 8.135 + tty->print_cr("subsystem_file_contents: subsystem path is NULL"); 8.136 + } 8.137 + return OSCONTAINER_ERROR; 8.138 + } 8.139 + 8.140 + strncpy(file, c->subsystem_path(), MAXPATHLEN); 8.141 + file[MAXPATHLEN-1] = '\0'; 8.142 + int filelen = strlen(file); 8.143 + if ((filelen + strlen(filename)) > (MAXPATHLEN-1)) { 8.144 + if (PrintContainerInfo) { 8.145 + tty->print_cr("File path too long %s, %s", file, filename); 8.146 + } 8.147 + return OSCONTAINER_ERROR; 8.148 + } 8.149 + strncat(file, filename, MAXPATHLEN-filelen); 8.150 + if (PrintContainerInfo) { 8.151 + tty->print_cr("Path to %s is %s", filename, file); 8.152 + } 8.153 + fp = fopen(file, "r"); 8.154 + if (fp != NULL) { 8.155 + p = fgets(buf, MAXPATHLEN, fp); 8.156 + if (p != NULL) { 8.157 + int matched = sscanf(p, scan_fmt, returnval); 8.158 + if (matched == 1) { 8.159 + fclose(fp); 8.160 + return 0; 8.161 + } else { 8.162 + if (PrintContainerInfo) { 8.163 + tty->print_cr("Type %s not found in file %s", scan_fmt, file); 8.164 + } 8.165 + } 8.166 + } else { 8.167 + if (PrintContainerInfo) { 8.168 + tty->print_cr("Empty file %s", file); 8.169 + } 8.170 + } 8.171 + } else { 8.172 + if (PrintContainerInfo) { 8.173 + tty->print_cr("Open of file %s failed, %s", file, strerror(errno)); 8.174 + } 8.175 + } 8.176 + if (fp != NULL) 8.177 + fclose(fp); 8.178 + return OSCONTAINER_ERROR; 8.179 +} 8.180 +PRAGMA_DIAG_POP 8.181 + 8.182 +#define GET_CONTAINER_INFO(return_type, subsystem, filename, \ 8.183 + logstring, scan_fmt, variable) \ 8.184 + return_type variable; \ 8.185 +{ \ 8.186 + int err; \ 8.187 + err = subsystem_file_contents(subsystem, \ 8.188 + filename, \ 8.189 + scan_fmt, \ 8.190 + &variable); \ 8.191 + if (err != 0) \ 8.192 + return (return_type) OSCONTAINER_ERROR; \ 8.193 + \ 8.194 + if (PrintContainerInfo) \ 8.195 + tty->print_cr(logstring, variable); \ 8.196 +} 8.197 + 8.198 +#define GET_CONTAINER_INFO_CPTR(return_type, subsystem, filename, \ 8.199 + logstring, scan_fmt, variable, bufsize) \ 8.200 + char variable[bufsize]; \ 8.201 +{ \ 8.202 + int err; \ 8.203 + err = subsystem_file_contents(subsystem, \ 8.204 + filename, \ 8.205 + scan_fmt, \ 8.206 + variable); \ 8.207 + if (err != 0) \ 8.208 + return (return_type) NULL; \ 8.209 + \ 8.210 + if (PrintContainerInfo) \ 8.211 + tty->print_cr(logstring, variable); \ 8.212 +} 8.213 + 8.214 +/* init 8.215 + * 8.216 + * Initialize the container support and determine if 8.217 + * we are running under cgroup control. 8.218 + */ 8.219 +void OSContainer::init() { 8.220 + int mountid; 8.221 + int parentid; 8.222 + int major; 8.223 + int minor; 8.224 + FILE *mntinfo = NULL; 8.225 + FILE *cgroup = NULL; 8.226 + char buf[MAXPATHLEN+1]; 8.227 + char tmproot[MAXPATHLEN+1]; 8.228 + char tmpmount[MAXPATHLEN+1]; 8.229 + char tmpbase[MAXPATHLEN+1]; 8.230 + char *p; 8.231 + jlong mem_limit; 8.232 + 8.233 + assert(!_is_initialized, "Initializing OSContainer more than once"); 8.234 + 8.235 + _is_initialized = true; 8.236 + _is_containerized = false; 8.237 + 8.238 + _unlimited_memory = (LONG_MAX / os::vm_page_size()) * os::vm_page_size(); 8.239 + 8.240 + if (PrintContainerInfo) { 8.241 + tty->print_cr("OSContainer::init: Initializing Container Support"); 8.242 + } 8.243 + if (!UseContainerSupport) { 8.244 + if (PrintContainerInfo) { 8.245 + tty->print_cr("Container Support not enabled"); 8.246 + } 8.247 + return; 8.248 + } 8.249 + 8.250 + /* 8.251 + * Find the cgroup mount point for memory and cpuset 8.252 + * by reading /proc/self/mountinfo 8.253 + * 8.254 + * Example for docker: 8.255 + * 219 214 0:29 /docker/7208cebd00fa5f2e342b1094f7bed87fa25661471a4637118e65f1c995be8a34 /sys/fs/cgroup/memory ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory 8.256 + * 8.257 + * Example for host: 8.258 + * 34 28 0:29 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,memory 8.259 + */ 8.260 + mntinfo = fopen("/proc/self/mountinfo", "r"); 8.261 + if (mntinfo == NULL) { 8.262 + if (PrintContainerInfo) { 8.263 + tty->print_cr("Can't open /proc/self/mountinfo, %s", 8.264 + strerror(errno)); 8.265 + } 8.266 + return; 8.267 + } 8.268 + 8.269 + while ( (p = fgets(buf, MAXPATHLEN, mntinfo)) != NULL) { 8.270 + // Look for the filesystem type and see if it's cgroup 8.271 + char fstype[MAXPATHLEN+1]; 8.272 + fstype[0] = '\0'; 8.273 + char *s = strstr(p, " - "); 8.274 + if (s != NULL && 8.275 + sscanf(s, " - %s", fstype) == 1 && 8.276 + strcmp(fstype, "cgroup") == 0) { 8.277 + 8.278 + if (strstr(p, "memory") != NULL) { 8.279 + int matched = sscanf(p, "%d %d %d:%d %s %s", 8.280 + &mountid, 8.281 + &parentid, 8.282 + &major, 8.283 + &minor, 8.284 + tmproot, 8.285 + tmpmount); 8.286 + if (matched == 6) { 8.287 + memory = new CgroupSubsystem(tmproot, tmpmount); 8.288 + } 8.289 + else 8.290 + if (PrintContainerInfo) { 8.291 + tty->print_cr("Incompatible str containing cgroup and memory: %s", p); 8.292 + } 8.293 + } else if (strstr(p, "cpuset") != NULL) { 8.294 + int matched = sscanf(p, "%d %d %d:%d %s %s", 8.295 + &mountid, 8.296 + &parentid, 8.297 + &major, 8.298 + &minor, 8.299 + tmproot, 8.300 + tmpmount); 8.301 + if (matched == 6) { 8.302 + cpuset = new CgroupSubsystem(tmproot, tmpmount); 8.303 + } 8.304 + else { 8.305 + if (PrintContainerInfo) { 8.306 + tty->print_cr("Incompatible str containing cgroup and cpuset: %s", p); 8.307 + } 8.308 + } 8.309 + } else if (strstr(p, "cpu,cpuacct") != NULL || strstr(p, "cpuacct,cpu") != NULL) { 8.310 + int matched = sscanf(p, "%d %d %d:%d %s %s", 8.311 + &mountid, 8.312 + &parentid, 8.313 + &major, 8.314 + &minor, 8.315 + tmproot, 8.316 + tmpmount); 8.317 + if (matched == 6) { 8.318 + cpu = new CgroupSubsystem(tmproot, tmpmount); 8.319 + cpuacct = new CgroupSubsystem(tmproot, tmpmount); 8.320 + } 8.321 + else { 8.322 + if (PrintContainerInfo) { 8.323 + tty->print_cr("Incompatible str containing cgroup and cpu,cpuacct: %s", p); 8.324 + } 8.325 + } 8.326 + } else if (strstr(p, "cpuacct") != NULL) { 8.327 + int matched = sscanf(p, "%d %d %d:%d %s %s", 8.328 + &mountid, 8.329 + &parentid, 8.330 + &major, 8.331 + &minor, 8.332 + tmproot, 8.333 + tmpmount); 8.334 + if (matched == 6) { 8.335 + cpuacct = new CgroupSubsystem(tmproot, tmpmount); 8.336 + } 8.337 + else { 8.338 + if (PrintContainerInfo) { 8.339 + tty->print_cr("Incompatible str containing cgroup and cpuacct: %s", p); 8.340 + } 8.341 + } 8.342 + } else if (strstr(p, "cpu") != NULL) { 8.343 + int matched = sscanf(p, "%d %d %d:%d %s %s", 8.344 + &mountid, 8.345 + &parentid, 8.346 + &major, 8.347 + &minor, 8.348 + tmproot, 8.349 + tmpmount); 8.350 + if (matched == 6) { 8.351 + cpu = new CgroupSubsystem(tmproot, tmpmount); 8.352 + } 8.353 + else { 8.354 + if (PrintContainerInfo) { 8.355 + tty->print_cr("Incompatible str containing cgroup and cpu: %s", p); 8.356 + } 8.357 + } 8.358 + } 8.359 + } 8.360 + } 8.361 + 8.362 + fclose(mntinfo); 8.363 + 8.364 + if (memory == NULL) { 8.365 + if (PrintContainerInfo) { 8.366 + tty->print_cr("Required cgroup memory subsystem not found"); 8.367 + } 8.368 + return; 8.369 + } 8.370 + if (cpuset == NULL) { 8.371 + if (PrintContainerInfo) { 8.372 + tty->print_cr("Required cgroup cpuset subsystem not found"); 8.373 + } 8.374 + return; 8.375 + } 8.376 + if (cpu == NULL) { 8.377 + if (PrintContainerInfo) { 8.378 + tty->print_cr("Required cgroup cpu subsystem not found"); 8.379 + } 8.380 + return; 8.381 + } 8.382 + if (cpuacct == NULL) { 8.383 + if (PrintContainerInfo) { 8.384 + tty->print_cr("Required cgroup cpuacct subsystem not found"); 8.385 + } 8.386 + return; 8.387 + } 8.388 + 8.389 + /* 8.390 + * Read /proc/self/cgroup and map host mount point to 8.391 + * local one via /proc/self/mountinfo content above 8.392 + * 8.393 + * Docker example: 8.394 + * 5:memory:/docker/6558aed8fc662b194323ceab5b964f69cf36b3e8af877a14b80256e93aecb044 8.395 + * 8.396 + * Host example: 8.397 + * 5:memory:/user.slice 8.398 + * 8.399 + * Construct a path to the process specific memory and cpuset 8.400 + * cgroup directory. 8.401 + * 8.402 + * For a container running under Docker from memory example above 8.403 + * the paths would be: 8.404 + * 8.405 + * /sys/fs/cgroup/memory 8.406 + * 8.407 + * For a Host from memory example above the path would be: 8.408 + * 8.409 + * /sys/fs/cgroup/memory/user.slice 8.410 + * 8.411 + */ 8.412 + cgroup = fopen("/proc/self/cgroup", "r"); 8.413 + if (cgroup == NULL) { 8.414 + if (PrintContainerInfo) { 8.415 + tty->print_cr("Can't open /proc/self/cgroup, %s", 8.416 + strerror(errno)); 8.417 + } 8.418 + return; 8.419 + } 8.420 + 8.421 + while ( (p = fgets(buf, MAXPATHLEN, cgroup)) != NULL) { 8.422 + int cgno; 8.423 + int matched; 8.424 + char *controller; 8.425 + char *base; 8.426 + 8.427 + /* Skip cgroup number */ 8.428 + strsep(&p, ":"); 8.429 + /* Get controller and base */ 8.430 + controller = strsep(&p, ":"); 8.431 + base = strsep(&p, "\n"); 8.432 + 8.433 + if (controller != NULL) { 8.434 + if (strstr(controller, "memory") != NULL) { 8.435 + memory->set_subsystem_path(base); 8.436 + } else if (strstr(controller, "cpuset") != NULL) { 8.437 + cpuset->set_subsystem_path(base); 8.438 + } else if (strstr(controller, "cpu,cpuacct") != NULL || strstr(controller, "cpuacct,cpu") != NULL) { 8.439 + cpu->set_subsystem_path(base); 8.440 + cpuacct->set_subsystem_path(base); 8.441 + } else if (strstr(controller, "cpuacct") != NULL) { 8.442 + cpuacct->set_subsystem_path(base); 8.443 + } else if (strstr(controller, "cpu") != NULL) { 8.444 + cpu->set_subsystem_path(base); 8.445 + } 8.446 + } 8.447 + } 8.448 + 8.449 + fclose(cgroup); 8.450 + 8.451 + // We need to update the amount of physical memory now that 8.452 + // command line arguments have been processed. 8.453 + if ((mem_limit = memory_limit_in_bytes()) > 0) { 8.454 + os::Linux::set_physical_memory(mem_limit); 8.455 + } 8.456 + 8.457 + _is_containerized = true; 8.458 + 8.459 +} 8.460 + 8.461 +const char * OSContainer::container_type() { 8.462 + if (is_containerized()) { 8.463 + return "cgroupv1"; 8.464 + } else { 8.465 + return NULL; 8.466 + } 8.467 +} 8.468 + 8.469 + 8.470 +/* memory_limit_in_bytes 8.471 + * 8.472 + * Return the limit of available memory for this process. 8.473 + * 8.474 + * return: 8.475 + * memory limit in bytes or 8.476 + * -1 for unlimited 8.477 + * OSCONTAINER_ERROR for not supported 8.478 + */ 8.479 +jlong OSContainer::memory_limit_in_bytes() { 8.480 + GET_CONTAINER_INFO(julong, memory, "/memory.limit_in_bytes", 8.481 + "Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, memlimit); 8.482 + 8.483 + if (memlimit >= _unlimited_memory) { 8.484 + if (PrintContainerInfo) { 8.485 + tty->print_cr("Memory Limit is: Unlimited"); 8.486 + } 8.487 + return (jlong)-1; 8.488 + } 8.489 + else { 8.490 + return (jlong)memlimit; 8.491 + } 8.492 +} 8.493 + 8.494 +jlong OSContainer::memory_and_swap_limit_in_bytes() { 8.495 + GET_CONTAINER_INFO(julong, memory, "/memory.memsw.limit_in_bytes", 8.496 + "Memory and Swap Limit is: " JULONG_FORMAT, JULONG_FORMAT, memswlimit); 8.497 + if (memswlimit >= _unlimited_memory) { 8.498 + if (PrintContainerInfo) { 8.499 + tty->print_cr("Memory and Swap Limit is: Unlimited"); 8.500 + } 8.501 + return (jlong)-1; 8.502 + } else { 8.503 + return (jlong)memswlimit; 8.504 + } 8.505 +} 8.506 + 8.507 +jlong OSContainer::memory_soft_limit_in_bytes() { 8.508 + GET_CONTAINER_INFO(julong, memory, "/memory.soft_limit_in_bytes", 8.509 + "Memory Soft Limit is: " JULONG_FORMAT, JULONG_FORMAT, memsoftlimit); 8.510 + if (memsoftlimit >= _unlimited_memory) { 8.511 + if (PrintContainerInfo) { 8.512 + tty->print_cr("Memory Soft Limit is: Unlimited"); 8.513 + } 8.514 + return (jlong)-1; 8.515 + } else { 8.516 + return (jlong)memsoftlimit; 8.517 + } 8.518 +} 8.519 + 8.520 +/* memory_usage_in_bytes 8.521 + * 8.522 + * Return the amount of used memory for this process. 8.523 + * 8.524 + * return: 8.525 + * memory usage in bytes or 8.526 + * -1 for unlimited 8.527 + * OSCONTAINER_ERROR for not supported 8.528 + */ 8.529 +jlong OSContainer::memory_usage_in_bytes() { 8.530 + GET_CONTAINER_INFO(jlong, memory, "/memory.usage_in_bytes", 8.531 + "Memory Usage is: " JLONG_FORMAT, JLONG_FORMAT, memusage); 8.532 + return memusage; 8.533 +} 8.534 + 8.535 +/* memory_max_usage_in_bytes 8.536 + * 8.537 + * Return the maximum amount of used memory for this process. 8.538 + * 8.539 + * return: 8.540 + * max memory usage in bytes or 8.541 + * OSCONTAINER_ERROR for not supported 8.542 + */ 8.543 +jlong OSContainer::memory_max_usage_in_bytes() { 8.544 + GET_CONTAINER_INFO(jlong, memory, "/memory.max_usage_in_bytes", 8.545 + "Maximum Memory Usage is: " JLONG_FORMAT, JLONG_FORMAT, memmaxusage); 8.546 + return memmaxusage; 8.547 +} 8.548 + 8.549 +/* active_processor_count 8.550 + * 8.551 + * Calculate an appropriate number of active processors for the 8.552 + * VM to use based on these three inputs. 8.553 + * 8.554 + * cpu affinity 8.555 + * cgroup cpu quota & cpu period 8.556 + * cgroup cpu shares 8.557 + * 8.558 + * Algorithm: 8.559 + * 8.560 + * Determine the number of available CPUs from sched_getaffinity 8.561 + * 8.562 + * If user specified a quota (quota != -1), calculate the number of 8.563 + * required CPUs by dividing quota by period. 8.564 + * 8.565 + * If shares are in effect (shares != -1), calculate the number 8.566 + * of CPUs required for the shares by dividing the share value 8.567 + * by PER_CPU_SHARES. 8.568 + * 8.569 + * All results of division are rounded up to the next whole number. 8.570 + * 8.571 + * If neither shares or quotas have been specified, return the 8.572 + * number of active processors in the system. 8.573 + * 8.574 + * If both shares and quotas have been specified, the results are 8.575 + * based on the flag PreferContainerQuotaForCPUCount. If true, 8.576 + * return the quota value. If false return the smallest value 8.577 + * between shares or quotas. 8.578 + * 8.579 + * If shares and/or quotas have been specified, the resulting number 8.580 + * returned will never exceed the number of active processors. 8.581 + * 8.582 + * return: 8.583 + * number of CPUs 8.584 + */ 8.585 +int OSContainer::active_processor_count() { 8.586 + int quota_count = 0, share_count = 0; 8.587 + int cpu_count, limit_count; 8.588 + int result; 8.589 + 8.590 + cpu_count = limit_count = os::Linux::active_processor_count(); 8.591 + int quota = cpu_quota(); 8.592 + int period = cpu_period(); 8.593 + int share = cpu_shares(); 8.594 + 8.595 + if (quota > -1 && period > 0) { 8.596 + quota_count = ceilf((float)quota / (float)period); 8.597 + if (PrintContainerInfo) { 8.598 + tty->print_cr("CPU Quota count based on quota/period: %d", quota_count); 8.599 + } 8.600 + } 8.601 + if (share > -1) { 8.602 + share_count = ceilf((float)share / (float)PER_CPU_SHARES); 8.603 + if (PrintContainerInfo) { 8.604 + tty->print_cr("CPU Share count based on shares: %d", share_count); 8.605 + } 8.606 + } 8.607 + 8.608 + // If both shares and quotas are setup results depend 8.609 + // on flag PreferContainerQuotaForCPUCount. 8.610 + // If true, limit CPU count to quota 8.611 + // If false, use minimum of shares and quotas 8.612 + if (quota_count !=0 && share_count != 0) { 8.613 + if (PreferContainerQuotaForCPUCount) { 8.614 + limit_count = quota_count; 8.615 + } else { 8.616 + limit_count = MIN2(quota_count, share_count); 8.617 + } 8.618 + } else if (quota_count != 0) { 8.619 + limit_count = quota_count; 8.620 + } else if (share_count != 0) { 8.621 + limit_count = share_count; 8.622 + } 8.623 + 8.624 + result = MIN2(cpu_count, limit_count); 8.625 + if (PrintContainerInfo) { 8.626 + tty->print_cr("OSContainer::active_processor_count: %d", result); 8.627 + } 8.628 + return result; 8.629 +} 8.630 + 8.631 +char * OSContainer::cpu_cpuset_cpus() { 8.632 + GET_CONTAINER_INFO_CPTR(cptr, cpuset, "/cpuset.cpus", 8.633 + "cpuset.cpus is: %s", "%1023s", cpus, 1024); 8.634 + return os::strdup(cpus); 8.635 +} 8.636 + 8.637 +char * OSContainer::cpu_cpuset_memory_nodes() { 8.638 + GET_CONTAINER_INFO_CPTR(cptr, cpuset, "/cpuset.mems", 8.639 + "cpuset.mems is: %s", "%1023s", mems, 1024); 8.640 + return os::strdup(mems); 8.641 +} 8.642 + 8.643 +/* cpu_quota 8.644 + * 8.645 + * Return the number of milliseconds per period 8.646 + * process is guaranteed to run. 8.647 + * 8.648 + * return: 8.649 + * quota time in milliseconds 8.650 + * -1 for no quota 8.651 + * OSCONTAINER_ERROR for not supported 8.652 + */ 8.653 +int OSContainer::cpu_quota() { 8.654 + GET_CONTAINER_INFO(int, cpu, "/cpu.cfs_quota_us", 8.655 + "CPU Quota is: %d", "%d", quota); 8.656 + return quota; 8.657 +} 8.658 + 8.659 +int OSContainer::cpu_period() { 8.660 + GET_CONTAINER_INFO(int, cpu, "/cpu.cfs_period_us", 8.661 + "CPU Period is: %d", "%d", period); 8.662 + return period; 8.663 +} 8.664 + 8.665 +/* cpu_shares 8.666 + * 8.667 + * Return the amount of cpu shares available to the process 8.668 + * 8.669 + * return: 8.670 + * Share number (typically a number relative to 1024) 8.671 + * (2048 typically expresses 2 CPUs worth of processing) 8.672 + * -1 for no share setup 8.673 + * OSCONTAINER_ERROR for not supported 8.674 + */ 8.675 +int OSContainer::cpu_shares() { 8.676 + GET_CONTAINER_INFO(int, cpu, "/cpu.shares", 8.677 + "CPU Shares is: %d", "%d", shares); 8.678 + // Convert 1024 to no shares setup 8.679 + if (shares == 1024) return -1; 8.680 + 8.681 + return shares; 8.682 +} 8.683 +
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/src/os/linux/vm/osContainer_linux.hpp Mon Jul 09 15:45:22 2018 +0000 9.3 @@ -0,0 +1,68 @@ 9.4 +/* 9.5 + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 9.7 + * 9.8 + * This code is free software; you can redistribute it and/or modify it 9.9 + * under the terms of the GNU General Public License version 2 only, as 9.10 + * published by the Free Software Foundation. 9.11 + * 9.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 9.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 9.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 9.15 + * version 2 for more details (a copy is included in the LICENSE file that 9.16 + * accompanied this code). 9.17 + * 9.18 + * You should have received a copy of the GNU General Public License version 9.19 + * 2 along with this work; if not, write to the Free Software Foundation, 9.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 9.21 + * 9.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 9.23 + * or visit www.oracle.com if you need additional information or have any 9.24 + * questions. 9.25 + * 9.26 + */ 9.27 + 9.28 +#ifndef OS_LINUX_VM_OSCONTAINER_LINUX_HPP 9.29 +#define OS_LINUX_VM_OSCONTAINER_LINUX_HPP 9.30 + 9.31 +#include "utilities/globalDefinitions.hpp" 9.32 +#include "utilities/macros.hpp" 9.33 +#include "memory/allocation.hpp" 9.34 + 9.35 +#define OSCONTAINER_ERROR (-2) 9.36 + 9.37 +class OSContainer: AllStatic { 9.38 + 9.39 + private: 9.40 + static bool _is_initialized; 9.41 + static bool _is_containerized; 9.42 + 9.43 + public: 9.44 + static void init(); 9.45 + static inline bool is_containerized(); 9.46 + static const char * container_type(); 9.47 + 9.48 + static jlong memory_limit_in_bytes(); 9.49 + static jlong memory_and_swap_limit_in_bytes(); 9.50 + static jlong memory_soft_limit_in_bytes(); 9.51 + static jlong memory_usage_in_bytes(); 9.52 + static jlong memory_max_usage_in_bytes(); 9.53 + 9.54 + static int active_processor_count(); 9.55 + 9.56 + static char * cpu_cpuset_cpus(); 9.57 + static char * cpu_cpuset_memory_nodes(); 9.58 + 9.59 + static int cpu_quota(); 9.60 + static int cpu_period(); 9.61 + 9.62 + static int cpu_shares(); 9.63 + 9.64 +}; 9.65 + 9.66 +inline bool OSContainer::is_containerized() { 9.67 + assert(_is_initialized, "OSContainer not initialized"); 9.68 + return _is_containerized; 9.69 +} 9.70 + 9.71 +#endif // OS_LINUX_VM_OSCONTAINER_LINUX_HPP
10.1 --- a/src/os/linux/vm/os_linux.cpp Mon Jul 09 05:53:08 2018 -0700 10.2 +++ b/src/os/linux/vm/os_linux.cpp Mon Jul 09 15:45:22 2018 +0000 10.3 @@ -37,6 +37,7 @@ 10.4 #include "mutex_linux.inline.hpp" 10.5 #include "oops/oop.inline.hpp" 10.6 #include "os_share_linux.hpp" 10.7 +#include "osContainer_linux.hpp" 10.8 #include "prims/jniFastGetField.hpp" 10.9 #include "prims/jvm.h" 10.10 #include "prims/jvm_misc.hpp" 10.11 @@ -179,13 +180,62 @@ 10.12 julong os::Linux::available_memory() { 10.13 // values in struct sysinfo are "unsigned long" 10.14 struct sysinfo si; 10.15 + julong avail_mem; 10.16 + 10.17 + if (OSContainer::is_containerized()) { 10.18 + jlong mem_limit, mem_usage; 10.19 + if ((mem_limit = OSContainer::memory_limit_in_bytes()) < 1) { 10.20 + if (PrintContainerInfo) { 10.21 + tty->print_cr("container memory limit %s: " JLONG_FORMAT ", using host value", 10.22 + mem_limit == OSCONTAINER_ERROR ? "failed" : "unlimited", mem_limit); 10.23 + } 10.24 + } 10.25 + 10.26 + if (mem_limit > 0 && (mem_usage = OSContainer::memory_usage_in_bytes()) < 1) { 10.27 + if (PrintContainerInfo) { 10.28 + tty->print_cr("container memory usage failed: " JLONG_FORMAT ", using host value", mem_usage); 10.29 + } 10.30 + } 10.31 + 10.32 + if (mem_limit > 0 && mem_usage > 0 ) { 10.33 + avail_mem = mem_limit > mem_usage ? (julong)mem_limit - (julong)mem_usage : 0; 10.34 + if (PrintContainerInfo) { 10.35 + tty->print_cr("available container memory: " JULONG_FORMAT, avail_mem); 10.36 + } 10.37 + return avail_mem; 10.38 + } 10.39 + } 10.40 + 10.41 sysinfo(&si); 10.42 - 10.43 - return (julong)si.freeram * si.mem_unit; 10.44 + avail_mem = (julong)si.freeram * si.mem_unit; 10.45 + if (Verbose) { 10.46 + tty->print_cr("available memory: " JULONG_FORMAT, avail_mem); 10.47 + } 10.48 + return avail_mem; 10.49 } 10.50 10.51 julong os::physical_memory() { 10.52 - return Linux::physical_memory(); 10.53 + jlong phys_mem = 0; 10.54 + if (OSContainer::is_containerized()) { 10.55 + jlong mem_limit; 10.56 + if ((mem_limit = OSContainer::memory_limit_in_bytes()) > 0) { 10.57 + if (PrintContainerInfo) { 10.58 + tty->print_cr("total container memory: " JLONG_FORMAT, mem_limit); 10.59 + } 10.60 + return mem_limit; 10.61 + } 10.62 + 10.63 + if (PrintContainerInfo) { 10.64 + tty->print_cr("container memory limit %s: " JLONG_FORMAT ", using host value", 10.65 + mem_limit == OSCONTAINER_ERROR ? "failed" : "unlimited", mem_limit); 10.66 + } 10.67 + } 10.68 + 10.69 + phys_mem = Linux::physical_memory(); 10.70 + if (Verbose) { 10.71 + tty->print_cr("total system memory: " JLONG_FORMAT, phys_mem); 10.72 + } 10.73 + return phys_mem; 10.74 } 10.75 10.76 //////////////////////////////////////////////////////////////////////////////// 10.77 @@ -2120,6 +2170,8 @@ 10.78 os::Posix::print_load_average(st); 10.79 10.80 os::Linux::print_full_memory_info(st); 10.81 + 10.82 + os::Linux::print_container_info(st); 10.83 } 10.84 10.85 // Try to identify popular distros. 10.86 @@ -2185,6 +2237,57 @@ 10.87 st->cr(); 10.88 } 10.89 10.90 +void os::Linux::print_container_info(outputStream* st) { 10.91 +if (!OSContainer::is_containerized()) { 10.92 + return; 10.93 + } 10.94 + 10.95 + st->print("container (cgroup) information:\n"); 10.96 + 10.97 + const char *p_ct = OSContainer::container_type(); 10.98 + st->print("container_type: %s\n", p_ct != NULL ? p_ct : "failed"); 10.99 + 10.100 + char *p = OSContainer::cpu_cpuset_cpus(); 10.101 + st->print("cpu_cpuset_cpus: %s\n", p != NULL ? p : "failed"); 10.102 + free(p); 10.103 + 10.104 + p = OSContainer::cpu_cpuset_memory_nodes(); 10.105 + st->print("cpu_memory_nodes: %s\n", p != NULL ? p : "failed"); 10.106 + free(p); 10.107 + 10.108 + int i = OSContainer::active_processor_count(); 10.109 + if (i > 0) { 10.110 + st->print("active_processor_count: %d\n", i); 10.111 + } else { 10.112 + st->print("active_processor_count: failed\n"); 10.113 + } 10.114 + 10.115 + i = OSContainer::cpu_quota(); 10.116 + st->print("cpu_quota: %d\n", i); 10.117 + 10.118 + i = OSContainer::cpu_period(); 10.119 + st->print("cpu_period: %d\n", i); 10.120 + 10.121 + i = OSContainer::cpu_shares(); 10.122 + st->print("cpu_shares: %d\n", i); 10.123 + 10.124 + jlong j = OSContainer::memory_limit_in_bytes(); 10.125 + st->print("memory_limit_in_bytes: " JLONG_FORMAT "\n", j); 10.126 + 10.127 + j = OSContainer::memory_and_swap_limit_in_bytes(); 10.128 + st->print("memory_and_swap_limit_in_bytes: " JLONG_FORMAT "\n", j); 10.129 + 10.130 + j = OSContainer::memory_soft_limit_in_bytes(); 10.131 + st->print("memory_soft_limit_in_bytes: " JLONG_FORMAT "\n", j); 10.132 + 10.133 + j = OSContainer::OSContainer::memory_usage_in_bytes(); 10.134 + st->print("memory_usage_in_bytes: " JLONG_FORMAT "\n", j); 10.135 + 10.136 + j = OSContainer::OSContainer::memory_max_usage_in_bytes(); 10.137 + st->print("memory_max_usage_in_bytes: " JLONG_FORMAT "\n", j); 10.138 + st->cr(); 10.139 +} 10.140 + 10.141 void os::print_memory_info(outputStream* st) { 10.142 10.143 st->print("Memory:"); 10.144 @@ -4956,6 +5059,10 @@ 10.145 } 10.146 } 10.147 10.148 +void os::pd_init_container_support() { 10.149 + OSContainer::init(); 10.150 +} 10.151 + 10.152 // this is called _after_ the global arguments have been parsed 10.153 jint os::init_2(void) 10.154 { 10.155 @@ -5136,7 +5243,7 @@ 10.156 // sched_getaffinity gives an accurate answer as it accounts for cpusets. 10.157 // If anything goes wrong we fallback to returning the number of online 10.158 // processors - which can be greater than the number available to the process. 10.159 -int os::active_processor_count() { 10.160 +int os::Linux::active_processor_count() { 10.161 cpu_set_t cpus; // can represent at most 1024 (CPU_SETSIZE) processors 10.162 int cpus_size = sizeof(cpu_set_t); 10.163 int cpu_count = 0; 10.164 @@ -5154,10 +5261,48 @@ 10.165 "which may exceed available processors", strerror(errno), cpu_count); 10.166 } 10.167 10.168 - assert(cpu_count > 0 && cpu_count <= processor_count(), "sanity check"); 10.169 + assert(cpu_count > 0 && cpu_count <= os::processor_count(), "sanity check"); 10.170 return cpu_count; 10.171 } 10.172 10.173 +// Determine the active processor count from one of 10.174 +// three different sources: 10.175 +// 10.176 +// 1. User option -XX:ActiveProcessorCount 10.177 +// 2. kernel os calls (sched_getaffinity or sysconf(_SC_NPROCESSORS_ONLN) 10.178 +// 3. extracted from cgroup cpu subsystem (shares and quotas) 10.179 +// 10.180 +// Option 1, if specified, will always override. 10.181 +// If the cgroup subsystem is active and configured, we 10.182 +// will return the min of the cgroup and option 2 results. 10.183 +// This is required since tools, such as numactl, that 10.184 +// alter cpu affinity do not update cgroup subsystem 10.185 +// cpuset configuration files. 10.186 +int os::active_processor_count() { 10.187 + // User has overridden the number of active processors 10.188 + if (ActiveProcessorCount > 0) { 10.189 + if (PrintActiveCpus) { 10.190 + tty->print_cr("active_processor_count: " 10.191 + "active processor count set by user : %d", 10.192 + ActiveProcessorCount); 10.193 + } 10.194 + return ActiveProcessorCount; 10.195 + } 10.196 + 10.197 + int active_cpus; 10.198 + if (OSContainer::is_containerized()) { 10.199 + active_cpus = OSContainer::active_processor_count(); 10.200 + if (PrintActiveCpus) { 10.201 + tty->print_cr("active_processor_count: determined by OSContainer: %d", 10.202 + active_cpus); 10.203 + } 10.204 + } else { 10.205 + active_cpus = os::Linux::active_processor_count(); 10.206 + } 10.207 + 10.208 + return active_cpus; 10.209 +} 10.210 + 10.211 void os::set_native_thread_name(const char *name) { 10.212 // Not yet implemented. 10.213 return;
11.1 --- a/src/os/linux/vm/os_linux.hpp Mon Jul 09 05:53:08 2018 -0700 11.2 +++ b/src/os/linux/vm/os_linux.hpp Mon Jul 09 15:45:22 2018 +0000 11.3 @@ -35,6 +35,7 @@ 11.4 11.5 class Linux { 11.6 friend class os; 11.7 + friend class OSContainer; 11.8 friend class TestReserveMemorySpecial; 11.9 11.10 // For signal-chaining 11.11 @@ -79,6 +80,9 @@ 11.12 11.13 static julong available_memory(); 11.14 static julong physical_memory() { return _physical_memory; } 11.15 + static void set_physical_memory(julong phys_mem) { _physical_memory = phys_mem; } 11.16 + static int active_processor_count(); 11.17 + 11.18 static void initialize_system_info(); 11.19 11.20 static int commit_memory_impl(char* addr, size_t bytes, bool exec); 11.21 @@ -116,6 +120,7 @@ 11.22 static bool release_memory_special_huge_tlbfs(char* base, size_t bytes); 11.23 11.24 static void print_full_memory_info(outputStream* st); 11.25 + static void print_container_info(outputStream* st); 11.26 static void print_distro_info(outputStream* st); 11.27 static void print_libversion_info(outputStream* st); 11.28
12.1 --- a/src/os/solaris/vm/os_solaris.cpp Mon Jul 09 05:53:08 2018 -0700 12.2 +++ b/src/os/solaris/vm/os_solaris.cpp Mon Jul 09 15:45:22 2018 +0000 12.3 @@ -359,6 +359,16 @@ 12.4 } 12.5 12.6 int os::active_processor_count() { 12.7 + // User has overridden the number of active processors 12.8 + if (ActiveProcessorCount > 0) { 12.9 + if (Verbose) { 12.10 + tty->print_cr("active_processor_count: " 12.11 + "active processor count set by user : %d", 12.12 + ActiveProcessorCount); 12.13 + } 12.14 + return ActiveProcessorCount; 12.15 + } 12.16 + 12.17 int online_cpus = sysconf(_SC_NPROCESSORS_ONLN); 12.18 pid_t pid = getpid(); 12.19 psetid_t pset = PS_NONE;
13.1 --- a/src/os/windows/vm/os_windows.cpp Mon Jul 09 05:53:08 2018 -0700 13.2 +++ b/src/os/windows/vm/os_windows.cpp Mon Jul 09 15:45:22 2018 +0000 13.3 @@ -716,6 +716,16 @@ 13.4 #endif 13.5 13.6 int os::active_processor_count() { 13.7 + // User has overridden the number of active processors 13.8 + if (ActiveProcessorCount > 0) { 13.9 + if (PrintActiveCpus) { 13.10 + tty->print_cr("active_processor_count: " 13.11 + "active processor count set by user : %d", 13.12 + ActiveProcessorCount); 13.13 + } 13.14 + return ActiveProcessorCount; 13.15 + } 13.16 + 13.17 DWORD_PTR lpProcessAffinityMask = 0; 13.18 DWORD_PTR lpSystemAffinityMask = 0; 13.19 int proc_count = processor_count();
14.1 --- a/src/share/vm/runtime/arguments.cpp Mon Jul 09 05:53:08 2018 -0700 14.2 +++ b/src/share/vm/runtime/arguments.cpp Mon Jul 09 15:45:22 2018 +0000 14.3 @@ -1,5 +1,5 @@ 14.4 /* 14.5 - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 14.6 + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. 14.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 14.8 * 14.9 * This code is free software; you can redistribute it and/or modify it 14.10 @@ -1801,20 +1801,34 @@ 14.11 } 14.12 } 14.13 14.14 + // Convert Fraction to Precentage values 14.15 + if (FLAG_IS_DEFAULT(MaxRAMPercentage) && 14.16 + !FLAG_IS_DEFAULT(MaxRAMFraction)) 14.17 + MaxRAMPercentage = 100.0 / MaxRAMFraction; 14.18 + 14.19 + if (FLAG_IS_DEFAULT(MinRAMPercentage) && 14.20 + !FLAG_IS_DEFAULT(MinRAMFraction)) 14.21 + MinRAMPercentage = 100.0 / MinRAMFraction; 14.22 + 14.23 + if (FLAG_IS_DEFAULT(InitialRAMPercentage) && 14.24 + !FLAG_IS_DEFAULT(InitialRAMFraction)) 14.25 + InitialRAMPercentage = 100.0 / InitialRAMFraction; 14.26 + 14.27 // If the maximum heap size has not been set with -Xmx, 14.28 // then set it as fraction of the size of physical memory, 14.29 // respecting the maximum and minimum sizes of the heap. 14.30 if (FLAG_IS_DEFAULT(MaxHeapSize)) { 14.31 - julong reasonable_max = phys_mem / MaxRAMFraction; 14.32 - 14.33 - if (phys_mem <= MaxHeapSize * MinRAMFraction) { 14.34 + julong reasonable_max = (julong)((phys_mem * MaxRAMPercentage) / 100); 14.35 + const julong reasonable_min = (julong)((phys_mem * MinRAMPercentage) / 100); 14.36 + if (reasonable_min < MaxHeapSize) { 14.37 // Small physical memory, so use a minimum fraction of it for the heap 14.38 - reasonable_max = phys_mem / MinRAMFraction; 14.39 + reasonable_max = reasonable_min; 14.40 } else { 14.41 // Not-small physical memory, so require a heap at least 14.42 // as large as MaxHeapSize 14.43 reasonable_max = MAX2(reasonable_max, (julong)MaxHeapSize); 14.44 } 14.45 + 14.46 if (!FLAG_IS_DEFAULT(ErgoHeapSizeLimit) && ErgoHeapSizeLimit != 0) { 14.47 // Limit the heap size to ErgoHeapSizeLimit 14.48 reasonable_max = MIN2(reasonable_max, (julong)ErgoHeapSizeLimit); 14.49 @@ -1856,7 +1870,7 @@ 14.50 reasonable_minimum = limit_by_allocatable_memory(reasonable_minimum); 14.51 14.52 if (InitialHeapSize == 0) { 14.53 - julong reasonable_initial = phys_mem / InitialRAMFraction; 14.54 + julong reasonable_initial = (julong)((phys_mem * InitialRAMPercentage) / 100); 14.55 14.56 reasonable_initial = MAX3(reasonable_initial, reasonable_minimum, (julong)min_heap_size()); 14.57 reasonable_initial = MIN2(reasonable_initial, (julong)MaxHeapSize); 14.58 @@ -1881,6 +1895,94 @@ 14.59 } 14.60 } 14.61 14.62 +// This option inspects the machine and attempts to set various 14.63 +// parameters to be optimal for long-running, memory allocation 14.64 +// intensive jobs. It is intended for machines with large 14.65 +// amounts of cpu and memory. 14.66 +jint Arguments::set_aggressive_heap_flags() { 14.67 + // initHeapSize is needed since _initial_heap_size is 4 bytes on a 32 bit 14.68 + // VM, but we may not be able to represent the total physical memory 14.69 + // available (like having 8gb of memory on a box but using a 32bit VM). 14.70 + // Thus, we need to make sure we're using a julong for intermediate 14.71 + // calculations. 14.72 + julong initHeapSize; 14.73 + julong total_memory = os::physical_memory(); 14.74 + 14.75 + if (total_memory < (julong) 256 * M) { 14.76 + jio_fprintf(defaultStream::error_stream(), 14.77 + "You need at least 256mb of memory to use -XX:+AggressiveHeap\n"); 14.78 + vm_exit(1); 14.79 + } 14.80 + 14.81 + // The heap size is half of available memory, or (at most) 14.82 + // all of possible memory less 160mb (leaving room for the OS 14.83 + // when using ISM). This is the maximum; because adaptive sizing 14.84 + // is turned on below, the actual space used may be smaller. 14.85 + 14.86 + initHeapSize = MIN2(total_memory / (julong) 2, 14.87 + total_memory - (julong) 160 * M); 14.88 + 14.89 + initHeapSize = limit_by_allocatable_memory(initHeapSize); 14.90 + 14.91 + if (FLAG_IS_DEFAULT(MaxHeapSize)) { 14.92 + FLAG_SET_CMDLINE(uintx, MaxHeapSize, initHeapSize); 14.93 + FLAG_SET_CMDLINE(uintx, InitialHeapSize, initHeapSize); 14.94 + // Currently the minimum size and the initial heap sizes are the same. 14.95 + set_min_heap_size(initHeapSize); 14.96 + } 14.97 + if (FLAG_IS_DEFAULT(NewSize)) { 14.98 + // Make the young generation 3/8ths of the total heap. 14.99 + FLAG_SET_CMDLINE(uintx, NewSize, 14.100 + ((julong) MaxHeapSize / (julong) 8) * (julong) 3); 14.101 + FLAG_SET_CMDLINE(uintx, MaxNewSize, NewSize); 14.102 + } 14.103 + 14.104 +#ifndef _ALLBSD_SOURCE // UseLargePages is not yet supported on BSD. 14.105 + FLAG_SET_DEFAULT(UseLargePages, true); 14.106 +#endif 14.107 + 14.108 + // Increase some data structure sizes for efficiency 14.109 + FLAG_SET_CMDLINE(uintx, BaseFootPrintEstimate, MaxHeapSize); 14.110 + FLAG_SET_CMDLINE(bool, ResizeTLAB, false); 14.111 + FLAG_SET_CMDLINE(uintx, TLABSize, 256 * K); 14.112 + 14.113 + // See the OldPLABSize comment below, but replace 'after promotion' 14.114 + // with 'after copying'. YoungPLABSize is the size of the survivor 14.115 + // space per-gc-thread buffers. The default is 4kw. 14.116 + FLAG_SET_CMDLINE(uintx, YoungPLABSize, 256 * K); // Note: this is in words 14.117 + 14.118 + // OldPLABSize is the size of the buffers in the old gen that 14.119 + // UseParallelGC uses to promote live data that doesn't fit in the 14.120 + // survivor spaces. At any given time, there's one for each gc thread. 14.121 + // The default size is 1kw. These buffers are rarely used, since the 14.122 + // survivor spaces are usually big enough. For specjbb, however, there 14.123 + // are occasions when there's lots of live data in the young gen 14.124 + // and we end up promoting some of it. We don't have a definite 14.125 + // explanation for why bumping OldPLABSize helps, but the theory 14.126 + // is that a bigger PLAB results in retaining something like the 14.127 + // original allocation order after promotion, which improves mutator 14.128 + // locality. A minor effect may be that larger PLABs reduce the 14.129 + // number of PLAB allocation events during gc. The value of 8kw 14.130 + // was arrived at by experimenting with specjbb. 14.131 + FLAG_SET_CMDLINE(uintx, OldPLABSize, 8 * K); // Note: this is in words 14.132 + 14.133 + // Enable parallel GC and adaptive generation sizing 14.134 + FLAG_SET_CMDLINE(bool, UseParallelGC, true); 14.135 + 14.136 + // Encourage steady state memory management 14.137 + FLAG_SET_CMDLINE(uintx, ThresholdTolerance, 100); 14.138 + 14.139 + // This appears to improve mutator locality 14.140 + FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false); 14.141 + 14.142 + // Get around early Solaris scheduling bug 14.143 + // (affinity vs other jobs on system) 14.144 + // but disallow DR and offlining (5008695). 14.145 + FLAG_SET_CMDLINE(bool, BindGCTaskThreadsToCPUs, true); 14.146 + 14.147 + return JNI_OK; 14.148 +} 14.149 + 14.150 // This must be called after ergonomics because we want bytecode rewriting 14.151 // if the server compiler is used, or if UseSharedSpaces is disabled. 14.152 void Arguments::set_bytecode_flags() { 14.153 @@ -2644,6 +2746,14 @@ 14.154 return result; 14.155 } 14.156 14.157 + // We need to ensure processor and memory resources have been properly 14.158 + // configured - which may rely on arguments we just processed - before 14.159 + // doing the final argument processing. Any argument processing that 14.160 + // needs to know about processor and memory resources must occur after 14.161 + // this point. 14.162 + 14.163 + os::init_container_support(); 14.164 + 14.165 // Do final processing now that all arguments have been parsed 14.166 result = finalize_vm_init_args(&scp, scp_assembly_required); 14.167 if (result != JNI_OK) { 14.168 @@ -3117,94 +3227,6 @@ 14.169 _exit_hook = CAST_TO_FN_PTR(exit_hook_t, option->extraInfo); 14.170 } else if (match_option(option, "abort", &tail)) { 14.171 _abort_hook = CAST_TO_FN_PTR(abort_hook_t, option->extraInfo); 14.172 - // -XX:+AggressiveHeap 14.173 - } else if (match_option(option, "-XX:+AggressiveHeap", &tail)) { 14.174 - 14.175 - // This option inspects the machine and attempts to set various 14.176 - // parameters to be optimal for long-running, memory allocation 14.177 - // intensive jobs. It is intended for machines with large 14.178 - // amounts of cpu and memory. 14.179 - 14.180 - // initHeapSize is needed since _initial_heap_size is 4 bytes on a 32 bit 14.181 - // VM, but we may not be able to represent the total physical memory 14.182 - // available (like having 8gb of memory on a box but using a 32bit VM). 14.183 - // Thus, we need to make sure we're using a julong for intermediate 14.184 - // calculations. 14.185 - julong initHeapSize; 14.186 - julong total_memory = os::physical_memory(); 14.187 - 14.188 - if (total_memory < (julong)256*M) { 14.189 - jio_fprintf(defaultStream::error_stream(), 14.190 - "You need at least 256mb of memory to use -XX:+AggressiveHeap\n"); 14.191 - vm_exit(1); 14.192 - } 14.193 - 14.194 - // The heap size is half of available memory, or (at most) 14.195 - // all of possible memory less 160mb (leaving room for the OS 14.196 - // when using ISM). This is the maximum; because adaptive sizing 14.197 - // is turned on below, the actual space used may be smaller. 14.198 - 14.199 - initHeapSize = MIN2(total_memory / (julong)2, 14.200 - total_memory - (julong)160*M); 14.201 - 14.202 - initHeapSize = limit_by_allocatable_memory(initHeapSize); 14.203 - 14.204 - if (FLAG_IS_DEFAULT(MaxHeapSize)) { 14.205 - FLAG_SET_CMDLINE(uintx, MaxHeapSize, initHeapSize); 14.206 - FLAG_SET_CMDLINE(uintx, InitialHeapSize, initHeapSize); 14.207 - // Currently the minimum size and the initial heap sizes are the same. 14.208 - set_min_heap_size(initHeapSize); 14.209 - } 14.210 - if (FLAG_IS_DEFAULT(NewSize)) { 14.211 - // Make the young generation 3/8ths of the total heap. 14.212 - FLAG_SET_CMDLINE(uintx, NewSize, 14.213 - ((julong)MaxHeapSize / (julong)8) * (julong)3); 14.214 - FLAG_SET_CMDLINE(uintx, MaxNewSize, NewSize); 14.215 - } 14.216 - 14.217 -#ifndef _ALLBSD_SOURCE // UseLargePages is not yet supported on BSD. 14.218 - FLAG_SET_DEFAULT(UseLargePages, true); 14.219 -#endif 14.220 - 14.221 - // Increase some data structure sizes for efficiency 14.222 - FLAG_SET_CMDLINE(uintx, BaseFootPrintEstimate, MaxHeapSize); 14.223 - FLAG_SET_CMDLINE(bool, ResizeTLAB, false); 14.224 - FLAG_SET_CMDLINE(uintx, TLABSize, 256*K); 14.225 - 14.226 - // See the OldPLABSize comment below, but replace 'after promotion' 14.227 - // with 'after copying'. YoungPLABSize is the size of the survivor 14.228 - // space per-gc-thread buffers. The default is 4kw. 14.229 - FLAG_SET_CMDLINE(uintx, YoungPLABSize, 256*K); // Note: this is in words 14.230 - 14.231 - // OldPLABSize is the size of the buffers in the old gen that 14.232 - // UseParallelGC uses to promote live data that doesn't fit in the 14.233 - // survivor spaces. At any given time, there's one for each gc thread. 14.234 - // The default size is 1kw. These buffers are rarely used, since the 14.235 - // survivor spaces are usually big enough. For specjbb, however, there 14.236 - // are occasions when there's lots of live data in the young gen 14.237 - // and we end up promoting some of it. We don't have a definite 14.238 - // explanation for why bumping OldPLABSize helps, but the theory 14.239 - // is that a bigger PLAB results in retaining something like the 14.240 - // original allocation order after promotion, which improves mutator 14.241 - // locality. A minor effect may be that larger PLABs reduce the 14.242 - // number of PLAB allocation events during gc. The value of 8kw 14.243 - // was arrived at by experimenting with specjbb. 14.244 - FLAG_SET_CMDLINE(uintx, OldPLABSize, 8*K); // Note: this is in words 14.245 - 14.246 - // Enable parallel GC and adaptive generation sizing 14.247 - FLAG_SET_CMDLINE(bool, UseParallelGC, true); 14.248 - 14.249 - // Encourage steady state memory management 14.250 - FLAG_SET_CMDLINE(uintx, ThresholdTolerance, 100); 14.251 - 14.252 - // This appears to improve mutator locality 14.253 - FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false); 14.254 - 14.255 - // Get around early Solaris scheduling bug 14.256 - // (affinity vs other jobs on system) 14.257 - // but disallow DR and offlining (5008695). 14.258 - FLAG_SET_CMDLINE(bool, BindGCTaskThreadsToCPUs, true); 14.259 - 14.260 } else if (match_option(option, "-XX:+NeverTenure", &tail)) { 14.261 // The last option must always win. 14.262 FLAG_SET_CMDLINE(bool, AlwaysTenure, false); 14.263 @@ -3605,6 +3627,15 @@ 14.264 return JNI_ERR; 14.265 } 14.266 14.267 + // This must be done after all arguments have been processed 14.268 + // and the container support has been initialized since AggressiveHeap 14.269 + // relies on the amount of total memory available. 14.270 + if (AggressiveHeap) { 14.271 + jint result = set_aggressive_heap_flags(); 14.272 + if (result != JNI_OK) { 14.273 + return result; 14.274 + } 14.275 + } 14.276 // This must be done after all arguments have been processed. 14.277 // java_compiler() true means set to "NONE" or empty. 14.278 if (java_compiler() && !xdebug_mode()) {
15.1 --- a/src/share/vm/runtime/arguments.hpp Mon Jul 09 05:53:08 2018 -0700 15.2 +++ b/src/share/vm/runtime/arguments.hpp Mon Jul 09 15:45:22 2018 +0000 15.3 @@ -1,5 +1,5 @@ 15.4 /* 15.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 15.6 + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. 15.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 15.8 * 15.9 * This code is free software; you can redistribute it and/or modify it 15.10 @@ -365,6 +365,8 @@ 15.11 // Aggressive optimization flags. 15.12 static void set_aggressive_opts_flags(); 15.13 15.14 + static jint set_aggressive_heap_flags(); 15.15 + 15.16 // Argument parsing 15.17 static void do_pd_flag_adjustments(); 15.18 static bool parse_argument(const char* arg, Flag::Flags origin);
16.1 --- a/src/share/vm/runtime/globals.hpp Mon Jul 09 05:53:08 2018 -0700 16.2 +++ b/src/share/vm/runtime/globals.hpp Mon Jul 09 15:45:22 2018 +0000 16.3 @@ -2068,13 +2068,23 @@ 16.4 product_pd(uint64_t, MaxRAM, \ 16.5 "Real memory size (in bytes) used to set maximum heap size") \ 16.6 \ 16.7 + product(bool, AggressiveHeap, false, \ 16.8 + "Optimize heap options for long-running memory intensive apps") \ 16.9 + \ 16.10 product(uintx, ErgoHeapSizeLimit, 0, \ 16.11 "Maximum ergonomically set heap size (in bytes); zero means use " \ 16.12 - "MaxRAM / MaxRAMFraction") \ 16.13 + "MaxRAM * MaxRAMPercentage / 100") \ 16.14 \ 16.15 experimental(bool, UseCGroupMemoryLimitForHeap, false, \ 16.16 "Use CGroup memory limit as physical memory limit for heap " \ 16.17 - "sizing") \ 16.18 + "sizing" \ 16.19 + "Deprecated, replaced by container support") \ 16.20 + \ 16.21 + diagnostic(bool, PrintContainerInfo, false, \ 16.22 + "Print container related information") \ 16.23 + \ 16.24 + diagnostic(bool, PrintActiveCpus, false, \ 16.25 + "Print the number of CPUs detected in os::active_processor_count") \ 16.26 \ 16.27 product(uintx, MaxRAMFraction, 4, \ 16.28 "Maximum fraction (1/n) of real memory used for maximum heap " \ 16.29 @@ -2091,6 +2101,19 @@ 16.30 product(uintx, InitialRAMFraction, 64, \ 16.31 "Fraction (1/n) of real memory used for initial heap size") \ 16.32 \ 16.33 + product(double, MaxRAMPercentage, 25.0, \ 16.34 + "Maximum percentage of real memory used for maximum heap size") \ 16.35 + \ 16.36 + product(double, MinRAMPercentage, 50.0, \ 16.37 + "Minimum percentage of real memory used for maximum heap" \ 16.38 + "size on systems with small physical memory size") \ 16.39 + \ 16.40 + product(double, InitialRAMPercentage, 1.5625, \ 16.41 + "Percentage of real memory used for initial heap size") \ 16.42 + \ 16.43 + product(intx, ActiveProcessorCount, -1, \ 16.44 + "Specify the CPU count the VM should use and report as active") \ 16.45 + \ 16.46 develop(uintx, MaxVirtMemFraction, 2, \ 16.47 "Maximum fraction (1/n) of virtual memory used for ergonomically "\ 16.48 "determining maximum heap size") \
17.1 --- a/src/share/vm/runtime/os.hpp Mon Jul 09 05:53:08 2018 -0700 17.2 +++ b/src/share/vm/runtime/os.hpp Mon Jul 09 15:45:22 2018 +0000 17.3 @@ -152,8 +152,16 @@ 17.4 static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned); 17.5 17.6 static void initialize_initial_active_processor_count(); 17.7 + 17.8 + LINUX_ONLY(static void pd_init_container_support();) 17.9 + 17.10 public: 17.11 static void init(void); // Called before command line parsing 17.12 + 17.13 + static void init_container_support() { // Called during command line parsing. 17.14 + LINUX_ONLY(pd_init_container_support();) 17.15 + } 17.16 + 17.17 static void init_before_ergo(void); // Called after command line parsing 17.18 // before VM ergonomics processing. 17.19 static jint init_2(void); // Called after command line parsing
18.1 --- a/src/share/vm/runtime/thread.cpp Mon Jul 09 05:53:08 2018 -0700 18.2 +++ b/src/share/vm/runtime/thread.cpp Mon Jul 09 15:45:22 2018 +0000 18.3 @@ -3343,6 +3343,7 @@ 18.4 Arguments::init_version_specific_system_properties(); 18.5 18.6 // Parse arguments 18.7 + // Note: this internally calls os::init_container_support() 18.8 jint parse_result = Arguments::parse(args); 18.9 if (parse_result != JNI_OK) return parse_result; 18.10