Merge

Fri, 27 Jul 2018 11:47:10 +0100

author
aefimov
date
Fri, 27 Jul 2018 11:47:10 +0100
changeset 9522
1b03cb76a59e
parent 9521
aec3b5f4ae34
parent 9415
541c205d7fd1
child 9523
09e0cda9f53d

Merge

.hgtags file | annotate | diff | comparison | revisions
     1.1 --- a/.hgtags	Wed Jul 11 15:59:47 2018 +0100
     1.2 +++ b/.hgtags	Fri Jul 27 11:47:10 2018 +0100
     1.3 @@ -1190,3 +1190,5 @@
     1.4  eed8e846c982d7474dd07fc873ba02f83ad1f847 jdk8u181-b13
     1.5  21a3fffc43418f4d75c2091bf03478330b8a9a98 jdk8u191-b01
     1.6  2bf8498a25ec87c92584a6542f8724644c8c5706 jdk8u201-b00
     1.7 +5aa3d728164a674d08ad847811be6bdd853e9bf8 jdk8u191-b02
     1.8 +dd79b482625361458b2b34e7d669ee982eee06a4 jdk8u191-b03
     2.1 --- a/src/os/aix/vm/os_aix.cpp	Wed Jul 11 15:59:47 2018 +0100
     2.2 +++ b/src/os/aix/vm/os_aix.cpp	Fri Jul 27 11:47:10 2018 +0100
     2.3 @@ -4008,6 +4008,16 @@
     2.4  };
     2.5  
     2.6  int os::active_processor_count() {
     2.7 +  // User has overridden the number of active processors
     2.8 +  if (ActiveProcessorCount > 0) {
     2.9 +    if (PrintActiveCpus) {
    2.10 +      tty->print_cr("active_processor_count: "
    2.11 +                    "active processor count set by user : %d",
    2.12 +                     ActiveProcessorCount);
    2.13 +    }
    2.14 +    return ActiveProcessorCount;
    2.15 +  }
    2.16 +
    2.17    int online_cpus = ::sysconf(_SC_NPROCESSORS_ONLN);
    2.18    assert(online_cpus > 0 && online_cpus <= processor_count(), "sanity check");
    2.19    return online_cpus;
     3.1 --- a/src/os/bsd/vm/os_bsd.cpp	Wed Jul 11 15:59:47 2018 +0100
     3.2 +++ b/src/os/bsd/vm/os_bsd.cpp	Fri Jul 27 11:47:10 2018 +0100
     3.3 @@ -3765,6 +3765,16 @@
     3.4  };
     3.5  
     3.6  int os::active_processor_count() {
     3.7 +  // User has overridden the number of active processors
     3.8 +  if (ActiveProcessorCount > 0) {
     3.9 +    if (PrintActiveCpus) {
    3.10 +      tty->print_cr("active_processor_count: "
    3.11 +                    "active processor count set by user : %d",
    3.12 +                     ActiveProcessorCount);
    3.13 +    }
    3.14 +    return ActiveProcessorCount;
    3.15 +  }
    3.16 +
    3.17    return _processor_count;
    3.18  }
    3.19  
     4.1 --- a/src/os/linux/vm/globals_linux.hpp	Wed Jul 11 15:59:47 2018 +0100
     4.2 +++ b/src/os/linux/vm/globals_linux.hpp	Fri Jul 27 11:47:10 2018 +0100
     4.3 @@ -1,5 +1,5 @@
     4.4  /*
     4.5 - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
     4.6 + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
     4.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.8   *
     4.9   * This code is free software; you can redistribute it and/or modify it
    4.10 @@ -49,8 +49,13 @@
    4.11    product(bool, UseSHM, false,                                          \
    4.12            "Use SYSV shared memory for large pages")                     \
    4.13                                                                          \
    4.14 -  diagnostic(bool, PrintActiveCpus, false,                              \
    4.15 -          "Print the number of CPUs detected in os::active_processor_count")
    4.16 +  product(bool, UseContainerSupport, true,                              \
    4.17 +          "Enable detection and runtime container configuration support") \
    4.18 +                                                                        \
    4.19 +  product(bool, PreferContainerQuotaForCPUCount, true,                  \
    4.20 +          "Calculate the container CPU availability based on the value" \
    4.21 +          " of quotas (if set), when true. Otherwise, use the CPU"      \
    4.22 +          " shares value, provided it is less than quota.")
    4.23  
    4.24  //
    4.25  // Defines Linux-specific default values. The flags are available on all
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/os/linux/vm/osContainer_linux.cpp	Fri Jul 27 11:47:10 2018 +0100
     5.3 @@ -0,0 +1,680 @@
     5.4 +/*
     5.5 + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
     5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5.7 + *
     5.8 + * This code is free software; you can redistribute it and/or modify it
     5.9 + * under the terms of the GNU General Public License version 2 only, as
    5.10 + * published by the Free Software Foundation.
    5.11 + *
    5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    5.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    5.15 + * version 2 for more details (a copy is included in the LICENSE file that
    5.16 + * accompanied this code).
    5.17 + *
    5.18 + * You should have received a copy of the GNU General Public License version
    5.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    5.21 + *
    5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    5.23 + * or visit www.oracle.com if you need additional information or have any
    5.24 + * questions.
    5.25 + *
    5.26 + */
    5.27 +
    5.28 +#include <string.h>
    5.29 +#include <math.h>
    5.30 +#include <errno.h>
    5.31 +#include "utilities/globalDefinitions.hpp"
    5.32 +#include "memory/allocation.hpp"
    5.33 +#include "runtime/os.hpp"
    5.34 +#include "osContainer_linux.hpp"
    5.35 +
    5.36 +#define PER_CPU_SHARES 1024
    5.37 +
    5.38 +bool  OSContainer::_is_initialized   = false;
    5.39 +bool  OSContainer::_is_containerized = false;
    5.40 +julong _unlimited_memory;
    5.41 +
    5.42 +class CgroupSubsystem: CHeapObj<mtInternal> {
    5.43 + friend class OSContainer;
    5.44 +
    5.45 + private:
    5.46 +    /* mountinfo contents */
    5.47 +    char *_root;
    5.48 +    char *_mount_point;
    5.49 +
    5.50 +    /* Constructed subsystem directory */
    5.51 +    char *_path;
    5.52 +
    5.53 + public:
    5.54 +    CgroupSubsystem(char *root, char *mountpoint) {
    5.55 +      _root = os::strdup(root);
    5.56 +      _mount_point = os::strdup(mountpoint);
    5.57 +      _path = NULL;
    5.58 +    }
    5.59 +
    5.60 +    /*
    5.61 +     * Set directory to subsystem specific files based
    5.62 +     * on the contents of the mountinfo and cgroup files.
    5.63 +     */
    5.64 +    void set_subsystem_path(char *cgroup_path) {
    5.65 +      char buf[MAXPATHLEN+1];
    5.66 +      if (_root != NULL && cgroup_path != NULL) {
    5.67 +        if (strcmp(_root, "/") == 0) {
    5.68 +          int buflen;
    5.69 +          strncpy(buf, _mount_point, MAXPATHLEN);
    5.70 +          buf[MAXPATHLEN-1] = '\0';
    5.71 +          if (strcmp(cgroup_path,"/") != 0) {
    5.72 +            buflen = strlen(buf);
    5.73 +            if ((buflen + strlen(cgroup_path)) > (MAXPATHLEN-1)) {
    5.74 +              return;
    5.75 +            }
    5.76 +            strncat(buf, cgroup_path, MAXPATHLEN-buflen);
    5.77 +            buf[MAXPATHLEN-1] = '\0';
    5.78 +          }
    5.79 +          _path = os::strdup(buf);
    5.80 +        } else {
    5.81 +          if (strcmp(_root, cgroup_path) == 0) {
    5.82 +            strncpy(buf, _mount_point, MAXPATHLEN);
    5.83 +            buf[MAXPATHLEN-1] = '\0';
    5.84 +            _path = os::strdup(buf);
    5.85 +          } else {
    5.86 +            char *p = strstr(_root, cgroup_path);
    5.87 +            if (p != NULL && p == _root) {
    5.88 +              if (strlen(cgroup_path) > strlen(_root)) {
    5.89 +                int buflen;
    5.90 +                strncpy(buf, _mount_point, MAXPATHLEN);
    5.91 +                buf[MAXPATHLEN-1] = '\0';
    5.92 +                buflen = strlen(buf);
    5.93 +                if ((buflen + strlen(cgroup_path)) > (MAXPATHLEN-1)) {
    5.94 +                  return;
    5.95 +                }
    5.96 +                strncat(buf, cgroup_path + strlen(_root), MAXPATHLEN-buflen);
    5.97 +                buf[MAXPATHLEN-1] = '\0';
    5.98 +                _path = os::strdup(buf);
    5.99 +              }
   5.100 +            }
   5.101 +          }
   5.102 +        }
   5.103 +      }
   5.104 +    }
   5.105 +
   5.106 +    char *subsystem_path() { return _path; }
   5.107 +};
   5.108 +
   5.109 +CgroupSubsystem* memory = NULL;
   5.110 +CgroupSubsystem* cpuset = NULL;
   5.111 +CgroupSubsystem* cpu = NULL;
   5.112 +CgroupSubsystem* cpuacct = NULL;
   5.113 +
   5.114 +typedef char * cptr;
   5.115 +
   5.116 +PRAGMA_DIAG_PUSH
   5.117 +PRAGMA_FORMAT_NONLITERAL_IGNORED
   5.118 +template <typename T> int subsystem_file_contents(CgroupSubsystem* c,
   5.119 +                                              const char *filename,
   5.120 +                                              const char *scan_fmt,
   5.121 +                                              T returnval) {
   5.122 +  FILE *fp = NULL;
   5.123 +  char *p;
   5.124 +  char file[MAXPATHLEN+1];
   5.125 +  char buf[MAXPATHLEN+1];
   5.126 +
   5.127 +  if (c == NULL) {
   5.128 +    if (PrintContainerInfo) {
   5.129 +      tty->print_cr("subsystem_file_contents: CgroupSubsytem* is NULL");
   5.130 +    }
   5.131 +    return OSCONTAINER_ERROR;
   5.132 +  }
   5.133 +  if (c->subsystem_path() == NULL) {
   5.134 +    if (PrintContainerInfo) {
   5.135 +      tty->print_cr("subsystem_file_contents: subsystem path is NULL");
   5.136 +    }
   5.137 +    return OSCONTAINER_ERROR;
   5.138 +  }
   5.139 +
   5.140 +  strncpy(file, c->subsystem_path(), MAXPATHLEN);
   5.141 +  file[MAXPATHLEN-1] = '\0';
   5.142 +  int filelen = strlen(file);
   5.143 +  if ((filelen + strlen(filename)) > (MAXPATHLEN-1)) {
   5.144 +    if (PrintContainerInfo) {
   5.145 +      tty->print_cr("File path too long %s, %s", file, filename);
   5.146 +    }
   5.147 +    return OSCONTAINER_ERROR;
   5.148 +  }
   5.149 +  strncat(file, filename, MAXPATHLEN-filelen);
   5.150 +  if (PrintContainerInfo) {
   5.151 +    tty->print_cr("Path to %s is %s", filename, file);
   5.152 +  }
   5.153 +  fp = fopen(file, "r");
   5.154 +  if (fp != NULL) {
   5.155 +    p = fgets(buf, MAXPATHLEN, fp);
   5.156 +    if (p != NULL) {
   5.157 +      int matched = sscanf(p, scan_fmt, returnval);
   5.158 +      if (matched == 1) {
   5.159 +        fclose(fp);
   5.160 +        return 0;
   5.161 +      } else {
   5.162 +        if (PrintContainerInfo) {
   5.163 +          tty->print_cr("Type %s not found in file %s", scan_fmt, file);
   5.164 +        }
   5.165 +      }
   5.166 +    } else {
   5.167 +      if (PrintContainerInfo) {
   5.168 +        tty->print_cr("Empty file %s", file);
   5.169 +      }
   5.170 +    }
   5.171 +  } else {
   5.172 +    if (PrintContainerInfo) {
   5.173 +      tty->print_cr("Open of file %s failed, %s", file, strerror(errno));
   5.174 +    }
   5.175 +  }
   5.176 +  if (fp != NULL)
   5.177 +    fclose(fp);
   5.178 +  return OSCONTAINER_ERROR;
   5.179 +}
   5.180 +PRAGMA_DIAG_POP
   5.181 +
   5.182 +#define GET_CONTAINER_INFO(return_type, subsystem, filename,              \
   5.183 +                           logstring, scan_fmt, variable)                 \
   5.184 +  return_type variable;                                                   \
   5.185 +{                                                                         \
   5.186 +  int err;                                                                \
   5.187 +  err = subsystem_file_contents(subsystem,                                \
   5.188 +                                filename,                                 \
   5.189 +                                scan_fmt,                                 \
   5.190 +                                &variable);                               \
   5.191 +  if (err != 0)                                                           \
   5.192 +    return (return_type) OSCONTAINER_ERROR;                               \
   5.193 +                                                                          \
   5.194 +  if (PrintContainerInfo)                                                 \
   5.195 +    tty->print_cr(logstring, variable);                                   \
   5.196 +}
   5.197 +
   5.198 +#define GET_CONTAINER_INFO_CPTR(return_type, subsystem, filename,         \
   5.199 +                               logstring, scan_fmt, variable, bufsize)    \
   5.200 +  char variable[bufsize];                                                 \
   5.201 +{                                                                         \
   5.202 +  int err;                                                                \
   5.203 +  err = subsystem_file_contents(subsystem,                                \
   5.204 +                                filename,                                 \
   5.205 +                                scan_fmt,                                 \
   5.206 +                                variable);                                \
   5.207 +  if (err != 0)                                                           \
   5.208 +    return (return_type) NULL;                                            \
   5.209 +                                                                          \
   5.210 +  if (PrintContainerInfo)                                                 \
   5.211 +    tty->print_cr(logstring, variable);                                   \
   5.212 +}
   5.213 +
   5.214 +/* init
   5.215 + *
   5.216 + * Initialize the container support and determine if
   5.217 + * we are running under cgroup control.
   5.218 + */
   5.219 +void OSContainer::init() {
   5.220 +  int mountid;
   5.221 +  int parentid;
   5.222 +  int major;
   5.223 +  int minor;
   5.224 +  FILE *mntinfo = NULL;
   5.225 +  FILE *cgroup = NULL;
   5.226 +  char buf[MAXPATHLEN+1];
   5.227 +  char tmproot[MAXPATHLEN+1];
   5.228 +  char tmpmount[MAXPATHLEN+1];
   5.229 +  char tmpbase[MAXPATHLEN+1];
   5.230 +  char *p;
   5.231 +  jlong mem_limit;
   5.232 +
   5.233 +  assert(!_is_initialized, "Initializing OSContainer more than once");
   5.234 +
   5.235 +  _is_initialized = true;
   5.236 +  _is_containerized = false;
   5.237 +
   5.238 +  _unlimited_memory = (LONG_MAX / os::vm_page_size()) * os::vm_page_size();
   5.239 +
   5.240 +  if (PrintContainerInfo) {
   5.241 +    tty->print_cr("OSContainer::init: Initializing Container Support");
   5.242 +  }
   5.243 +  if (!UseContainerSupport) {
   5.244 +    if (PrintContainerInfo) {
   5.245 +      tty->print_cr("Container Support not enabled");
   5.246 +    }
   5.247 +    return;
   5.248 +  }
   5.249 +
   5.250 +  /*
   5.251 +   * Find the cgroup mount point for memory and cpuset
   5.252 +   * by reading /proc/self/mountinfo
   5.253 +   *
   5.254 +   * Example for docker:
   5.255 +   * 219 214 0:29 /docker/7208cebd00fa5f2e342b1094f7bed87fa25661471a4637118e65f1c995be8a34 /sys/fs/cgroup/memory ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory
   5.256 +   *
   5.257 +   * Example for host:
   5.258 +   * 34 28 0:29 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,memory
   5.259 +   */
   5.260 +  mntinfo = fopen("/proc/self/mountinfo", "r");
   5.261 +  if (mntinfo == NULL) {
   5.262 +      if (PrintContainerInfo) {
   5.263 +        tty->print_cr("Can't open /proc/self/mountinfo, %s",
   5.264 +                       strerror(errno));
   5.265 +      }
   5.266 +      return;
   5.267 +  }
   5.268 +
   5.269 +  while ( (p = fgets(buf, MAXPATHLEN, mntinfo)) != NULL) {
   5.270 +    // Look for the filesystem type and see if it's cgroup
   5.271 +    char fstype[MAXPATHLEN+1];
   5.272 +    fstype[0] = '\0';
   5.273 +    char *s =  strstr(p, " - ");
   5.274 +    if (s != NULL &&
   5.275 +        sscanf(s, " - %s", fstype) == 1 &&
   5.276 +        strcmp(fstype, "cgroup") == 0) {
   5.277 +
   5.278 +      if (strstr(p, "memory") != NULL) {
   5.279 +        int matched = sscanf(p, "%d %d %d:%d %s %s",
   5.280 +                             &mountid,
   5.281 +                             &parentid,
   5.282 +                             &major,
   5.283 +                             &minor,
   5.284 +                             tmproot,
   5.285 +                             tmpmount);
   5.286 +        if (matched == 6) {
   5.287 +          memory = new CgroupSubsystem(tmproot, tmpmount);
   5.288 +        }
   5.289 +        else
   5.290 +          if (PrintContainerInfo) {
   5.291 +            tty->print_cr("Incompatible str containing cgroup and memory: %s", p);
   5.292 +          }
   5.293 +      } else if (strstr(p, "cpuset") != NULL) {
   5.294 +        int matched = sscanf(p, "%d %d %d:%d %s %s",
   5.295 +                             &mountid,
   5.296 +                             &parentid,
   5.297 +                             &major,
   5.298 +                             &minor,
   5.299 +                             tmproot,
   5.300 +                             tmpmount);
   5.301 +        if (matched == 6) {
   5.302 +          cpuset = new CgroupSubsystem(tmproot, tmpmount);
   5.303 +        }
   5.304 +        else {
   5.305 +          if (PrintContainerInfo) {
   5.306 +            tty->print_cr("Incompatible str containing cgroup and cpuset: %s", p);
   5.307 +          }
   5.308 +        }
   5.309 +      } else if (strstr(p, "cpu,cpuacct") != NULL || strstr(p, "cpuacct,cpu") != NULL) {
   5.310 +        int matched = sscanf(p, "%d %d %d:%d %s %s",
   5.311 +                             &mountid,
   5.312 +                             &parentid,
   5.313 +                             &major,
   5.314 +                             &minor,
   5.315 +                             tmproot,
   5.316 +                             tmpmount);
   5.317 +        if (matched == 6) {
   5.318 +          cpu = new CgroupSubsystem(tmproot, tmpmount);
   5.319 +          cpuacct = new CgroupSubsystem(tmproot, tmpmount);
   5.320 +        }
   5.321 +        else {
   5.322 +          if (PrintContainerInfo) {
   5.323 +            tty->print_cr("Incompatible str containing cgroup and cpu,cpuacct: %s", p);
   5.324 +          }
   5.325 +        }
   5.326 +      } else if (strstr(p, "cpuacct") != NULL) {
   5.327 +        int matched = sscanf(p, "%d %d %d:%d %s %s",
   5.328 +                             &mountid,
   5.329 +                             &parentid,
   5.330 +                             &major,
   5.331 +                             &minor,
   5.332 +                             tmproot,
   5.333 +                             tmpmount);
   5.334 +        if (matched == 6) {
   5.335 +          cpuacct = new CgroupSubsystem(tmproot, tmpmount);
   5.336 +        }
   5.337 +        else {
   5.338 +          if (PrintContainerInfo) {
   5.339 +            tty->print_cr("Incompatible str containing cgroup and cpuacct: %s", p);
   5.340 +          }
   5.341 +        }
   5.342 +      } else if (strstr(p, "cpu") != NULL) {
   5.343 +        int matched = sscanf(p, "%d %d %d:%d %s %s",
   5.344 +                             &mountid,
   5.345 +                             &parentid,
   5.346 +                             &major,
   5.347 +                             &minor,
   5.348 +                             tmproot,
   5.349 +                             tmpmount);
   5.350 +        if (matched == 6) {
   5.351 +          cpu = new CgroupSubsystem(tmproot, tmpmount);
   5.352 +        }
   5.353 +        else {
   5.354 +          if (PrintContainerInfo) {
   5.355 +            tty->print_cr("Incompatible str containing cgroup and cpu: %s", p);
   5.356 +          }
   5.357 +        }
   5.358 +      }
   5.359 +    }
   5.360 +  }
   5.361 +
   5.362 +  fclose(mntinfo);
   5.363 +
   5.364 +  if (memory == NULL) {
   5.365 +    if (PrintContainerInfo) {
   5.366 +      tty->print_cr("Required cgroup memory subsystem not found");
   5.367 +    }
   5.368 +    return;
   5.369 +  }
   5.370 +  if (cpuset == NULL) {
   5.371 +    if (PrintContainerInfo) {
   5.372 +      tty->print_cr("Required cgroup cpuset subsystem not found");
   5.373 +    }
   5.374 +    return;
   5.375 +  }
   5.376 +  if (cpu == NULL) {
   5.377 +    if (PrintContainerInfo) {
   5.378 +      tty->print_cr("Required cgroup cpu subsystem not found");
   5.379 +    }
   5.380 +    return;
   5.381 +  }
   5.382 +  if (cpuacct == NULL) {
   5.383 +    if (PrintContainerInfo) {
   5.384 +      tty->print_cr("Required cgroup cpuacct subsystem not found");
   5.385 +    }
   5.386 +    return;
   5.387 +  }
   5.388 +
   5.389 +  /*
   5.390 +   * Read /proc/self/cgroup and map host mount point to
   5.391 +   * local one via /proc/self/mountinfo content above
   5.392 +   *
   5.393 +   * Docker example:
   5.394 +   * 5:memory:/docker/6558aed8fc662b194323ceab5b964f69cf36b3e8af877a14b80256e93aecb044
   5.395 +   *
   5.396 +   * Host example:
   5.397 +   * 5:memory:/user.slice
   5.398 +   *
   5.399 +   * Construct a path to the process specific memory and cpuset
   5.400 +   * cgroup directory.
   5.401 +   *
   5.402 +   * For a container running under Docker from memory example above
   5.403 +   * the paths would be:
   5.404 +   *
   5.405 +   * /sys/fs/cgroup/memory
   5.406 +   *
   5.407 +   * For a Host from memory example above the path would be:
   5.408 +   *
   5.409 +   * /sys/fs/cgroup/memory/user.slice
   5.410 +   *
   5.411 +   */
   5.412 +  cgroup = fopen("/proc/self/cgroup", "r");
   5.413 +  if (cgroup == NULL) {
   5.414 +    if (PrintContainerInfo) {
   5.415 +      tty->print_cr("Can't open /proc/self/cgroup, %s",
   5.416 +                     strerror(errno));
   5.417 +      }
   5.418 +    return;
   5.419 +  }
   5.420 +
   5.421 +  while ( (p = fgets(buf, MAXPATHLEN, cgroup)) != NULL) {
   5.422 +    int cgno;
   5.423 +    int matched;
   5.424 +    char *controller;
   5.425 +    char *base;
   5.426 +
   5.427 +    /* Skip cgroup number */
   5.428 +    strsep(&p, ":");
   5.429 +    /* Get controller and base */
   5.430 +    controller = strsep(&p, ":");
   5.431 +    base = strsep(&p, "\n");
   5.432 +
   5.433 +    if (controller != NULL) {
   5.434 +      if (strstr(controller, "memory") != NULL) {
   5.435 +        memory->set_subsystem_path(base);
   5.436 +      } else if (strstr(controller, "cpuset") != NULL) {
   5.437 +        cpuset->set_subsystem_path(base);
   5.438 +      } else if (strstr(controller, "cpu,cpuacct") != NULL || strstr(controller, "cpuacct,cpu") != NULL) {
   5.439 +        cpu->set_subsystem_path(base);
   5.440 +        cpuacct->set_subsystem_path(base);
   5.441 +      } else if (strstr(controller, "cpuacct") != NULL) {
   5.442 +        cpuacct->set_subsystem_path(base);
   5.443 +      } else if (strstr(controller, "cpu") != NULL) {
   5.444 +        cpu->set_subsystem_path(base);
   5.445 +      }
   5.446 +    }
   5.447 +  }
   5.448 +
   5.449 +  fclose(cgroup);
   5.450 +
   5.451 +  // We need to update the amount of physical memory now that
   5.452 +  // command line arguments have been processed.
   5.453 +  if ((mem_limit = memory_limit_in_bytes()) > 0) {
   5.454 +    os::Linux::set_physical_memory(mem_limit);
   5.455 +  }
   5.456 +
   5.457 +  _is_containerized = true;
   5.458 +
   5.459 +}
   5.460 +
   5.461 +const char * OSContainer::container_type() {
   5.462 +  if (is_containerized()) {
   5.463 +    return "cgroupv1";
   5.464 +  } else {
   5.465 +    return NULL;
   5.466 +  }
   5.467 +}
   5.468 +
   5.469 +
   5.470 +/* memory_limit_in_bytes
   5.471 + *
   5.472 + * Return the limit of available memory for this process.
   5.473 + *
   5.474 + * return:
   5.475 + *    memory limit in bytes or
   5.476 + *    -1 for unlimited
   5.477 + *    OSCONTAINER_ERROR for not supported
   5.478 + */
   5.479 +jlong OSContainer::memory_limit_in_bytes() {
   5.480 +  GET_CONTAINER_INFO(julong, memory, "/memory.limit_in_bytes",
   5.481 +                     "Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, memlimit);
   5.482 +
   5.483 +  if (memlimit >= _unlimited_memory) {
   5.484 +    if (PrintContainerInfo) {
   5.485 +      tty->print_cr("Memory Limit is: Unlimited");
   5.486 +    }
   5.487 +    return (jlong)-1;
   5.488 +  }
   5.489 +  else {
   5.490 +    return (jlong)memlimit;
   5.491 +  }
   5.492 +}
   5.493 +
   5.494 +jlong OSContainer::memory_and_swap_limit_in_bytes() {
   5.495 +  GET_CONTAINER_INFO(julong, memory, "/memory.memsw.limit_in_bytes",
   5.496 +                     "Memory and Swap Limit is: " JULONG_FORMAT, JULONG_FORMAT, memswlimit);
   5.497 +  if (memswlimit >= _unlimited_memory) {
   5.498 +    if (PrintContainerInfo) {
   5.499 +      tty->print_cr("Memory and Swap Limit is: Unlimited");
   5.500 +    }
   5.501 +    return (jlong)-1;
   5.502 +  } else {
   5.503 +    return (jlong)memswlimit;
   5.504 +  }
   5.505 +}
   5.506 +
   5.507 +jlong OSContainer::memory_soft_limit_in_bytes() {
   5.508 +  GET_CONTAINER_INFO(julong, memory, "/memory.soft_limit_in_bytes",
   5.509 +                     "Memory Soft Limit is: " JULONG_FORMAT, JULONG_FORMAT, memsoftlimit);
   5.510 +  if (memsoftlimit >= _unlimited_memory) {
   5.511 +    if (PrintContainerInfo) {
   5.512 +      tty->print_cr("Memory Soft Limit is: Unlimited");
   5.513 +    }
   5.514 +    return (jlong)-1;
   5.515 +  } else {
   5.516 +    return (jlong)memsoftlimit;
   5.517 +  }
   5.518 +}
   5.519 +
   5.520 +/* memory_usage_in_bytes
   5.521 + *
   5.522 + * Return the amount of used memory for this process.
   5.523 + *
   5.524 + * return:
   5.525 + *    memory usage in bytes or
   5.526 + *    -1 for unlimited
   5.527 + *    OSCONTAINER_ERROR for not supported
   5.528 + */
   5.529 +jlong OSContainer::memory_usage_in_bytes() {
   5.530 +  GET_CONTAINER_INFO(jlong, memory, "/memory.usage_in_bytes",
   5.531 +                     "Memory Usage is: " JLONG_FORMAT, JLONG_FORMAT, memusage);
   5.532 +  return memusage;
   5.533 +}
   5.534 +
   5.535 +/* memory_max_usage_in_bytes
   5.536 + *
   5.537 + * Return the maximum amount of used memory for this process.
   5.538 + *
   5.539 + * return:
   5.540 + *    max memory usage in bytes or
   5.541 + *    OSCONTAINER_ERROR for not supported
   5.542 + */
   5.543 +jlong OSContainer::memory_max_usage_in_bytes() {
   5.544 +  GET_CONTAINER_INFO(jlong, memory, "/memory.max_usage_in_bytes",
   5.545 +                     "Maximum Memory Usage is: " JLONG_FORMAT, JLONG_FORMAT, memmaxusage);
   5.546 +  return memmaxusage;
   5.547 +}
   5.548 +
   5.549 +/* active_processor_count
   5.550 + *
   5.551 + * Calculate an appropriate number of active processors for the
   5.552 + * VM to use based on these three inputs.
   5.553 + *
   5.554 + * cpu affinity
   5.555 + * cgroup cpu quota & cpu period
   5.556 + * cgroup cpu shares
   5.557 + *
   5.558 + * Algorithm:
   5.559 + *
   5.560 + * Determine the number of available CPUs from sched_getaffinity
   5.561 + *
   5.562 + * If user specified a quota (quota != -1), calculate the number of
   5.563 + * required CPUs by dividing quota by period.
   5.564 + *
   5.565 + * If shares are in effect (shares != -1), calculate the number
   5.566 + * of CPUs required for the shares by dividing the share value
   5.567 + * by PER_CPU_SHARES.
   5.568 + *
   5.569 + * All results of division are rounded up to the next whole number.
   5.570 + *
   5.571 + * If neither shares or quotas have been specified, return the
   5.572 + * number of active processors in the system.
   5.573 + *
   5.574 + * If both shares and quotas have been specified, the results are
   5.575 + * based on the flag PreferContainerQuotaForCPUCount.  If true,
   5.576 + * return the quota value.  If false return the smallest value
   5.577 + * between shares or quotas.
   5.578 + *
   5.579 + * If shares and/or quotas have been specified, the resulting number
   5.580 + * returned will never exceed the number of active processors.
   5.581 + *
   5.582 + * return:
   5.583 + *    number of CPUs
   5.584 + */
   5.585 +int OSContainer::active_processor_count() {
   5.586 +  int quota_count = 0, share_count = 0;
   5.587 +  int cpu_count, limit_count;
   5.588 +  int result;
   5.589 +
   5.590 +  cpu_count = limit_count = os::Linux::active_processor_count();
   5.591 +  int quota  = cpu_quota();
   5.592 +  int period = cpu_period();
   5.593 +  int share  = cpu_shares();
   5.594 +
   5.595 +  if (quota > -1 && period > 0) {
   5.596 +    quota_count = ceilf((float)quota / (float)period);
   5.597 +    if (PrintContainerInfo) {
   5.598 +      tty->print_cr("CPU Quota count based on quota/period: %d", quota_count);
   5.599 +    }
   5.600 +  }
   5.601 +  if (share > -1) {
   5.602 +    share_count = ceilf((float)share / (float)PER_CPU_SHARES);
   5.603 +    if (PrintContainerInfo) {
   5.604 +      tty->print_cr("CPU Share count based on shares: %d", share_count);
   5.605 +    }
   5.606 +  }
   5.607 +
   5.608 +  // If both shares and quotas are setup results depend
   5.609 +  // on flag PreferContainerQuotaForCPUCount.
   5.610 +  // If true, limit CPU count to quota
   5.611 +  // If false, use minimum of shares and quotas
   5.612 +  if (quota_count !=0 && share_count != 0) {
   5.613 +    if (PreferContainerQuotaForCPUCount) {
   5.614 +      limit_count = quota_count;
   5.615 +    } else {
   5.616 +      limit_count = MIN2(quota_count, share_count);
   5.617 +    }
   5.618 +  } else if (quota_count != 0) {
   5.619 +    limit_count = quota_count;
   5.620 +  } else if (share_count != 0) {
   5.621 +    limit_count = share_count;
   5.622 +  }
   5.623 +
   5.624 +  result = MIN2(cpu_count, limit_count);
   5.625 +  if (PrintContainerInfo) {
   5.626 +    tty->print_cr("OSContainer::active_processor_count: %d", result);
   5.627 +  }
   5.628 +  return result;
   5.629 +}
   5.630 +
   5.631 +char * OSContainer::cpu_cpuset_cpus() {
   5.632 +  GET_CONTAINER_INFO_CPTR(cptr, cpuset, "/cpuset.cpus",
   5.633 +                     "cpuset.cpus is: %s", "%1023s", cpus, 1024);
   5.634 +  return os::strdup(cpus);
   5.635 +}
   5.636 +
   5.637 +char * OSContainer::cpu_cpuset_memory_nodes() {
   5.638 +  GET_CONTAINER_INFO_CPTR(cptr, cpuset, "/cpuset.mems",
   5.639 +                     "cpuset.mems is: %s", "%1023s", mems, 1024);
   5.640 +  return os::strdup(mems);
   5.641 +}
   5.642 +
   5.643 +/* cpu_quota
   5.644 + *
   5.645 + * Return the number of milliseconds per period
   5.646 + * process is guaranteed to run.
   5.647 + *
   5.648 + * return:
   5.649 + *    quota time in milliseconds
   5.650 + *    -1 for no quota
   5.651 + *    OSCONTAINER_ERROR for not supported
   5.652 + */
   5.653 +int OSContainer::cpu_quota() {
   5.654 +  GET_CONTAINER_INFO(int, cpu, "/cpu.cfs_quota_us",
   5.655 +                     "CPU Quota is: %d", "%d", quota);
   5.656 +  return quota;
   5.657 +}
   5.658 +
   5.659 +int OSContainer::cpu_period() {
   5.660 +  GET_CONTAINER_INFO(int, cpu, "/cpu.cfs_period_us",
   5.661 +                     "CPU Period is: %d", "%d", period);
   5.662 +  return period;
   5.663 +}
   5.664 +
   5.665 +/* cpu_shares
   5.666 + *
   5.667 + * Return the amount of cpu shares available to the process
   5.668 + *
   5.669 + * return:
   5.670 + *    Share number (typically a number relative to 1024)
   5.671 + *                 (2048 typically expresses 2 CPUs worth of processing)
   5.672 + *    -1 for no share setup
   5.673 + *    OSCONTAINER_ERROR for not supported
   5.674 + */
   5.675 +int OSContainer::cpu_shares() {
   5.676 +  GET_CONTAINER_INFO(int, cpu, "/cpu.shares",
   5.677 +                     "CPU Shares is: %d", "%d", shares);
   5.678 +  // Convert 1024 to no shares setup
   5.679 +  if (shares == 1024) return -1;
   5.680 +
   5.681 +  return shares;
   5.682 +}
   5.683 +
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/os/linux/vm/osContainer_linux.hpp	Fri Jul 27 11:47:10 2018 +0100
     6.3 @@ -0,0 +1,68 @@
     6.4 +/*
     6.5 + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
     6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.7 + *
     6.8 + * This code is free software; you can redistribute it and/or modify it
     6.9 + * under the terms of the GNU General Public License version 2 only, as
    6.10 + * published by the Free Software Foundation.
    6.11 + *
    6.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    6.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    6.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    6.15 + * version 2 for more details (a copy is included in the LICENSE file that
    6.16 + * accompanied this code).
    6.17 + *
    6.18 + * You should have received a copy of the GNU General Public License version
    6.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    6.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    6.21 + *
    6.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    6.23 + * or visit www.oracle.com if you need additional information or have any
    6.24 + * questions.
    6.25 + *
    6.26 + */
    6.27 +
    6.28 +#ifndef OS_LINUX_VM_OSCONTAINER_LINUX_HPP
    6.29 +#define OS_LINUX_VM_OSCONTAINER_LINUX_HPP
    6.30 +
    6.31 +#include "utilities/globalDefinitions.hpp"
    6.32 +#include "utilities/macros.hpp"
    6.33 +#include "memory/allocation.hpp"
    6.34 +
    6.35 +#define OSCONTAINER_ERROR (-2)
    6.36 +
    6.37 +class OSContainer: AllStatic {
    6.38 +
    6.39 + private:
    6.40 +  static bool   _is_initialized;
    6.41 +  static bool   _is_containerized;
    6.42 +
    6.43 + public:
    6.44 +  static void init();
    6.45 +  static inline bool is_containerized();
    6.46 +  static const char * container_type();
    6.47 +
    6.48 +  static jlong memory_limit_in_bytes();
    6.49 +  static jlong memory_and_swap_limit_in_bytes();
    6.50 +  static jlong memory_soft_limit_in_bytes();
    6.51 +  static jlong memory_usage_in_bytes();
    6.52 +  static jlong memory_max_usage_in_bytes();
    6.53 +
    6.54 +  static int active_processor_count();
    6.55 +
    6.56 +  static char * cpu_cpuset_cpus();
    6.57 +  static char * cpu_cpuset_memory_nodes();
    6.58 +
    6.59 +  static int cpu_quota();
    6.60 +  static int cpu_period();
    6.61 +
    6.62 +  static int cpu_shares();
    6.63 +
    6.64 +};
    6.65 +
    6.66 +inline bool OSContainer::is_containerized() {
    6.67 +  assert(_is_initialized, "OSContainer not initialized");
    6.68 +  return _is_containerized;
    6.69 +}
    6.70 +
    6.71 +#endif // OS_LINUX_VM_OSCONTAINER_LINUX_HPP
     7.1 --- a/src/os/linux/vm/os_linux.cpp	Wed Jul 11 15:59:47 2018 +0100
     7.2 +++ b/src/os/linux/vm/os_linux.cpp	Fri Jul 27 11:47:10 2018 +0100
     7.3 @@ -37,6 +37,7 @@
     7.4  #include "mutex_linux.inline.hpp"
     7.5  #include "oops/oop.inline.hpp"
     7.6  #include "os_share_linux.hpp"
     7.7 +#include "osContainer_linux.hpp"
     7.8  #include "prims/jniFastGetField.hpp"
     7.9  #include "prims/jvm.h"
    7.10  #include "prims/jvm_misc.hpp"
    7.11 @@ -179,13 +180,62 @@
    7.12  julong os::Linux::available_memory() {
    7.13    // values in struct sysinfo are "unsigned long"
    7.14    struct sysinfo si;
    7.15 +  julong avail_mem;
    7.16 +
    7.17 +  if (OSContainer::is_containerized()) {
    7.18 +    jlong mem_limit, mem_usage;
    7.19 +    if ((mem_limit = OSContainer::memory_limit_in_bytes()) < 1) {
    7.20 +      if (PrintContainerInfo) {
    7.21 +        tty->print_cr("container memory limit %s: " JLONG_FORMAT ", using host value",
    7.22 +                       mem_limit == OSCONTAINER_ERROR ? "failed" : "unlimited", mem_limit);
    7.23 +      }
    7.24 +    }
    7.25 +
    7.26 +    if (mem_limit > 0 && (mem_usage = OSContainer::memory_usage_in_bytes()) < 1) {
    7.27 +      if (PrintContainerInfo) {
    7.28 +        tty->print_cr("container memory usage failed: " JLONG_FORMAT ", using host value", mem_usage);
    7.29 +      }
    7.30 +    }
    7.31 +
    7.32 +    if (mem_limit > 0 && mem_usage > 0 ) {
    7.33 +      avail_mem = mem_limit > mem_usage ? (julong)mem_limit - (julong)mem_usage : 0;
    7.34 +      if (PrintContainerInfo) {
    7.35 +        tty->print_cr("available container memory: " JULONG_FORMAT, avail_mem);
    7.36 +      }
    7.37 +      return avail_mem;
    7.38 +    }
    7.39 +  }
    7.40 +
    7.41    sysinfo(&si);
    7.42 -
    7.43 -  return (julong)si.freeram * si.mem_unit;
    7.44 +  avail_mem = (julong)si.freeram * si.mem_unit;
    7.45 +  if (Verbose) {
    7.46 +    tty->print_cr("available memory: " JULONG_FORMAT, avail_mem);
    7.47 +  }
    7.48 +  return avail_mem;
    7.49  }
    7.50  
    7.51  julong os::physical_memory() {
    7.52 -  return Linux::physical_memory();
    7.53 +  jlong phys_mem = 0;
    7.54 +  if (OSContainer::is_containerized()) {
    7.55 +    jlong mem_limit;
    7.56 +    if ((mem_limit = OSContainer::memory_limit_in_bytes()) > 0) {
    7.57 +      if (PrintContainerInfo) {
    7.58 +        tty->print_cr("total container memory: " JLONG_FORMAT, mem_limit);
    7.59 +      }
    7.60 +      return mem_limit;
    7.61 +    }
    7.62 +
    7.63 +    if (PrintContainerInfo) {
    7.64 +      tty->print_cr("container memory limit %s: " JLONG_FORMAT ", using host value",
    7.65 +                     mem_limit == OSCONTAINER_ERROR ? "failed" : "unlimited", mem_limit);
    7.66 +    }
    7.67 +  }
    7.68 +
    7.69 +  phys_mem = Linux::physical_memory();
    7.70 +  if (Verbose) {
    7.71 +    tty->print_cr("total system memory: " JLONG_FORMAT, phys_mem);
    7.72 +  }
    7.73 +  return phys_mem;
    7.74  }
    7.75  
    7.76  ////////////////////////////////////////////////////////////////////////////////
    7.77 @@ -2114,6 +2164,8 @@
    7.78    os::Posix::print_load_average(st);
    7.79  
    7.80    os::Linux::print_full_memory_info(st);
    7.81 +
    7.82 +  os::Linux::print_container_info(st);
    7.83  }
    7.84  
    7.85  // Try to identify popular distros.
    7.86 @@ -2179,6 +2231,57 @@
    7.87     st->cr();
    7.88  }
    7.89  
    7.90 +void os::Linux::print_container_info(outputStream* st) {
    7.91 +if (!OSContainer::is_containerized()) {
    7.92 +    return;
    7.93 +  }
    7.94 +
    7.95 +  st->print("container (cgroup) information:\n");
    7.96 +
    7.97 +  const char *p_ct = OSContainer::container_type();
    7.98 +  st->print("container_type: %s\n", p_ct != NULL ? p_ct : "failed");
    7.99 +
   7.100 +  char *p = OSContainer::cpu_cpuset_cpus();
   7.101 +  st->print("cpu_cpuset_cpus: %s\n", p != NULL ? p : "failed");
   7.102 +  free(p);
   7.103 +
   7.104 +  p = OSContainer::cpu_cpuset_memory_nodes();
   7.105 +  st->print("cpu_memory_nodes: %s\n", p != NULL ? p : "failed");
   7.106 +  free(p);
   7.107 +
   7.108 +  int i = OSContainer::active_processor_count();
   7.109 +  if (i > 0) {
   7.110 +    st->print("active_processor_count: %d\n", i);
   7.111 +  } else {
   7.112 +    st->print("active_processor_count: failed\n");
   7.113 +  }
   7.114 +
   7.115 +  i = OSContainer::cpu_quota();
   7.116 +  st->print("cpu_quota: %d\n", i);
   7.117 +
   7.118 +  i = OSContainer::cpu_period();
   7.119 +  st->print("cpu_period: %d\n", i);
   7.120 +
   7.121 +  i = OSContainer::cpu_shares();
   7.122 +  st->print("cpu_shares: %d\n", i);
   7.123 +
   7.124 +  jlong j = OSContainer::memory_limit_in_bytes();
   7.125 +  st->print("memory_limit_in_bytes: " JLONG_FORMAT "\n", j);
   7.126 +
   7.127 +  j = OSContainer::memory_and_swap_limit_in_bytes();
   7.128 +  st->print("memory_and_swap_limit_in_bytes: " JLONG_FORMAT "\n", j);
   7.129 +
   7.130 +  j = OSContainer::memory_soft_limit_in_bytes();
   7.131 +  st->print("memory_soft_limit_in_bytes: " JLONG_FORMAT "\n", j);
   7.132 +
   7.133 +  j = OSContainer::OSContainer::memory_usage_in_bytes();
   7.134 +  st->print("memory_usage_in_bytes: " JLONG_FORMAT "\n", j);
   7.135 +
   7.136 +  j = OSContainer::OSContainer::memory_max_usage_in_bytes();
   7.137 +  st->print("memory_max_usage_in_bytes: " JLONG_FORMAT "\n", j);
   7.138 +  st->cr();
   7.139 +}
   7.140 +
   7.141  void os::print_memory_info(outputStream* st) {
   7.142  
   7.143    st->print("Memory:");
   7.144 @@ -4951,6 +5054,10 @@
   7.145    }
   7.146  }
   7.147  
   7.148 +void os::pd_init_container_support() {
   7.149 +  OSContainer::init();
   7.150 +}
   7.151 +
   7.152  // this is called _after_ the global arguments have been parsed
   7.153  jint os::init_2(void)
   7.154  {
   7.155 @@ -5131,7 +5238,7 @@
   7.156  // sched_getaffinity gives an accurate answer as it accounts for cpusets.
   7.157  // If anything goes wrong we fallback to returning the number of online
   7.158  // processors - which can be greater than the number available to the process.
   7.159 -int os::active_processor_count() {
   7.160 +int os::Linux::active_processor_count() {
   7.161    cpu_set_t cpus;  // can represent at most 1024 (CPU_SETSIZE) processors
   7.162    int cpus_size = sizeof(cpu_set_t);
   7.163    int cpu_count = 0;
   7.164 @@ -5149,10 +5256,48 @@
   7.165              "which may exceed available processors", strerror(errno), cpu_count);
   7.166    }
   7.167  
   7.168 -  assert(cpu_count > 0 && cpu_count <= processor_count(), "sanity check");
   7.169 +  assert(cpu_count > 0 && cpu_count <= os::processor_count(), "sanity check");
   7.170    return cpu_count;
   7.171  }
   7.172  
   7.173 +// Determine the active processor count from one of
   7.174 +// three different sources:
   7.175 +//
   7.176 +// 1. User option -XX:ActiveProcessorCount
   7.177 +// 2. kernel os calls (sched_getaffinity or sysconf(_SC_NPROCESSORS_ONLN)
   7.178 +// 3. extracted from cgroup cpu subsystem (shares and quotas)
   7.179 +//
   7.180 +// Option 1, if specified, will always override.
   7.181 +// If the cgroup subsystem is active and configured, we
   7.182 +// will return the min of the cgroup and option 2 results.
   7.183 +// This is required since tools, such as numactl, that
   7.184 +// alter cpu affinity do not update cgroup subsystem
   7.185 +// cpuset configuration files.
   7.186 +int os::active_processor_count() {
   7.187 +  // User has overridden the number of active processors
   7.188 +  if (ActiveProcessorCount > 0) {
   7.189 +    if (PrintActiveCpus) {
   7.190 +      tty->print_cr("active_processor_count: "
   7.191 +                    "active processor count set by user : %d",
   7.192 +                    ActiveProcessorCount);
   7.193 +    }
   7.194 +    return ActiveProcessorCount;
   7.195 +  }
   7.196 +
   7.197 +  int active_cpus;
   7.198 +  if (OSContainer::is_containerized()) {
   7.199 +    active_cpus = OSContainer::active_processor_count();
   7.200 +    if (PrintActiveCpus) {
   7.201 +      tty->print_cr("active_processor_count: determined by OSContainer: %d",
   7.202 +                     active_cpus);
   7.203 +    }
   7.204 +  } else {
   7.205 +    active_cpus = os::Linux::active_processor_count();
   7.206 +  }
   7.207 +
   7.208 +  return active_cpus;
   7.209 +}
   7.210 +
   7.211  void os::set_native_thread_name(const char *name) {
   7.212    // Not yet implemented.
   7.213    return;
     8.1 --- a/src/os/linux/vm/os_linux.hpp	Wed Jul 11 15:59:47 2018 +0100
     8.2 +++ b/src/os/linux/vm/os_linux.hpp	Fri Jul 27 11:47:10 2018 +0100
     8.3 @@ -35,6 +35,7 @@
     8.4  
     8.5  class Linux {
     8.6    friend class os;
     8.7 +  friend class OSContainer;
     8.8    friend class TestReserveMemorySpecial;
     8.9  
    8.10    // For signal-chaining
    8.11 @@ -79,6 +80,9 @@
    8.12  
    8.13    static julong available_memory();
    8.14    static julong physical_memory() { return _physical_memory; }
    8.15 +  static void set_physical_memory(julong phys_mem) { _physical_memory = phys_mem; }
    8.16 +  static int active_processor_count();
    8.17 +
    8.18    static void initialize_system_info();
    8.19  
    8.20    static int commit_memory_impl(char* addr, size_t bytes, bool exec);
    8.21 @@ -116,6 +120,7 @@
    8.22    static bool release_memory_special_huge_tlbfs(char* base, size_t bytes);
    8.23  
    8.24    static void print_full_memory_info(outputStream* st);
    8.25 +  static void print_container_info(outputStream* st);
    8.26    static void print_distro_info(outputStream* st);
    8.27    static void print_libversion_info(outputStream* st);
    8.28  
     9.1 --- a/src/os/solaris/vm/os_solaris.cpp	Wed Jul 11 15:59:47 2018 +0100
     9.2 +++ b/src/os/solaris/vm/os_solaris.cpp	Fri Jul 27 11:47:10 2018 +0100
     9.3 @@ -357,6 +357,16 @@
     9.4  }
     9.5  
     9.6  int os::active_processor_count() {
     9.7 +  // User has overridden the number of active processors
     9.8 +  if (ActiveProcessorCount > 0) {
     9.9 +    if (Verbose) {
    9.10 +      tty->print_cr("active_processor_count: "
    9.11 +                    "active processor count set by user : %d",
    9.12 +                     ActiveProcessorCount);
    9.13 +    }
    9.14 +    return ActiveProcessorCount;
    9.15 +  }
    9.16 +
    9.17    int online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
    9.18    pid_t pid = getpid();
    9.19    psetid_t pset = PS_NONE;
    10.1 --- a/src/os/windows/vm/os_windows.cpp	Wed Jul 11 15:59:47 2018 +0100
    10.2 +++ b/src/os/windows/vm/os_windows.cpp	Fri Jul 27 11:47:10 2018 +0100
    10.3 @@ -716,6 +716,16 @@
    10.4  #endif
    10.5  
    10.6  int os::active_processor_count() {
    10.7 +  // User has overridden the number of active processors
    10.8 +  if (ActiveProcessorCount > 0) {
    10.9 +    if (PrintActiveCpus) {
   10.10 +      tty->print_cr("active_processor_count: "
   10.11 +                    "active processor count set by user : %d",
   10.12 +                     ActiveProcessorCount);
   10.13 +    }
   10.14 +    return ActiveProcessorCount;
   10.15 +  }
   10.16 +
   10.17    DWORD_PTR lpProcessAffinityMask = 0;
   10.18    DWORD_PTR lpSystemAffinityMask = 0;
   10.19    int proc_count = processor_count();
    11.1 --- a/src/share/vm/runtime/arguments.cpp	Wed Jul 11 15:59:47 2018 +0100
    11.2 +++ b/src/share/vm/runtime/arguments.cpp	Fri Jul 27 11:47:10 2018 +0100
    11.3 @@ -1,5 +1,5 @@
    11.4  /*
    11.5 - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
    11.6 + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
    11.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.8   *
    11.9   * This code is free software; you can redistribute it and/or modify it
   11.10 @@ -1801,20 +1801,34 @@
   11.11      }
   11.12    }
   11.13  
   11.14 +  // Convert Fraction to Precentage values
   11.15 +  if (FLAG_IS_DEFAULT(MaxRAMPercentage) &&
   11.16 +      !FLAG_IS_DEFAULT(MaxRAMFraction))
   11.17 +    MaxRAMPercentage = 100.0 / MaxRAMFraction;
   11.18 +
   11.19 +   if (FLAG_IS_DEFAULT(MinRAMPercentage) &&
   11.20 +       !FLAG_IS_DEFAULT(MinRAMFraction))
   11.21 +     MinRAMPercentage = 100.0 / MinRAMFraction;
   11.22 +
   11.23 +   if (FLAG_IS_DEFAULT(InitialRAMPercentage) &&
   11.24 +       !FLAG_IS_DEFAULT(InitialRAMFraction))
   11.25 +     InitialRAMPercentage = 100.0 / InitialRAMFraction;
   11.26 +
   11.27    // If the maximum heap size has not been set with -Xmx,
   11.28    // then set it as fraction of the size of physical memory,
   11.29    // respecting the maximum and minimum sizes of the heap.
   11.30    if (FLAG_IS_DEFAULT(MaxHeapSize)) {
   11.31 -    julong reasonable_max = phys_mem / MaxRAMFraction;
   11.32 -
   11.33 -    if (phys_mem <= MaxHeapSize * MinRAMFraction) {
   11.34 +    julong reasonable_max = (julong)((phys_mem * MaxRAMPercentage) / 100);
   11.35 +    const julong reasonable_min = (julong)((phys_mem * MinRAMPercentage) / 100);
   11.36 +    if (reasonable_min < MaxHeapSize) {
   11.37        // Small physical memory, so use a minimum fraction of it for the heap
   11.38 -      reasonable_max = phys_mem / MinRAMFraction;
   11.39 +      reasonable_max = reasonable_min;
   11.40      } else {
   11.41        // Not-small physical memory, so require a heap at least
   11.42        // as large as MaxHeapSize
   11.43        reasonable_max = MAX2(reasonable_max, (julong)MaxHeapSize);
   11.44      }
   11.45 +
   11.46      if (!FLAG_IS_DEFAULT(ErgoHeapSizeLimit) && ErgoHeapSizeLimit != 0) {
   11.47        // Limit the heap size to ErgoHeapSizeLimit
   11.48        reasonable_max = MIN2(reasonable_max, (julong)ErgoHeapSizeLimit);
   11.49 @@ -1856,7 +1870,7 @@
   11.50      reasonable_minimum = limit_by_allocatable_memory(reasonable_minimum);
   11.51  
   11.52      if (InitialHeapSize == 0) {
   11.53 -      julong reasonable_initial = phys_mem / InitialRAMFraction;
   11.54 +      julong reasonable_initial = (julong)((phys_mem * InitialRAMPercentage) / 100);
   11.55  
   11.56        reasonable_initial = MAX3(reasonable_initial, reasonable_minimum, (julong)min_heap_size());
   11.57        reasonable_initial = MIN2(reasonable_initial, (julong)MaxHeapSize);
   11.58 @@ -1881,6 +1895,94 @@
   11.59    }
   11.60  }
   11.61  
   11.62 +// This option inspects the machine and attempts to set various
   11.63 +// parameters to be optimal for long-running, memory allocation
   11.64 +// intensive jobs.  It is intended for machines with large
   11.65 +// amounts of cpu and memory.
   11.66 +jint Arguments::set_aggressive_heap_flags() {
   11.67 +  // initHeapSize is needed since _initial_heap_size is 4 bytes on a 32 bit
   11.68 +  // VM, but we may not be able to represent the total physical memory
   11.69 +  // available (like having 8gb of memory on a box but using a 32bit VM).
   11.70 +  // Thus, we need to make sure we're using a julong for intermediate
   11.71 +  // calculations.
   11.72 +  julong initHeapSize;
   11.73 +  julong total_memory = os::physical_memory();
   11.74 +
   11.75 +  if (total_memory < (julong) 256 * M) {
   11.76 +    jio_fprintf(defaultStream::error_stream(),
   11.77 +            "You need at least 256mb of memory to use -XX:+AggressiveHeap\n");
   11.78 +    vm_exit(1);
   11.79 +  }
   11.80 +
   11.81 +  // The heap size is half of available memory, or (at most)
   11.82 +  // all of possible memory less 160mb (leaving room for the OS
   11.83 +  // when using ISM).  This is the maximum; because adaptive sizing
   11.84 +  // is turned on below, the actual space used may be smaller.
   11.85 +
   11.86 +  initHeapSize = MIN2(total_memory / (julong) 2,
   11.87 +                      total_memory - (julong) 160 * M);
   11.88 +
   11.89 +  initHeapSize = limit_by_allocatable_memory(initHeapSize);
   11.90 +
   11.91 +  if (FLAG_IS_DEFAULT(MaxHeapSize)) {
   11.92 +    FLAG_SET_CMDLINE(uintx, MaxHeapSize, initHeapSize);
   11.93 +    FLAG_SET_CMDLINE(uintx, InitialHeapSize, initHeapSize);
   11.94 +    // Currently the minimum size and the initial heap sizes are the same.
   11.95 +    set_min_heap_size(initHeapSize);
   11.96 +  }
   11.97 +  if (FLAG_IS_DEFAULT(NewSize)) {
   11.98 +    // Make the young generation 3/8ths of the total heap.
   11.99 +    FLAG_SET_CMDLINE(uintx, NewSize,
  11.100 +            ((julong) MaxHeapSize / (julong) 8) * (julong) 3);
  11.101 +    FLAG_SET_CMDLINE(uintx, MaxNewSize, NewSize);
  11.102 +  }
  11.103 +
  11.104 +#ifndef _ALLBSD_SOURCE  // UseLargePages is not yet supported on BSD.
  11.105 +  FLAG_SET_DEFAULT(UseLargePages, true);
  11.106 +#endif
  11.107 +
  11.108 +  // Increase some data structure sizes for efficiency
  11.109 +  FLAG_SET_CMDLINE(uintx, BaseFootPrintEstimate, MaxHeapSize);
  11.110 +  FLAG_SET_CMDLINE(bool, ResizeTLAB, false);
  11.111 +  FLAG_SET_CMDLINE(uintx, TLABSize, 256 * K);
  11.112 +
  11.113 +  // See the OldPLABSize comment below, but replace 'after promotion'
  11.114 +  // with 'after copying'.  YoungPLABSize is the size of the survivor
  11.115 +  // space per-gc-thread buffers.  The default is 4kw.
  11.116 +  FLAG_SET_CMDLINE(uintx, YoungPLABSize, 256 * K);     // Note: this is in words
  11.117 +
  11.118 +  // OldPLABSize is the size of the buffers in the old gen that
  11.119 +  // UseParallelGC uses to promote live data that doesn't fit in the
  11.120 +  // survivor spaces.  At any given time, there's one for each gc thread.
  11.121 +  // The default size is 1kw. These buffers are rarely used, since the
  11.122 +  // survivor spaces are usually big enough.  For specjbb, however, there
  11.123 +  // are occasions when there's lots of live data in the young gen
  11.124 +  // and we end up promoting some of it.  We don't have a definite
  11.125 +  // explanation for why bumping OldPLABSize helps, but the theory
  11.126 +  // is that a bigger PLAB results in retaining something like the
  11.127 +  // original allocation order after promotion, which improves mutator
  11.128 +  // locality.  A minor effect may be that larger PLABs reduce the
  11.129 +  // number of PLAB allocation events during gc.  The value of 8kw
  11.130 +  // was arrived at by experimenting with specjbb.
  11.131 +  FLAG_SET_CMDLINE(uintx, OldPLABSize, 8 * K);      // Note: this is in words
  11.132 +
  11.133 +  // Enable parallel GC and adaptive generation sizing
  11.134 +  FLAG_SET_CMDLINE(bool, UseParallelGC, true);
  11.135 +
  11.136 +  // Encourage steady state memory management
  11.137 +  FLAG_SET_CMDLINE(uintx, ThresholdTolerance, 100);
  11.138 +
  11.139 +  // This appears to improve mutator locality
  11.140 +  FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false);
  11.141 +
  11.142 +  // Get around early Solaris scheduling bug
  11.143 +  // (affinity vs other jobs on system)
  11.144 +  // but disallow DR and offlining (5008695).
  11.145 +  FLAG_SET_CMDLINE(bool, BindGCTaskThreadsToCPUs, true);
  11.146 +
  11.147 +  return JNI_OK;
  11.148 +}
  11.149 +
  11.150  // This must be called after ergonomics because we want bytecode rewriting
  11.151  // if the server compiler is used, or if UseSharedSpaces is disabled.
  11.152  void Arguments::set_bytecode_flags() {
  11.153 @@ -2644,6 +2746,14 @@
  11.154      return result;
  11.155    }
  11.156  
  11.157 +  // We need to ensure processor and memory resources have been properly
  11.158 +  // configured - which may rely on arguments we just processed - before
  11.159 +  // doing the final argument processing. Any argument processing that
  11.160 +  // needs to know about processor and memory resources must occur after
  11.161 +  // this point.
  11.162 +
  11.163 +  os::init_container_support();
  11.164 +
  11.165    // Do final processing now that all arguments have been parsed
  11.166    result = finalize_vm_init_args(&scp, scp_assembly_required);
  11.167    if (result != JNI_OK) {
  11.168 @@ -3117,94 +3227,6 @@
  11.169        _exit_hook = CAST_TO_FN_PTR(exit_hook_t, option->extraInfo);
  11.170      } else if (match_option(option, "abort", &tail)) {
  11.171        _abort_hook = CAST_TO_FN_PTR(abort_hook_t, option->extraInfo);
  11.172 -    // -XX:+AggressiveHeap
  11.173 -    } else if (match_option(option, "-XX:+AggressiveHeap", &tail)) {
  11.174 -
  11.175 -      // This option inspects the machine and attempts to set various
  11.176 -      // parameters to be optimal for long-running, memory allocation
  11.177 -      // intensive jobs.  It is intended for machines with large
  11.178 -      // amounts of cpu and memory.
  11.179 -
  11.180 -      // initHeapSize is needed since _initial_heap_size is 4 bytes on a 32 bit
  11.181 -      // VM, but we may not be able to represent the total physical memory
  11.182 -      // available (like having 8gb of memory on a box but using a 32bit VM).
  11.183 -      // Thus, we need to make sure we're using a julong for intermediate
  11.184 -      // calculations.
  11.185 -      julong initHeapSize;
  11.186 -      julong total_memory = os::physical_memory();
  11.187 -
  11.188 -      if (total_memory < (julong)256*M) {
  11.189 -        jio_fprintf(defaultStream::error_stream(),
  11.190 -                    "You need at least 256mb of memory to use -XX:+AggressiveHeap\n");
  11.191 -        vm_exit(1);
  11.192 -      }
  11.193 -
  11.194 -      // The heap size is half of available memory, or (at most)
  11.195 -      // all of possible memory less 160mb (leaving room for the OS
  11.196 -      // when using ISM).  This is the maximum; because adaptive sizing
  11.197 -      // is turned on below, the actual space used may be smaller.
  11.198 -
  11.199 -      initHeapSize = MIN2(total_memory / (julong)2,
  11.200 -                          total_memory - (julong)160*M);
  11.201 -
  11.202 -      initHeapSize = limit_by_allocatable_memory(initHeapSize);
  11.203 -
  11.204 -      if (FLAG_IS_DEFAULT(MaxHeapSize)) {
  11.205 -         FLAG_SET_CMDLINE(uintx, MaxHeapSize, initHeapSize);
  11.206 -         FLAG_SET_CMDLINE(uintx, InitialHeapSize, initHeapSize);
  11.207 -         // Currently the minimum size and the initial heap sizes are the same.
  11.208 -         set_min_heap_size(initHeapSize);
  11.209 -      }
  11.210 -      if (FLAG_IS_DEFAULT(NewSize)) {
  11.211 -         // Make the young generation 3/8ths of the total heap.
  11.212 -         FLAG_SET_CMDLINE(uintx, NewSize,
  11.213 -                                ((julong)MaxHeapSize / (julong)8) * (julong)3);
  11.214 -         FLAG_SET_CMDLINE(uintx, MaxNewSize, NewSize);
  11.215 -      }
  11.216 -
  11.217 -#ifndef _ALLBSD_SOURCE  // UseLargePages is not yet supported on BSD.
  11.218 -      FLAG_SET_DEFAULT(UseLargePages, true);
  11.219 -#endif
  11.220 -
  11.221 -      // Increase some data structure sizes for efficiency
  11.222 -      FLAG_SET_CMDLINE(uintx, BaseFootPrintEstimate, MaxHeapSize);
  11.223 -      FLAG_SET_CMDLINE(bool, ResizeTLAB, false);
  11.224 -      FLAG_SET_CMDLINE(uintx, TLABSize, 256*K);
  11.225 -
  11.226 -      // See the OldPLABSize comment below, but replace 'after promotion'
  11.227 -      // with 'after copying'.  YoungPLABSize is the size of the survivor
  11.228 -      // space per-gc-thread buffers.  The default is 4kw.
  11.229 -      FLAG_SET_CMDLINE(uintx, YoungPLABSize, 256*K);      // Note: this is in words
  11.230 -
  11.231 -      // OldPLABSize is the size of the buffers in the old gen that
  11.232 -      // UseParallelGC uses to promote live data that doesn't fit in the
  11.233 -      // survivor spaces.  At any given time, there's one for each gc thread.
  11.234 -      // The default size is 1kw. These buffers are rarely used, since the
  11.235 -      // survivor spaces are usually big enough.  For specjbb, however, there
  11.236 -      // are occasions when there's lots of live data in the young gen
  11.237 -      // and we end up promoting some of it.  We don't have a definite
  11.238 -      // explanation for why bumping OldPLABSize helps, but the theory
  11.239 -      // is that a bigger PLAB results in retaining something like the
  11.240 -      // original allocation order after promotion, which improves mutator
  11.241 -      // locality.  A minor effect may be that larger PLABs reduce the
  11.242 -      // number of PLAB allocation events during gc.  The value of 8kw
  11.243 -      // was arrived at by experimenting with specjbb.
  11.244 -      FLAG_SET_CMDLINE(uintx, OldPLABSize, 8*K);  // Note: this is in words
  11.245 -
  11.246 -      // Enable parallel GC and adaptive generation sizing
  11.247 -      FLAG_SET_CMDLINE(bool, UseParallelGC, true);
  11.248 -
  11.249 -      // Encourage steady state memory management
  11.250 -      FLAG_SET_CMDLINE(uintx, ThresholdTolerance, 100);
  11.251 -
  11.252 -      // This appears to improve mutator locality
  11.253 -      FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false);
  11.254 -
  11.255 -      // Get around early Solaris scheduling bug
  11.256 -      // (affinity vs other jobs on system)
  11.257 -      // but disallow DR and offlining (5008695).
  11.258 -      FLAG_SET_CMDLINE(bool, BindGCTaskThreadsToCPUs, true);
  11.259 -
  11.260      } else if (match_option(option, "-XX:+NeverTenure", &tail)) {
  11.261        // The last option must always win.
  11.262        FLAG_SET_CMDLINE(bool, AlwaysTenure, false);
  11.263 @@ -3605,6 +3627,15 @@
  11.264      return JNI_ERR;
  11.265    }
  11.266  
  11.267 +  // This must be done after all arguments have been processed
  11.268 +  // and the container support has been initialized since AggressiveHeap
  11.269 +  // relies on the amount of total memory available.
  11.270 +  if (AggressiveHeap) {
  11.271 +    jint result = set_aggressive_heap_flags();
  11.272 +    if (result != JNI_OK) {
  11.273 +      return result;
  11.274 +    }
  11.275 +  }
  11.276    // This must be done after all arguments have been processed.
  11.277    // java_compiler() true means set to "NONE" or empty.
  11.278    if (java_compiler() && !xdebug_mode()) {
    12.1 --- a/src/share/vm/runtime/arguments.hpp	Wed Jul 11 15:59:47 2018 +0100
    12.2 +++ b/src/share/vm/runtime/arguments.hpp	Fri Jul 27 11:47:10 2018 +0100
    12.3 @@ -1,5 +1,5 @@
    12.4  /*
    12.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
    12.6 + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
    12.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    12.8   *
    12.9   * This code is free software; you can redistribute it and/or modify it
   12.10 @@ -365,6 +365,8 @@
   12.11    // Aggressive optimization flags.
   12.12    static void set_aggressive_opts_flags();
   12.13  
   12.14 +  static jint set_aggressive_heap_flags();
   12.15 +
   12.16    // Argument parsing
   12.17    static void do_pd_flag_adjustments();
   12.18    static bool parse_argument(const char* arg, Flag::Flags origin);
    13.1 --- a/src/share/vm/runtime/globals.hpp	Wed Jul 11 15:59:47 2018 +0100
    13.2 +++ b/src/share/vm/runtime/globals.hpp	Fri Jul 27 11:47:10 2018 +0100
    13.3 @@ -2064,13 +2064,23 @@
    13.4    product_pd(uint64_t, MaxRAM,                                              \
    13.5            "Real memory size (in bytes) used to set maximum heap size")      \
    13.6                                                                              \
    13.7 +  product(bool, AggressiveHeap, false,                                      \
    13.8 +          "Optimize heap options for long-running memory intensive apps")   \
    13.9 +                                                                            \
   13.10    product(uintx, ErgoHeapSizeLimit, 0,                                      \
   13.11            "Maximum ergonomically set heap size (in bytes); zero means use " \
   13.12 -          "MaxRAM / MaxRAMFraction")                                        \
   13.13 +          "MaxRAM * MaxRAMPercentage / 100")                                \
   13.14                                                                              \
   13.15    experimental(bool, UseCGroupMemoryLimitForHeap, false,                    \
   13.16            "Use CGroup memory limit as physical memory limit for heap "      \
   13.17 -          "sizing")                                                         \
   13.18 +          "sizing"                                                          \
   13.19 +          "Deprecated, replaced by container support")                      \
   13.20 +                                                                            \
   13.21 +  diagnostic(bool, PrintContainerInfo, false,                               \
   13.22 +          "Print container related information")                            \
   13.23 +                                                                            \
   13.24 +  diagnostic(bool, PrintActiveCpus, false,                                  \
   13.25 +           "Print the number of CPUs detected in os::active_processor_count") \
   13.26                                                                              \
   13.27    product(uintx, MaxRAMFraction, 4,                                         \
   13.28            "Maximum fraction (1/n) of real memory used for maximum heap "    \
   13.29 @@ -2087,6 +2097,19 @@
   13.30    product(uintx, InitialRAMFraction, 64,                                    \
   13.31            "Fraction (1/n) of real memory used for initial heap size")       \
   13.32                                                                              \
   13.33 +  product(double, MaxRAMPercentage, 25.0,                                   \
   13.34 +          "Maximum percentage of real memory used for maximum heap size")   \
   13.35 +                                                                            \
   13.36 +  product(double, MinRAMPercentage, 50.0,                                   \
   13.37 +          "Minimum percentage of real memory used for maximum heap"         \
   13.38 +          "size on systems with small physical memory size")                \
   13.39 +                                                                            \
   13.40 +  product(double, InitialRAMPercentage, 1.5625,                             \
   13.41 +          "Percentage of real memory used for initial heap size")           \
   13.42 +                                                                            \
   13.43 +  product(intx, ActiveProcessorCount, -1,                                   \
   13.44 +          "Specify the CPU count the VM should use and report as active")   \
   13.45 +                                                                            \
   13.46    develop(uintx, MaxVirtMemFraction, 2,                                     \
   13.47            "Maximum fraction (1/n) of virtual memory used for ergonomically "\
   13.48            "determining maximum heap size")                                  \
    14.1 --- a/src/share/vm/runtime/os.hpp	Wed Jul 11 15:59:47 2018 +0100
    14.2 +++ b/src/share/vm/runtime/os.hpp	Fri Jul 27 11:47:10 2018 +0100
    14.3 @@ -152,8 +152,16 @@
    14.4    static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned);
    14.5  
    14.6    static void initialize_initial_active_processor_count();
    14.7 +
    14.8 +  LINUX_ONLY(static void pd_init_container_support();)
    14.9 +
   14.10   public:
   14.11    static void init(void);                      // Called before command line parsing
   14.12 +
   14.13 +  static void init_container_support() {       // Called during command line parsing.
   14.14 +     LINUX_ONLY(pd_init_container_support();)
   14.15 +  }
   14.16 +
   14.17    static void init_before_ergo(void);          // Called after command line parsing
   14.18                                                 // before VM ergonomics processing.
   14.19    static jint init_2(void);                    // Called after command line parsing
    15.1 --- a/src/share/vm/runtime/thread.cpp	Wed Jul 11 15:59:47 2018 +0100
    15.2 +++ b/src/share/vm/runtime/thread.cpp	Fri Jul 27 11:47:10 2018 +0100
    15.3 @@ -3335,6 +3335,7 @@
    15.4    Arguments::init_version_specific_system_properties();
    15.5  
    15.6    // Parse arguments
    15.7 +  // Note: this internally calls os::init_container_support()
    15.8    jint parse_result = Arguments::parse(args);
    15.9    if (parse_result != JNI_OK) return parse_result;
   15.10  

mercurial