Path: blob/master/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp
40951 views
/*1* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include <string.h>25#include <math.h>26#include <errno.h>27#include "cgroupV1Subsystem_linux.hpp"28#include "logging/log.hpp"29#include "memory/allocation.hpp"30#include "runtime/globals.hpp"31#include "runtime/os.hpp"32#include "utilities/globalDefinitions.hpp"3334/*35* Set directory to subsystem specific files based36* on the contents of the mountinfo and cgroup files.37*/38void CgroupV1Controller::set_subsystem_path(char *cgroup_path) {39char buf[MAXPATHLEN+1];40if (_root != NULL && cgroup_path != NULL) {41if (strcmp(_root, "/") == 0) {42int buflen;43strncpy(buf, _mount_point, MAXPATHLEN);44buf[MAXPATHLEN-1] = '\0';45if (strcmp(cgroup_path,"/") != 0) {46buflen = strlen(buf);47if ((buflen + strlen(cgroup_path)) > (MAXPATHLEN-1)) {48return;49}50strncat(buf, cgroup_path, MAXPATHLEN-buflen);51buf[MAXPATHLEN-1] = '\0';52}53_path = os::strdup(buf);54} else {55if (strcmp(_root, cgroup_path) == 0) {56strncpy(buf, _mount_point, MAXPATHLEN);57buf[MAXPATHLEN-1] = '\0';58_path = os::strdup(buf);59} else {60char *p = strstr(cgroup_path, _root);61if (p != NULL && p == _root) {62if (strlen(cgroup_path) > strlen(_root)) {63int buflen;64strncpy(buf, _mount_point, MAXPATHLEN);65buf[MAXPATHLEN-1] = '\0';66buflen = strlen(buf);67if ((buflen + strlen(cgroup_path) - strlen(_root)) > (MAXPATHLEN-1)) {68return;69}70strncat(buf, cgroup_path + strlen(_root), MAXPATHLEN-buflen);71buf[MAXPATHLEN-1] = '\0';72_path = os::strdup(buf);73}74}75}76}77}78}7980/* uses_mem_hierarchy81*82* Return whether or not hierarchical cgroup accounting is being83* done.84*85* return:86* A number > 0 if true, or87* OSCONTAINER_ERROR for not supported88*/89jlong CgroupV1MemoryController::uses_mem_hierarchy() {90GET_CONTAINER_INFO(jlong, this, "/memory.use_hierarchy",91"Use Hierarchy is: " JLONG_FORMAT, JLONG_FORMAT, use_hierarchy);92return use_hierarchy;93}9495void CgroupV1MemoryController::set_subsystem_path(char *cgroup_path) {96CgroupV1Controller::set_subsystem_path(cgroup_path);97jlong hierarchy = uses_mem_hierarchy();98if (hierarchy > 0) {99set_hierarchical(true);100}101}102103jlong CgroupV1Subsystem::read_memory_limit_in_bytes() {104GET_CONTAINER_INFO(julong, _memory->controller(), "/memory.limit_in_bytes",105"Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, memlimit);106107if (memlimit >= _unlimited_memory) {108log_trace(os, container)("Non-Hierarchical Memory Limit is: Unlimited");109CgroupV1MemoryController* mem_controller = reinterpret_cast<CgroupV1MemoryController*>(_memory->controller());110if (mem_controller->is_hierarchical()) {111const char* matchline = "hierarchical_memory_limit";112const char* format = "%s " JULONG_FORMAT;113GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", matchline,114"Hierarchical Memory Limit is: " JULONG_FORMAT, format, hier_memlimit)115if (hier_memlimit >= _unlimited_memory) {116log_trace(os, container)("Hierarchical Memory Limit is: Unlimited");117} else {118return (jlong)hier_memlimit;119}120}121return (jlong)-1;122}123else {124return (jlong)memlimit;125}126}127128jlong CgroupV1Subsystem::memory_and_swap_limit_in_bytes() {129GET_CONTAINER_INFO(julong, _memory->controller(), "/memory.memsw.limit_in_bytes",130"Memory and Swap Limit is: " JULONG_FORMAT, JULONG_FORMAT, memswlimit);131if (memswlimit >= _unlimited_memory) {132log_trace(os, container)("Non-Hierarchical Memory and Swap Limit is: Unlimited");133CgroupV1MemoryController* mem_controller = reinterpret_cast<CgroupV1MemoryController*>(_memory->controller());134if (mem_controller->is_hierarchical()) {135const char* matchline = "hierarchical_memsw_limit";136const char* format = "%s " JULONG_FORMAT;137GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", matchline,138"Hierarchical Memory and Swap Limit is : " JULONG_FORMAT, format, hier_memlimit)139if (hier_memlimit >= _unlimited_memory) {140log_trace(os, container)("Hierarchical Memory and Swap Limit is: Unlimited");141} else {142return (jlong)hier_memlimit;143}144}145return (jlong)-1;146} else {147return (jlong)memswlimit;148}149}150151jlong CgroupV1Subsystem::memory_soft_limit_in_bytes() {152GET_CONTAINER_INFO(julong, _memory->controller(), "/memory.soft_limit_in_bytes",153"Memory Soft Limit is: " JULONG_FORMAT, JULONG_FORMAT, memsoftlimit);154if (memsoftlimit >= _unlimited_memory) {155log_trace(os, container)("Memory Soft Limit is: Unlimited");156return (jlong)-1;157} else {158return (jlong)memsoftlimit;159}160}161162/* memory_usage_in_bytes163*164* Return the amount of used memory for this process.165*166* return:167* memory usage in bytes or168* -1 for unlimited169* OSCONTAINER_ERROR for not supported170*/171jlong CgroupV1Subsystem::memory_usage_in_bytes() {172GET_CONTAINER_INFO(jlong, _memory->controller(), "/memory.usage_in_bytes",173"Memory Usage is: " JLONG_FORMAT, JLONG_FORMAT, memusage);174return memusage;175}176177/* memory_max_usage_in_bytes178*179* Return the maximum amount of used memory for this process.180*181* return:182* max memory usage in bytes or183* OSCONTAINER_ERROR for not supported184*/185jlong CgroupV1Subsystem::memory_max_usage_in_bytes() {186GET_CONTAINER_INFO(jlong, _memory->controller(), "/memory.max_usage_in_bytes",187"Maximum Memory Usage is: " JLONG_FORMAT, JLONG_FORMAT, memmaxusage);188return memmaxusage;189}190191char * CgroupV1Subsystem::cpu_cpuset_cpus() {192GET_CONTAINER_INFO_CPTR(cptr, _cpuset, "/cpuset.cpus",193"cpuset.cpus is: %s", "%1023s", cpus, 1024);194return os::strdup(cpus);195}196197char * CgroupV1Subsystem::cpu_cpuset_memory_nodes() {198GET_CONTAINER_INFO_CPTR(cptr, _cpuset, "/cpuset.mems",199"cpuset.mems is: %s", "%1023s", mems, 1024);200return os::strdup(mems);201}202203/* cpu_quota204*205* Return the number of microseconds per period206* process is guaranteed to run.207*208* return:209* quota time in microseconds210* -1 for no quota211* OSCONTAINER_ERROR for not supported212*/213int CgroupV1Subsystem::cpu_quota() {214GET_CONTAINER_INFO(int, _cpu->controller(), "/cpu.cfs_quota_us",215"CPU Quota is: %d", "%d", quota);216return quota;217}218219int CgroupV1Subsystem::cpu_period() {220GET_CONTAINER_INFO(int, _cpu->controller(), "/cpu.cfs_period_us",221"CPU Period is: %d", "%d", period);222return period;223}224225/* cpu_shares226*227* Return the amount of cpu shares available to the process228*229* return:230* Share number (typically a number relative to 1024)231* (2048 typically expresses 2 CPUs worth of processing)232* -1 for no share setup233* OSCONTAINER_ERROR for not supported234*/235int CgroupV1Subsystem::cpu_shares() {236GET_CONTAINER_INFO(int, _cpu->controller(), "/cpu.shares",237"CPU Shares is: %d", "%d", shares);238// Convert 1024 to no shares setup239if (shares == 1024) return -1;240241return shares;242}243244245