Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp
40951 views
1
/*
2
* Copyright (c) 2020, Red Hat Inc.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
#include "cgroupV2Subsystem_linux.hpp"
26
27
/* cpu_shares
28
*
29
* Return the amount of cpu shares available to the process
30
*
31
* return:
32
* Share number (typically a number relative to 1024)
33
* (2048 typically expresses 2 CPUs worth of processing)
34
* -1 for no share setup
35
* OSCONTAINER_ERROR for not supported
36
*/
37
int CgroupV2Subsystem::cpu_shares() {
38
GET_CONTAINER_INFO(int, _unified, "/cpu.weight",
39
"Raw value for CPU shares is: %d", "%d", shares);
40
// Convert default value of 100 to no shares setup
41
if (shares == 100) {
42
log_debug(os, container)("CPU Shares is: %d", -1);
43
return -1;
44
}
45
46
// CPU shares (OCI) value needs to get translated into
47
// a proper Cgroups v2 value. See:
48
// https://github.com/containers/crun/blob/master/crun.1.md#cpu-controller
49
//
50
// Use the inverse of (x == OCI value, y == cgroupsv2 value):
51
// ((262142 * y - 1)/9999) + 2 = x
52
//
53
int x = 262142 * shares - 1;
54
double frac = x/9999.0;
55
x = ((int)frac) + 2;
56
log_trace(os, container)("Scaled CPU shares value is: %d", x);
57
// Since the scaled value is not precise, return the closest
58
// multiple of PER_CPU_SHARES for a more conservative mapping
59
if ( x <= PER_CPU_SHARES ) {
60
// will always map to 1 CPU
61
log_debug(os, container)("CPU Shares is: %d", x);
62
return x;
63
}
64
int f = x/PER_CPU_SHARES;
65
int lower_multiple = f * PER_CPU_SHARES;
66
int upper_multiple = (f + 1) * PER_CPU_SHARES;
67
int distance_lower = MAX2(lower_multiple, x) - MIN2(lower_multiple, x);
68
int distance_upper = MAX2(upper_multiple, x) - MIN2(upper_multiple, x);
69
x = distance_lower <= distance_upper ? lower_multiple : upper_multiple;
70
log_trace(os, container)("Closest multiple of %d of the CPU Shares value is: %d", PER_CPU_SHARES, x);
71
log_debug(os, container)("CPU Shares is: %d", x);
72
return x;
73
}
74
75
/* cpu_quota
76
*
77
* Return the number of microseconds per period
78
* process is guaranteed to run.
79
*
80
* return:
81
* quota time in microseconds
82
* -1 for no quota
83
* OSCONTAINER_ERROR for not supported
84
*/
85
int CgroupV2Subsystem::cpu_quota() {
86
char * cpu_quota_str = cpu_quota_val();
87
int limit = (int)limit_from_str(cpu_quota_str);
88
log_trace(os, container)("CPU Quota is: %d", limit);
89
return limit;
90
}
91
92
char * CgroupV2Subsystem::cpu_cpuset_cpus() {
93
GET_CONTAINER_INFO_CPTR(cptr, _unified, "/cpuset.cpus",
94
"cpuset.cpus is: %s", "%1023s", cpus, 1024);
95
if (cpus == NULL) {
96
return NULL;
97
}
98
return os::strdup(cpus);
99
}
100
101
char* CgroupV2Subsystem::cpu_quota_val() {
102
GET_CONTAINER_INFO_CPTR(cptr, _unified, "/cpu.max",
103
"Raw value for CPU quota is: %s", "%s %*d", quota, 1024);
104
if (quota == NULL) {
105
return NULL;
106
}
107
return os::strdup(quota);
108
}
109
110
char * CgroupV2Subsystem::cpu_cpuset_memory_nodes() {
111
GET_CONTAINER_INFO_CPTR(cptr, _unified, "/cpuset.mems",
112
"cpuset.mems is: %s", "%1023s", mems, 1024);
113
if (mems == NULL) {
114
return NULL;
115
}
116
return os::strdup(mems);
117
}
118
119
int CgroupV2Subsystem::cpu_period() {
120
GET_CONTAINER_INFO(int, _unified, "/cpu.max",
121
"CPU Period is: %d", "%*s %d", period);
122
return period;
123
}
124
125
/* memory_usage_in_bytes
126
*
127
* Return the amount of used memory used by this cgroup and decendents
128
*
129
* return:
130
* memory usage in bytes or
131
* -1 for unlimited
132
* OSCONTAINER_ERROR for not supported
133
*/
134
jlong CgroupV2Subsystem::memory_usage_in_bytes() {
135
GET_CONTAINER_INFO(jlong, _unified, "/memory.current",
136
"Memory Usage is: " JLONG_FORMAT, JLONG_FORMAT, memusage);
137
return memusage;
138
}
139
140
jlong CgroupV2Subsystem::memory_soft_limit_in_bytes() {
141
char* mem_soft_limit_str = mem_soft_limit_val();
142
return limit_from_str(mem_soft_limit_str);
143
}
144
145
jlong CgroupV2Subsystem::memory_max_usage_in_bytes() {
146
// Log this string at trace level so as to make tests happy.
147
log_trace(os, container)("Maximum Memory Usage is not supported.");
148
return OSCONTAINER_ERROR; // not supported
149
}
150
151
char* CgroupV2Subsystem::mem_soft_limit_val() {
152
GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.low",
153
"Memory Soft Limit is: %s", "%s", mem_soft_limit_str, 1024);
154
if (mem_soft_limit_str == NULL) {
155
return NULL;
156
}
157
return os::strdup(mem_soft_limit_str);
158
}
159
160
// Note that for cgroups v2 the actual limits set for swap and
161
// memory live in two different files, memory.swap.max and memory.max
162
// respectively. In order to properly report a cgroup v1 like
163
// compound value we need to sum the two values. Setting a swap limit
164
// without also setting a memory limit is not allowed.
165
jlong CgroupV2Subsystem::memory_and_swap_limit_in_bytes() {
166
char* mem_swp_limit_str = mem_swp_limit_val();
167
jlong swap_limit = limit_from_str(mem_swp_limit_str);
168
if (swap_limit >= 0) {
169
jlong memory_limit = read_memory_limit_in_bytes();
170
assert(memory_limit >= 0, "swap limit without memory limit?");
171
return memory_limit + swap_limit;
172
}
173
return swap_limit;
174
}
175
176
char* CgroupV2Subsystem::mem_swp_limit_val() {
177
GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.swap.max",
178
"Memory and Swap Limit is: %s", "%s", mem_swp_limit_str, 1024);
179
if (mem_swp_limit_str == NULL) {
180
return NULL;
181
}
182
return os::strdup(mem_swp_limit_str);
183
}
184
185
/* memory_limit_in_bytes
186
*
187
* Return the limit of available memory for this process.
188
*
189
* return:
190
* memory limit in bytes or
191
* -1 for unlimited, OSCONTAINER_ERROR for an error
192
*/
193
jlong CgroupV2Subsystem::read_memory_limit_in_bytes() {
194
char * mem_limit_str = mem_limit_val();
195
jlong limit = limit_from_str(mem_limit_str);
196
if (log_is_enabled(Trace, os, container)) {
197
if (limit == -1) {
198
log_trace(os, container)("Memory Limit is: Unlimited");
199
} else {
200
log_trace(os, container)("Memory Limit is: " JLONG_FORMAT, limit);
201
}
202
}
203
return limit;
204
}
205
206
jlong CgroupV2Subsystem::limit_from_str(char* limit_str) {
207
if (limit_str == NULL) {
208
return OSCONTAINER_ERROR;
209
}
210
// Unlimited memory in Cgroups V2 is the literal string 'max'
211
if (strcmp("max", limit_str) == 0) {
212
os::free(limit_str);
213
return (jlong)-1;
214
}
215
julong limit;
216
if (sscanf(limit_str, JULONG_FORMAT, &limit) != 1) {
217
os::free(limit_str);
218
return OSCONTAINER_ERROR;
219
}
220
os::free(limit_str);
221
return (jlong)limit;
222
}
223
224
char* CgroupV2Subsystem::mem_limit_val() {
225
GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.max",
226
"Raw value for memory limit is: %s", "%s", mem_limit_str, 1024);
227
if (mem_limit_str == NULL) {
228
return NULL;
229
}
230
return os::strdup(mem_limit_str);
231
}
232
233
char* CgroupV2Controller::construct_path(char* mount_path, char *cgroup_path) {
234
char buf[MAXPATHLEN+1];
235
int buflen;
236
strncpy(buf, mount_path, MAXPATHLEN);
237
buf[MAXPATHLEN] = '\0';
238
buflen = strlen(buf);
239
if ((buflen + strlen(cgroup_path)) > MAXPATHLEN) {
240
return NULL;
241
}
242
strncat(buf, cgroup_path, MAXPATHLEN-buflen);
243
buf[MAXPATHLEN] = '\0';
244
return os::strdup(buf);
245
}
246
247
248