Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/management/OperatingSystemImpl.c
32287 views
/*1* Copyright (c) 2003, 2019, 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. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include "jni.h"26#include "jni_util.h"27#include "jlong.h"28#include "jvm.h"29#include "management.h"30#include "sun_management_OperatingSystemImpl.h"3132#include <sys/types.h>33#include <sys/stat.h>34#if defined(_ALLBSD_SOURCE)35#include <sys/sysctl.h>36#ifdef __APPLE__37#include <sys/param.h>38#include <sys/mount.h>39#include <mach/mach.h>40#include <sys/proc_info.h>41#include <libproc.h>42#endif43#elif !defined(_AIX)44#include <sys/swap.h>45#endif46#include <sys/resource.h>47#include <sys/times.h>48#ifndef _ALLBSD_SOURCE49#include <sys/sysinfo.h>50#endif51#include <ctype.h>52#include <dirent.h>53#include <errno.h>54#include <fcntl.h>55#include <limits.h>56#include <stdlib.h>57#include <unistd.h>5859#if defined(_AIX)60#include <libperfstat.h>61#endif6263static jlong page_size = 0;6465#if defined(_ALLBSD_SOURCE) || defined(_AIX)66#define MB (1024UL * 1024UL)67#else6869/* This gets us the new structured proc interfaces of 5.6 & later */70/* - see comment in <sys/procfs.h> */71#define _STRUCTURED_PROC 172#ifndef __ANDROID__73#include <sys/procfs.h>74#endif7576#endif /* _ALLBSD_SOURCE */7778static struct dirent* read_dir(DIR* dirp, struct dirent* entry) {79#ifdef __solaris__80struct dirent* dbuf = readdir(dirp);81return dbuf;82#else /* __linux__ || _ALLBSD_SOURCE */83struct dirent* p;84if (readdir_r(dirp, entry, &p) == 0) {85return p;86} else {87return NULL;88}89#endif90}9192// true = get available swap in bytes93// false = get total swap in bytes94static jlong get_total_or_available_swap_space_size(JNIEnv* env, jboolean available) {95#ifdef __solaris__96long total, avail;97int nswap, i, count;98swaptbl_t *stbl;99char *strtab;100101// First get the number of swap resource entries102if ((nswap = swapctl(SC_GETNSWP, NULL)) == -1) {103throw_internal_error(env, "swapctl failed to get nswap");104return -1;105}106if (nswap == 0) {107return 0;108}109110// Allocate storage for resource entries111stbl = (swaptbl_t*) malloc(nswap * sizeof(swapent_t) +112sizeof(struct swaptable));113if (stbl == NULL) {114JNU_ThrowOutOfMemoryError(env, 0);115return -1;116}117118// Allocate storage for the table119strtab = (char*) malloc((nswap + 1) * MAXPATHLEN);120if (strtab == NULL) {121free(stbl);122JNU_ThrowOutOfMemoryError(env, 0);123return -1;124}125126for (i = 0; i < (nswap + 1); i++) {127stbl->swt_ent[i].ste_path = strtab + (i * MAXPATHLEN);128}129stbl->swt_n = nswap + 1;130131// Get the entries132if ((count = swapctl(SC_LIST, stbl)) < 0) {133free(stbl);134free(strtab);135throw_internal_error(env, "swapctl failed to get swap list");136return -1;137}138139// Sum the entries to get total and free swap140total = 0;141avail = 0;142for (i = 0; i < count; i++) {143total += stbl->swt_ent[i].ste_pages;144avail += stbl->swt_ent[i].ste_free;145}146147free(stbl);148free(strtab);149return available ? ((jlong)avail * page_size) :150((jlong)total * page_size);151#elif defined(__linux__)152int ret;153FILE *fp;154jlong total = 0, avail = 0;155156struct sysinfo si;157ret = sysinfo(&si);158if (ret != 0) {159throw_internal_error(env, "sysinfo failed to get swap size");160}161total = (jlong)si.totalswap * si.mem_unit;162avail = (jlong)si.freeswap * si.mem_unit;163164return available ? avail : total;165#elif defined(__APPLE__)166struct xsw_usage vmusage;167size_t size = sizeof(vmusage);168if (sysctlbyname("vm.swapusage", &vmusage, &size, NULL, 0) != 0) {169throw_internal_error(env, "sysctlbyname failed");170}171return available ? (jlong)vmusage.xsu_avail : (jlong)vmusage.xsu_total;172#else /* _ALLBSD_SOURCE */173/*174* XXXBSD: there's no way available to get swap info in175* FreeBSD. Usage of libkvm is not an option here176*/177// throw_internal_error(env, "Unimplemented in FreeBSD");178return (0);179#endif180}181182JNIEXPORT void JNICALL183Java_sun_management_OperatingSystemImpl_initialize184(JNIEnv *env, jclass cls)185{186page_size = sysconf(_SC_PAGESIZE);187}188189JNIEXPORT jlong JNICALL190Java_sun_management_OperatingSystemImpl_getCommittedVirtualMemorySize191(JNIEnv *env, jobject mbean)192{193#ifdef __solaris__194psinfo_t psinfo;195ssize_t result;196size_t remaining;197char* addr;198int fd;199200fd = JVM_Open("/proc/self/psinfo", O_RDONLY, 0);201if (fd < 0) {202throw_internal_error(env, "Unable to open /proc/self/psinfo");203return -1;204}205206addr = (char *)&psinfo;207for (remaining = sizeof(psinfo_t); remaining > 0;) {208result = JVM_Read(fd, addr, remaining);209if (result < 0) {210JVM_Close(fd);211throw_internal_error(env, "Unable to read /proc/self/psinfo");212return -1;213}214remaining -= result;215addr += result;216}217218JVM_Close(fd);219return (jlong) psinfo.pr_size * 1024;220#elif defined(__linux__)221FILE *fp;222unsigned long vsize = 0;223224if ((fp = fopen("/proc/self/stat", "r")) == NULL) {225throw_internal_error(env, "Unable to open /proc/self/stat");226return -1;227}228229// Ignore everything except the vsize entry230if (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) {231throw_internal_error(env, "Unable to get virtual memory usage");232fclose(fp);233return -1;234}235236fclose(fp);237return (jlong)vsize;238#elif defined(__APPLE__)239struct task_basic_info t_info;240mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;241242kern_return_t res = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);243if (res != KERN_SUCCESS) {244throw_internal_error(env, "task_info failed");245}246return t_info.virtual_size;247#else /* _ALLBSD_SOURCE */248/*249* XXXBSD: there's no way available to do it in FreeBSD, AFAIK.250*/251// throw_internal_error(env, "Unimplemented in FreeBSD");252return (64 * MB);253#endif254}255256JNIEXPORT jlong JNICALL257Java_sun_management_OperatingSystemImpl_getTotalSwapSpaceSize0258(JNIEnv *env, jobject mbean)259{260return get_total_or_available_swap_space_size(env, JNI_FALSE);261}262263JNIEXPORT jlong JNICALL264Java_sun_management_OperatingSystemImpl_getFreeSwapSpaceSize0265(JNIEnv *env, jobject mbean)266{267return get_total_or_available_swap_space_size(env, JNI_TRUE);268}269270JNIEXPORT jlong JNICALL271Java_sun_management_OperatingSystemImpl_getProcessCpuTime272(JNIEnv *env, jobject mbean)273{274#ifdef __APPLE__275struct rusage usage;276if (getrusage(RUSAGE_SELF, &usage) != 0) {277throw_internal_error(env, "getrusage failed");278return -1;279}280jlong microsecs =281usage.ru_utime.tv_sec * 1000 * 1000 + usage.ru_utime.tv_usec +282usage.ru_stime.tv_sec * 1000 * 1000 + usage.ru_stime.tv_usec;283return microsecs * 1000;284#else285jlong clk_tck, ns_per_clock_tick;286jlong cpu_time_ns;287struct tms time;288289/*290* BSDNOTE: FreeBSD implements _SC_CLK_TCK since FreeBSD 5, so291* add a magic to handle it292*/293#if defined(__solaris__) || defined(_SC_CLK_TCK)294clk_tck = (jlong) sysconf(_SC_CLK_TCK);295#elif defined(__linux__) || defined(_ALLBSD_SOURCE)296clk_tck = 100;297#endif298if (clk_tck == -1) {299throw_internal_error(env,300"sysconf failed - not able to get clock tick");301return -1;302}303304times(&time);305ns_per_clock_tick = (jlong) 1000 * 1000 * 1000 / (jlong) clk_tck;306cpu_time_ns = ((jlong)time.tms_utime + (jlong) time.tms_stime) *307ns_per_clock_tick;308return cpu_time_ns;309#endif310}311312JNIEXPORT jlong JNICALL313Java_sun_management_OperatingSystemImpl_getFreePhysicalMemorySize0314(JNIEnv *env, jobject mbean)315{316#ifdef __APPLE__317mach_msg_type_number_t count;318vm_statistics_data_t vm_stats;319kern_return_t res;320321count = HOST_VM_INFO_COUNT;322res = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stats, &count);323if (res != KERN_SUCCESS) {324throw_internal_error(env, "host_statistics failed");325return -1;326}327return (jlong)vm_stats.free_count * page_size;328#elif defined(_ALLBSD_SOURCE)329/*330* XXBSDL no way to do it in FreeBSD331*/332// throw_internal_error(env, "unimplemented in FreeBSD")333return (128 * MB);334#elif defined(_AIX)335perfstat_memory_total_t memory_info;336if (-1 != perfstat_memory_total(NULL, &memory_info, sizeof(perfstat_memory_total_t), 1)) {337return (jlong)(memory_info.real_free * 4L * 1024L);338}339return -1;340#else // solaris / linux341jlong num_avail_physical_pages = sysconf(_SC_AVPHYS_PAGES);342return (num_avail_physical_pages * page_size);343#endif344}345346JNIEXPORT jlong JNICALL347Java_sun_management_OperatingSystemImpl_getTotalPhysicalMemorySize0348(JNIEnv *env, jobject mbean)349{350#ifdef _ALLBSD_SOURCE351jlong result = 0;352int mib[2];353size_t rlen;354355mib[0] = CTL_HW;356mib[1] = HW_MEMSIZE;357rlen = sizeof(result);358if (sysctl(mib, 2, &result, &rlen, NULL, 0) != 0) {359throw_internal_error(env, "sysctl failed");360return -1;361}362return result;363#elif defined(_AIX)364perfstat_memory_total_t memory_info;365if (-1 != perfstat_memory_total(NULL, &memory_info, sizeof(perfstat_memory_total_t), 1)) {366return (jlong)(memory_info.real_total * 4L * 1024L);367}368return -1;369#else // solaris / linux370jlong num_physical_pages = sysconf(_SC_PHYS_PAGES);371return (num_physical_pages * page_size);372#endif373}374375376377JNIEXPORT jlong JNICALL378Java_sun_management_OperatingSystemImpl_getOpenFileDescriptorCount379(JNIEnv *env, jobject mbean)380{381#ifdef __APPLE__382// This code is influenced by the darwin lsof source383pid_t my_pid;384struct proc_bsdinfo bsdinfo;385struct proc_fdinfo *fds;386int nfiles;387kern_return_t kres;388int res;389size_t fds_size;390391kres = pid_for_task(mach_task_self(), &my_pid);392if (kres != KERN_SUCCESS) {393throw_internal_error(env, "pid_for_task failed");394return -1;395}396397// get the maximum number of file descriptors398res = proc_pidinfo(my_pid, PROC_PIDTBSDINFO, 0, &bsdinfo, PROC_PIDTBSDINFO_SIZE);399if (res <= 0) {400throw_internal_error(env, "proc_pidinfo with PROC_PIDTBSDINFO failed");401return -1;402}403404// allocate memory to hold the fd information (we don't acutally use this information405// but need it to get the number of open files)406fds_size = bsdinfo.pbi_nfiles * sizeof(struct proc_fdinfo);407fds = malloc(fds_size);408if (fds == NULL) {409JNU_ThrowOutOfMemoryError(env, "could not allocate space for file descriptors");410return -1;411}412413// get the list of open files - the return value is the number of bytes414// proc_pidinfo filled in415res = proc_pidinfo(my_pid, PROC_PIDLISTFDS, 0, fds, fds_size);416if (res <= 0) {417free(fds);418throw_internal_error(env, "proc_pidinfo failed for PROC_PIDLISTFDS");419return -1;420}421nfiles = res / sizeof(struct proc_fdinfo);422free(fds);423424return nfiles;425#elif defined(_ALLBSD_SOURCE)426/*427* XXXBSD: there's no way available to do it in FreeBSD, AFAIK.428*/429// throw_internal_error(env, "Unimplemented in FreeBSD");430return (100);431#else /* solaris/linux */432DIR *dirp;433struct dirent dbuf;434struct dirent* dentp;435jlong fds = 0;436437#if defined(_AIX)438/* AIX does not understand '/proc/self' - it requires the real process ID */439#define FD_DIR aix_fd_dir440char aix_fd_dir[32]; /* the pid has at most 19 digits */441snprintf(aix_fd_dir, 32, "/proc/%d/fd", getpid());442#else443#define FD_DIR "/proc/self/fd"444#endif445446dirp = opendir(FD_DIR);447if (dirp == NULL) {448throw_internal_error(env, "Unable to open directory /proc/self/fd");449return -1;450}451452// iterate through directory entries, skipping '.' and '..'453// each entry represents an open file descriptor.454while ((dentp = read_dir(dirp, &dbuf)) != NULL) {455if (isdigit(dentp->d_name[0])) {456fds++;457}458}459460closedir(dirp);461// subtract by 1 which was the fd open for this implementation462return (fds - 1);463#endif464}465466#ifndef __linux__467JNIEXPORT jdouble JNICALL468Java_sun_management_OperatingSystemImpl_getSingleCpuLoad0469(JNIEnv *env, jobject mbean, jint cpu_number)470{471return -1.0;472}473474JNIEXPORT jint JNICALL475Java_sun_management_OperatingSystemImpl_getHostConfiguredCpuCount0476(JNIEnv *env, jobject mbean)477{478return -1;479}480#endif481482JNIEXPORT jlong JNICALL483Java_sun_management_OperatingSystemImpl_getMaxFileDescriptorCount484(JNIEnv *env, jobject mbean)485{486struct rlimit rlp;487488if (getrlimit(RLIMIT_NOFILE, &rlp) == -1) {489throw_internal_error(env, "getrlimit failed");490return -1;491}492return (jlong) rlp.rlim_cur;493}494495496