blob: fff365ecb8464fbca0ad6824ff76f7867ddcea41 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2005 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any 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 "com_sun_management_UnixOperatingSystem.h"
32
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <sys/swap.h>
36#include <sys/resource.h>
37#include <sys/times.h>
38#include <sys/sysinfo.h>
39#include <ctype.h>
40#include <dirent.h>
41#include <errno.h>
42#include <fcntl.h>
43#include <limits.h>
44#include <stdlib.h>
45#include <unistd.h>
46
47static jlong page_size = 0;
48
49/* This gets us the new structured proc interfaces of 5.6 & later */
50/* - see comment in <sys/procfs.h> */
51#define _STRUCTURED_PROC 1
52#include <sys/procfs.h>
53
54static struct dirent* read_dir(DIR* dirp, struct dirent* entry) {
55#ifdef __solaris__
56 struct dirent* dbuf = readdir(dirp);
57 return dbuf;
58#else /* __linux__ */
59 struct dirent* p;
60 if (readdir_r(dirp, entry, &p) == 0) {
61 return p;
62 } else {
63 return NULL;
64 }
65#endif
66}
67
68// true = get available swap in bytes
69// false = get total swap in bytes
70static jlong get_total_or_available_swap_space_size(JNIEnv* env, jboolean available) {
71#ifdef __solaris__
72 long total, avail;
73 int nswap, i, count;
74 swaptbl_t *stbl;
75 char *strtab;
76
77 // First get the number of swap resource entries
78 if ((nswap = swapctl(SC_GETNSWP, NULL)) == -1) {
79 throw_internal_error(env, "swapctl failed to get nswap");
80 return -1;
81 }
82 if (nswap == 0) {
83 return 0;
84 }
85
86 // Allocate storage for resource entries
87 stbl = (swaptbl_t*) malloc(nswap * sizeof(swapent_t) +
88 sizeof(struct swaptable));
89 if (stbl == NULL) {
90 JNU_ThrowOutOfMemoryError(env, 0);
91 return -1;
92 }
93
94 // Allocate storage for the table
95 strtab = (char*) malloc((nswap + 1) * MAXPATHLEN);
96 if (strtab == NULL) {
97 free(stbl);
98 JNU_ThrowOutOfMemoryError(env, 0);
99 return -1;
100 }
101
102 for (i = 0; i < (nswap + 1); i++) {
103 stbl->swt_ent[i].ste_path = strtab + (i * MAXPATHLEN);
104 }
105 stbl->swt_n = nswap + 1;
106
107 // Get the entries
108 if ((count = swapctl(SC_LIST, stbl)) < 0) {
109 free(stbl);
110 free(strtab);
111 throw_internal_error(env, "swapctl failed to get swap list");
112 return -1;
113 }
114
115 // Sum the entries to get total and free swap
116 total = 0;
117 avail = 0;
118 for (i = 0; i < count; i++) {
119 total += stbl->swt_ent[i].ste_pages;
120 avail += stbl->swt_ent[i].ste_free;
121 }
122
123 free(stbl);
124 free(strtab);
125 return available ? ((jlong)avail * page_size) :
126 ((jlong)total * page_size);
127#else /* __linux__ */
128 int ret;
129 FILE *fp;
130 jlong total = 0, avail = 0;
131
132 struct sysinfo si;
133 ret = sysinfo(&si);
134 if (ret != 0) {
135 throw_internal_error(env, "sysinfo failed to get swap size");
136 }
137 total = (jlong)si.totalswap * si.mem_unit;
138 avail = (jlong)si.freeswap * si.mem_unit;
139
140 return available ? avail : total;
141#endif
142}
143
144JNIEXPORT void JNICALL
145Java_com_sun_management_UnixOperatingSystem_initialize
146 (JNIEnv *env, jclass cls)
147{
148 page_size = sysconf(_SC_PAGESIZE);
149}
150
151JNIEXPORT jlong JNICALL
152Java_com_sun_management_UnixOperatingSystem_getCommittedVirtualMemorySize
153 (JNIEnv *env, jobject mbean)
154{
155#ifdef __solaris__
156 psinfo_t psinfo;
157 ssize_t result;
158 size_t remaining;
159 char* addr;
160 int fd;
161
162 fd = JVM_Open("/proc/self/psinfo", O_RDONLY, 0);
163 if (fd < 0) {
164 throw_internal_error(env, "Unable to open /proc/self/psinfo");
165 return -1;
166 }
167
168 addr = (char *)&psinfo;
169 for (remaining = sizeof(psinfo_t); remaining > 0;) {
170 result = JVM_Read(fd, addr, remaining);
171 if (result < 0) {
172 JVM_Close(fd);
173 throw_internal_error(env, "Unable to read /proc/self/psinfo");
174 return -1;
175 }
176 remaining -= result;
177 addr += result;
178 }
179
180 JVM_Close(fd);
181 return (jlong) psinfo.pr_size * 1024;
182#else /* __linux__ */
183 FILE *fp;
184 unsigned long vsize = 0;
185
186 if ((fp = fopen("/proc/self/stat", "r")) == NULL) {
187 throw_internal_error(env, "Unable to open /proc/self/stat");
188 return -1;
189 }
190
191 // Ignore everything except the vsize entry
192 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) {
193 throw_internal_error(env, "Unable to get virtual memory usage");
194 fclose(fp);
195 return -1;
196 }
197
198 fclose(fp);
199 return (jlong)vsize;
200#endif
201}
202
203JNIEXPORT jlong JNICALL
204Java_com_sun_management_UnixOperatingSystem_getTotalSwapSpaceSize
205 (JNIEnv *env, jobject mbean)
206{
207 return get_total_or_available_swap_space_size(env, JNI_FALSE);
208}
209
210JNIEXPORT jlong JNICALL
211Java_com_sun_management_UnixOperatingSystem_getFreeSwapSpaceSize
212 (JNIEnv *env, jobject mbean)
213{
214 return get_total_or_available_swap_space_size(env, JNI_TRUE);
215}
216
217JNIEXPORT jlong JNICALL
218Java_com_sun_management_UnixOperatingSystem_getProcessCpuTime
219 (JNIEnv *env, jobject mbean)
220{
221 jlong clk_tck, ns_per_clock_tick;
222 jlong cpu_time_ns;
223 struct tms time;
224
225#ifdef __solaris__
226 clk_tck = (jlong) sysconf(_SC_CLK_TCK);
227#else /* __linux__ */
228 clk_tck = 100;
229#endif
230 if (clk_tck == -1) {
231 throw_internal_error(env,
232 "sysconf failed - not able to get clock tick");
233 return -1;
234 }
235
236 times(&time);
237 ns_per_clock_tick = (jlong) 1000 * 1000 * 1000 / (jlong) clk_tck;
238 cpu_time_ns = ((jlong)time.tms_utime + (jlong) time.tms_stime) *
239 ns_per_clock_tick;
240 return cpu_time_ns;
241}
242
243JNIEXPORT jlong JNICALL
244Java_com_sun_management_UnixOperatingSystem_getFreePhysicalMemorySize
245 (JNIEnv *env, jobject mbean)
246{
247 jlong num_avail_physical_pages = sysconf(_SC_AVPHYS_PAGES);
248 return (num_avail_physical_pages * page_size);
249}
250
251JNIEXPORT jlong JNICALL
252Java_com_sun_management_UnixOperatingSystem_getTotalPhysicalMemorySize
253 (JNIEnv *env, jobject mbean)
254{
255 jlong num_physical_pages = sysconf(_SC_PHYS_PAGES);
256 return (num_physical_pages * page_size);
257}
258
259JNIEXPORT jlong JNICALL
260Java_com_sun_management_UnixOperatingSystem_getOpenFileDescriptorCount
261 (JNIEnv *env, jobject mbean)
262{
263 DIR *dirp;
264 struct dirent dbuf;
265 struct dirent* dentp;
266 jlong fds = 0;
267
268 dirp = opendir("/proc/self/fd");
269 if (dirp == NULL) {
270 throw_internal_error(env, "Unable to open directory /proc/self/fd");
271 return -1;
272 }
273
274 // iterate through directory entries, skipping '.' and '..'
275 // each entry represents an open file descriptor.
276 while ((dentp = read_dir(dirp, &dbuf)) != NULL) {
277 if (isdigit(dentp->d_name[0])) {
278 fds++;
279 }
280 }
281
282 closedir(dirp);
283 // subtract by 1 which was the fd open for this implementation
284 return (fds - 1);
285}
286
287JNIEXPORT jlong JNICALL
288Java_com_sun_management_UnixOperatingSystem_getMaxFileDescriptorCount
289 (JNIEnv *env, jobject mbean)
290{
291 struct rlimit rlp;
292
293 if (getrlimit(RLIMIT_NOFILE, &rlp) == -1) {
294 throw_internal_error(env, "getrlimit failed");
295 return -1;
296 }
297 return (jlong) rlp.rlim_cur;
298}