1
/* Licensed to the Apache Software Foundation (ASF) under one or more
2
* contributor license agreements. See the NOTICE file distributed with
3
* this work for additional information regarding copyright ownership.
4
* The ASF licenses this file to You under the Apache License, Version 2.0
5
* (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
20
* @version $Revision: 708867 $, $Date: 2008-10-29 11:39:16 +0100 (Wed, 29 Oct 2008) $
24
#include "apr_pools.h"
25
#include "apr_network_io.h"
29
#if defined(__linux__)
30
#include <sys/sysinfo.h>
36
#include <sys/sysinfo.h>
40
#include <mach/mach_init.h>
41
#include <mach/mach_host.h>
42
#include <mach/host_info.h>
43
#include <sys/sysctl.h>
51
#define LOG_WARN LOG_WARNING
55
#define MAX_PROC_PATH_LEN 64
57
#define PSINFO_T_SZ sizeof(psinfo_t)
58
#define PRUSAGE_T_SZ sizeof(prusage_t)
60
static int proc_open(const char *type)
62
char proc_path[MAX_PROC_PATH_LEN+1];
64
sprintf(proc_path, "/proc/self/%s", type);
65
return open(proc_path, O_RDONLY);
68
static int proc_read(void *buf, const size_t size, int filedes)
73
bytes = pread(filedes, buf, size, 0);
85
TCN_IMPLEMENT_CALL(jboolean, OS, is)(TCN_STDARGS, jint type)
90
#if defined(__linux__)
98
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
102
#if defined(__APPLE__) || defined(DARWIN)
110
TCN_IMPLEMENT_CALL(jint, OS, info)(TCN_STDARGS,
115
jsize ilen = (*e)->GetArrayLength(e, inf);
116
jlong *pvals = (*e)->GetLongArrayElements(e, inf, NULL);
122
for (i = 0; i < 16; i++)
124
#if defined(__linux__)
128
rv = apr_get_os_error();
130
pvals[0] = (jlong)(info.totalram * info.mem_unit);
131
pvals[1] = (jlong)(info.freeram * info.mem_unit);
132
pvals[2] = (jlong)(info.totalswap * info.mem_unit);
133
pvals[3] = (jlong)(info.freeswap * info.mem_unit);
134
pvals[4] = (jlong)(info.sharedram * info.mem_unit);
135
pvals[5] = (jlong)(info.bufferram * info.mem_unit);
136
pvals[6] = (jlong)(100 - (info.freeram * 100 / info.totalram));
142
/* static variables with basic procfs info */
143
static long creation = 0; /* unix timestamp of process creation */
144
static int psinf_fd = 0; /* file descriptor for the psinfo procfs file */
145
static int prusg_fd = 0; /* file descriptor for the usage procfs file */
146
static size_t rss = 0; /* maximum of resident set size from previous calls */
147
/* static variables with basic kstat info */
148
static kstat_ctl_t *kstat_ctl = NULL; /* kstat control object, only initialized once */
149
static kstat_t *kstat_cpu[MAX_CPUS]; /* array of kstat objects for per cpu statistics */
150
static int cpu_count = 0; /* number of cpu structures found in kstat */
151
static kid_t kid = 0; /* kstat ID, for which the kstat_ctl holds the correct chain */
152
/* non-static variables - general use */
153
int res = 0; /* general result state */
154
/* non-static variables - sysinfo/swapctl use */
155
long ret_sysconf; /* value returned from sysconf call */
156
long tck_dividend; /* factor used by transforming tick numbers to milliseconds */
157
long tck_divisor; /* divisor used by transforming tick numbers to milliseconds */
158
long sys_pagesize = sysconf(_SC_PAGESIZE); /* size of a system memory page in bytes */
159
long sys_clk_tck = sysconf(_SC_CLK_TCK); /* number of system ticks per second */
160
struct anoninfo info; /* structure for information about sizes in anonymous memory system */
161
/* non-static variables - procfs use */
162
psinfo_t psinf; /* psinfo structure from procfs */
163
prusage_t prusg; /* usage structure from procfs */
164
size_t new_rss = 0; /* resident set size read from procfs */
165
time_t now; /* time needed for calculating process creation time */
166
/* non-static variables - kstat use */
167
kstat_t *kstat = NULL; /* kstat working pointer */
168
cpu_sysinfo_t cpu; /* cpu sysinfo working pointer */
169
kid_t new_kid = 0; /* kstat ID returned from chain update */
170
int new_kstat = 0; /* flag indicating, if kstat structure has changed since last call */
174
if (sys_pagesize <= 0) {
175
rv = apr_get_os_error();
178
ret_sysconf = sysconf(_SC_PHYS_PAGES);
179
if (ret_sysconf >= 0) {
180
pvals[0] = (jlong)((jlong)sys_pagesize * ret_sysconf);
183
rv = apr_get_os_error();
185
ret_sysconf = sysconf(_SC_AVPHYS_PAGES);
186
if (ret_sysconf >= 0) {
187
pvals[1] = (jlong)((jlong)sys_pagesize * ret_sysconf);
190
rv = apr_get_os_error();
192
res=swapctl(SC_AINFO, &info);
194
pvals[2] = (jlong)((jlong)sys_pagesize * info.ani_max);
195
pvals[3] = (jlong)((jlong)sys_pagesize * info.ani_free);
196
pvals[6] = (jlong)(100 - (jlong)info.ani_free * 100 / info.ani_max);
199
rv = apr_get_os_error();
204
psinf_fd = proc_open("psinfo");
206
res = proc_read(&psinf, PSINFO_T_SZ, psinf_fd);
208
new_rss = psinf.pr_rssize*1024;
209
pvals[13] = (jlong)(new_rss);
213
pvals[14] = (jlong)(rss);
217
rv = apr_get_os_error();
220
prusg_fd = proc_open("usage");
222
res = proc_read(&prusg, PRUSAGE_T_SZ, prusg_fd);
226
creation = (long)(now - (prusg.pr_tstamp.tv_sec -
227
prusg.pr_create.tv_sec));
229
pvals[10] = (jlong)(creation);
230
pvals[11] = (jlong)((jlong)prusg.pr_stime.tv_sec * 1000 +
231
(prusg.pr_stime.tv_nsec / 1000000));
232
pvals[12] = (jlong)((jlong)prusg.pr_utime.tv_sec * 1000 +
233
(prusg.pr_utime.tv_nsec / 1000000));
234
pvals[15] = (jlong)(prusg.pr_majf);
238
rv = apr_get_os_error();
241
if (sys_clk_tck <= 0) {
242
rv = apr_get_os_error();
246
tck_divisor = sys_clk_tck;
247
for (i = 0; i < 3; i++) {
248
if (tck_divisor % 2 == 0) {
249
tck_divisor = tck_divisor / 2;
250
tck_dividend = tck_dividend / 2;
252
if (tck_divisor % 5 == 0) {
253
tck_divisor = tck_divisor / 5;
254
tck_dividend = tck_dividend / 5;
257
if (kstat_ctl == NULL) {
258
kstat_ctl = kstat_open();
259
kid = kstat_ctl->kc_chain_id;
262
new_kid = kstat_chain_update(kstat_ctl);
264
res=kstat_close(kstat_ctl);
265
kstat_ctl = kstat_open();
266
kid = kstat_ctl->kc_chain_id;
268
} else if (new_kid > 0 && kid != new_kid) {
275
for (kstat = kstat_ctl->kc_chain; kstat; kstat = kstat->ks_next) {
276
if (strncmp(kstat->ks_name, "cpu_stat", 8) == 0) {
277
kstat_cpu[cpu_count++]=kstat;
281
for (i = 0; i < cpu_count; i++) {
282
new_kid = kstat_read(kstat_ctl, kstat_cpu[i], NULL);
284
cpu = ((cpu_stat_t *)kstat_cpu[i]->ks_data)->cpu_sysinfo;
285
if ( tck_divisor == 1 ) {
286
pvals[7] += (jlong)(((jlong)cpu.cpu[CPU_IDLE]) * tck_dividend);
287
pvals[7] += (jlong)(((jlong)cpu.cpu[CPU_WAIT]) * tck_dividend);
288
pvals[8] += (jlong)(((jlong)cpu.cpu[CPU_KERNEL]) * tck_dividend);
289
pvals[9] += (jlong)(((jlong)cpu.cpu[CPU_USER]) * tck_dividend);
291
pvals[7] += (jlong)(((jlong)cpu.cpu[CPU_IDLE]) * tck_dividend / tck_divisor);
292
pvals[7] += (jlong)(((jlong)cpu.cpu[CPU_WAIT]) * tck_dividend / tck_divisor);
293
pvals[8] += (jlong)(((jlong)cpu.cpu[CPU_KERNEL]) * tck_dividend / tck_divisor);
294
pvals[9] += (jlong)(((jlong)cpu.cpu[CPU_USER]) * tck_dividend / tck_divisor);
301
* The next two are not implemented yet for Solaris
302
* inf[4] - Amount of shared memory
303
* inf[5] - Memory used by buffers
308
#elif defined(DARWIN)
311
size_t len = sizeof(mem_total);
313
vm_statistics_data_t vm_info;
314
mach_msg_type_number_t info_count = HOST_VM_INFO_COUNT;
316
sysctlbyname("hw.memsize", &mem_total, &len, NULL, 0);
317
pvals[0] = (jlong)mem_total;
319
host_statistics(mach_host_self (), HOST_VM_INFO, (host_info_t)&vm_info, &info_count);
320
pvals[1] = (jlong)(((double)vm_info.free_count)*vm_page_size);
321
pvals[6] = (jlong)(100 - (pvals[1] * 100 / mem_total));
328
(*e)->ReleaseLongArrayElements(e, inf, pvals, 0);
332
#define LOG_MSG_DOMAIN "Native"
335
TCN_IMPLEMENT_CALL(jstring, OS, expand)(TCN_STDARGS, jstring val)
338
TCN_ALLOC_CSTRING(val);
342
/* TODO: Make ${ENVAR} expansion */
343
str = (*e)->NewStringUTF(e, J2S(val));
345
TCN_FREE_CSTRING(val);
349
TCN_IMPLEMENT_CALL(void, OS, sysloginit)(TCN_STDARGS, jstring domain)
352
TCN_ALLOC_CSTRING(domain);
355
if ((d = J2S(domain)) == NULL)
358
openlog(d, LOG_CONS | LOG_PID, LOG_LOCAL0);
359
TCN_FREE_CSTRING(domain);
362
TCN_IMPLEMENT_CALL(void, OS, syslog)(TCN_STDARGS, jint level,
365
TCN_ALLOC_CSTRING(msg);
386
syslog (id, "%s", J2S(msg));
388
TCN_FREE_CSTRING(msg);