Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/management/OperatingSystemImpl.c
32287 views
1
/*
2
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
#include "jni.h"
27
#include "jni_util.h"
28
#include "jlong.h"
29
#include "jvm.h"
30
#include "management.h"
31
#include "sun_management_OperatingSystemImpl.h"
32
33
#include <sys/types.h>
34
#include <sys/stat.h>
35
#if defined(_ALLBSD_SOURCE)
36
#include <sys/sysctl.h>
37
#ifdef __APPLE__
38
#include <sys/param.h>
39
#include <sys/mount.h>
40
#include <mach/mach.h>
41
#include <sys/proc_info.h>
42
#include <libproc.h>
43
#endif
44
#elif !defined(_AIX)
45
#include <sys/swap.h>
46
#endif
47
#include <sys/resource.h>
48
#include <sys/times.h>
49
#ifndef _ALLBSD_SOURCE
50
#include <sys/sysinfo.h>
51
#endif
52
#include <ctype.h>
53
#include <dirent.h>
54
#include <errno.h>
55
#include <fcntl.h>
56
#include <limits.h>
57
#include <stdlib.h>
58
#include <unistd.h>
59
60
#if defined(_AIX)
61
#include <libperfstat.h>
62
#endif
63
64
static jlong page_size = 0;
65
66
#if defined(_ALLBSD_SOURCE) || defined(_AIX)
67
#define MB (1024UL * 1024UL)
68
#else
69
70
/* This gets us the new structured proc interfaces of 5.6 & later */
71
/* - see comment in <sys/procfs.h> */
72
#define _STRUCTURED_PROC 1
73
#ifndef __ANDROID__
74
#include <sys/procfs.h>
75
#endif
76
77
#endif /* _ALLBSD_SOURCE */
78
79
static struct dirent* read_dir(DIR* dirp, struct dirent* entry) {
80
#ifdef __solaris__
81
struct dirent* dbuf = readdir(dirp);
82
return dbuf;
83
#else /* __linux__ || _ALLBSD_SOURCE */
84
struct dirent* p;
85
if (readdir_r(dirp, entry, &p) == 0) {
86
return p;
87
} else {
88
return NULL;
89
}
90
#endif
91
}
92
93
// true = get available swap in bytes
94
// false = get total swap in bytes
95
static jlong get_total_or_available_swap_space_size(JNIEnv* env, jboolean available) {
96
#ifdef __solaris__
97
long total, avail;
98
int nswap, i, count;
99
swaptbl_t *stbl;
100
char *strtab;
101
102
// First get the number of swap resource entries
103
if ((nswap = swapctl(SC_GETNSWP, NULL)) == -1) {
104
throw_internal_error(env, "swapctl failed to get nswap");
105
return -1;
106
}
107
if (nswap == 0) {
108
return 0;
109
}
110
111
// Allocate storage for resource entries
112
stbl = (swaptbl_t*) malloc(nswap * sizeof(swapent_t) +
113
sizeof(struct swaptable));
114
if (stbl == NULL) {
115
JNU_ThrowOutOfMemoryError(env, 0);
116
return -1;
117
}
118
119
// Allocate storage for the table
120
strtab = (char*) malloc((nswap + 1) * MAXPATHLEN);
121
if (strtab == NULL) {
122
free(stbl);
123
JNU_ThrowOutOfMemoryError(env, 0);
124
return -1;
125
}
126
127
for (i = 0; i < (nswap + 1); i++) {
128
stbl->swt_ent[i].ste_path = strtab + (i * MAXPATHLEN);
129
}
130
stbl->swt_n = nswap + 1;
131
132
// Get the entries
133
if ((count = swapctl(SC_LIST, stbl)) < 0) {
134
free(stbl);
135
free(strtab);
136
throw_internal_error(env, "swapctl failed to get swap list");
137
return -1;
138
}
139
140
// Sum the entries to get total and free swap
141
total = 0;
142
avail = 0;
143
for (i = 0; i < count; i++) {
144
total += stbl->swt_ent[i].ste_pages;
145
avail += stbl->swt_ent[i].ste_free;
146
}
147
148
free(stbl);
149
free(strtab);
150
return available ? ((jlong)avail * page_size) :
151
((jlong)total * page_size);
152
#elif defined(__linux__)
153
int ret;
154
FILE *fp;
155
jlong total = 0, avail = 0;
156
157
struct sysinfo si;
158
ret = sysinfo(&si);
159
if (ret != 0) {
160
throw_internal_error(env, "sysinfo failed to get swap size");
161
}
162
total = (jlong)si.totalswap * si.mem_unit;
163
avail = (jlong)si.freeswap * si.mem_unit;
164
165
return available ? avail : total;
166
#elif defined(__APPLE__)
167
struct xsw_usage vmusage;
168
size_t size = sizeof(vmusage);
169
if (sysctlbyname("vm.swapusage", &vmusage, &size, NULL, 0) != 0) {
170
throw_internal_error(env, "sysctlbyname failed");
171
}
172
return available ? (jlong)vmusage.xsu_avail : (jlong)vmusage.xsu_total;
173
#else /* _ALLBSD_SOURCE */
174
/*
175
* XXXBSD: there's no way available to get swap info in
176
* FreeBSD. Usage of libkvm is not an option here
177
*/
178
// throw_internal_error(env, "Unimplemented in FreeBSD");
179
return (0);
180
#endif
181
}
182
183
JNIEXPORT void JNICALL
184
Java_sun_management_OperatingSystemImpl_initialize
185
(JNIEnv *env, jclass cls)
186
{
187
page_size = sysconf(_SC_PAGESIZE);
188
}
189
190
JNIEXPORT jlong JNICALL
191
Java_sun_management_OperatingSystemImpl_getCommittedVirtualMemorySize
192
(JNIEnv *env, jobject mbean)
193
{
194
#ifdef __solaris__
195
psinfo_t psinfo;
196
ssize_t result;
197
size_t remaining;
198
char* addr;
199
int fd;
200
201
fd = JVM_Open("/proc/self/psinfo", O_RDONLY, 0);
202
if (fd < 0) {
203
throw_internal_error(env, "Unable to open /proc/self/psinfo");
204
return -1;
205
}
206
207
addr = (char *)&psinfo;
208
for (remaining = sizeof(psinfo_t); remaining > 0;) {
209
result = JVM_Read(fd, addr, remaining);
210
if (result < 0) {
211
JVM_Close(fd);
212
throw_internal_error(env, "Unable to read /proc/self/psinfo");
213
return -1;
214
}
215
remaining -= result;
216
addr += result;
217
}
218
219
JVM_Close(fd);
220
return (jlong) psinfo.pr_size * 1024;
221
#elif defined(__linux__)
222
FILE *fp;
223
unsigned long vsize = 0;
224
225
if ((fp = fopen("/proc/self/stat", "r")) == NULL) {
226
throw_internal_error(env, "Unable to open /proc/self/stat");
227
return -1;
228
}
229
230
// Ignore everything except the vsize entry
231
if (fscanf(fp, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %*d %*d %*d %*d %*d %*d %*u %*u %*d %lu %*[^\n]\n", &vsize) == EOF) {
232
throw_internal_error(env, "Unable to get virtual memory usage");
233
fclose(fp);
234
return -1;
235
}
236
237
fclose(fp);
238
return (jlong)vsize;
239
#elif defined(__APPLE__)
240
struct task_basic_info t_info;
241
mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
242
243
kern_return_t res = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);
244
if (res != KERN_SUCCESS) {
245
throw_internal_error(env, "task_info failed");
246
}
247
return t_info.virtual_size;
248
#else /* _ALLBSD_SOURCE */
249
/*
250
* XXXBSD: there's no way available to do it in FreeBSD, AFAIK.
251
*/
252
// throw_internal_error(env, "Unimplemented in FreeBSD");
253
return (64 * MB);
254
#endif
255
}
256
257
JNIEXPORT jlong JNICALL
258
Java_sun_management_OperatingSystemImpl_getTotalSwapSpaceSize0
259
(JNIEnv *env, jobject mbean)
260
{
261
return get_total_or_available_swap_space_size(env, JNI_FALSE);
262
}
263
264
JNIEXPORT jlong JNICALL
265
Java_sun_management_OperatingSystemImpl_getFreeSwapSpaceSize0
266
(JNIEnv *env, jobject mbean)
267
{
268
return get_total_or_available_swap_space_size(env, JNI_TRUE);
269
}
270
271
JNIEXPORT jlong JNICALL
272
Java_sun_management_OperatingSystemImpl_getProcessCpuTime
273
(JNIEnv *env, jobject mbean)
274
{
275
#ifdef __APPLE__
276
struct rusage usage;
277
if (getrusage(RUSAGE_SELF, &usage) != 0) {
278
throw_internal_error(env, "getrusage failed");
279
return -1;
280
}
281
jlong microsecs =
282
usage.ru_utime.tv_sec * 1000 * 1000 + usage.ru_utime.tv_usec +
283
usage.ru_stime.tv_sec * 1000 * 1000 + usage.ru_stime.tv_usec;
284
return microsecs * 1000;
285
#else
286
jlong clk_tck, ns_per_clock_tick;
287
jlong cpu_time_ns;
288
struct tms time;
289
290
/*
291
* BSDNOTE: FreeBSD implements _SC_CLK_TCK since FreeBSD 5, so
292
* add a magic to handle it
293
*/
294
#if defined(__solaris__) || defined(_SC_CLK_TCK)
295
clk_tck = (jlong) sysconf(_SC_CLK_TCK);
296
#elif defined(__linux__) || defined(_ALLBSD_SOURCE)
297
clk_tck = 100;
298
#endif
299
if (clk_tck == -1) {
300
throw_internal_error(env,
301
"sysconf failed - not able to get clock tick");
302
return -1;
303
}
304
305
times(&time);
306
ns_per_clock_tick = (jlong) 1000 * 1000 * 1000 / (jlong) clk_tck;
307
cpu_time_ns = ((jlong)time.tms_utime + (jlong) time.tms_stime) *
308
ns_per_clock_tick;
309
return cpu_time_ns;
310
#endif
311
}
312
313
JNIEXPORT jlong JNICALL
314
Java_sun_management_OperatingSystemImpl_getFreePhysicalMemorySize0
315
(JNIEnv *env, jobject mbean)
316
{
317
#ifdef __APPLE__
318
mach_msg_type_number_t count;
319
vm_statistics_data_t vm_stats;
320
kern_return_t res;
321
322
count = HOST_VM_INFO_COUNT;
323
res = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stats, &count);
324
if (res != KERN_SUCCESS) {
325
throw_internal_error(env, "host_statistics failed");
326
return -1;
327
}
328
return (jlong)vm_stats.free_count * page_size;
329
#elif defined(_ALLBSD_SOURCE)
330
/*
331
* XXBSDL no way to do it in FreeBSD
332
*/
333
// throw_internal_error(env, "unimplemented in FreeBSD")
334
return (128 * MB);
335
#elif defined(_AIX)
336
perfstat_memory_total_t memory_info;
337
if (-1 != perfstat_memory_total(NULL, &memory_info, sizeof(perfstat_memory_total_t), 1)) {
338
return (jlong)(memory_info.real_free * 4L * 1024L);
339
}
340
return -1;
341
#else // solaris / linux
342
jlong num_avail_physical_pages = sysconf(_SC_AVPHYS_PAGES);
343
return (num_avail_physical_pages * page_size);
344
#endif
345
}
346
347
JNIEXPORT jlong JNICALL
348
Java_sun_management_OperatingSystemImpl_getTotalPhysicalMemorySize0
349
(JNIEnv *env, jobject mbean)
350
{
351
#ifdef _ALLBSD_SOURCE
352
jlong result = 0;
353
int mib[2];
354
size_t rlen;
355
356
mib[0] = CTL_HW;
357
mib[1] = HW_MEMSIZE;
358
rlen = sizeof(result);
359
if (sysctl(mib, 2, &result, &rlen, NULL, 0) != 0) {
360
throw_internal_error(env, "sysctl failed");
361
return -1;
362
}
363
return result;
364
#elif defined(_AIX)
365
perfstat_memory_total_t memory_info;
366
if (-1 != perfstat_memory_total(NULL, &memory_info, sizeof(perfstat_memory_total_t), 1)) {
367
return (jlong)(memory_info.real_total * 4L * 1024L);
368
}
369
return -1;
370
#else // solaris / linux
371
jlong num_physical_pages = sysconf(_SC_PHYS_PAGES);
372
return (num_physical_pages * page_size);
373
#endif
374
}
375
376
377
378
JNIEXPORT jlong JNICALL
379
Java_sun_management_OperatingSystemImpl_getOpenFileDescriptorCount
380
(JNIEnv *env, jobject mbean)
381
{
382
#ifdef __APPLE__
383
// This code is influenced by the darwin lsof source
384
pid_t my_pid;
385
struct proc_bsdinfo bsdinfo;
386
struct proc_fdinfo *fds;
387
int nfiles;
388
kern_return_t kres;
389
int res;
390
size_t fds_size;
391
392
kres = pid_for_task(mach_task_self(), &my_pid);
393
if (kres != KERN_SUCCESS) {
394
throw_internal_error(env, "pid_for_task failed");
395
return -1;
396
}
397
398
// get the maximum number of file descriptors
399
res = proc_pidinfo(my_pid, PROC_PIDTBSDINFO, 0, &bsdinfo, PROC_PIDTBSDINFO_SIZE);
400
if (res <= 0) {
401
throw_internal_error(env, "proc_pidinfo with PROC_PIDTBSDINFO failed");
402
return -1;
403
}
404
405
// allocate memory to hold the fd information (we don't acutally use this information
406
// but need it to get the number of open files)
407
fds_size = bsdinfo.pbi_nfiles * sizeof(struct proc_fdinfo);
408
fds = malloc(fds_size);
409
if (fds == NULL) {
410
JNU_ThrowOutOfMemoryError(env, "could not allocate space for file descriptors");
411
return -1;
412
}
413
414
// get the list of open files - the return value is the number of bytes
415
// proc_pidinfo filled in
416
res = proc_pidinfo(my_pid, PROC_PIDLISTFDS, 0, fds, fds_size);
417
if (res <= 0) {
418
free(fds);
419
throw_internal_error(env, "proc_pidinfo failed for PROC_PIDLISTFDS");
420
return -1;
421
}
422
nfiles = res / sizeof(struct proc_fdinfo);
423
free(fds);
424
425
return nfiles;
426
#elif defined(_ALLBSD_SOURCE)
427
/*
428
* XXXBSD: there's no way available to do it in FreeBSD, AFAIK.
429
*/
430
// throw_internal_error(env, "Unimplemented in FreeBSD");
431
return (100);
432
#else /* solaris/linux */
433
DIR *dirp;
434
struct dirent dbuf;
435
struct dirent* dentp;
436
jlong fds = 0;
437
438
#if defined(_AIX)
439
/* AIX does not understand '/proc/self' - it requires the real process ID */
440
#define FD_DIR aix_fd_dir
441
char aix_fd_dir[32]; /* the pid has at most 19 digits */
442
snprintf(aix_fd_dir, 32, "/proc/%d/fd", getpid());
443
#else
444
#define FD_DIR "/proc/self/fd"
445
#endif
446
447
dirp = opendir(FD_DIR);
448
if (dirp == NULL) {
449
throw_internal_error(env, "Unable to open directory /proc/self/fd");
450
return -1;
451
}
452
453
// iterate through directory entries, skipping '.' and '..'
454
// each entry represents an open file descriptor.
455
while ((dentp = read_dir(dirp, &dbuf)) != NULL) {
456
if (isdigit(dentp->d_name[0])) {
457
fds++;
458
}
459
}
460
461
closedir(dirp);
462
// subtract by 1 which was the fd open for this implementation
463
return (fds - 1);
464
#endif
465
}
466
467
#ifndef __linux__
468
JNIEXPORT jdouble JNICALL
469
Java_sun_management_OperatingSystemImpl_getSingleCpuLoad0
470
(JNIEnv *env, jobject mbean, jint cpu_number)
471
{
472
return -1.0;
473
}
474
475
JNIEXPORT jint JNICALL
476
Java_sun_management_OperatingSystemImpl_getHostConfiguredCpuCount0
477
(JNIEnv *env, jobject mbean)
478
{
479
return -1;
480
}
481
#endif
482
483
JNIEXPORT jlong JNICALL
484
Java_sun_management_OperatingSystemImpl_getMaxFileDescriptorCount
485
(JNIEnv *env, jobject mbean)
486
{
487
struct rlimit rlp;
488
489
if (getrlimit(RLIMIT_NOFILE, &rlp) == -1) {
490
throw_internal_error(env, "getrlimit failed");
491
return -1;
492
}
493
return (jlong) rlp.rlim_cur;
494
}
495
496