src/os/linux/vm/osContainer_linux.cpp

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

author
poonam
date
Fri, 06 Jul 2018 18:50:13 +0000
changeset 9413
5aa3d728164a
parent 9348
cb9634ab2906
permissions
-rw-r--r--

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

poonam@9348 1 /*
poonam@9348 2 * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
poonam@9348 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
poonam@9348 4 *
poonam@9348 5 * This code is free software; you can redistribute it and/or modify it
poonam@9348 6 * under the terms of the GNU General Public License version 2 only, as
poonam@9348 7 * published by the Free Software Foundation.
poonam@9348 8 *
poonam@9348 9 * This code is distributed in the hope that it will be useful, but WITHOUT
poonam@9348 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
poonam@9348 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
poonam@9348 12 * version 2 for more details (a copy is included in the LICENSE file that
poonam@9348 13 * accompanied this code).
poonam@9348 14 *
poonam@9348 15 * You should have received a copy of the GNU General Public License version
poonam@9348 16 * 2 along with this work; if not, write to the Free Software Foundation,
poonam@9348 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
poonam@9348 18 *
poonam@9348 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
poonam@9348 20 * or visit www.oracle.com if you need additional information or have any
poonam@9348 21 * questions.
poonam@9348 22 *
poonam@9348 23 */
poonam@9348 24
poonam@9348 25 #include <string.h>
poonam@9348 26 #include <math.h>
poonam@9348 27 #include <errno.h>
poonam@9348 28 #include "utilities/globalDefinitions.hpp"
poonam@9348 29 #include "memory/allocation.hpp"
poonam@9348 30 #include "runtime/os.hpp"
poonam@9348 31 #include "osContainer_linux.hpp"
poonam@9348 32
poonam@9348 33 #define PER_CPU_SHARES 1024
poonam@9348 34
poonam@9348 35 bool OSContainer::_is_initialized = false;
poonam@9348 36 bool OSContainer::_is_containerized = false;
poonam@9348 37 julong _unlimited_memory;
poonam@9348 38
poonam@9348 39 class CgroupSubsystem: CHeapObj<mtInternal> {
poonam@9348 40 friend class OSContainer;
poonam@9348 41
poonam@9348 42 private:
poonam@9348 43 /* mountinfo contents */
poonam@9348 44 char *_root;
poonam@9348 45 char *_mount_point;
poonam@9348 46
poonam@9348 47 /* Constructed subsystem directory */
poonam@9348 48 char *_path;
poonam@9348 49
poonam@9348 50 public:
poonam@9348 51 CgroupSubsystem(char *root, char *mountpoint) {
poonam@9348 52 _root = os::strdup(root);
poonam@9348 53 _mount_point = os::strdup(mountpoint);
poonam@9348 54 _path = NULL;
poonam@9348 55 }
poonam@9348 56
poonam@9348 57 /*
poonam@9348 58 * Set directory to subsystem specific files based
poonam@9348 59 * on the contents of the mountinfo and cgroup files.
poonam@9348 60 */
poonam@9348 61 void set_subsystem_path(char *cgroup_path) {
poonam@9348 62 char buf[MAXPATHLEN+1];
poonam@9348 63 if (_root != NULL && cgroup_path != NULL) {
poonam@9348 64 if (strcmp(_root, "/") == 0) {
poonam@9348 65 int buflen;
poonam@9348 66 strncpy(buf, _mount_point, MAXPATHLEN);
poonam@9348 67 buf[MAXPATHLEN-1] = '\0';
poonam@9348 68 if (strcmp(cgroup_path,"/") != 0) {
poonam@9348 69 buflen = strlen(buf);
poonam@9348 70 if ((buflen + strlen(cgroup_path)) > (MAXPATHLEN-1)) {
poonam@9348 71 return;
poonam@9348 72 }
poonam@9348 73 strncat(buf, cgroup_path, MAXPATHLEN-buflen);
poonam@9348 74 buf[MAXPATHLEN-1] = '\0';
poonam@9348 75 }
poonam@9348 76 _path = os::strdup(buf);
poonam@9348 77 } else {
poonam@9348 78 if (strcmp(_root, cgroup_path) == 0) {
poonam@9348 79 strncpy(buf, _mount_point, MAXPATHLEN);
poonam@9348 80 buf[MAXPATHLEN-1] = '\0';
poonam@9348 81 _path = os::strdup(buf);
poonam@9348 82 } else {
poonam@9348 83 char *p = strstr(_root, cgroup_path);
poonam@9348 84 if (p != NULL && p == _root) {
poonam@9348 85 if (strlen(cgroup_path) > strlen(_root)) {
poonam@9348 86 int buflen;
poonam@9348 87 strncpy(buf, _mount_point, MAXPATHLEN);
poonam@9348 88 buf[MAXPATHLEN-1] = '\0';
poonam@9348 89 buflen = strlen(buf);
poonam@9348 90 if ((buflen + strlen(cgroup_path)) > (MAXPATHLEN-1)) {
poonam@9348 91 return;
poonam@9348 92 }
poonam@9348 93 strncat(buf, cgroup_path + strlen(_root), MAXPATHLEN-buflen);
poonam@9348 94 buf[MAXPATHLEN-1] = '\0';
poonam@9348 95 _path = os::strdup(buf);
poonam@9348 96 }
poonam@9348 97 }
poonam@9348 98 }
poonam@9348 99 }
poonam@9348 100 }
poonam@9348 101 }
poonam@9348 102
poonam@9348 103 char *subsystem_path() { return _path; }
poonam@9348 104 };
poonam@9348 105
poonam@9348 106 CgroupSubsystem* memory = NULL;
poonam@9348 107 CgroupSubsystem* cpuset = NULL;
poonam@9348 108 CgroupSubsystem* cpu = NULL;
poonam@9348 109 CgroupSubsystem* cpuacct = NULL;
poonam@9348 110
poonam@9348 111 typedef char * cptr;
poonam@9348 112
poonam@9348 113 PRAGMA_DIAG_PUSH
poonam@9348 114 PRAGMA_FORMAT_NONLITERAL_IGNORED
poonam@9348 115 template <typename T> int subsystem_file_contents(CgroupSubsystem* c,
poonam@9348 116 const char *filename,
poonam@9348 117 const char *scan_fmt,
poonam@9348 118 T returnval) {
poonam@9348 119 FILE *fp = NULL;
poonam@9348 120 char *p;
poonam@9348 121 char file[MAXPATHLEN+1];
poonam@9348 122 char buf[MAXPATHLEN+1];
poonam@9348 123
poonam@9348 124 if (c == NULL) {
poonam@9348 125 if (PrintContainerInfo) {
poonam@9348 126 tty->print_cr("subsystem_file_contents: CgroupSubsytem* is NULL");
poonam@9348 127 }
poonam@9348 128 return OSCONTAINER_ERROR;
poonam@9348 129 }
poonam@9348 130 if (c->subsystem_path() == NULL) {
poonam@9348 131 if (PrintContainerInfo) {
poonam@9348 132 tty->print_cr("subsystem_file_contents: subsystem path is NULL");
poonam@9348 133 }
poonam@9348 134 return OSCONTAINER_ERROR;
poonam@9348 135 }
poonam@9348 136
poonam@9348 137 strncpy(file, c->subsystem_path(), MAXPATHLEN);
poonam@9348 138 file[MAXPATHLEN-1] = '\0';
poonam@9348 139 int filelen = strlen(file);
poonam@9348 140 if ((filelen + strlen(filename)) > (MAXPATHLEN-1)) {
poonam@9348 141 if (PrintContainerInfo) {
poonam@9348 142 tty->print_cr("File path too long %s, %s", file, filename);
poonam@9348 143 }
poonam@9348 144 return OSCONTAINER_ERROR;
poonam@9348 145 }
poonam@9348 146 strncat(file, filename, MAXPATHLEN-filelen);
poonam@9348 147 if (PrintContainerInfo) {
poonam@9348 148 tty->print_cr("Path to %s is %s", filename, file);
poonam@9348 149 }
poonam@9348 150 fp = fopen(file, "r");
poonam@9348 151 if (fp != NULL) {
poonam@9348 152 p = fgets(buf, MAXPATHLEN, fp);
poonam@9348 153 if (p != NULL) {
poonam@9348 154 int matched = sscanf(p, scan_fmt, returnval);
poonam@9348 155 if (matched == 1) {
poonam@9348 156 fclose(fp);
poonam@9348 157 return 0;
poonam@9348 158 } else {
poonam@9348 159 if (PrintContainerInfo) {
poonam@9348 160 tty->print_cr("Type %s not found in file %s", scan_fmt, file);
poonam@9348 161 }
poonam@9348 162 }
poonam@9348 163 } else {
poonam@9348 164 if (PrintContainerInfo) {
poonam@9348 165 tty->print_cr("Empty file %s", file);
poonam@9348 166 }
poonam@9348 167 }
poonam@9348 168 } else {
poonam@9348 169 if (PrintContainerInfo) {
poonam@9348 170 tty->print_cr("Open of file %s failed, %s", file, strerror(errno));
poonam@9348 171 }
poonam@9348 172 }
poonam@9348 173 if (fp != NULL)
poonam@9348 174 fclose(fp);
poonam@9348 175 return OSCONTAINER_ERROR;
poonam@9348 176 }
poonam@9348 177 PRAGMA_DIAG_POP
poonam@9348 178
poonam@9348 179 #define GET_CONTAINER_INFO(return_type, subsystem, filename, \
poonam@9348 180 logstring, scan_fmt, variable) \
poonam@9348 181 return_type variable; \
poonam@9348 182 { \
poonam@9348 183 int err; \
poonam@9348 184 err = subsystem_file_contents(subsystem, \
poonam@9348 185 filename, \
poonam@9348 186 scan_fmt, \
poonam@9348 187 &variable); \
poonam@9348 188 if (err != 0) \
poonam@9348 189 return (return_type) OSCONTAINER_ERROR; \
poonam@9348 190 \
poonam@9348 191 if (PrintContainerInfo) \
poonam@9348 192 tty->print_cr(logstring, variable); \
poonam@9348 193 }
poonam@9348 194
poonam@9348 195 #define GET_CONTAINER_INFO_CPTR(return_type, subsystem, filename, \
poonam@9348 196 logstring, scan_fmt, variable, bufsize) \
poonam@9348 197 char variable[bufsize]; \
poonam@9348 198 { \
poonam@9348 199 int err; \
poonam@9348 200 err = subsystem_file_contents(subsystem, \
poonam@9348 201 filename, \
poonam@9348 202 scan_fmt, \
poonam@9348 203 variable); \
poonam@9348 204 if (err != 0) \
poonam@9348 205 return (return_type) NULL; \
poonam@9348 206 \
poonam@9348 207 if (PrintContainerInfo) \
poonam@9348 208 tty->print_cr(logstring, variable); \
poonam@9348 209 }
poonam@9348 210
poonam@9348 211 /* init
poonam@9348 212 *
poonam@9348 213 * Initialize the container support and determine if
poonam@9348 214 * we are running under cgroup control.
poonam@9348 215 */
poonam@9348 216 void OSContainer::init() {
poonam@9348 217 int mountid;
poonam@9348 218 int parentid;
poonam@9348 219 int major;
poonam@9348 220 int minor;
poonam@9348 221 FILE *mntinfo = NULL;
poonam@9348 222 FILE *cgroup = NULL;
poonam@9348 223 char buf[MAXPATHLEN+1];
poonam@9348 224 char tmproot[MAXPATHLEN+1];
poonam@9348 225 char tmpmount[MAXPATHLEN+1];
poonam@9348 226 char tmpbase[MAXPATHLEN+1];
poonam@9348 227 char *p;
poonam@9348 228 jlong mem_limit;
poonam@9348 229
poonam@9348 230 assert(!_is_initialized, "Initializing OSContainer more than once");
poonam@9348 231
poonam@9348 232 _is_initialized = true;
poonam@9348 233 _is_containerized = false;
poonam@9348 234
poonam@9348 235 _unlimited_memory = (LONG_MAX / os::vm_page_size()) * os::vm_page_size();
poonam@9348 236
poonam@9348 237 if (PrintContainerInfo) {
poonam@9348 238 tty->print_cr("OSContainer::init: Initializing Container Support");
poonam@9348 239 }
poonam@9348 240 if (!UseContainerSupport) {
poonam@9348 241 if (PrintContainerInfo) {
poonam@9348 242 tty->print_cr("Container Support not enabled");
poonam@9348 243 }
poonam@9348 244 return;
poonam@9348 245 }
poonam@9348 246
poonam@9348 247 /*
poonam@9348 248 * Find the cgroup mount point for memory and cpuset
poonam@9348 249 * by reading /proc/self/mountinfo
poonam@9348 250 *
poonam@9348 251 * Example for docker:
poonam@9348 252 * 219 214 0:29 /docker/7208cebd00fa5f2e342b1094f7bed87fa25661471a4637118e65f1c995be8a34 /sys/fs/cgroup/memory ro,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory
poonam@9348 253 *
poonam@9348 254 * Example for host:
poonam@9348 255 * 34 28 0:29 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,memory
poonam@9348 256 */
poonam@9348 257 mntinfo = fopen("/proc/self/mountinfo", "r");
poonam@9348 258 if (mntinfo == NULL) {
poonam@9348 259 if (PrintContainerInfo) {
poonam@9348 260 tty->print_cr("Can't open /proc/self/mountinfo, %s",
poonam@9348 261 strerror(errno));
poonam@9348 262 }
poonam@9348 263 return;
poonam@9348 264 }
poonam@9348 265
poonam@9348 266 while ( (p = fgets(buf, MAXPATHLEN, mntinfo)) != NULL) {
poonam@9348 267 // Look for the filesystem type and see if it's cgroup
poonam@9348 268 char fstype[MAXPATHLEN+1];
poonam@9348 269 fstype[0] = '\0';
poonam@9348 270 char *s = strstr(p, " - ");
poonam@9348 271 if (s != NULL &&
poonam@9348 272 sscanf(s, " - %s", fstype) == 1 &&
poonam@9348 273 strcmp(fstype, "cgroup") == 0) {
poonam@9348 274
poonam@9348 275 if (strstr(p, "memory") != NULL) {
poonam@9348 276 int matched = sscanf(p, "%d %d %d:%d %s %s",
poonam@9348 277 &mountid,
poonam@9348 278 &parentid,
poonam@9348 279 &major,
poonam@9348 280 &minor,
poonam@9348 281 tmproot,
poonam@9348 282 tmpmount);
poonam@9348 283 if (matched == 6) {
poonam@9348 284 memory = new CgroupSubsystem(tmproot, tmpmount);
poonam@9348 285 }
poonam@9348 286 else
poonam@9348 287 if (PrintContainerInfo) {
poonam@9348 288 tty->print_cr("Incompatible str containing cgroup and memory: %s", p);
poonam@9348 289 }
poonam@9348 290 } else if (strstr(p, "cpuset") != NULL) {
poonam@9348 291 int matched = sscanf(p, "%d %d %d:%d %s %s",
poonam@9348 292 &mountid,
poonam@9348 293 &parentid,
poonam@9348 294 &major,
poonam@9348 295 &minor,
poonam@9348 296 tmproot,
poonam@9348 297 tmpmount);
poonam@9348 298 if (matched == 6) {
poonam@9348 299 cpuset = new CgroupSubsystem(tmproot, tmpmount);
poonam@9348 300 }
poonam@9348 301 else {
poonam@9348 302 if (PrintContainerInfo) {
poonam@9348 303 tty->print_cr("Incompatible str containing cgroup and cpuset: %s", p);
poonam@9348 304 }
poonam@9348 305 }
poonam@9348 306 } else if (strstr(p, "cpu,cpuacct") != NULL || strstr(p, "cpuacct,cpu") != NULL) {
poonam@9348 307 int matched = sscanf(p, "%d %d %d:%d %s %s",
poonam@9348 308 &mountid,
poonam@9348 309 &parentid,
poonam@9348 310 &major,
poonam@9348 311 &minor,
poonam@9348 312 tmproot,
poonam@9348 313 tmpmount);
poonam@9348 314 if (matched == 6) {
poonam@9348 315 cpu = new CgroupSubsystem(tmproot, tmpmount);
poonam@9348 316 cpuacct = new CgroupSubsystem(tmproot, tmpmount);
poonam@9348 317 }
poonam@9348 318 else {
poonam@9348 319 if (PrintContainerInfo) {
poonam@9348 320 tty->print_cr("Incompatible str containing cgroup and cpu,cpuacct: %s", p);
poonam@9348 321 }
poonam@9348 322 }
poonam@9348 323 } else if (strstr(p, "cpuacct") != NULL) {
poonam@9348 324 int matched = sscanf(p, "%d %d %d:%d %s %s",
poonam@9348 325 &mountid,
poonam@9348 326 &parentid,
poonam@9348 327 &major,
poonam@9348 328 &minor,
poonam@9348 329 tmproot,
poonam@9348 330 tmpmount);
poonam@9348 331 if (matched == 6) {
poonam@9348 332 cpuacct = new CgroupSubsystem(tmproot, tmpmount);
poonam@9348 333 }
poonam@9348 334 else {
poonam@9348 335 if (PrintContainerInfo) {
poonam@9348 336 tty->print_cr("Incompatible str containing cgroup and cpuacct: %s", p);
poonam@9348 337 }
poonam@9348 338 }
poonam@9348 339 } else if (strstr(p, "cpu") != NULL) {
poonam@9348 340 int matched = sscanf(p, "%d %d %d:%d %s %s",
poonam@9348 341 &mountid,
poonam@9348 342 &parentid,
poonam@9348 343 &major,
poonam@9348 344 &minor,
poonam@9348 345 tmproot,
poonam@9348 346 tmpmount);
poonam@9348 347 if (matched == 6) {
poonam@9348 348 cpu = new CgroupSubsystem(tmproot, tmpmount);
poonam@9348 349 }
poonam@9348 350 else {
poonam@9348 351 if (PrintContainerInfo) {
poonam@9348 352 tty->print_cr("Incompatible str containing cgroup and cpu: %s", p);
poonam@9348 353 }
poonam@9348 354 }
poonam@9348 355 }
poonam@9348 356 }
poonam@9348 357 }
poonam@9348 358
poonam@9348 359 fclose(mntinfo);
poonam@9348 360
poonam@9348 361 if (memory == NULL) {
poonam@9348 362 if (PrintContainerInfo) {
poonam@9348 363 tty->print_cr("Required cgroup memory subsystem not found");
poonam@9348 364 }
poonam@9348 365 return;
poonam@9348 366 }
poonam@9348 367 if (cpuset == NULL) {
poonam@9348 368 if (PrintContainerInfo) {
poonam@9348 369 tty->print_cr("Required cgroup cpuset subsystem not found");
poonam@9348 370 }
poonam@9348 371 return;
poonam@9348 372 }
poonam@9348 373 if (cpu == NULL) {
poonam@9348 374 if (PrintContainerInfo) {
poonam@9348 375 tty->print_cr("Required cgroup cpu subsystem not found");
poonam@9348 376 }
poonam@9348 377 return;
poonam@9348 378 }
poonam@9348 379 if (cpuacct == NULL) {
poonam@9348 380 if (PrintContainerInfo) {
poonam@9348 381 tty->print_cr("Required cgroup cpuacct subsystem not found");
poonam@9348 382 }
poonam@9348 383 return;
poonam@9348 384 }
poonam@9348 385
poonam@9348 386 /*
poonam@9348 387 * Read /proc/self/cgroup and map host mount point to
poonam@9348 388 * local one via /proc/self/mountinfo content above
poonam@9348 389 *
poonam@9348 390 * Docker example:
poonam@9348 391 * 5:memory:/docker/6558aed8fc662b194323ceab5b964f69cf36b3e8af877a14b80256e93aecb044
poonam@9348 392 *
poonam@9348 393 * Host example:
poonam@9348 394 * 5:memory:/user.slice
poonam@9348 395 *
poonam@9348 396 * Construct a path to the process specific memory and cpuset
poonam@9348 397 * cgroup directory.
poonam@9348 398 *
poonam@9348 399 * For a container running under Docker from memory example above
poonam@9348 400 * the paths would be:
poonam@9348 401 *
poonam@9348 402 * /sys/fs/cgroup/memory
poonam@9348 403 *
poonam@9348 404 * For a Host from memory example above the path would be:
poonam@9348 405 *
poonam@9348 406 * /sys/fs/cgroup/memory/user.slice
poonam@9348 407 *
poonam@9348 408 */
poonam@9348 409 cgroup = fopen("/proc/self/cgroup", "r");
poonam@9348 410 if (cgroup == NULL) {
poonam@9348 411 if (PrintContainerInfo) {
poonam@9348 412 tty->print_cr("Can't open /proc/self/cgroup, %s",
poonam@9348 413 strerror(errno));
poonam@9348 414 }
poonam@9348 415 return;
poonam@9348 416 }
poonam@9348 417
poonam@9348 418 while ( (p = fgets(buf, MAXPATHLEN, cgroup)) != NULL) {
poonam@9348 419 int cgno;
poonam@9348 420 int matched;
poonam@9348 421 char *controller;
poonam@9348 422 char *base;
poonam@9348 423
poonam@9348 424 /* Skip cgroup number */
poonam@9348 425 strsep(&p, ":");
poonam@9348 426 /* Get controller and base */
poonam@9348 427 controller = strsep(&p, ":");
poonam@9348 428 base = strsep(&p, "\n");
poonam@9348 429
poonam@9348 430 if (controller != NULL) {
poonam@9348 431 if (strstr(controller, "memory") != NULL) {
poonam@9348 432 memory->set_subsystem_path(base);
poonam@9348 433 } else if (strstr(controller, "cpuset") != NULL) {
poonam@9348 434 cpuset->set_subsystem_path(base);
poonam@9348 435 } else if (strstr(controller, "cpu,cpuacct") != NULL || strstr(controller, "cpuacct,cpu") != NULL) {
poonam@9348 436 cpu->set_subsystem_path(base);
poonam@9348 437 cpuacct->set_subsystem_path(base);
poonam@9348 438 } else if (strstr(controller, "cpuacct") != NULL) {
poonam@9348 439 cpuacct->set_subsystem_path(base);
poonam@9348 440 } else if (strstr(controller, "cpu") != NULL) {
poonam@9348 441 cpu->set_subsystem_path(base);
poonam@9348 442 }
poonam@9348 443 }
poonam@9348 444 }
poonam@9348 445
poonam@9348 446 fclose(cgroup);
poonam@9348 447
poonam@9348 448 // We need to update the amount of physical memory now that
poonam@9348 449 // command line arguments have been processed.
poonam@9348 450 if ((mem_limit = memory_limit_in_bytes()) > 0) {
poonam@9348 451 os::Linux::set_physical_memory(mem_limit);
poonam@9348 452 }
poonam@9348 453
poonam@9348 454 _is_containerized = true;
poonam@9348 455
poonam@9348 456 }
poonam@9348 457
poonam@9348 458 const char * OSContainer::container_type() {
poonam@9348 459 if (is_containerized()) {
poonam@9348 460 return "cgroupv1";
poonam@9348 461 } else {
poonam@9348 462 return NULL;
poonam@9348 463 }
poonam@9348 464 }
poonam@9348 465
poonam@9348 466
poonam@9348 467 /* memory_limit_in_bytes
poonam@9348 468 *
poonam@9348 469 * Return the limit of available memory for this process.
poonam@9348 470 *
poonam@9348 471 * return:
poonam@9348 472 * memory limit in bytes or
poonam@9348 473 * -1 for unlimited
poonam@9348 474 * OSCONTAINER_ERROR for not supported
poonam@9348 475 */
poonam@9348 476 jlong OSContainer::memory_limit_in_bytes() {
poonam@9348 477 GET_CONTAINER_INFO(julong, memory, "/memory.limit_in_bytes",
poonam@9348 478 "Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, memlimit);
poonam@9348 479
poonam@9348 480 if (memlimit >= _unlimited_memory) {
poonam@9348 481 if (PrintContainerInfo) {
poonam@9348 482 tty->print_cr("Memory Limit is: Unlimited");
poonam@9348 483 }
poonam@9348 484 return (jlong)-1;
poonam@9348 485 }
poonam@9348 486 else {
poonam@9348 487 return (jlong)memlimit;
poonam@9348 488 }
poonam@9348 489 }
poonam@9348 490
poonam@9348 491 jlong OSContainer::memory_and_swap_limit_in_bytes() {
poonam@9348 492 GET_CONTAINER_INFO(julong, memory, "/memory.memsw.limit_in_bytes",
poonam@9348 493 "Memory and Swap Limit is: " JULONG_FORMAT, JULONG_FORMAT, memswlimit);
poonam@9348 494 if (memswlimit >= _unlimited_memory) {
poonam@9348 495 if (PrintContainerInfo) {
poonam@9348 496 tty->print_cr("Memory and Swap Limit is: Unlimited");
poonam@9348 497 }
poonam@9348 498 return (jlong)-1;
poonam@9348 499 } else {
poonam@9348 500 return (jlong)memswlimit;
poonam@9348 501 }
poonam@9348 502 }
poonam@9348 503
poonam@9348 504 jlong OSContainer::memory_soft_limit_in_bytes() {
poonam@9348 505 GET_CONTAINER_INFO(julong, memory, "/memory.soft_limit_in_bytes",
poonam@9348 506 "Memory Soft Limit is: " JULONG_FORMAT, JULONG_FORMAT, memsoftlimit);
poonam@9348 507 if (memsoftlimit >= _unlimited_memory) {
poonam@9348 508 if (PrintContainerInfo) {
poonam@9348 509 tty->print_cr("Memory Soft Limit is: Unlimited");
poonam@9348 510 }
poonam@9348 511 return (jlong)-1;
poonam@9348 512 } else {
poonam@9348 513 return (jlong)memsoftlimit;
poonam@9348 514 }
poonam@9348 515 }
poonam@9348 516
poonam@9348 517 /* memory_usage_in_bytes
poonam@9348 518 *
poonam@9348 519 * Return the amount of used memory for this process.
poonam@9348 520 *
poonam@9348 521 * return:
poonam@9348 522 * memory usage in bytes or
poonam@9348 523 * -1 for unlimited
poonam@9348 524 * OSCONTAINER_ERROR for not supported
poonam@9348 525 */
poonam@9348 526 jlong OSContainer::memory_usage_in_bytes() {
poonam@9348 527 GET_CONTAINER_INFO(jlong, memory, "/memory.usage_in_bytes",
poonam@9348 528 "Memory Usage is: " JLONG_FORMAT, JLONG_FORMAT, memusage);
poonam@9348 529 return memusage;
poonam@9348 530 }
poonam@9348 531
poonam@9348 532 /* memory_max_usage_in_bytes
poonam@9348 533 *
poonam@9348 534 * Return the maximum amount of used memory for this process.
poonam@9348 535 *
poonam@9348 536 * return:
poonam@9348 537 * max memory usage in bytes or
poonam@9348 538 * OSCONTAINER_ERROR for not supported
poonam@9348 539 */
poonam@9348 540 jlong OSContainer::memory_max_usage_in_bytes() {
poonam@9348 541 GET_CONTAINER_INFO(jlong, memory, "/memory.max_usage_in_bytes",
poonam@9348 542 "Maximum Memory Usage is: " JLONG_FORMAT, JLONG_FORMAT, memmaxusage);
poonam@9348 543 return memmaxusage;
poonam@9348 544 }
poonam@9348 545
poonam@9348 546 /* active_processor_count
poonam@9348 547 *
poonam@9348 548 * Calculate an appropriate number of active processors for the
poonam@9348 549 * VM to use based on these three inputs.
poonam@9348 550 *
poonam@9348 551 * cpu affinity
poonam@9348 552 * cgroup cpu quota & cpu period
poonam@9348 553 * cgroup cpu shares
poonam@9348 554 *
poonam@9348 555 * Algorithm:
poonam@9348 556 *
poonam@9348 557 * Determine the number of available CPUs from sched_getaffinity
poonam@9348 558 *
poonam@9348 559 * If user specified a quota (quota != -1), calculate the number of
poonam@9348 560 * required CPUs by dividing quota by period.
poonam@9348 561 *
poonam@9348 562 * If shares are in effect (shares != -1), calculate the number
poonam@9348 563 * of CPUs required for the shares by dividing the share value
poonam@9348 564 * by PER_CPU_SHARES.
poonam@9348 565 *
poonam@9348 566 * All results of division are rounded up to the next whole number.
poonam@9348 567 *
poonam@9348 568 * If neither shares or quotas have been specified, return the
poonam@9348 569 * number of active processors in the system.
poonam@9348 570 *
poonam@9348 571 * If both shares and quotas have been specified, the results are
poonam@9348 572 * based on the flag PreferContainerQuotaForCPUCount. If true,
poonam@9348 573 * return the quota value. If false return the smallest value
poonam@9348 574 * between shares or quotas.
poonam@9348 575 *
poonam@9348 576 * If shares and/or quotas have been specified, the resulting number
poonam@9348 577 * returned will never exceed the number of active processors.
poonam@9348 578 *
poonam@9348 579 * return:
poonam@9348 580 * number of CPUs
poonam@9348 581 */
poonam@9348 582 int OSContainer::active_processor_count() {
poonam@9348 583 int quota_count = 0, share_count = 0;
poonam@9348 584 int cpu_count, limit_count;
poonam@9348 585 int result;
poonam@9348 586
poonam@9348 587 cpu_count = limit_count = os::Linux::active_processor_count();
poonam@9348 588 int quota = cpu_quota();
poonam@9348 589 int period = cpu_period();
poonam@9348 590 int share = cpu_shares();
poonam@9348 591
poonam@9348 592 if (quota > -1 && period > 0) {
poonam@9348 593 quota_count = ceilf((float)quota / (float)period);
poonam@9348 594 if (PrintContainerInfo) {
poonam@9348 595 tty->print_cr("CPU Quota count based on quota/period: %d", quota_count);
poonam@9348 596 }
poonam@9348 597 }
poonam@9348 598 if (share > -1) {
poonam@9348 599 share_count = ceilf((float)share / (float)PER_CPU_SHARES);
poonam@9348 600 if (PrintContainerInfo) {
poonam@9348 601 tty->print_cr("CPU Share count based on shares: %d", share_count);
poonam@9348 602 }
poonam@9348 603 }
poonam@9348 604
poonam@9348 605 // If both shares and quotas are setup results depend
poonam@9348 606 // on flag PreferContainerQuotaForCPUCount.
poonam@9348 607 // If true, limit CPU count to quota
poonam@9348 608 // If false, use minimum of shares and quotas
poonam@9348 609 if (quota_count !=0 && share_count != 0) {
poonam@9348 610 if (PreferContainerQuotaForCPUCount) {
poonam@9348 611 limit_count = quota_count;
poonam@9348 612 } else {
poonam@9348 613 limit_count = MIN2(quota_count, share_count);
poonam@9348 614 }
poonam@9348 615 } else if (quota_count != 0) {
poonam@9348 616 limit_count = quota_count;
poonam@9348 617 } else if (share_count != 0) {
poonam@9348 618 limit_count = share_count;
poonam@9348 619 }
poonam@9348 620
poonam@9348 621 result = MIN2(cpu_count, limit_count);
poonam@9348 622 if (PrintContainerInfo) {
poonam@9348 623 tty->print_cr("OSContainer::active_processor_count: %d", result);
poonam@9348 624 }
poonam@9348 625 return result;
poonam@9348 626 }
poonam@9348 627
poonam@9348 628 char * OSContainer::cpu_cpuset_cpus() {
poonam@9348 629 GET_CONTAINER_INFO_CPTR(cptr, cpuset, "/cpuset.cpus",
poonam@9348 630 "cpuset.cpus is: %s", "%1023s", cpus, 1024);
poonam@9348 631 return os::strdup(cpus);
poonam@9348 632 }
poonam@9348 633
poonam@9348 634 char * OSContainer::cpu_cpuset_memory_nodes() {
poonam@9348 635 GET_CONTAINER_INFO_CPTR(cptr, cpuset, "/cpuset.mems",
poonam@9348 636 "cpuset.mems is: %s", "%1023s", mems, 1024);
poonam@9348 637 return os::strdup(mems);
poonam@9348 638 }
poonam@9348 639
poonam@9348 640 /* cpu_quota
poonam@9348 641 *
poonam@9348 642 * Return the number of milliseconds per period
poonam@9348 643 * process is guaranteed to run.
poonam@9348 644 *
poonam@9348 645 * return:
poonam@9348 646 * quota time in milliseconds
poonam@9348 647 * -1 for no quota
poonam@9348 648 * OSCONTAINER_ERROR for not supported
poonam@9348 649 */
poonam@9348 650 int OSContainer::cpu_quota() {
poonam@9348 651 GET_CONTAINER_INFO(int, cpu, "/cpu.cfs_quota_us",
poonam@9348 652 "CPU Quota is: %d", "%d", quota);
poonam@9348 653 return quota;
poonam@9348 654 }
poonam@9348 655
poonam@9348 656 int OSContainer::cpu_period() {
poonam@9348 657 GET_CONTAINER_INFO(int, cpu, "/cpu.cfs_period_us",
poonam@9348 658 "CPU Period is: %d", "%d", period);
poonam@9348 659 return period;
poonam@9348 660 }
poonam@9348 661
poonam@9348 662 /* cpu_shares
poonam@9348 663 *
poonam@9348 664 * Return the amount of cpu shares available to the process
poonam@9348 665 *
poonam@9348 666 * return:
poonam@9348 667 * Share number (typically a number relative to 1024)
poonam@9348 668 * (2048 typically expresses 2 CPUs worth of processing)
poonam@9348 669 * -1 for no share setup
poonam@9348 670 * OSCONTAINER_ERROR for not supported
poonam@9348 671 */
poonam@9348 672 int OSContainer::cpu_shares() {
poonam@9348 673 GET_CONTAINER_INFO(int, cpu, "/cpu.shares",
poonam@9348 674 "CPU Shares is: %d", "%d", shares);
poonam@9348 675 // Convert 1024 to no shares setup
poonam@9348 676 if (shares == 1024) return -1;
poonam@9348 677
poonam@9348 678 return shares;
poonam@9348 679 }
poonam@9348 680

mercurial