8146115: Improve docker container detection and resource configuration usage

Fri, 06 Jul 2018 18:50:13 +0000

author
poonam
date
Fri, 06 Jul 2018 18:50:13 +0000
changeset 9348
cb9634ab2906
parent 9347
06dcd58caf4a
child 9350
aeacee5afc4d

8146115: Improve docker container detection and resource configuration usage
Reviewed-by: bobv, dbuck

src/os/aix/vm/os_aix.cpp file | annotate | diff | comparison | revisions
src/os/bsd/vm/os_bsd.cpp file | annotate | diff | comparison | revisions
src/os/linux/vm/globals_linux.hpp file | annotate | diff | comparison | revisions
src/os/linux/vm/osContainer_linux.cpp file | annotate | diff | comparison | revisions
src/os/linux/vm/osContainer_linux.hpp file | annotate | diff | comparison | revisions
src/os/linux/vm/os_linux.cpp file | annotate | diff | comparison | revisions
src/os/linux/vm/os_linux.hpp file | annotate | diff | comparison | revisions
src/os/solaris/vm/os_solaris.cpp file | annotate | diff | comparison | revisions
src/os/windows/vm/os_windows.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/arguments.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/arguments.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/globals.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/os.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/thread.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/os/aix/vm/os_aix.cpp	Fri Jul 06 07:33:25 2018 -0700
     1.2 +++ b/src/os/aix/vm/os_aix.cpp	Fri Jul 06 18:50:13 2018 +0000
     1.3 @@ -4008,6 +4008,16 @@
     1.4  };
     1.5  
     1.6  int os::active_processor_count() {
     1.7 +  // User has overridden the number of active processors
     1.8 +  if (ActiveProcessorCount > 0) {
     1.9 +    if (PrintActiveCpus) {
    1.10 +      tty->print_cr("active_processor_count: "
    1.11 +                    "active processor count set by user : %d",
    1.12 +                     ActiveProcessorCount);
    1.13 +    }
    1.14 +    return ActiveProcessorCount;
    1.15 +  }
    1.16 +
    1.17    int online_cpus = ::sysconf(_SC_NPROCESSORS_ONLN);
    1.18    assert(online_cpus > 0 && online_cpus <= processor_count(), "sanity check");
    1.19    return online_cpus;
     2.1 --- a/src/os/bsd/vm/os_bsd.cpp	Fri Jul 06 07:33:25 2018 -0700
     2.2 +++ b/src/os/bsd/vm/os_bsd.cpp	Fri Jul 06 18:50:13 2018 +0000
     2.3 @@ -3765,6 +3765,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    return _processor_count;
    2.18  }
    2.19  
     3.1 --- a/src/os/linux/vm/globals_linux.hpp	Fri Jul 06 07:33:25 2018 -0700
     3.2 +++ b/src/os/linux/vm/globals_linux.hpp	Fri Jul 06 18:50:13 2018 +0000
     3.3 @@ -1,5 +1,5 @@
     3.4  /*
     3.5 - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
     3.6 + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
     3.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.8   *
     3.9   * This code is free software; you can redistribute it and/or modify it
    3.10 @@ -49,8 +49,13 @@
    3.11    product(bool, UseSHM, false,                                          \
    3.12            "Use SYSV shared memory for large pages")                     \
    3.13                                                                          \
    3.14 -  diagnostic(bool, PrintActiveCpus, false,                              \
    3.15 -          "Print the number of CPUs detected in os::active_processor_count")
    3.16 +  product(bool, UseContainerSupport, true,                              \
    3.17 +          "Enable detection and runtime container configuration support") \
    3.18 +                                                                        \
    3.19 +  product(bool, PreferContainerQuotaForCPUCount, true,                  \
    3.20 +          "Calculate the container CPU availability based on the value" \
    3.21 +          " of quotas (if set), when true. Otherwise, use the CPU"      \
    3.22 +          " shares value, provided it is less than quota.")
    3.23  
    3.24  //
    3.25  // Defines Linux-specific default values. The flags are available on all
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/os/linux/vm/osContainer_linux.cpp	Fri Jul 06 18:50:13 2018 +0000
     4.3 @@ -0,0 +1,680 @@
     4.4 +/*
     4.5 + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
     4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.7 + *
     4.8 + * This code is free software; you can redistribute it and/or modify it
     4.9 + * under the terms of the GNU General Public License version 2 only, as
    4.10 + * published by the Free Software Foundation.
    4.11 + *
    4.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    4.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    4.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    4.15 + * version 2 for more details (a copy is included in the LICENSE file that
    4.16 + * accompanied this code).
    4.17 + *
    4.18 + * You should have received a copy of the GNU General Public License version
    4.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    4.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    4.21 + *
    4.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    4.23 + * or visit www.oracle.com if you need additional information or have any
    4.24 + * questions.
    4.25 + *
    4.26 + */
    4.27 +
    4.28 +#include <string.h>
    4.29 +#include <math.h>
    4.30 +#include <errno.h>
    4.31 +#include "utilities/globalDefinitions.hpp"
    4.32 +#include "memory/allocation.hpp"
    4.33 +#include "runtime/os.hpp"
    4.34 +#include "osContainer_linux.hpp"
    4.35 +
    4.36 +#define PER_CPU_SHARES 1024
    4.37 +
    4.38 +bool  OSContainer::_is_initialized   = false;
    4.39 +bool  OSContainer::_is_containerized = false;
    4.40 +julong _unlimited_memory;
    4.41 +
    4.42 +class CgroupSubsystem: CHeapObj<mtInternal> {
    4.43 + friend class OSContainer;
    4.44 +
    4.45 + private:
    4.46 +    /* mountinfo contents */
    4.47 +    char *_root;
    4.48 +    char *_mount_point;
    4.49 +
    4.50 +    /* Constructed subsystem directory */
    4.51 +    char *_path;
    4.52 +
    4.53 + public:
    4.54 +    CgroupSubsystem(char *root, char *mountpoint) {
    4.55 +      _root = os::strdup(root);
    4.56 +      _mount_point = os::strdup(mountpoint);
    4.57 +      _path = NULL;
    4.58 +    }
    4.59 +
    4.60 +    /*
    4.61 +     * Set directory to subsystem specific files based
    4.62 +     * on the contents of the mountinfo and cgroup files.
    4.63 +     */
    4.64 +    void set_subsystem_path(char *cgroup_path) {
    4.65 +      char buf[MAXPATHLEN+1];
    4.66 +      if (_root != NULL && cgroup_path != NULL) {
    4.67 +        if (strcmp(_root, "/") == 0) {
    4.68 +          int buflen;
    4.69 +          strncpy(buf, _mount_point, MAXPATHLEN);
    4.70 +          buf[MAXPATHLEN-1] = '\0';
    4.71 +          if (strcmp(cgroup_path,"/") != 0) {
    4.72 +            buflen = strlen(buf);
    4.73 +            if ((buflen + strlen(cgroup_path)) > (MAXPATHLEN-1)) {
    4.74 +              return;
    4.75 +            }
    4.76 +            strncat(buf, cgroup_path, MAXPATHLEN-buflen);
    4.77 +            buf[MAXPATHLEN-1] = '\0';
    4.78 +          }
    4.79 +          _path = os::strdup(buf);
    4.80 +        } else {
    4.81 +          if (strcmp(_root, cgroup_path) == 0) {
    4.82 +            strncpy(buf, _mount_point, MAXPATHLEN);
    4.83 +            buf[MAXPATHLEN-1] = '\0';
    4.84 +            _path = os::strdup(buf);
    4.85 +          } else {
    4.86 +            char *p = strstr(_root, cgroup_path);
    4.87 +            if (p != NULL && p == _root) {
    4.88 +              if (strlen(cgroup_path) > strlen(_root)) {
    4.89 +                int buflen;
    4.90 +                strncpy(buf, _mount_point, MAXPATHLEN);
    4.91 +                buf[MAXPATHLEN-1] = '\0';
    4.92 +                buflen = strlen(buf);
    4.93 +                if ((buflen + strlen(cgroup_path)) > (MAXPATHLEN-1)) {
    4.94 +                  return;
    4.95 +                }
    4.96 +                strncat(buf, cgroup_path + strlen(_root), MAXPATHLEN-buflen);
    4.97 +                buf[MAXPATHLEN-1] = '\0';
    4.98 +                _path = os::strdup(buf);
    4.99 +              }
   4.100 +            }
   4.101 +          }
   4.102 +        }
   4.103 +      }
   4.104 +    }
   4.105 +
   4.106 +    char *subsystem_path() { return _path; }
   4.107 +};
   4.108 +
   4.109 +CgroupSubsystem* memory = NULL;
   4.110 +CgroupSubsystem* cpuset = NULL;
   4.111 +CgroupSubsystem* cpu = NULL;
   4.112 +CgroupSubsystem* cpuacct = NULL;
   4.113 +
   4.114 +typedef char * cptr;
   4.115 +
   4.116 +PRAGMA_DIAG_PUSH
   4.117 +PRAGMA_FORMAT_NONLITERAL_IGNORED
   4.118 +template <typename T> int subsystem_file_contents(CgroupSubsystem* c,
   4.119 +                                              const char *filename,
   4.120 +                                              const char *scan_fmt,
   4.121 +                                              T returnval) {
   4.122 +  FILE *fp = NULL;
   4.123 +  char *p;
   4.124 +  char file[MAXPATHLEN+1];
   4.125 +  char buf[MAXPATHLEN+1];
   4.126 +
   4.127 +  if (c == NULL) {
   4.128 +    if (PrintContainerInfo) {
   4.129 +      tty->print_cr("subsystem_file_contents: CgroupSubsytem* is NULL");
   4.130 +    }
   4.131 +    return OSCONTAINER_ERROR;
   4.132 +  }
   4.133 +  if (c->subsystem_path() == NULL) {
   4.134 +    if (PrintContainerInfo) {
   4.135 +      tty->print_cr("subsystem_file_contents: subsystem path is NULL");
   4.136 +    }
   4.137 +    return OSCONTAINER_ERROR;
   4.138 +  }
   4.139 +
   4.140 +  strncpy(file, c->subsystem_path(), MAXPATHLEN);
   4.141 +  file[MAXPATHLEN-1] = '\0';
   4.142 +  int filelen = strlen(file);
   4.143 +  if ((filelen + strlen(filename)) > (MAXPATHLEN-1)) {
   4.144 +    if (PrintContainerInfo) {
   4.145 +      tty->print_cr("File path too long %s, %s", file, filename);
   4.146 +    }
   4.147 +    return OSCONTAINER_ERROR;
   4.148 +  }
   4.149 +  strncat(file, filename, MAXPATHLEN-filelen);
   4.150 +  if (PrintContainerInfo) {
   4.151 +    tty->print_cr("Path to %s is %s", filename, file);
   4.152 +  }
   4.153 +  fp = fopen(file, "r");
   4.154 +  if (fp != NULL) {
   4.155 +    p = fgets(buf, MAXPATHLEN, fp);
   4.156 +    if (p != NULL) {
   4.157 +      int matched = sscanf(p, scan_fmt, returnval);
   4.158 +      if (matched == 1) {
   4.159 +        fclose(fp);
   4.160 +        return 0;
   4.161 +      } else {
   4.162 +        if (PrintContainerInfo) {
   4.163 +          tty->print_cr("Type %s not found in file %s", scan_fmt, file);
   4.164 +        }
   4.165 +      }
   4.166 +    } else {
   4.167 +      if (PrintContainerInfo) {
   4.168 +        tty->print_cr("Empty file %s", file);
   4.169 +      }
   4.170 +    }
   4.171 +  } else {
   4.172 +    if (PrintContainerInfo) {
   4.173 +      tty->print_cr("Open of file %s failed, %s", file, strerror(errno));
   4.174 +    }
   4.175 +  }
   4.176 +  if (fp != NULL)
   4.177 +    fclose(fp);
   4.178 +  return OSCONTAINER_ERROR;
   4.179 +}
   4.180 +PRAGMA_DIAG_POP
   4.181 +
   4.182 +#define GET_CONTAINER_INFO(return_type, subsystem, filename,              \
   4.183 +                           logstring, scan_fmt, variable)                 \
   4.184 +  return_type variable;                                                   \
   4.185 +{                                                                         \
   4.186 +  int err;                                                                \
   4.187 +  err = subsystem_file_contents(subsystem,                                \
   4.188 +                                filename,                                 \
   4.189 +                                scan_fmt,                                 \
   4.190 +                                &variable);                               \
   4.191 +  if (err != 0)                                                           \
   4.192 +    return (return_type) OSCONTAINER_ERROR;                               \
   4.193 +                                                                          \
   4.194 +  if (PrintContainerInfo)                                                 \
   4.195 +    tty->print_cr(logstring, variable);                                   \
   4.196 +}
   4.197 +
   4.198 +#define GET_CONTAINER_INFO_CPTR(return_type, subsystem, filename,         \
   4.199 +                               logstring, scan_fmt, variable, bufsize)    \
   4.200 +  char variable[bufsize];                                                 \
   4.201 +{                                                                         \
   4.202 +  int err;                                                                \
   4.203 +  err = subsystem_file_contents(subsystem,                                \
   4.204 +                                filename,                                 \
   4.205 +                                scan_fmt,                                 \
   4.206 +                                variable);                                \
   4.207 +  if (err != 0)                                                           \
   4.208 +    return (return_type) NULL;                                            \
   4.209 +                                                                          \
   4.210 +  if (PrintContainerInfo)                                                 \
   4.211 +    tty->print_cr(logstring, variable);                                   \
   4.212 +}
   4.213 +
   4.214 +/* init
   4.215 + *
   4.216 + * Initialize the container support and determine if
   4.217 + * we are running under cgroup control.
   4.218 + */
   4.219 +void OSContainer::init() {
   4.220 +  int mountid;
   4.221 +  int parentid;
   4.222 +  int major;
   4.223 +  int minor;
   4.224 +  FILE *mntinfo = NULL;
   4.225 +  FILE *cgroup = NULL;
   4.226 +  char buf[MAXPATHLEN+1];
   4.227 +  char tmproot[MAXPATHLEN+1];
   4.228 +  char tmpmount[MAXPATHLEN+1];
   4.229 +  char tmpbase[MAXPATHLEN+1];
   4.230 +  char *p;
   4.231 +  jlong mem_limit;
   4.232 +
   4.233 +  assert(!_is_initialized, "Initializing OSContainer more than once");
   4.234 +
   4.235 +  _is_initialized = true;
   4.236 +  _is_containerized = false;
   4.237 +
   4.238 +  _unlimited_memory = (LONG_MAX / os::vm_page_size()) * os::vm_page_size();
   4.239 +
   4.240 +  if (PrintContainerInfo) {
   4.241 +    tty->print_cr("OSContainer::init: Initializing Container Support");
   4.242 +  }
   4.243 +  if (!UseContainerSupport) {
   4.244 +    if (PrintContainerInfo) {
   4.245 +      tty->print_cr("Container Support not enabled");
   4.246 +    }
   4.247 +    return;
   4.248 +  }
   4.249 +
   4.250 +  /*
   4.251 +   * Find the cgroup mount point for memory and cpuset
   4.252 +   * by reading /proc/self/mountinfo
   4.253 +   *
   4.254 +   * Example for docker:
   4.255 +   * 219 214 0:29 /docker/7208cebd00fa5f2e342b1094f7bed87fa25661471a4637118e65f1c995be8a34 /sys/fs/cgroup/memory ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory
   4.256 +   *
   4.257 +   * Example for host:
   4.258 +   * 34 28 0:29 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,memory
   4.259 +   */
   4.260 +  mntinfo = fopen("/proc/self/mountinfo", "r");
   4.261 +  if (mntinfo == NULL) {
   4.262 +      if (PrintContainerInfo) {
   4.263 +        tty->print_cr("Can't open /proc/self/mountinfo, %s",
   4.264 +                       strerror(errno));
   4.265 +      }
   4.266 +      return;
   4.267 +  }
   4.268 +
   4.269 +  while ( (p = fgets(buf, MAXPATHLEN, mntinfo)) != NULL) {
   4.270 +    // Look for the filesystem type and see if it's cgroup
   4.271 +    char fstype[MAXPATHLEN+1];
   4.272 +    fstype[0] = '\0';
   4.273 +    char *s =  strstr(p, " - ");
   4.274 +    if (s != NULL &&
   4.275 +        sscanf(s, " - %s", fstype) == 1 &&
   4.276 +        strcmp(fstype, "cgroup") == 0) {
   4.277 +
   4.278 +      if (strstr(p, "memory") != NULL) {
   4.279 +        int matched = sscanf(p, "%d %d %d:%d %s %s",
   4.280 +                             &mountid,
   4.281 +                             &parentid,
   4.282 +                             &major,
   4.283 +                             &minor,
   4.284 +                             tmproot,
   4.285 +                             tmpmount);
   4.286 +        if (matched == 6) {
   4.287 +          memory = new CgroupSubsystem(tmproot, tmpmount);
   4.288 +        }
   4.289 +        else
   4.290 +          if (PrintContainerInfo) {
   4.291 +            tty->print_cr("Incompatible str containing cgroup and memory: %s", p);
   4.292 +          }
   4.293 +      } else if (strstr(p, "cpuset") != NULL) {
   4.294 +        int matched = sscanf(p, "%d %d %d:%d %s %s",
   4.295 +                             &mountid,
   4.296 +                             &parentid,
   4.297 +                             &major,
   4.298 +                             &minor,
   4.299 +                             tmproot,
   4.300 +                             tmpmount);
   4.301 +        if (matched == 6) {
   4.302 +          cpuset = new CgroupSubsystem(tmproot, tmpmount);
   4.303 +        }
   4.304 +        else {
   4.305 +          if (PrintContainerInfo) {
   4.306 +            tty->print_cr("Incompatible str containing cgroup and cpuset: %s", p);
   4.307 +          }
   4.308 +        }
   4.309 +      } else if (strstr(p, "cpu,cpuacct") != NULL || strstr(p, "cpuacct,cpu") != NULL) {
   4.310 +        int matched = sscanf(p, "%d %d %d:%d %s %s",
   4.311 +                             &mountid,
   4.312 +                             &parentid,
   4.313 +                             &major,
   4.314 +                             &minor,
   4.315 +                             tmproot,
   4.316 +                             tmpmount);
   4.317 +        if (matched == 6) {
   4.318 +          cpu = new CgroupSubsystem(tmproot, tmpmount);
   4.319 +          cpuacct = new CgroupSubsystem(tmproot, tmpmount);
   4.320 +        }
   4.321 +        else {
   4.322 +          if (PrintContainerInfo) {
   4.323 +            tty->print_cr("Incompatible str containing cgroup and cpu,cpuacct: %s", p);
   4.324 +          }
   4.325 +        }
   4.326 +      } else if (strstr(p, "cpuacct") != NULL) {
   4.327 +        int matched = sscanf(p, "%d %d %d:%d %s %s",
   4.328 +                             &mountid,
   4.329 +                             &parentid,
   4.330 +                             &major,
   4.331 +                             &minor,
   4.332 +                             tmproot,
   4.333 +                             tmpmount);
   4.334 +        if (matched == 6) {
   4.335 +          cpuacct = new CgroupSubsystem(tmproot, tmpmount);
   4.336 +        }
   4.337 +        else {
   4.338 +          if (PrintContainerInfo) {
   4.339 +            tty->print_cr("Incompatible str containing cgroup and cpuacct: %s", p);
   4.340 +          }
   4.341 +        }
   4.342 +      } else if (strstr(p, "cpu") != NULL) {
   4.343 +        int matched = sscanf(p, "%d %d %d:%d %s %s",
   4.344 +                             &mountid,
   4.345 +                             &parentid,
   4.346 +                             &major,
   4.347 +                             &minor,
   4.348 +                             tmproot,
   4.349 +                             tmpmount);
   4.350 +        if (matched == 6) {
   4.351 +          cpu = new CgroupSubsystem(tmproot, tmpmount);
   4.352 +        }
   4.353 +        else {
   4.354 +          if (PrintContainerInfo) {
   4.355 +            tty->print_cr("Incompatible str containing cgroup and cpu: %s", p);
   4.356 +          }
   4.357 +        }
   4.358 +      }
   4.359 +    }
   4.360 +  }
   4.361 +
   4.362 +  fclose(mntinfo);
   4.363 +
   4.364 +  if (memory == NULL) {
   4.365 +    if (PrintContainerInfo) {
   4.366 +      tty->print_cr("Required cgroup memory subsystem not found");
   4.367 +    }
   4.368 +    return;
   4.369 +  }
   4.370 +  if (cpuset == NULL) {
   4.371 +    if (PrintContainerInfo) {
   4.372 +      tty->print_cr("Required cgroup cpuset subsystem not found");
   4.373 +    }
   4.374 +    return;
   4.375 +  }
   4.376 +  if (cpu == NULL) {
   4.377 +    if (PrintContainerInfo) {
   4.378 +      tty->print_cr("Required cgroup cpu subsystem not found");
   4.379 +    }
   4.380 +    return;
   4.381 +  }
   4.382 +  if (cpuacct == NULL) {
   4.383 +    if (PrintContainerInfo) {
   4.384 +      tty->print_cr("Required cgroup cpuacct subsystem not found");
   4.385 +    }
   4.386 +    return;
   4.387 +  }
   4.388 +
   4.389 +  /*
   4.390 +   * Read /proc/self/cgroup and map host mount point to
   4.391 +   * local one via /proc/self/mountinfo content above
   4.392 +   *
   4.393 +   * Docker example:
   4.394 +   * 5:memory:/docker/6558aed8fc662b194323ceab5b964f69cf36b3e8af877a14b80256e93aecb044
   4.395 +   *
   4.396 +   * Host example:
   4.397 +   * 5:memory:/user.slice
   4.398 +   *
   4.399 +   * Construct a path to the process specific memory and cpuset
   4.400 +   * cgroup directory.
   4.401 +   *
   4.402 +   * For a container running under Docker from memory example above
   4.403 +   * the paths would be:
   4.404 +   *
   4.405 +   * /sys/fs/cgroup/memory
   4.406 +   *
   4.407 +   * For a Host from memory example above the path would be:
   4.408 +   *
   4.409 +   * /sys/fs/cgroup/memory/user.slice
   4.410 +   *
   4.411 +   */
   4.412 +  cgroup = fopen("/proc/self/cgroup", "r");
   4.413 +  if (cgroup == NULL) {
   4.414 +    if (PrintContainerInfo) {
   4.415 +      tty->print_cr("Can't open /proc/self/cgroup, %s",
   4.416 +                     strerror(errno));
   4.417 +      }
   4.418 +    return;
   4.419 +  }
   4.420 +
   4.421 +  while ( (p = fgets(buf, MAXPATHLEN, cgroup)) != NULL) {
   4.422 +    int cgno;
   4.423 +    int matched;
   4.424 +    char *controller;
   4.425 +    char *base;
   4.426 +
   4.427 +    /* Skip cgroup number */
   4.428 +    strsep(&p, ":");
   4.429 +    /* Get controller and base */
   4.430 +    controller = strsep(&p, ":");
   4.431 +    base = strsep(&p, "\n");
   4.432 +
   4.433 +    if (controller != NULL) {
   4.434 +      if (strstr(controller, "memory") != NULL) {
   4.435 +        memory->set_subsystem_path(base);
   4.436 +      } else if (strstr(controller, "cpuset") != NULL) {
   4.437 +        cpuset->set_subsystem_path(base);
   4.438 +      } else if (strstr(controller, "cpu,cpuacct") != NULL || strstr(controller, "cpuacct,cpu") != NULL) {
   4.439 +        cpu->set_subsystem_path(base);
   4.440 +        cpuacct->set_subsystem_path(base);
   4.441 +      } else if (strstr(controller, "cpuacct") != NULL) {
   4.442 +        cpuacct->set_subsystem_path(base);
   4.443 +      } else if (strstr(controller, "cpu") != NULL) {
   4.444 +        cpu->set_subsystem_path(base);
   4.445 +      }
   4.446 +    }
   4.447 +  }
   4.448 +
   4.449 +  fclose(cgroup);
   4.450 +
   4.451 +  // We need to update the amount of physical memory now that
   4.452 +  // command line arguments have been processed.
   4.453 +  if ((mem_limit = memory_limit_in_bytes()) > 0) {
   4.454 +    os::Linux::set_physical_memory(mem_limit);
   4.455 +  }
   4.456 +
   4.457 +  _is_containerized = true;
   4.458 +
   4.459 +}
   4.460 +
   4.461 +const char * OSContainer::container_type() {
   4.462 +  if (is_containerized()) {
   4.463 +    return "cgroupv1";
   4.464 +  } else {
   4.465 +    return NULL;
   4.466 +  }
   4.467 +}
   4.468 +
   4.469 +
   4.470 +/* memory_limit_in_bytes
   4.471 + *
   4.472 + * Return the limit of available memory for this process.
   4.473 + *
   4.474 + * return:
   4.475 + *    memory limit in bytes or
   4.476 + *    -1 for unlimited
   4.477 + *    OSCONTAINER_ERROR for not supported
   4.478 + */
   4.479 +jlong OSContainer::memory_limit_in_bytes() {
   4.480 +  GET_CONTAINER_INFO(julong, memory, "/memory.limit_in_bytes",
   4.481 +                     "Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, memlimit);
   4.482 +
   4.483 +  if (memlimit >= _unlimited_memory) {
   4.484 +    if (PrintContainerInfo) {
   4.485 +      tty->print_cr("Memory Limit is: Unlimited");
   4.486 +    }
   4.487 +    return (jlong)-1;
   4.488 +  }
   4.489 +  else {
   4.490 +    return (jlong)memlimit;
   4.491 +  }
   4.492 +}
   4.493 +
   4.494 +jlong OSContainer::memory_and_swap_limit_in_bytes() {
   4.495 +  GET_CONTAINER_INFO(julong, memory, "/memory.memsw.limit_in_bytes",
   4.496 +                     "Memory and Swap Limit is: " JULONG_FORMAT, JULONG_FORMAT, memswlimit);
   4.497 +  if (memswlimit >= _unlimited_memory) {
   4.498 +    if (PrintContainerInfo) {
   4.499 +      tty->print_cr("Memory and Swap Limit is: Unlimited");
   4.500 +    }
   4.501 +    return (jlong)-1;
   4.502 +  } else {
   4.503 +    return (jlong)memswlimit;
   4.504 +  }
   4.505 +}
   4.506 +
   4.507 +jlong OSContainer::memory_soft_limit_in_bytes() {
   4.508 +  GET_CONTAINER_INFO(julong, memory, "/memory.soft_limit_in_bytes",
   4.509 +                     "Memory Soft Limit is: " JULONG_FORMAT, JULONG_FORMAT, memsoftlimit);
   4.510 +  if (memsoftlimit >= _unlimited_memory) {
   4.511 +    if (PrintContainerInfo) {
   4.512 +      tty->print_cr("Memory Soft Limit is: Unlimited");
   4.513 +    }
   4.514 +    return (jlong)-1;
   4.515 +  } else {
   4.516 +    return (jlong)memsoftlimit;
   4.517 +  }
   4.518 +}
   4.519 +
   4.520 +/* memory_usage_in_bytes
   4.521 + *
   4.522 + * Return the amount of used memory for this process.
   4.523 + *
   4.524 + * return:
   4.525 + *    memory usage in bytes or
   4.526 + *    -1 for unlimited
   4.527 + *    OSCONTAINER_ERROR for not supported
   4.528 + */
   4.529 +jlong OSContainer::memory_usage_in_bytes() {
   4.530 +  GET_CONTAINER_INFO(jlong, memory, "/memory.usage_in_bytes",
   4.531 +                     "Memory Usage is: " JLONG_FORMAT, JLONG_FORMAT, memusage);
   4.532 +  return memusage;
   4.533 +}
   4.534 +
   4.535 +/* memory_max_usage_in_bytes
   4.536 + *
   4.537 + * Return the maximum amount of used memory for this process.
   4.538 + *
   4.539 + * return:
   4.540 + *    max memory usage in bytes or
   4.541 + *    OSCONTAINER_ERROR for not supported
   4.542 + */
   4.543 +jlong OSContainer::memory_max_usage_in_bytes() {
   4.544 +  GET_CONTAINER_INFO(jlong, memory, "/memory.max_usage_in_bytes",
   4.545 +                     "Maximum Memory Usage is: " JLONG_FORMAT, JLONG_FORMAT, memmaxusage);
   4.546 +  return memmaxusage;
   4.547 +}
   4.548 +
   4.549 +/* active_processor_count
   4.550 + *
   4.551 + * Calculate an appropriate number of active processors for the
   4.552 + * VM to use based on these three inputs.
   4.553 + *
   4.554 + * cpu affinity
   4.555 + * cgroup cpu quota & cpu period
   4.556 + * cgroup cpu shares
   4.557 + *
   4.558 + * Algorithm:
   4.559 + *
   4.560 + * Determine the number of available CPUs from sched_getaffinity
   4.561 + *
   4.562 + * If user specified a quota (quota != -1), calculate the number of
   4.563 + * required CPUs by dividing quota by period.
   4.564 + *
   4.565 + * If shares are in effect (shares != -1), calculate the number
   4.566 + * of CPUs required for the shares by dividing the share value
   4.567 + * by PER_CPU_SHARES.
   4.568 + *
   4.569 + * All results of division are rounded up to the next whole number.
   4.570 + *
   4.571 + * If neither shares or quotas have been specified, return the
   4.572 + * number of active processors in the system.
   4.573 + *
   4.574 + * If both shares and quotas have been specified, the results are
   4.575 + * based on the flag PreferContainerQuotaForCPUCount.  If true,
   4.576 + * return the quota value.  If false return the smallest value
   4.577 + * between shares or quotas.
   4.578 + *
   4.579 + * If shares and/or quotas have been specified, the resulting number
   4.580 + * returned will never exceed the number of active processors.
   4.581 + *
   4.582 + * return:
   4.583 + *    number of CPUs
   4.584 + */
   4.585 +int OSContainer::active_processor_count() {
   4.586 +  int quota_count = 0, share_count = 0;
   4.587 +  int cpu_count, limit_count;
   4.588 +  int result;
   4.589 +
   4.590 +  cpu_count = limit_count = os::Linux::active_processor_count();
   4.591 +  int quota  = cpu_quota();
   4.592 +  int period = cpu_period();
   4.593 +  int share  = cpu_shares();
   4.594 +
   4.595 +  if (quota > -1 && period > 0) {
   4.596 +    quota_count = ceilf((float)quota / (float)period);
   4.597 +    if (PrintContainerInfo) {
   4.598 +      tty->print_cr("CPU Quota count based on quota/period: %d", quota_count);
   4.599 +    }
   4.600 +  }
   4.601 +  if (share > -1) {
   4.602 +    share_count = ceilf((float)share / (float)PER_CPU_SHARES);
   4.603 +    if (PrintContainerInfo) {
   4.604 +      tty->print_cr("CPU Share count based on shares: %d", share_count);
   4.605 +    }
   4.606 +  }
   4.607 +
   4.608 +  // If both shares and quotas are setup results depend
   4.609 +  // on flag PreferContainerQuotaForCPUCount.
   4.610 +  // If true, limit CPU count to quota
   4.611 +  // If false, use minimum of shares and quotas
   4.612 +  if (quota_count !=0 && share_count != 0) {
   4.613 +    if (PreferContainerQuotaForCPUCount) {
   4.614 +      limit_count = quota_count;
   4.615 +    } else {
   4.616 +      limit_count = MIN2(quota_count, share_count);
   4.617 +    }
   4.618 +  } else if (quota_count != 0) {
   4.619 +    limit_count = quota_count;
   4.620 +  } else if (share_count != 0) {
   4.621 +    limit_count = share_count;
   4.622 +  }
   4.623 +
   4.624 +  result = MIN2(cpu_count, limit_count);
   4.625 +  if (PrintContainerInfo) {
   4.626 +    tty->print_cr("OSContainer::active_processor_count: %d", result);
   4.627 +  }
   4.628 +  return result;
   4.629 +}
   4.630 +
   4.631 +char * OSContainer::cpu_cpuset_cpus() {
   4.632 +  GET_CONTAINER_INFO_CPTR(cptr, cpuset, "/cpuset.cpus",
   4.633 +                     "cpuset.cpus is: %s", "%1023s", cpus, 1024);
   4.634 +  return os::strdup(cpus);
   4.635 +}
   4.636 +
   4.637 +char * OSContainer::cpu_cpuset_memory_nodes() {
   4.638 +  GET_CONTAINER_INFO_CPTR(cptr, cpuset, "/cpuset.mems",
   4.639 +                     "cpuset.mems is: %s", "%1023s", mems, 1024);
   4.640 +  return os::strdup(mems);
   4.641 +}
   4.642 +
   4.643 +/* cpu_quota
   4.644 + *
   4.645 + * Return the number of milliseconds per period
   4.646 + * process is guaranteed to run.
   4.647 + *
   4.648 + * return:
   4.649 + *    quota time in milliseconds
   4.650 + *    -1 for no quota
   4.651 + *    OSCONTAINER_ERROR for not supported
   4.652 + */
   4.653 +int OSContainer::cpu_quota() {
   4.654 +  GET_CONTAINER_INFO(int, cpu, "/cpu.cfs_quota_us",
   4.655 +                     "CPU Quota is: %d", "%d", quota);
   4.656 +  return quota;
   4.657 +}
   4.658 +
   4.659 +int OSContainer::cpu_period() {
   4.660 +  GET_CONTAINER_INFO(int, cpu, "/cpu.cfs_period_us",
   4.661 +                     "CPU Period is: %d", "%d", period);
   4.662 +  return period;
   4.663 +}
   4.664 +
   4.665 +/* cpu_shares
   4.666 + *
   4.667 + * Return the amount of cpu shares available to the process
   4.668 + *
   4.669 + * return:
   4.670 + *    Share number (typically a number relative to 1024)
   4.671 + *                 (2048 typically expresses 2 CPUs worth of processing)
   4.672 + *    -1 for no share setup
   4.673 + *    OSCONTAINER_ERROR for not supported
   4.674 + */
   4.675 +int OSContainer::cpu_shares() {
   4.676 +  GET_CONTAINER_INFO(int, cpu, "/cpu.shares",
   4.677 +                     "CPU Shares is: %d", "%d", shares);
   4.678 +  // Convert 1024 to no shares setup
   4.679 +  if (shares == 1024) return -1;
   4.680 +
   4.681 +  return shares;
   4.682 +}
   4.683 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/os/linux/vm/osContainer_linux.hpp	Fri Jul 06 18:50:13 2018 +0000
     5.3 @@ -0,0 +1,68 @@
     5.4 +/*
     5.5 + * Copyright (c) 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 +#ifndef OS_LINUX_VM_OSCONTAINER_LINUX_HPP
    5.29 +#define OS_LINUX_VM_OSCONTAINER_LINUX_HPP
    5.30 +
    5.31 +#include "utilities/globalDefinitions.hpp"
    5.32 +#include "utilities/macros.hpp"
    5.33 +#include "memory/allocation.hpp"
    5.34 +
    5.35 +#define OSCONTAINER_ERROR (-2)
    5.36 +
    5.37 +class OSContainer: AllStatic {
    5.38 +
    5.39 + private:
    5.40 +  static bool   _is_initialized;
    5.41 +  static bool   _is_containerized;
    5.42 +
    5.43 + public:
    5.44 +  static void init();
    5.45 +  static inline bool is_containerized();
    5.46 +  static const char * container_type();
    5.47 +
    5.48 +  static jlong memory_limit_in_bytes();
    5.49 +  static jlong memory_and_swap_limit_in_bytes();
    5.50 +  static jlong memory_soft_limit_in_bytes();
    5.51 +  static jlong memory_usage_in_bytes();
    5.52 +  static jlong memory_max_usage_in_bytes();
    5.53 +
    5.54 +  static int active_processor_count();
    5.55 +
    5.56 +  static char * cpu_cpuset_cpus();
    5.57 +  static char * cpu_cpuset_memory_nodes();
    5.58 +
    5.59 +  static int cpu_quota();
    5.60 +  static int cpu_period();
    5.61 +
    5.62 +  static int cpu_shares();
    5.63 +
    5.64 +};
    5.65 +
    5.66 +inline bool OSContainer::is_containerized() {
    5.67 +  assert(_is_initialized, "OSContainer not initialized");
    5.68 +  return _is_containerized;
    5.69 +}
    5.70 +
    5.71 +#endif // OS_LINUX_VM_OSCONTAINER_LINUX_HPP
     6.1 --- a/src/os/linux/vm/os_linux.cpp	Fri Jul 06 07:33:25 2018 -0700
     6.2 +++ b/src/os/linux/vm/os_linux.cpp	Fri Jul 06 18:50:13 2018 +0000
     6.3 @@ -37,6 +37,7 @@
     6.4  #include "mutex_linux.inline.hpp"
     6.5  #include "oops/oop.inline.hpp"
     6.6  #include "os_share_linux.hpp"
     6.7 +#include "osContainer_linux.hpp"
     6.8  #include "prims/jniFastGetField.hpp"
     6.9  #include "prims/jvm.h"
    6.10  #include "prims/jvm_misc.hpp"
    6.11 @@ -179,13 +180,62 @@
    6.12  julong os::Linux::available_memory() {
    6.13    // values in struct sysinfo are "unsigned long"
    6.14    struct sysinfo si;
    6.15 +  julong avail_mem;
    6.16 +
    6.17 +  if (OSContainer::is_containerized()) {
    6.18 +    jlong mem_limit, mem_usage;
    6.19 +    if ((mem_limit = OSContainer::memory_limit_in_bytes()) < 1) {
    6.20 +      if (PrintContainerInfo) {
    6.21 +        tty->print_cr("container memory limit %s: " JLONG_FORMAT ", using host value",
    6.22 +                       mem_limit == OSCONTAINER_ERROR ? "failed" : "unlimited", mem_limit);
    6.23 +      }
    6.24 +    }
    6.25 +
    6.26 +    if (mem_limit > 0 && (mem_usage = OSContainer::memory_usage_in_bytes()) < 1) {
    6.27 +      if (PrintContainerInfo) {
    6.28 +        tty->print_cr("container memory usage failed: " JLONG_FORMAT ", using host value", mem_usage);
    6.29 +      }
    6.30 +    }
    6.31 +
    6.32 +    if (mem_limit > 0 && mem_usage > 0 ) {
    6.33 +      avail_mem = mem_limit > mem_usage ? (julong)mem_limit - (julong)mem_usage : 0;
    6.34 +      if (PrintContainerInfo) {
    6.35 +        tty->print_cr("available container memory: " JULONG_FORMAT, avail_mem);
    6.36 +      }
    6.37 +      return avail_mem;
    6.38 +    }
    6.39 +  }
    6.40 +
    6.41    sysinfo(&si);
    6.42 -
    6.43 -  return (julong)si.freeram * si.mem_unit;
    6.44 +  avail_mem = (julong)si.freeram * si.mem_unit;
    6.45 +  if (Verbose) {
    6.46 +    tty->print_cr("available memory: " JULONG_FORMAT, avail_mem);
    6.47 +  }
    6.48 +  return avail_mem;
    6.49  }
    6.50  
    6.51  julong os::physical_memory() {
    6.52 -  return Linux::physical_memory();
    6.53 +  jlong phys_mem = 0;
    6.54 +  if (OSContainer::is_containerized()) {
    6.55 +    jlong mem_limit;
    6.56 +    if ((mem_limit = OSContainer::memory_limit_in_bytes()) > 0) {
    6.57 +      if (PrintContainerInfo) {
    6.58 +        tty->print_cr("total container memory: " JLONG_FORMAT, mem_limit);
    6.59 +      }
    6.60 +      return mem_limit;
    6.61 +    }
    6.62 +
    6.63 +    if (PrintContainerInfo) {
    6.64 +      tty->print_cr("container memory limit %s: " JLONG_FORMAT ", using host value",
    6.65 +                     mem_limit == OSCONTAINER_ERROR ? "failed" : "unlimited", mem_limit);
    6.66 +    }
    6.67 +  }
    6.68 +
    6.69 +  phys_mem = Linux::physical_memory();
    6.70 +  if (Verbose) {
    6.71 +    tty->print_cr("total system memory: " JLONG_FORMAT, phys_mem);
    6.72 +  }
    6.73 +  return phys_mem;
    6.74  }
    6.75  
    6.76  ////////////////////////////////////////////////////////////////////////////////
    6.77 @@ -2120,6 +2170,8 @@
    6.78    os::Posix::print_load_average(st);
    6.79  
    6.80    os::Linux::print_full_memory_info(st);
    6.81 +
    6.82 +  os::Linux::print_container_info(st);
    6.83  }
    6.84  
    6.85  // Try to identify popular distros.
    6.86 @@ -2185,6 +2237,57 @@
    6.87     st->cr();
    6.88  }
    6.89  
    6.90 +void os::Linux::print_container_info(outputStream* st) {
    6.91 +if (!OSContainer::is_containerized()) {
    6.92 +    return;
    6.93 +  }
    6.94 +
    6.95 +  st->print("container (cgroup) information:\n");
    6.96 +
    6.97 +  const char *p_ct = OSContainer::container_type();
    6.98 +  st->print("container_type: %s\n", p_ct != NULL ? p_ct : "failed");
    6.99 +
   6.100 +  char *p = OSContainer::cpu_cpuset_cpus();
   6.101 +  st->print("cpu_cpuset_cpus: %s\n", p != NULL ? p : "failed");
   6.102 +  free(p);
   6.103 +
   6.104 +  p = OSContainer::cpu_cpuset_memory_nodes();
   6.105 +  st->print("cpu_memory_nodes: %s\n", p != NULL ? p : "failed");
   6.106 +  free(p);
   6.107 +
   6.108 +  int i = OSContainer::active_processor_count();
   6.109 +  if (i > 0) {
   6.110 +    st->print("active_processor_count: %d\n", i);
   6.111 +  } else {
   6.112 +    st->print("active_processor_count: failed\n");
   6.113 +  }
   6.114 +
   6.115 +  i = OSContainer::cpu_quota();
   6.116 +  st->print("cpu_quota: %d\n", i);
   6.117 +
   6.118 +  i = OSContainer::cpu_period();
   6.119 +  st->print("cpu_period: %d\n", i);
   6.120 +
   6.121 +  i = OSContainer::cpu_shares();
   6.122 +  st->print("cpu_shares: %d\n", i);
   6.123 +
   6.124 +  jlong j = OSContainer::memory_limit_in_bytes();
   6.125 +  st->print("memory_limit_in_bytes: " JLONG_FORMAT "\n", j);
   6.126 +
   6.127 +  j = OSContainer::memory_and_swap_limit_in_bytes();
   6.128 +  st->print("memory_and_swap_limit_in_bytes: " JLONG_FORMAT "\n", j);
   6.129 +
   6.130 +  j = OSContainer::memory_soft_limit_in_bytes();
   6.131 +  st->print("memory_soft_limit_in_bytes: " JLONG_FORMAT "\n", j);
   6.132 +
   6.133 +  j = OSContainer::OSContainer::memory_usage_in_bytes();
   6.134 +  st->print("memory_usage_in_bytes: " JLONG_FORMAT "\n", j);
   6.135 +
   6.136 +  j = OSContainer::OSContainer::memory_max_usage_in_bytes();
   6.137 +  st->print("memory_max_usage_in_bytes: " JLONG_FORMAT "\n", j);
   6.138 +  st->cr();
   6.139 +}
   6.140 +
   6.141  void os::print_memory_info(outputStream* st) {
   6.142  
   6.143    st->print("Memory:");
   6.144 @@ -4956,6 +5059,10 @@
   6.145    }
   6.146  }
   6.147  
   6.148 +void os::pd_init_container_support() {
   6.149 +  OSContainer::init();
   6.150 +}
   6.151 +
   6.152  // this is called _after_ the global arguments have been parsed
   6.153  jint os::init_2(void)
   6.154  {
   6.155 @@ -5136,7 +5243,7 @@
   6.156  // sched_getaffinity gives an accurate answer as it accounts for cpusets.
   6.157  // If anything goes wrong we fallback to returning the number of online
   6.158  // processors - which can be greater than the number available to the process.
   6.159 -int os::active_processor_count() {
   6.160 +int os::Linux::active_processor_count() {
   6.161    cpu_set_t cpus;  // can represent at most 1024 (CPU_SETSIZE) processors
   6.162    int cpus_size = sizeof(cpu_set_t);
   6.163    int cpu_count = 0;
   6.164 @@ -5154,10 +5261,48 @@
   6.165              "which may exceed available processors", strerror(errno), cpu_count);
   6.166    }
   6.167  
   6.168 -  assert(cpu_count > 0 && cpu_count <= processor_count(), "sanity check");
   6.169 +  assert(cpu_count > 0 && cpu_count <= os::processor_count(), "sanity check");
   6.170    return cpu_count;
   6.171  }
   6.172  
   6.173 +// Determine the active processor count from one of
   6.174 +// three different sources:
   6.175 +//
   6.176 +// 1. User option -XX:ActiveProcessorCount
   6.177 +// 2. kernel os calls (sched_getaffinity or sysconf(_SC_NPROCESSORS_ONLN)
   6.178 +// 3. extracted from cgroup cpu subsystem (shares and quotas)
   6.179 +//
   6.180 +// Option 1, if specified, will always override.
   6.181 +// If the cgroup subsystem is active and configured, we
   6.182 +// will return the min of the cgroup and option 2 results.
   6.183 +// This is required since tools, such as numactl, that
   6.184 +// alter cpu affinity do not update cgroup subsystem
   6.185 +// cpuset configuration files.
   6.186 +int os::active_processor_count() {
   6.187 +  // User has overridden the number of active processors
   6.188 +  if (ActiveProcessorCount > 0) {
   6.189 +    if (PrintActiveCpus) {
   6.190 +      tty->print_cr("active_processor_count: "
   6.191 +                    "active processor count set by user : %d",
   6.192 +                    ActiveProcessorCount);
   6.193 +    }
   6.194 +    return ActiveProcessorCount;
   6.195 +  }
   6.196 +
   6.197 +  int active_cpus;
   6.198 +  if (OSContainer::is_containerized()) {
   6.199 +    active_cpus = OSContainer::active_processor_count();
   6.200 +    if (PrintActiveCpus) {
   6.201 +      tty->print_cr("active_processor_count: determined by OSContainer: %d",
   6.202 +                     active_cpus);
   6.203 +    }
   6.204 +  } else {
   6.205 +    active_cpus = os::Linux::active_processor_count();
   6.206 +  }
   6.207 +
   6.208 +  return active_cpus;
   6.209 +}
   6.210 +
   6.211  void os::set_native_thread_name(const char *name) {
   6.212    // Not yet implemented.
   6.213    return;
     7.1 --- a/src/os/linux/vm/os_linux.hpp	Fri Jul 06 07:33:25 2018 -0700
     7.2 +++ b/src/os/linux/vm/os_linux.hpp	Fri Jul 06 18:50:13 2018 +0000
     7.3 @@ -35,6 +35,7 @@
     7.4  
     7.5  class Linux {
     7.6    friend class os;
     7.7 +  friend class OSContainer;
     7.8    friend class TestReserveMemorySpecial;
     7.9  
    7.10    // For signal-chaining
    7.11 @@ -79,6 +80,9 @@
    7.12  
    7.13    static julong available_memory();
    7.14    static julong physical_memory() { return _physical_memory; }
    7.15 +  static void set_physical_memory(julong phys_mem) { _physical_memory = phys_mem; }
    7.16 +  static int active_processor_count();
    7.17 +
    7.18    static void initialize_system_info();
    7.19  
    7.20    static int commit_memory_impl(char* addr, size_t bytes, bool exec);
    7.21 @@ -116,6 +120,7 @@
    7.22    static bool release_memory_special_huge_tlbfs(char* base, size_t bytes);
    7.23  
    7.24    static void print_full_memory_info(outputStream* st);
    7.25 +  static void print_container_info(outputStream* st);
    7.26    static void print_distro_info(outputStream* st);
    7.27    static void print_libversion_info(outputStream* st);
    7.28  
     8.1 --- a/src/os/solaris/vm/os_solaris.cpp	Fri Jul 06 07:33:25 2018 -0700
     8.2 +++ b/src/os/solaris/vm/os_solaris.cpp	Fri Jul 06 18:50:13 2018 +0000
     8.3 @@ -359,6 +359,16 @@
     8.4  }
     8.5  
     8.6  int os::active_processor_count() {
     8.7 +  // User has overridden the number of active processors
     8.8 +  if (ActiveProcessorCount > 0) {
     8.9 +    if (Verbose) {
    8.10 +      tty->print_cr("active_processor_count: "
    8.11 +                    "active processor count set by user : %d",
    8.12 +                     ActiveProcessorCount);
    8.13 +    }
    8.14 +    return ActiveProcessorCount;
    8.15 +  }
    8.16 +
    8.17    int online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
    8.18    pid_t pid = getpid();
    8.19    psetid_t pset = PS_NONE;
     9.1 --- a/src/os/windows/vm/os_windows.cpp	Fri Jul 06 07:33:25 2018 -0700
     9.2 +++ b/src/os/windows/vm/os_windows.cpp	Fri Jul 06 18:50:13 2018 +0000
     9.3 @@ -716,6 +716,16 @@
     9.4  #endif
     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 (PrintActiveCpus) {
    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    DWORD_PTR lpProcessAffinityMask = 0;
    9.18    DWORD_PTR lpSystemAffinityMask = 0;
    9.19    int proc_count = processor_count();
    10.1 --- a/src/share/vm/runtime/arguments.cpp	Fri Jul 06 07:33:25 2018 -0700
    10.2 +++ b/src/share/vm/runtime/arguments.cpp	Fri Jul 06 18:50:13 2018 +0000
    10.3 @@ -1,5 +1,5 @@
    10.4  /*
    10.5 - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
    10.6 + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
    10.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.8   *
    10.9   * This code is free software; you can redistribute it and/or modify it
   10.10 @@ -1801,20 +1801,34 @@
   10.11      }
   10.12    }
   10.13  
   10.14 +  // Convert Fraction to Precentage values
   10.15 +  if (FLAG_IS_DEFAULT(MaxRAMPercentage) &&
   10.16 +      !FLAG_IS_DEFAULT(MaxRAMFraction))
   10.17 +    MaxRAMPercentage = 100.0 / MaxRAMFraction;
   10.18 +
   10.19 +   if (FLAG_IS_DEFAULT(MinRAMPercentage) &&
   10.20 +       !FLAG_IS_DEFAULT(MinRAMFraction))
   10.21 +     MinRAMPercentage = 100.0 / MinRAMFraction;
   10.22 +
   10.23 +   if (FLAG_IS_DEFAULT(InitialRAMPercentage) &&
   10.24 +       !FLAG_IS_DEFAULT(InitialRAMFraction))
   10.25 +     InitialRAMPercentage = 100.0 / InitialRAMFraction;
   10.26 +
   10.27    // If the maximum heap size has not been set with -Xmx,
   10.28    // then set it as fraction of the size of physical memory,
   10.29    // respecting the maximum and minimum sizes of the heap.
   10.30    if (FLAG_IS_DEFAULT(MaxHeapSize)) {
   10.31 -    julong reasonable_max = phys_mem / MaxRAMFraction;
   10.32 -
   10.33 -    if (phys_mem <= MaxHeapSize * MinRAMFraction) {
   10.34 +    julong reasonable_max = (julong)((phys_mem * MaxRAMPercentage) / 100);
   10.35 +    const julong reasonable_min = (julong)((phys_mem * MinRAMPercentage) / 100);
   10.36 +    if (reasonable_min < MaxHeapSize) {
   10.37        // Small physical memory, so use a minimum fraction of it for the heap
   10.38 -      reasonable_max = phys_mem / MinRAMFraction;
   10.39 +      reasonable_max = reasonable_min;
   10.40      } else {
   10.41        // Not-small physical memory, so require a heap at least
   10.42        // as large as MaxHeapSize
   10.43        reasonable_max = MAX2(reasonable_max, (julong)MaxHeapSize);
   10.44      }
   10.45 +
   10.46      if (!FLAG_IS_DEFAULT(ErgoHeapSizeLimit) && ErgoHeapSizeLimit != 0) {
   10.47        // Limit the heap size to ErgoHeapSizeLimit
   10.48        reasonable_max = MIN2(reasonable_max, (julong)ErgoHeapSizeLimit);
   10.49 @@ -1856,7 +1870,7 @@
   10.50      reasonable_minimum = limit_by_allocatable_memory(reasonable_minimum);
   10.51  
   10.52      if (InitialHeapSize == 0) {
   10.53 -      julong reasonable_initial = phys_mem / InitialRAMFraction;
   10.54 +      julong reasonable_initial = (julong)((phys_mem * InitialRAMPercentage) / 100);
   10.55  
   10.56        reasonable_initial = MAX3(reasonable_initial, reasonable_minimum, (julong)min_heap_size());
   10.57        reasonable_initial = MIN2(reasonable_initial, (julong)MaxHeapSize);
   10.58 @@ -1881,6 +1895,94 @@
   10.59    }
   10.60  }
   10.61  
   10.62 +// This option inspects the machine and attempts to set various
   10.63 +// parameters to be optimal for long-running, memory allocation
   10.64 +// intensive jobs.  It is intended for machines with large
   10.65 +// amounts of cpu and memory.
   10.66 +jint Arguments::set_aggressive_heap_flags() {
   10.67 +  // initHeapSize is needed since _initial_heap_size is 4 bytes on a 32 bit
   10.68 +  // VM, but we may not be able to represent the total physical memory
   10.69 +  // available (like having 8gb of memory on a box but using a 32bit VM).
   10.70 +  // Thus, we need to make sure we're using a julong for intermediate
   10.71 +  // calculations.
   10.72 +  julong initHeapSize;
   10.73 +  julong total_memory = os::physical_memory();
   10.74 +
   10.75 +  if (total_memory < (julong) 256 * M) {
   10.76 +    jio_fprintf(defaultStream::error_stream(),
   10.77 +            "You need at least 256mb of memory to use -XX:+AggressiveHeap\n");
   10.78 +    vm_exit(1);
   10.79 +  }
   10.80 +
   10.81 +  // The heap size is half of available memory, or (at most)
   10.82 +  // all of possible memory less 160mb (leaving room for the OS
   10.83 +  // when using ISM).  This is the maximum; because adaptive sizing
   10.84 +  // is turned on below, the actual space used may be smaller.
   10.85 +
   10.86 +  initHeapSize = MIN2(total_memory / (julong) 2,
   10.87 +                      total_memory - (julong) 160 * M);
   10.88 +
   10.89 +  initHeapSize = limit_by_allocatable_memory(initHeapSize);
   10.90 +
   10.91 +  if (FLAG_IS_DEFAULT(MaxHeapSize)) {
   10.92 +    FLAG_SET_CMDLINE(uintx, MaxHeapSize, initHeapSize);
   10.93 +    FLAG_SET_CMDLINE(uintx, InitialHeapSize, initHeapSize);
   10.94 +    // Currently the minimum size and the initial heap sizes are the same.
   10.95 +    set_min_heap_size(initHeapSize);
   10.96 +  }
   10.97 +  if (FLAG_IS_DEFAULT(NewSize)) {
   10.98 +    // Make the young generation 3/8ths of the total heap.
   10.99 +    FLAG_SET_CMDLINE(uintx, NewSize,
  10.100 +            ((julong) MaxHeapSize / (julong) 8) * (julong) 3);
  10.101 +    FLAG_SET_CMDLINE(uintx, MaxNewSize, NewSize);
  10.102 +  }
  10.103 +
  10.104 +#ifndef _ALLBSD_SOURCE  // UseLargePages is not yet supported on BSD.
  10.105 +  FLAG_SET_DEFAULT(UseLargePages, true);
  10.106 +#endif
  10.107 +
  10.108 +  // Increase some data structure sizes for efficiency
  10.109 +  FLAG_SET_CMDLINE(uintx, BaseFootPrintEstimate, MaxHeapSize);
  10.110 +  FLAG_SET_CMDLINE(bool, ResizeTLAB, false);
  10.111 +  FLAG_SET_CMDLINE(uintx, TLABSize, 256 * K);
  10.112 +
  10.113 +  // See the OldPLABSize comment below, but replace 'after promotion'
  10.114 +  // with 'after copying'.  YoungPLABSize is the size of the survivor
  10.115 +  // space per-gc-thread buffers.  The default is 4kw.
  10.116 +  FLAG_SET_CMDLINE(uintx, YoungPLABSize, 256 * K);     // Note: this is in words
  10.117 +
  10.118 +  // OldPLABSize is the size of the buffers in the old gen that
  10.119 +  // UseParallelGC uses to promote live data that doesn't fit in the
  10.120 +  // survivor spaces.  At any given time, there's one for each gc thread.
  10.121 +  // The default size is 1kw. These buffers are rarely used, since the
  10.122 +  // survivor spaces are usually big enough.  For specjbb, however, there
  10.123 +  // are occasions when there's lots of live data in the young gen
  10.124 +  // and we end up promoting some of it.  We don't have a definite
  10.125 +  // explanation for why bumping OldPLABSize helps, but the theory
  10.126 +  // is that a bigger PLAB results in retaining something like the
  10.127 +  // original allocation order after promotion, which improves mutator
  10.128 +  // locality.  A minor effect may be that larger PLABs reduce the
  10.129 +  // number of PLAB allocation events during gc.  The value of 8kw
  10.130 +  // was arrived at by experimenting with specjbb.
  10.131 +  FLAG_SET_CMDLINE(uintx, OldPLABSize, 8 * K);      // Note: this is in words
  10.132 +
  10.133 +  // Enable parallel GC and adaptive generation sizing
  10.134 +  FLAG_SET_CMDLINE(bool, UseParallelGC, true);
  10.135 +
  10.136 +  // Encourage steady state memory management
  10.137 +  FLAG_SET_CMDLINE(uintx, ThresholdTolerance, 100);
  10.138 +
  10.139 +  // This appears to improve mutator locality
  10.140 +  FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false);
  10.141 +
  10.142 +  // Get around early Solaris scheduling bug
  10.143 +  // (affinity vs other jobs on system)
  10.144 +  // but disallow DR and offlining (5008695).
  10.145 +  FLAG_SET_CMDLINE(bool, BindGCTaskThreadsToCPUs, true);
  10.146 +
  10.147 +  return JNI_OK;
  10.148 +}
  10.149 +
  10.150  // This must be called after ergonomics because we want bytecode rewriting
  10.151  // if the server compiler is used, or if UseSharedSpaces is disabled.
  10.152  void Arguments::set_bytecode_flags() {
  10.153 @@ -2644,6 +2746,14 @@
  10.154      return result;
  10.155    }
  10.156  
  10.157 +  // We need to ensure processor and memory resources have been properly
  10.158 +  // configured - which may rely on arguments we just processed - before
  10.159 +  // doing the final argument processing. Any argument processing that
  10.160 +  // needs to know about processor and memory resources must occur after
  10.161 +  // this point.
  10.162 +
  10.163 +  os::init_container_support();
  10.164 +
  10.165    // Do final processing now that all arguments have been parsed
  10.166    result = finalize_vm_init_args(&scp, scp_assembly_required);
  10.167    if (result != JNI_OK) {
  10.168 @@ -3117,94 +3227,6 @@
  10.169        _exit_hook = CAST_TO_FN_PTR(exit_hook_t, option->extraInfo);
  10.170      } else if (match_option(option, "abort", &tail)) {
  10.171        _abort_hook = CAST_TO_FN_PTR(abort_hook_t, option->extraInfo);
  10.172 -    // -XX:+AggressiveHeap
  10.173 -    } else if (match_option(option, "-XX:+AggressiveHeap", &tail)) {
  10.174 -
  10.175 -      // This option inspects the machine and attempts to set various
  10.176 -      // parameters to be optimal for long-running, memory allocation
  10.177 -      // intensive jobs.  It is intended for machines with large
  10.178 -      // amounts of cpu and memory.
  10.179 -
  10.180 -      // initHeapSize is needed since _initial_heap_size is 4 bytes on a 32 bit
  10.181 -      // VM, but we may not be able to represent the total physical memory
  10.182 -      // available (like having 8gb of memory on a box but using a 32bit VM).
  10.183 -      // Thus, we need to make sure we're using a julong for intermediate
  10.184 -      // calculations.
  10.185 -      julong initHeapSize;
  10.186 -      julong total_memory = os::physical_memory();
  10.187 -
  10.188 -      if (total_memory < (julong)256*M) {
  10.189 -        jio_fprintf(defaultStream::error_stream(),
  10.190 -                    "You need at least 256mb of memory to use -XX:+AggressiveHeap\n");
  10.191 -        vm_exit(1);
  10.192 -      }
  10.193 -
  10.194 -      // The heap size is half of available memory, or (at most)
  10.195 -      // all of possible memory less 160mb (leaving room for the OS
  10.196 -      // when using ISM).  This is the maximum; because adaptive sizing
  10.197 -      // is turned on below, the actual space used may be smaller.
  10.198 -
  10.199 -      initHeapSize = MIN2(total_memory / (julong)2,
  10.200 -                          total_memory - (julong)160*M);
  10.201 -
  10.202 -      initHeapSize = limit_by_allocatable_memory(initHeapSize);
  10.203 -
  10.204 -      if (FLAG_IS_DEFAULT(MaxHeapSize)) {
  10.205 -         FLAG_SET_CMDLINE(uintx, MaxHeapSize, initHeapSize);
  10.206 -         FLAG_SET_CMDLINE(uintx, InitialHeapSize, initHeapSize);
  10.207 -         // Currently the minimum size and the initial heap sizes are the same.
  10.208 -         set_min_heap_size(initHeapSize);
  10.209 -      }
  10.210 -      if (FLAG_IS_DEFAULT(NewSize)) {
  10.211 -         // Make the young generation 3/8ths of the total heap.
  10.212 -         FLAG_SET_CMDLINE(uintx, NewSize,
  10.213 -                                ((julong)MaxHeapSize / (julong)8) * (julong)3);
  10.214 -         FLAG_SET_CMDLINE(uintx, MaxNewSize, NewSize);
  10.215 -      }
  10.216 -
  10.217 -#ifndef _ALLBSD_SOURCE  // UseLargePages is not yet supported on BSD.
  10.218 -      FLAG_SET_DEFAULT(UseLargePages, true);
  10.219 -#endif
  10.220 -
  10.221 -      // Increase some data structure sizes for efficiency
  10.222 -      FLAG_SET_CMDLINE(uintx, BaseFootPrintEstimate, MaxHeapSize);
  10.223 -      FLAG_SET_CMDLINE(bool, ResizeTLAB, false);
  10.224 -      FLAG_SET_CMDLINE(uintx, TLABSize, 256*K);
  10.225 -
  10.226 -      // See the OldPLABSize comment below, but replace 'after promotion'
  10.227 -      // with 'after copying'.  YoungPLABSize is the size of the survivor
  10.228 -      // space per-gc-thread buffers.  The default is 4kw.
  10.229 -      FLAG_SET_CMDLINE(uintx, YoungPLABSize, 256*K);      // Note: this is in words
  10.230 -
  10.231 -      // OldPLABSize is the size of the buffers in the old gen that
  10.232 -      // UseParallelGC uses to promote live data that doesn't fit in the
  10.233 -      // survivor spaces.  At any given time, there's one for each gc thread.
  10.234 -      // The default size is 1kw. These buffers are rarely used, since the
  10.235 -      // survivor spaces are usually big enough.  For specjbb, however, there
  10.236 -      // are occasions when there's lots of live data in the young gen
  10.237 -      // and we end up promoting some of it.  We don't have a definite
  10.238 -      // explanation for why bumping OldPLABSize helps, but the theory
  10.239 -      // is that a bigger PLAB results in retaining something like the
  10.240 -      // original allocation order after promotion, which improves mutator
  10.241 -      // locality.  A minor effect may be that larger PLABs reduce the
  10.242 -      // number of PLAB allocation events during gc.  The value of 8kw
  10.243 -      // was arrived at by experimenting with specjbb.
  10.244 -      FLAG_SET_CMDLINE(uintx, OldPLABSize, 8*K);  // Note: this is in words
  10.245 -
  10.246 -      // Enable parallel GC and adaptive generation sizing
  10.247 -      FLAG_SET_CMDLINE(bool, UseParallelGC, true);
  10.248 -
  10.249 -      // Encourage steady state memory management
  10.250 -      FLAG_SET_CMDLINE(uintx, ThresholdTolerance, 100);
  10.251 -
  10.252 -      // This appears to improve mutator locality
  10.253 -      FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false);
  10.254 -
  10.255 -      // Get around early Solaris scheduling bug
  10.256 -      // (affinity vs other jobs on system)
  10.257 -      // but disallow DR and offlining (5008695).
  10.258 -      FLAG_SET_CMDLINE(bool, BindGCTaskThreadsToCPUs, true);
  10.259 -
  10.260      } else if (match_option(option, "-XX:+NeverTenure", &tail)) {
  10.261        // The last option must always win.
  10.262        FLAG_SET_CMDLINE(bool, AlwaysTenure, false);
  10.263 @@ -3605,6 +3627,15 @@
  10.264      return JNI_ERR;
  10.265    }
  10.266  
  10.267 +  // This must be done after all arguments have been processed
  10.268 +  // and the container support has been initialized since AggressiveHeap
  10.269 +  // relies on the amount of total memory available.
  10.270 +  if (AggressiveHeap) {
  10.271 +    jint result = set_aggressive_heap_flags();
  10.272 +    if (result != JNI_OK) {
  10.273 +      return result;
  10.274 +    }
  10.275 +  }
  10.276    // This must be done after all arguments have been processed.
  10.277    // java_compiler() true means set to "NONE" or empty.
  10.278    if (java_compiler() && !xdebug_mode()) {
    11.1 --- a/src/share/vm/runtime/arguments.hpp	Fri Jul 06 07:33:25 2018 -0700
    11.2 +++ b/src/share/vm/runtime/arguments.hpp	Fri Jul 06 18:50:13 2018 +0000
    11.3 @@ -1,5 +1,5 @@
    11.4  /*
    11.5 - * Copyright (c) 1997, 2014, 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 @@ -365,6 +365,8 @@
   11.11    // Aggressive optimization flags.
   11.12    static void set_aggressive_opts_flags();
   11.13  
   11.14 +  static jint set_aggressive_heap_flags();
   11.15 +
   11.16    // Argument parsing
   11.17    static void do_pd_flag_adjustments();
   11.18    static bool parse_argument(const char* arg, Flag::Flags origin);
    12.1 --- a/src/share/vm/runtime/globals.hpp	Fri Jul 06 07:33:25 2018 -0700
    12.2 +++ b/src/share/vm/runtime/globals.hpp	Fri Jul 06 18:50:13 2018 +0000
    12.3 @@ -2068,13 +2068,23 @@
    12.4    product_pd(uint64_t, MaxRAM,                                              \
    12.5            "Real memory size (in bytes) used to set maximum heap size")      \
    12.6                                                                              \
    12.7 +  product(bool, AggressiveHeap, false,                                      \
    12.8 +          "Optimize heap options for long-running memory intensive apps")   \
    12.9 +                                                                            \
   12.10    product(uintx, ErgoHeapSizeLimit, 0,                                      \
   12.11            "Maximum ergonomically set heap size (in bytes); zero means use " \
   12.12 -          "MaxRAM / MaxRAMFraction")                                        \
   12.13 +          "MaxRAM * MaxRAMPercentage / 100")                                \
   12.14                                                                              \
   12.15    experimental(bool, UseCGroupMemoryLimitForHeap, false,                    \
   12.16            "Use CGroup memory limit as physical memory limit for heap "      \
   12.17 -          "sizing")                                                         \
   12.18 +          "sizing"                                                          \
   12.19 +          "Deprecated, replaced by container support")                      \
   12.20 +                                                                            \
   12.21 +  diagnostic(bool, PrintContainerInfo, false,                               \
   12.22 +          "Print container related information")                            \
   12.23 +                                                                            \
   12.24 +  diagnostic(bool, PrintActiveCpus, false,                                  \
   12.25 +           "Print the number of CPUs detected in os::active_processor_count") \
   12.26                                                                              \
   12.27    product(uintx, MaxRAMFraction, 4,                                         \
   12.28            "Maximum fraction (1/n) of real memory used for maximum heap "    \
   12.29 @@ -2091,6 +2101,19 @@
   12.30    product(uintx, InitialRAMFraction, 64,                                    \
   12.31            "Fraction (1/n) of real memory used for initial heap size")       \
   12.32                                                                              \
   12.33 +  product(double, MaxRAMPercentage, 25.0,                                   \
   12.34 +          "Maximum percentage of real memory used for maximum heap size")   \
   12.35 +                                                                            \
   12.36 +  product(double, MinRAMPercentage, 50.0,                                   \
   12.37 +          "Minimum percentage of real memory used for maximum heap"         \
   12.38 +          "size on systems with small physical memory size")                \
   12.39 +                                                                            \
   12.40 +  product(double, InitialRAMPercentage, 1.5625,                             \
   12.41 +          "Percentage of real memory used for initial heap size")           \
   12.42 +                                                                            \
   12.43 +  product(intx, ActiveProcessorCount, -1,                                   \
   12.44 +          "Specify the CPU count the VM should use and report as active")   \
   12.45 +                                                                            \
   12.46    develop(uintx, MaxVirtMemFraction, 2,                                     \
   12.47            "Maximum fraction (1/n) of virtual memory used for ergonomically "\
   12.48            "determining maximum heap size")                                  \
    13.1 --- a/src/share/vm/runtime/os.hpp	Fri Jul 06 07:33:25 2018 -0700
    13.2 +++ b/src/share/vm/runtime/os.hpp	Fri Jul 06 18:50:13 2018 +0000
    13.3 @@ -152,8 +152,16 @@
    13.4    static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned);
    13.5  
    13.6    static void initialize_initial_active_processor_count();
    13.7 +
    13.8 +  LINUX_ONLY(static void pd_init_container_support();)
    13.9 +
   13.10   public:
   13.11    static void init(void);                      // Called before command line parsing
   13.12 +
   13.13 +  static void init_container_support() {       // Called during command line parsing.
   13.14 +     LINUX_ONLY(pd_init_container_support();)
   13.15 +  }
   13.16 +
   13.17    static void init_before_ergo(void);          // Called after command line parsing
   13.18                                                 // before VM ergonomics processing.
   13.19    static jint init_2(void);                    // Called after command line parsing
    14.1 --- a/src/share/vm/runtime/thread.cpp	Fri Jul 06 07:33:25 2018 -0700
    14.2 +++ b/src/share/vm/runtime/thread.cpp	Fri Jul 06 18:50:13 2018 +0000
    14.3 @@ -3343,6 +3343,7 @@
    14.4    Arguments::init_version_specific_system_properties();
    14.5  
    14.6    // Parse arguments
    14.7 +  // Note: this internally calls os::init_container_support()
    14.8    jint parse_result = Arguments::parse(args);
    14.9    if (parse_result != JNI_OK) return parse_result;
   14.10  

mercurial