1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <stddef.h>
30 #include <kstat.h>
31
32 #include "jkstat.h"
33
34 /*
35 * Class descriptors
36 */
37 #define DOUBLE_CLASS_DESC "java/lang/Double"
38 #define LONG_CLASS_DESC "java/lang/Long"
39 #define UI64_CLASS_DESC "com/sun/solaris/service/pools/UnsignedInt64"
40 #define HRTIME_CLASS_DESC "com/sun/solaris/service/pools/HRTime"
41 #define KSTAT_CLASS_DESC "com/sun/solaris/service/kstat/Kstat"
42 #define KSTATCTL_CLASS_DESC "com/sun/solaris/service/kstat/KstatCtl"
43 #define KSTAT_READ_EX_CLASS_DESC \
44 "com/sun/solaris/service/kstat/KstatReadException"
45 #define KSTAT_TNS_EX_CLASS_DESC \
46 "com/sun/solaris/service/kstat/KstatTypeNotSupportedException"
47 #define THROWABLE_CLASS_DESC "java/lang/Throwable"
48
49 #define CLASS_FIELD_DESC(class_desc) "L" class_desc ";"
50
51 /*
52 * Cached class, method, and field IDs.
53 */
54 static jclass doubleclass;
55 static jclass hrtimeclass;
56 static jclass kstatclass;
57 static jclass kstatctlclass;
58 static jclass longclass;
59 static jclass ui64class;
60 static jfieldID kstat_kctl_fieldid;
61 static jfieldID kstat_ksp_fieldid;
62 static jfieldID kstatctl_kctl_fieldid;
63 static jmethodID doublecons_mid;
64 static jmethodID hrtimecons_mid;
65 static jmethodID kstatcons_mid;
66 static jmethodID longcons_mid;
67 static jmethodID ui64cons_mid;
68
69 static jobject
makeUnsignedInt64(JNIEnv * env,uint64_t value)70 makeUnsignedInt64(JNIEnv *env, uint64_t value)
71 {
72 jobject valueObj;
73 jobject byteArray;
74 jbyte *bytes;
75 int i;
76
77 if (!(byteArray = (*env)->NewByteArray(env, 9)))
78 return (NULL); /* OutOfMemoryError thrown */
79 if (!(bytes = (*env)->GetByteArrayElements(env, byteArray, NULL)))
80 return (NULL); /* OutOfMemoryError thrown */
81
82 /*
83 * Interpret the uint64_t as a 9-byte big-endian signed quantity
84 * suitable for constructing an UnsignedInt64 or BigInteger.
85 */
86 for (i = 8; i >= 1; i--) {
87 bytes[i] = value & 0xff;
88 value >>= 8;
89 }
90 bytes[0] = 0;
91 (*env)->ReleaseByteArrayElements(env, byteArray, bytes, 0);
92
93 if (!(valueObj = (*env)->NewObject(env, ui64class, ui64cons_mid,
94 byteArray)))
95 return (NULL); /* exception thrown */
96
97 return (valueObj);
98 }
99
100 /*
101 * Return a Long object with the given value.
102 */
103 static jobject
makeLong(JNIEnv * env,jlong value)104 makeLong(JNIEnv *env, jlong value)
105 {
106 jobject valueObj;
107
108 if (!(valueObj = (*env)->NewObject(env, longclass, longcons_mid,
109 value)))
110 return (NULL); /* exception thrown */
111
112 return (valueObj);
113 }
114
115 /*
116 * Return a Double object with the given value.
117 */
118 static jobject
makeDouble(JNIEnv * env,jdouble value)119 makeDouble(JNIEnv *env, jdouble value)
120 {
121 jobject valueObj;
122
123 if (!(valueObj = (*env)->NewObject(env, doubleclass, doublecons_mid,
124 value)))
125 return (NULL); /* exception thrown */
126
127 return (valueObj);
128 }
129
130 /*
131 * Returns the kctl_t * from kstat_open(3kstat).
132 */
133 /*ARGSUSED*/
134 JNIEXPORT jlong JNICALL
Java_com_sun_solaris_service_kstat_KstatCtl_open(JNIEnv * env,jobject obj)135 Java_com_sun_solaris_service_kstat_KstatCtl_open(JNIEnv *env, jobject obj)
136 {
137 return ((jlong)(uintptr_t)kstat_open());
138 }
139
140 /*
141 * Invokes kstat_close(3kstat).
142 */
143 /*ARGSUSED*/
144 JNIEXPORT jint JNICALL
Java_com_sun_solaris_service_kstat_KstatCtl_close(JNIEnv * env,jobject obj,jlong kctl)145 Java_com_sun_solaris_service_kstat_KstatCtl_close(JNIEnv *env, jobject obj,
146 jlong kctl)
147 {
148 if (kctl)
149 return (kstat_close((kstat_ctl_t *)(uintptr_t)kctl));
150 else
151 return (0);
152 }
153
154 /*
155 * Invoke kstat_read(3kstat) for the given Kstat object.
156 */
Java_com_sun_solaris_service_kstat_Kstat_read(JNIEnv * env,jobject obj)157 JNIEXPORT void JNICALL Java_com_sun_solaris_service_kstat_Kstat_read(
158 JNIEnv *env, jobject obj)
159 {
160 kstat_ctl_t *kctl =
161 ((kstat_ctl_t *)(uintptr_t)(*env)->GetLongField(env, obj,
162 kstat_kctl_fieldid));
163 kstat_t *ksp = ((kstat_t *)(uintptr_t)(*env)->GetLongField(env, obj,
164 kstat_ksp_fieldid));
165 kid_t kid;
166
167 if (!ksp || !kctl)
168 return; /* exception thronw */
169
170 kid = kstat_read((kstat_ctl_t *)kctl, (kstat_t *)ksp, NULL);
171 if (kid == -1) {
172 jclass e;
173 if (!(e = (*env)->FindClass(env, KSTAT_READ_EX_CLASS_DESC)))
174 return; /* exception thrown */
175
176 (*env)->Throw(env, (*env)->NewObject(env, e,
177 (*env)->GetStaticMethodID(env, e, "<init>",
178 "()" CLASS_FIELD_DESC(THROWABLE_CLASS_DESC))));
179 }
180 }
181
182 /*
183 * Return a Kstat object corresponding to the result of
184 * kstat_lookup(3kstat).
185 */
186 JNIEXPORT jobject JNICALL
Java_com_sun_solaris_service_kstat_KstatCtl_lookup(JNIEnv * env,jobject obj,jstring moduleObj,jint instance,jstring nameObj)187 Java_com_sun_solaris_service_kstat_KstatCtl_lookup(JNIEnv *env, jobject obj,
188 jstring moduleObj, jint instance, jstring nameObj)
189 {
190 const char *module = NULL;
191 const char *name = NULL;
192 kstat_ctl_t *kctl;
193 kstat_t *ksp;
194 jobject kstatObject = NULL;
195
196 if (moduleObj == NULL || nameObj == NULL)
197 return (NULL);
198
199 if (!(module = (*env)->GetStringUTFChars(env, moduleObj, NULL)))
200 goto done; /* exception thrown */
201 if (!(name = (*env)->GetStringUTFChars(env, nameObj, NULL)))
202 goto done; /* exception thrown */
203
204 kctl = (kstat_ctl_t *)(uintptr_t)(*env)->GetLongField(env, obj,
205 kstatctl_kctl_fieldid);
206 ksp = kstat_lookup(kctl, (char *)module, instance, (char *)name);
207 if (ksp)
208 kstatObject = (*env)->NewObject(env, kstatclass, kstatcons_mid,
209 (jlong)(uintptr_t)kctl, (jlong)(uintptr_t)ksp);
210
211 done:
212 if (name)
213 (*env)->ReleaseStringUTFChars(env, nameObj, name);
214 if (module)
215 (*env)->ReleaseStringUTFChars(env, moduleObj, module);
216
217 return (kstatObject);
218 }
219
220 /*
221 * Returns the named value -- the value of the named kstat, or field in
222 * a raw kstat, as applicable, and available. Returns <i>null</i> if no
223 * such named kstat or field is available.
224 *
225 * Throws KstatTypeNotSupportedException if the raw kstat is not
226 * understood. (Presently, none are.)
227 */
228 JNIEXPORT jobject JNICALL
Java_com_sun_solaris_service_kstat_Kstat_getValue(JNIEnv * env,jobject obj,jstring nameObj)229 Java_com_sun_solaris_service_kstat_Kstat_getValue(JNIEnv *env, jobject obj,
230 jstring nameObj)
231 {
232 kstat_t *ksp = ((kstat_t *)(uintptr_t)(*env)->GetLongField(env, obj,
233 kstat_ksp_fieldid));
234 jobject valueObj = NULL;
235 kstat_named_t *ksnp;
236 const char *name;
237 jclass exceptionClass;
238
239 if (!nameObj)
240 return (NULL);
241
242 if (!(name = (*env)->GetStringUTFChars(env, nameObj, NULL)))
243 return (NULL); /* exception thrown */
244
245 if (!(exceptionClass = (*env)->FindClass(env,
246 KSTAT_TNS_EX_CLASS_DESC))) {
247 (*env)->ReleaseStringUTFChars(env, nameObj, name);
248 return (NULL); /* exception thrown */
249 }
250
251 switch (ksp->ks_type) {
252 case KSTAT_TYPE_NAMED:
253 ksnp = kstat_data_lookup(ksp, (char *)name);
254 if (ksnp == NULL)
255 break;
256 switch (ksnp->data_type) {
257 case KSTAT_DATA_CHAR:
258 valueObj = makeLong(env, ksnp->value.c[0]);
259 break;
260 case KSTAT_DATA_INT32:
261 valueObj = makeLong(env, ksnp->value.i32);
262 break;
263 case KSTAT_DATA_UINT32:
264 valueObj = makeLong(env, ksnp->value.ui32);
265 break;
266 case KSTAT_DATA_INT64:
267 valueObj = makeLong(env, ksnp->value.i64);
268 break;
269 case KSTAT_DATA_UINT64:
270 valueObj = makeUnsignedInt64(env, ksnp->value.ui64);
271 break;
272 case KSTAT_DATA_STRING:
273 valueObj = (*env)->NewStringUTF(env,
274 KSTAT_NAMED_STR_PTR(ksnp));
275 break;
276 case KSTAT_DATA_FLOAT:
277 valueObj = makeDouble(env, ksnp->value.f);
278 break;
279 case KSTAT_DATA_DOUBLE:
280 valueObj = makeDouble(env, ksnp->value.d);
281 break;
282 default:
283 goto fail;
284 }
285 break;
286 default:
287 goto fail;
288 }
289
290 (*env)->ReleaseStringUTFChars(env, nameObj, name);
291 return (valueObj);
292
293 fail:
294 (*env)->ReleaseStringUTFChars(env, nameObj, name);
295 (*env)->Throw(env, (*env)->NewObject(env, exceptionClass,
296 (*env)->GetStaticMethodID(env, exceptionClass, "<init>",
297 "()" CLASS_FIELD_DESC(THROWABLE_CLASS_DESC))));
298
299 return (valueObj);
300 }
301
302 /*
303 * Given a Kstat object, return, as an HRTime object, its kstat_t's
304 * field at the given offset.
305 */
306 static jobject
ksobj_get_hrtime(JNIEnv * env,jobject obj,offset_t ksfieldoff)307 ksobj_get_hrtime(JNIEnv *env, jobject obj, offset_t ksfieldoff)
308 {
309 kstat_t *ksp = ((kstat_t *)(uintptr_t)(*env)->GetLongField(env, obj,
310 kstat_ksp_fieldid));
311
312 if (!ksp)
313 return (NULL); /* exception thrown */
314
315 return ((*env)->NewObject(env, hrtimeclass, hrtimecons_mid,
316 makeUnsignedInt64(env, *((hrtime_t *)ksp + ksfieldoff *
317 sizeof (hrtime_t)))));
318 }
319
320 /*
321 * Given a Kstat object, return as an HRTime object its ks_snaptime
322 * field.
323 */
324 JNIEXPORT jobject JNICALL
Java_com_sun_solaris_service_kstat_Kstat_getSnapTime(JNIEnv * env,jobject obj)325 Java_com_sun_solaris_service_kstat_Kstat_getSnapTime(JNIEnv *env, jobject obj)
326 {
327 return (ksobj_get_hrtime(env, obj, offsetof(kstat_t, ks_snaptime)));
328 }
329
330 /*
331 * Given a Kstat object, return as an HRTime object its ks_crtime
332 * field.
333 */
334 JNIEXPORT jobject JNICALL
Java_com_sun_solaris_service_kstat_Kstat_getCreationTime(JNIEnv * env,jobject obj)335 Java_com_sun_solaris_service_kstat_Kstat_getCreationTime(JNIEnv *env,
336 jobject obj)
337 {
338 return (ksobj_get_hrtime(env, obj, offsetof(kstat_t, ks_crtime)));
339 }
340
341 /*
342 * Invoke kstat_chain_update(3kstat) for the kstat chain corresponding
343 * to the given KstatCtl object.
344 */
345 JNIEXPORT void JNICALL
Java_com_sun_solaris_service_kstat_KstatCtl_chainUpdate(JNIEnv * env,jobject obj)346 Java_com_sun_solaris_service_kstat_KstatCtl_chainUpdate(JNIEnv *env,
347 jobject obj)
348 {
349 kstat_ctl_t *kctl;
350
351 kctl = (kstat_ctl_t *)(uintptr_t)(*env)->GetLongField(env, obj,
352 kstatctl_kctl_fieldid);
353
354 (void) kstat_chain_update(kctl);
355 }
356
357 /*
358 * Cache class, method, and field IDs.
359 */
360 /*ARGSUSED*/
361 JNIEXPORT void JNICALL
Java_com_sun_solaris_service_kstat_KstatCtl_init(JNIEnv * env,jclass clazz)362 Java_com_sun_solaris_service_kstat_KstatCtl_init(JNIEnv *env, jclass clazz)
363 {
364 jclass doubleclass_lref;
365 jclass hrtimeclass_lref;
366 jclass kstatclass_lref;
367 jclass kstatctlclass_lref;
368 jclass longclass_lref;
369 jclass ui64class_lref;
370
371 if (!(doubleclass_lref = (*env)->FindClass(env, DOUBLE_CLASS_DESC)))
372 return; /* exception thrown */
373 if (!(doubleclass = (*env)->NewGlobalRef(env, doubleclass_lref)))
374 return; /* exception thrown */
375 if (!(doublecons_mid = (*env)->GetMethodID(env, doubleclass, "<init>",
376 "(D)V")))
377 return; /* exception thrown */
378
379 if (!(hrtimeclass_lref = (*env)->FindClass(env, HRTIME_CLASS_DESC)))
380 return; /* exception thrown */
381 if (!(hrtimeclass = (*env)->NewGlobalRef(env, hrtimeclass_lref)))
382 return; /* exception thrown */
383 if (!(hrtimecons_mid = (*env)->GetMethodID(env, hrtimeclass, "<init>",
384 "(" CLASS_FIELD_DESC(UI64_CLASS_DESC) ")V")))
385 return; /* exception thrown */
386
387 if (!(kstatclass_lref = (*env)->FindClass(env, KSTAT_CLASS_DESC)))
388 return; /* exception thrown */
389 if (!(kstatclass = (*env)->NewGlobalRef(env, kstatclass_lref)))
390 return; /* exception thrown */
391 if (!(kstatcons_mid = (*env)->GetMethodID(env, kstatclass, "<init>",
392 "(JJ)V")))
393 return; /* exception thrown */
394 if (!(kstat_kctl_fieldid = (*env)->GetFieldID(env, kstatclass, "kctl",
395 "J")))
396 return; /* exception thrown */
397 if (!(kstat_ksp_fieldid = (*env)->GetFieldID(env, kstatclass, "ksp",
398 "J")))
399 return; /* exception thrown */
400
401 if (!(kstatctlclass_lref = (*env)->FindClass(env, KSTATCTL_CLASS_DESC)))
402 return; /* exception thrown */
403 if (!(kstatctlclass = (*env)->NewGlobalRef(env, kstatctlclass_lref)))
404 return; /* exception thrown */
405 if (!(kstatctl_kctl_fieldid = (*env)->GetFieldID(env, kstatctlclass,
406 "kctl", "J")))
407 return; /* exception thrown */
408
409 if (!(longclass_lref = (*env)->FindClass(env, LONG_CLASS_DESC)))
410 return; /* exception thrown */
411 if (!(longclass = (*env)->NewGlobalRef(env, longclass_lref)))
412 return; /* exception thrown */
413 if (!(longcons_mid = (*env)->GetMethodID(env, longclass, "<init>",
414 "(J)V")))
415 return; /* exception thrown */
416
417 if (!(ui64class_lref = (*env)->FindClass(env, UI64_CLASS_DESC)))
418 return; /* exception thrown */
419 if (!(ui64class = (*env)->NewGlobalRef(env, ui64class_lref)))
420 return; /* exception thrown */
421 ui64cons_mid = (*env)->GetMethodID(env, ui64class, "<init>", "([B)V");
422 }
423