xref: /titanic_50/usr/src/lib/libdtrace_jni/common/dtj_consume.c (revision 0173c38a73f34277e0c97a19fedfd25d81ba8380)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 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 <stdio.h>
30 #include <ctype.h>
31 #include <limits.h>
32 #include <errno.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <strings.h>
36 #include <sys/wait.h>
37 #include <limits.h>
38 #include <signal.h>
39 #include <libproc.h>
40 #include <pthread.h>
41 #include <dtrace_jni.h>
42 
43 /*
44  * Implements the work done in the running consumer loop.  The native Java
45  * methods (JNI layer) are implemented in dtrace_jni.c.
46  */
47 
48 /* Record handler passed to dtrace_work() */
49 static int dtj_chewrec(const dtrace_probedata_t *, const dtrace_recdesc_t *,
50     void *);
51 /* Probe data handler passed to dtrace_work() */
52 static int dtj_chew(const dtrace_probedata_t *, void *);
53 
54 /* Processes requests from LocalConsumer enqueued during dtrace_sleep() */
55 static dtj_status_t dtj_process_requests(dtj_java_consumer_t *);
56 
57 /*
58  * Callback handlers set in dtj_set_callback_handlers(), called from libdtrace
59  * in the consumer loop (from dtrace_work())
60  */
61 static int dtj_drophandler(const dtrace_dropdata_t *, void *);
62 static int dtj_errhandler(const dtrace_errdata_t *, void *);
63 static void dtj_prochandler(struct ps_prochandle *, const char *, void *);
64 static int dtj_setopthandler(const dtrace_setoptdata_t *, void *);
65 /*
66  * Buffered output handler called from libdtrace in both the consumer loop (from
67  * dtrace_work()) and the get_aggregate() function (from
68  * dtrace_aggregate_print()).
69  */
70 static int dtj_bufhandler(const dtrace_bufdata_t *, void *);
71 
72 /* Conversion of libdtrace data into Java Objects */
73 static jobject dtj_recdata(dtj_java_consumer_t *, uint32_t, caddr_t);
74 static jobject dtj_bytedata(JNIEnv *, uint32_t, caddr_t);
75 static jobject dtj_new_stack_record(const caddr_t, const dtrace_recdesc_t *,
76     dtj_java_consumer_t *);
77 static jobject dtj_new_probedata_stack_record(const dtrace_probedata_t *,
78     const dtrace_recdesc_t *, dtj_java_consumer_t *);
79 /* Aggregation data */
80 static jobject dtj_new_tuple_stack_record(const dtrace_aggdata_t *,
81     const dtrace_recdesc_t *, const char *, dtj_java_consumer_t *);
82 static jobject dtj_new_distribution(const dtrace_aggdata_t *,
83     const dtrace_recdesc_t *, dtj_java_consumer_t *);
84 static jobject dtj_new_aggval(dtj_java_consumer_t *, const dtrace_aggdata_t *,
85     const dtrace_recdesc_t *);
86 static int64_t dtj_average(caddr_t, uint64_t);
87 static int64_t dtj_avg_total(caddr_t, uint64_t);
88 static int64_t dtj_avg_count(caddr_t);
89 
90 /* Aggregation functions */
91 static void dtj_aggwalk_init(dtj_java_consumer_t *);
92 static int dtj_agghandler(const dtrace_bufdata_t *, dtj_java_consumer_t *);
93 static boolean_t dtj_is_included(const dtrace_aggdata_t *,
94     dtj_java_consumer_t *);
95 static void dtj_attach_frames(dtj_java_consumer_t *, jobject,
96     jobjectArray);
97 static boolean_t dtj_is_stack_action(dtrace_actkind_t);
98 static int dtj_clear(const dtrace_aggdata_t *, void *);
99 
100 /*
101  * The consumer loop needs to protect calls to libdtrace functions with a global
102  * lock.  JNI native method calls in dtrace_jni.c are already protected and do
103  * not need this function.
104  */
105 dtj_status_t
106 dtj_get_dtrace_error(dtj_java_consumer_t *jc, dtj_error_t *e)
107 {
108 	JNIEnv *jenv = jc->dtjj_jenv;
109 	dtrace_hdl_t *dtp = jc->dtjj_consumer->dtjc_dtp;
110 
111 	/* Grab global lock */
112 	(*jenv)->MonitorEnter(jenv, g_caller_jc);
113 	if ((*jenv)->ExceptionCheck(jenv)) {
114 		WRAP_EXCEPTION(jenv);
115 		return (DTJ_ERR);
116 	}
117 	e->dtje_number = dtrace_errno(dtp);
118 	e->dtje_message = dtrace_errmsg(dtp, e->dtje_number);
119 	(*jenv)->MonitorExit(jenv, g_caller_jc);
120 	if ((*jenv)->ExceptionCheck(jenv)) {
121 		WRAP_EXCEPTION(jenv);
122 		return (DTJ_ERR);
123 	}
124 	return (DTJ_OK);
125 }
126 
127 /*
128  * Protected by global lock (LocalConsumer.class) that protects call to
129  * Java_org_opensolaris_os_dtrace_LocalConsumer__1go()
130  */
131 dtj_status_t
132 dtj_set_callback_handlers(dtj_java_consumer_t *jc)
133 {
134 	dtrace_hdl_t *dtp = jc->dtjj_consumer->dtjc_dtp;
135 	dtrace_optval_t optval;
136 
137 	/*
138 	 * The user argument to the bufhandler is the lookup key used to obtain
139 	 * the thread-specific java consumer.  The java consumer contains JNI
140 	 * state specific to either the consumer loop or the getAggregate()
141 	 * call.
142 	 */
143 	if (dtrace_handle_buffered(dtp, &dtj_bufhandler, NULL) == -1) {
144 		dtj_throw_dtrace_exception(jc,
145 		    "failed to establish buffered handler: %s",
146 		    dtrace_errmsg(dtp, dtrace_errno(dtp)));
147 		return (DTJ_ERR);
148 	}
149 
150 	if (dtrace_handle_drop(dtp, &dtj_drophandler, NULL) == -1) {
151 		dtj_throw_dtrace_exception(jc,
152 		    "failed to establish drop handler: %s",
153 		    dtrace_errmsg(dtp, dtrace_errno(dtp)));
154 		return (DTJ_ERR);
155 	}
156 
157 	if (dtrace_handle_err(dtp, &dtj_errhandler, NULL) == -1) {
158 		dtj_throw_dtrace_exception(jc,
159 		    "failed to establish error handler: %s",
160 		    dtrace_errmsg(dtp, dtrace_errno(dtp)));
161 		return (DTJ_ERR);
162 	}
163 
164 	if (dtrace_handle_proc(dtp, &dtj_prochandler, NULL) == -1) {
165 		dtj_throw_dtrace_exception(jc,
166 		    "failed to establish proc handler: %s",
167 		    dtrace_errmsg(dtp, dtrace_errno(dtp)));
168 		return (DTJ_ERR);
169 	}
170 
171 	if (dtrace_getopt(dtp, "flowindent", &optval) == -1) {
172 		dtj_throw_dtrace_exception(jc,
173 		    "couldn't get option %s: %s", "flowindent",
174 		    dtrace_errmsg(dtp, dtrace_errno(dtp)));
175 		return (DTJ_ERR);
176 	}
177 
178 	jc->dtjj_consumer->dtjc_flow = (optval != DTRACEOPT_UNSET);
179 
180 	if (dtrace_handle_setopt(dtp, &dtj_setopthandler, NULL) == -1) {
181 		dtj_throw_dtrace_exception(jc,
182 		    "failed to establish setopt handler: %s",
183 		    dtrace_errmsg(dtp, dtrace_errno(dtp)));
184 		return (DTJ_ERR);
185 	}
186 
187 	return (DTJ_OK);
188 }
189 
190 static int
191 /* ARGSUSED */
192 dtj_drophandler(const dtrace_dropdata_t *data, void *arg)
193 {
194 	dtj_java_consumer_t *jc;
195 	JNIEnv *jenv;
196 
197 	const char *dropkind;
198 
199 	jstring msg = NULL;
200 	jstring kind = NULL;
201 	jobject drop = NULL;
202 
203 	jc = pthread_getspecific(g_dtj_consumer_key);
204 	jenv = jc->dtjj_jenv;
205 
206 	msg = dtj_NewStringNative(jenv, data->dtdda_msg);
207 	if ((*jenv)->ExceptionCheck(jenv)) {
208 		return (DTRACE_HANDLE_ABORT);
209 	}
210 	switch (data->dtdda_kind) {
211 	case DTRACEDROP_PRINCIPAL:
212 		dropkind = "PRINCIPAL";
213 		break;
214 	case DTRACEDROP_AGGREGATION:
215 		dropkind = "AGGREGATION";
216 		break;
217 	case DTRACEDROP_DYNAMIC:
218 		dropkind = "DYNAMIC";
219 		break;
220 	case DTRACEDROP_DYNRINSE:
221 		dropkind = "DYNRINSE";
222 		break;
223 	case DTRACEDROP_DYNDIRTY:
224 		dropkind = "DYNDIRTY";
225 		break;
226 	case DTRACEDROP_SPEC:
227 		dropkind = "SPEC";
228 		break;
229 	case DTRACEDROP_SPECBUSY:
230 		dropkind = "SPECBUSY";
231 		break;
232 	case DTRACEDROP_SPECUNAVAIL:
233 		dropkind = "SPECUNAVAIL";
234 		break;
235 	case DTRACEDROP_STKSTROVERFLOW:
236 		dropkind = "STKSTROVERFLOW";
237 		break;
238 	case DTRACEDROP_DBLERROR:
239 		dropkind = "DBLERROR";
240 		break;
241 	default:
242 		dropkind = "UNKNOWN";
243 	}
244 	kind = (*jenv)->NewStringUTF(jenv, dropkind);
245 	if ((*jenv)->ExceptionCheck(jenv)) {
246 		(*jenv)->DeleteLocalRef(jenv, msg);
247 		return (DTRACE_HANDLE_ABORT);
248 	}
249 	drop = (*jenv)->NewObject(jenv, g_drop_jc, g_dropinit_jm,
250 	    data->dtdda_cpu, kind, data->dtdda_drops, data->dtdda_total, msg);
251 	(*jenv)->DeleteLocalRef(jenv, kind);
252 	(*jenv)->DeleteLocalRef(jenv, msg);
253 	if ((*jenv)->ExceptionCheck(jenv)) {
254 		return (DTRACE_HANDLE_ABORT);
255 	}
256 	(*jenv)->CallVoidMethod(jenv, jc->dtjj_caller, g_drop_jm, drop);
257 	(*jenv)->DeleteLocalRef(jenv, drop);
258 	if ((*jenv)->ExceptionCheck(jenv)) {
259 		return (DTRACE_HANDLE_ABORT);
260 	}
261 
262 	return (DTRACE_HANDLE_OK);
263 }
264 
265 static int
266 /* ARGSUSED */
267 dtj_errhandler(const dtrace_errdata_t *data, void *arg)
268 {
269 	dtj_java_consumer_t *jc;
270 	JNIEnv *jenv;
271 
272 	const char *f;
273 	int64_t addr;
274 
275 	jobject probe = NULL;
276 	jstring fault = NULL;
277 	jstring msg = NULL;
278 	jobject error = NULL;
279 
280 	jc = pthread_getspecific(g_dtj_consumer_key);
281 	jenv = jc->dtjj_jenv;
282 
283 	probe = dtj_new_probedesc(jc, data->dteda_pdesc);
284 	if (!probe) {
285 		return (DTRACE_HANDLE_ABORT);
286 	}
287 	f = dtj_get_fault_name(data->dteda_fault);
288 	if (f) {
289 		fault = (*jenv)->NewStringUTF(jenv, f);
290 		if ((*jenv)->ExceptionCheck(jenv)) {
291 			(*jenv)->DeleteLocalRef(jenv, probe);
292 			return (DTRACE_HANDLE_ABORT);
293 		}
294 	}
295 	switch (data->dteda_fault) {
296 	case DTRACEFLT_BADADDR:
297 	case DTRACEFLT_BADALIGN:
298 		addr = data->dteda_addr;
299 		break;
300 	default:
301 		addr = -1;
302 	}
303 	msg = dtj_NewStringNative(jenv, data->dteda_msg);
304 	if ((*jenv)->ExceptionCheck(jenv)) {
305 		(*jenv)->DeleteLocalRef(jenv, probe);
306 		(*jenv)->DeleteLocalRef(jenv, fault);
307 		return (DTRACE_HANDLE_ABORT);
308 	}
309 	error = (*jenv)->NewObject(jenv, g_error_jc, g_errinit_jm,
310 	    probe,
311 	    data->dteda_edesc->dtepd_epid,
312 	    data->dteda_cpu,
313 	    data->dteda_action,
314 	    data->dteda_offset,
315 	    fault, addr, msg);
316 	(*jenv)->DeleteLocalRef(jenv, msg);
317 	(*jenv)->DeleteLocalRef(jenv, fault);
318 	(*jenv)->DeleteLocalRef(jenv, probe);
319 	if ((*jenv)->ExceptionCheck(jenv)) {
320 		return (DTRACE_HANDLE_ABORT);
321 	}
322 	(*jenv)->CallVoidMethod(jenv, jc->dtjj_caller, g_error_jm, error);
323 	(*jenv)->DeleteLocalRef(jenv, error);
324 	if ((*jenv)->ExceptionCheck(jenv)) {
325 		return (DTRACE_HANDLE_ABORT);
326 	}
327 
328 	return (DTRACE_HANDLE_OK);
329 }
330 
331 /*
332  * Since the function signature does not allow us to return an abort signal, we
333  * need to temporarily clear any pending exception before returning, since
334  * without the abort we can't guarantee that the exception will be checked in
335  * time to prevent invalid JNI function calls.
336  */
337 static void
338 /* ARGSUSED */
339 dtj_prochandler(struct ps_prochandle *P, const char *msg, void *arg)
340 {
341 	dtj_java_consumer_t *jc;
342 	JNIEnv *jenv;
343 
344 	const psinfo_t *prp = Ppsinfo(P);
345 	int pid = Pstatus(P)->pr_pid;
346 	int signal = -1;
347 	char signame[SIG2STR_MAX];
348 	const char *statusname;
349 	int exit = INT_MAX; /* invalid initial status */
350 
351 	jstring status = NULL;
352 	jstring signalName = NULL;
353 	jstring message = NULL;
354 	jobject process = NULL;
355 
356 	jc = pthread_getspecific(g_dtj_consumer_key);
357 	jenv = jc->dtjj_jenv;
358 
359 	switch (Pstate(P)) {
360 	case PS_RUN:
361 		statusname = "RUN";
362 		break;
363 	case PS_STOP:
364 		statusname = "STOP";
365 		break;
366 	case PS_UNDEAD:
367 		statusname = "UNDEAD";
368 		if (prp != NULL) {
369 			exit = WEXITSTATUS(prp->pr_wstat);
370 		}
371 		if (prp != NULL && WIFSIGNALED(prp->pr_wstat)) {
372 			signal = WTERMSIG(prp->pr_wstat);
373 			(void) proc_signame(signal, signame, sizeof (signame));
374 			signalName = (*jenv)->NewStringUTF(jenv, signame);
375 			if ((*jenv)->ExceptionCheck(jenv)) {
376 				goto proc_end;
377 			}
378 		}
379 		++jc->dtjj_consumer->dtjc_procs_ended;
380 		break;
381 	case PS_LOST:
382 		statusname = "LOST";
383 		++jc->dtjj_consumer->dtjc_procs_ended;
384 		break;
385 	case PS_DEAD:
386 		/*
387 		 * PS_DEAD not handled by dtrace.c prochandler, still this is a
388 		 * case of process termination and it can't hurt to handle it.
389 		 */
390 		statusname = "DEAD";
391 		++jc->dtjj_consumer->dtjc_procs_ended;
392 		break;
393 	default:
394 		/*
395 		 * Unexpected, but erring on the side of tolerance by not
396 		 * crashing the consumer.  Failure to notify listeners of
397 		 * process state not handled by the dtrace.c prochandler does
398 		 * not seem serious.
399 		 */
400 		return;
401 	}
402 
403 	status = (*jenv)->NewStringUTF(jenv, statusname);
404 	if ((*jenv)->ExceptionCheck(jenv)) {
405 		(*jenv)->DeleteLocalRef(jenv, signalName);
406 		goto proc_end;
407 	}
408 	if (msg) {
409 		message = dtj_NewStringNative(jenv, msg);
410 		if (!message) {
411 			(*jenv)->DeleteLocalRef(jenv, status);
412 			(*jenv)->DeleteLocalRef(jenv, signalName);
413 			goto proc_end;
414 		}
415 	}
416 	process = (*jenv)->NewObject(jenv, g_process_jc, g_procinit_jm,
417 	    pid, status, signal, signalName, NULL, message);
418 	(*jenv)->DeleteLocalRef(jenv, status);
419 	(*jenv)->DeleteLocalRef(jenv, signalName);
420 	(*jenv)->DeleteLocalRef(jenv, message);
421 	if ((*jenv)->ExceptionCheck(jenv)) {
422 		goto proc_end;
423 	}
424 	if (exit != INT_MAX) {
425 		/* valid exit status */
426 		(*jenv)->CallVoidMethod(jenv, process, g_procexit_jm, exit);
427 		if ((*jenv)->ExceptionCheck(jenv)) {
428 			(*jenv)->DeleteLocalRef(jenv, process);
429 			goto proc_end;
430 		}
431 	}
432 	(*jenv)->CallVoidMethod(jenv, jc->dtjj_caller, g_proc_jm, process);
433 	(*jenv)->DeleteLocalRef(jenv, process);
434 
435 proc_end:
436 
437 	if ((*jenv)->ExceptionCheck(jenv)) {
438 		/*
439 		 * Save the exception so we can rethrow it later when it's safe.
440 		 */
441 		if (!jc->dtjj_exception) {
442 			jthrowable e = (*jenv)->ExceptionOccurred(jenv);
443 			jc->dtjj_exception = e;
444 		}
445 		(*jenv)->ExceptionClear(jenv);
446 	}
447 }
448 
449 static int
450 /* ARGSUSED */
451 dtj_setopthandler(const dtrace_setoptdata_t *data, void *arg)
452 {
453 	dtj_java_consumer_t *jc;
454 
455 	jc = pthread_getspecific(g_dtj_consumer_key);
456 	if (strcmp(data->dtsda_option, "flowindent") == 0) {
457 		jc->dtjj_consumer->dtjc_flow =
458 		    (data->dtsda_newval != DTRACEOPT_UNSET);
459 	}
460 	return (DTRACE_HANDLE_OK);
461 }
462 
463 /*
464  * Most of this function lifted from libdtrace/common/dt_consume.c
465  * dt_print_bytes().
466  */
467 static jobject
468 dtj_bytedata(JNIEnv *jenv, uint32_t nbytes, caddr_t addr)
469 {
470 	/*
471 	 * If the byte stream is a series of printable characters, followed by
472 	 * a terminating byte, we print it out as a string.  Otherwise, we
473 	 * assume that it's something else and just print the bytes.
474 	 */
475 	int i, j;
476 	char *c = addr;
477 
478 	jobject jobj = NULL; /* return value */
479 
480 	if (nbytes == 0) {
481 		return ((*jenv)->NewStringUTF(jenv, ""));
482 	}
483 
484 	for (i = 0; i < nbytes; i++) {
485 		/*
486 		 * We define a "printable character" to be one for which
487 		 * isprint(3C) returns non-zero, isspace(3C) returns non-zero,
488 		 * or a character which is either backspace or the bell.
489 		 * Backspace and the bell are regrettably special because
490 		 * they fail the first two tests -- and yet they are entirely
491 		 * printable.  These are the only two control characters that
492 		 * have meaning for the terminal and for which isprint(3C) and
493 		 * isspace(3C) return 0.
494 		 */
495 		if (isprint(c[i]) || isspace(c[i]) ||
496 		    c[i] == '\b' || c[i] == '\a')
497 			continue;
498 
499 		if (c[i] == '\0' && i > 0) {
500 			/*
501 			 * This looks like it might be a string.  Before we
502 			 * assume that it is indeed a string, check the
503 			 * remainder of the byte range; if it contains
504 			 * additional non-nul characters, we'll assume that
505 			 * it's a binary stream that just happens to look like
506 			 * a string.
507 			 */
508 			for (j = i + 1; j < nbytes; j++) {
509 				if (c[j] != '\0')
510 					break;
511 			}
512 
513 			if (j != nbytes)
514 				break;
515 
516 			/* It's a string */
517 			return (dtj_NewStringNative(jenv, (char *)addr));
518 		}
519 
520 		break;
521 	}
522 
523 	if (i == nbytes) {
524 		/*
525 		 * The byte range is all printable characters, but there is
526 		 * no trailing nul byte.  We'll assume that it's a string.
527 		 */
528 		char *s = malloc(nbytes + 1);
529 		if (!s) {
530 			dtj_throw_out_of_memory(jenv,
531 			    "failed to allocate string value");
532 			return (NULL);
533 		}
534 		(void) strncpy(s, c, nbytes);
535 		s[nbytes] = '\0';
536 		jobj = dtj_NewStringNative(jenv, s);
537 		free(s);
538 		return (jobj);
539 	}
540 
541 	/* return byte array */
542 	jobj = (*jenv)->NewByteArray(jenv, nbytes);
543 	if ((*jenv)->ExceptionCheck(jenv)) {
544 		return (NULL);
545 	}
546 	(*jenv)->SetByteArrayRegion(jenv, (jbyteArray)jobj, 0, nbytes,
547 	    (const jbyte *)c);
548 	if ((*jenv)->ExceptionCheck(jenv)) {
549 		WRAP_EXCEPTION(jenv);
550 		(*jenv)->DeleteLocalRef(jenv, jobj);
551 		return (NULL);
552 	}
553 	return (jobj);
554 }
555 
556 /*
557  * Return NULL if memory could not be allocated (OutOfMemoryError is thrown in
558  * that case).
559  */
560 static jobject
561 dtj_recdata(dtj_java_consumer_t *jc, uint32_t size, caddr_t addr)
562 {
563 	JNIEnv *jenv = jc->dtjj_jenv;
564 	jobject jobj;
565 
566 	switch (size) {
567 	case 1:
568 		jobj = (*jenv)->NewObject(jenv, g_byte_jc,
569 		    g_byteinit_jm, *((char *)addr));
570 		break;
571 	case 2:
572 		jobj = (*jenv)->NewObject(jenv, g_short_jc,
573 		    /* LINTED - alignment */
574 		    g_shortinit_jm, *((int16_t *)addr));
575 		break;
576 	case 4:
577 		jobj = (*jenv)->NewObject(jenv, g_int_jc,
578 		    /* LINTED - alignment */
579 		    g_intinit_jm, *((int32_t *)addr));
580 		break;
581 	case 8:
582 		jobj = (*jenv)->NewObject(jenv, g_long_jc,
583 		    /* LINTED - alignment */
584 		    g_longinit_jm, *((int64_t *)addr));
585 		break;
586 	default:
587 		jobj = dtj_bytedata(jenv, size, addr);
588 		break;
589 	}
590 
591 	return (jobj);
592 }
593 
594 /*
595  * This is the record handling function passed to dtrace_work().  It differs
596  * from the bufhandler registered with dtrace_handle_buffered() as follows:
597  *
598  * 1.  It does not have access to libdtrace formatted output.
599  * 2.  It is called once for every D program statement, not for every
600  *     output-producing D action or aggregation record.  A statement may be a
601  *     variable assignment, having no size and producing no output.
602  * 3.  It is called for the D exit() action; the bufhandler is not.
603  * 4.  In response to the printa() action, it is called with a record having an
604  *     action of type DTRACEACT_PRINTA.  The bufhandler never sees that action
605  *     value.  It only sees the output-producing aggregation records.
606  * 5.  It is called with a NULL record at the end of each probedata.
607  */
608 static int
609 dtj_chewrec(const dtrace_probedata_t *data, const dtrace_recdesc_t *rec,
610     void *arg)
611 {
612 	dtj_java_consumer_t *jc = arg;
613 	JNIEnv *jenv = jc->dtjj_jenv;
614 
615 	const dtrace_eprobedesc_t *edesc = data->dtpda_edesc;
616 	dtrace_actkind_t act;
617 	int r;
618 
619 	/*
620 	 * Update the record index to that of the current record, or to that of
621 	 * the last record if rec is NULL (signalling end of probe data).
622 	 */
623 	if (rec == NULL) {
624 		r = edesc->dtepd_nrecs; /* end of probe data */
625 	} else {
626 		/*
627 		 * This record handler is called once for the printf() action,
628 		 * but there may be multiple records in the probedata
629 		 * corresponding to the unformatted elements of that printf().
630 		 * We don't know ahead of time how many probedata records
631 		 * libdtrace will consume to produce output for one printf()
632 		 * action, so we look back at the previous call to dtj_chewrec()
633 		 * to see how many probedata records were consumed.  All
634 		 * non-null elements in the range from the previous record index
635 		 * up to and not including the current record index are assumed
636 		 * to be unformatted printf() elements, and will be attached to
637 		 * the PrintfRecord from the previous call.  A null element in
638 		 * that range is the result of a D program statement preceding
639 		 * the printf() that is not a D action.  These generate
640 		 * probedata records accounted for by the null placeholder, but
641 		 * do not advance the probedata offset and are not part of the
642 		 * subsequent printf().
643 		 *
644 		 * If rec->dtrd_size == 0, the record represents a D program
645 		 * statement that is not a D action.  It has no size and does
646 		 * not advance the offset in the probedata.  Handle it normally
647 		 * without special-casing or premature return, since in all
648 		 * cases we look at the previous record later in this function.
649 		 */
650 		for (r = jc->dtjj_consumer->dtjc_probedata_rec_i;
651 		    ((r < edesc->dtepd_nrecs) &&
652 		    (edesc->dtepd_rec[r].dtrd_offset < rec->dtrd_offset));
653 		    ++r) {
654 		}
655 	}
656 
657 	/*
658 	 * Attach the Java representations of the libdtrace data elements
659 	 * pertaining to the previous call to this record handler to the
660 	 * previous Java Record.  (All data elements belonging to the current
661 	 * probedata are added to a single list by the probedata consumer
662 	 * function dtj_chew() before this record consumer function is ever
663 	 * called.) For example, if the previous Record was generated by the
664 	 * printf() action, and dtj_chew() listed 3 records for its 3
665 	 * unformatted elements, those 3 libdtrace records comprise 1
666 	 * PrintfRecord.  Note that we cannot know how many data elements apply
667 	 * to the current rec until we find out the data index where the next
668 	 * rec starts.  (The knowledge of how many probedata records to consume
669 	 * is private to libdtrace.)
670 	 */
671 	if (jc->dtjj_consumer->dtjc_probedata_act == DTRACEACT_PRINTF) {
672 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
673 		    g_pdataattach_jm,
674 		    jc->dtjj_consumer->dtjc_probedata_rec_i, r - 1);
675 		if ((*jenv)->ExceptionCheck(jenv)) {
676 			WRAP_EXCEPTION(jenv);
677 			return (DTRACE_CONSUME_ABORT);
678 		}
679 	}
680 
681 	if (rec == NULL) {
682 		/*
683 		 * End of probe data.  Notify listeners of the new ProbeData
684 		 * instance.
685 		 */
686 		if (jc->dtjj_probedata) {
687 			/* previous probedata */
688 			(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
689 			    g_pdataclear_jm);
690 			if ((*jenv)->ExceptionCheck(jenv)) {
691 				WRAP_EXCEPTION(jenv);
692 				return (DTRACE_CONSUME_ABORT);
693 			}
694 			(*jenv)->CallVoidMethod(jenv, jc->dtjj_caller,
695 			    g_pdatanext_jm, jc->dtjj_probedata);
696 			(*jenv)->DeleteLocalRef(jenv, jc->dtjj_probedata);
697 			jc->dtjj_probedata = NULL;
698 			if ((*jenv)->ExceptionCheck(jenv)) {
699 				/*
700 				 * Do not wrap exception thrown from
701 				 * ConsumerListener.
702 				 */
703 				return (DTRACE_CONSUME_ABORT);
704 			}
705 		}
706 		(*jenv)->DeleteLocalRef(jenv, jc->dtjj_printa_buffer);
707 		jc->dtjj_printa_buffer = NULL;
708 		return (DTRACE_CONSUME_NEXT);
709 	}
710 
711 	act = rec->dtrd_action;
712 
713 	/* Set previous record action and data index to current */
714 	jc->dtjj_consumer->dtjc_probedata_act = act;
715 	jc->dtjj_consumer->dtjc_probedata_rec_i = r;
716 
717 	switch (act) {
718 	case DTRACEACT_DIFEXPR:
719 		if (rec->dtrd_size == 0) {
720 			/*
721 			 * The current record is not a D action, but a program
722 			 * statement such as a variable assignment, not to be
723 			 * confused with the trace() action.
724 			 */
725 			break;
726 		}
727 		/*
728 		 * Add a Record for the trace() action that references the
729 		 * native probedata element listed at the current index.
730 		 */
731 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
732 		    g_pdataadd_trace_jm,
733 		    jc->dtjj_consumer->dtjc_probedata_rec_i);
734 		if ((*jenv)->ExceptionCheck(jenv)) {
735 			WRAP_EXCEPTION(jenv);
736 			return (DTRACE_CONSUME_ABORT);
737 		}
738 		break;
739 	case DTRACEACT_PRINTF:
740 		/*
741 		 * Just add an empty PrintfRecord for now.  We'll attach the
742 		 * unformatted elements in a subsequent call to this function.
743 		 * (We don't know how many there will be.)
744 		 */
745 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
746 		    g_pdataadd_printf_jm);
747 		if ((*jenv)->ExceptionCheck(jenv)) {
748 			WRAP_EXCEPTION(jenv);
749 			return (DTRACE_CONSUME_ABORT);
750 		}
751 		/* defer formatted string to dtj_bufhandler() */
752 		break;
753 	case DTRACEACT_PRINTA: {
754 		jobject jbuf = NULL;
755 
756 		dtj_aggwalk_init(jc);
757 		if ((*jenv)->ExceptionCheck(jenv)) {
758 			WRAP_EXCEPTION(jenv);
759 			return (DTRACE_CONSUME_ABORT);
760 		}
761 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
762 		    g_pdataadd_printa_jm,
763 		    jc->dtjj_consumer->dtjc_printa_snaptime,
764 		    (rec->dtrd_format != 0));
765 		if ((*jenv)->ExceptionCheck(jenv)) {
766 			WRAP_EXCEPTION(jenv);
767 			return (DTRACE_CONSUME_ABORT);
768 		}
769 		if (jc->dtjj_printa_buffer == NULL) {
770 			/*
771 			 * Create a StringBuffer to collect the pieces of
772 			 * formatted output into a single String.
773 			 */
774 			jbuf = (*jenv)->NewObject(jenv, g_buf_jc,
775 			    g_bufinit_jm);
776 			if (!jbuf) {
777 				/* OutOfMemoryError pending */
778 				return (DTRACE_CONSUME_ABORT);
779 			}
780 			jc->dtjj_printa_buffer = jbuf;
781 		}
782 		/* defer aggregation records to dtj_bufhandler() */
783 		break;
784 	}
785 	case DTRACEACT_EXIT:
786 		/*
787 		 * Add a Record for the exit() action that references the native
788 		 * probedata element listed at the current index.
789 		 */
790 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
791 		    g_pdataadd_exit_jm,
792 		    jc->dtjj_consumer->dtjc_probedata_rec_i);
793 		if ((*jenv)->ExceptionCheck(jenv)) {
794 			WRAP_EXCEPTION(jenv);
795 			return (DTRACE_CONSUME_ABORT);
796 		}
797 		return (DTRACE_CONSUME_NEXT);
798 	}
799 
800 	return (DTRACE_CONSUME_THIS);
801 }
802 
803 /*
804  * This is the probe handling function passed to dtrace_work().  It is is called
805  * once every time a probe fires.  It is the first of all the callbacks for the
806  * current probe.  It is followed by multiple callbacks to dtj_chewrec(), one
807  * for each probedata record.  Each call to dtj_chewrec() is followed by zero or
808  * more callbacks to the bufhandler, one for each output-producing action or
809  * aggregation record.
810  */
811 static int
812 dtj_chew(const dtrace_probedata_t *data, void *arg)
813 {
814 	dtj_java_consumer_t *jc = arg;
815 	JNIEnv *jenv = jc->dtjj_jenv;
816 
817 	dtrace_eprobedesc_t *edesc;
818 	dtrace_probedesc_t *pdesc;
819 	dtrace_recdesc_t *rec;
820 	int epid;
821 	int cpu;
822 	int nrecs;
823 	int i;
824 
825 	jobject jpdata = NULL;
826 	jobject jprobe = NULL;
827 	jobject jflow = NULL;
828 	jstring jflowkind = NULL;
829 	jobject jobj = NULL;
830 
831 	edesc = data->dtpda_edesc;
832 	epid = (int)edesc->dtepd_epid;
833 	pdesc = data->dtpda_pdesc;
834 	cpu = (int)data->dtpda_cpu;
835 	if ((jprobe = dtj_new_probedesc(jc, pdesc)) == NULL) {
836 		/* java exception pending */
837 		return (DTRACE_CONSUME_ABORT);
838 	}
839 	nrecs = edesc->dtepd_nrecs;
840 
841 	if (jc->dtjj_consumer->dtjc_flow) {
842 		const char *kind;
843 		switch (data->dtpda_flow) {
844 		case DTRACEFLOW_ENTRY:
845 			kind = "ENTRY";
846 			break;
847 		case DTRACEFLOW_RETURN:
848 			kind = "RETURN";
849 			break;
850 		case DTRACEFLOW_NONE:
851 			kind = "NONE";
852 			break;
853 		default:
854 			kind = NULL;
855 		}
856 		if (kind != NULL) {
857 			int depth;
858 			jflowkind = (*jenv)->NewStringUTF(jenv, kind);
859 			if ((*jenv)->ExceptionCheck(jenv)) {
860 				WRAP_EXCEPTION(jenv);
861 				(*jenv)->DeleteLocalRef(jenv, jprobe);
862 				return (DTRACE_CONSUME_ABORT);
863 			}
864 			/*
865 			 * Use the knowledge that libdtrace indents 2 spaces per
866 			 * level in the call stack to calculate the depth.
867 			 */
868 			depth = (data->dtpda_indent / 2);
869 			jflow = (*jenv)->NewObject(jenv, g_flow_jc,
870 			    g_flowinit_jm, jflowkind, depth);
871 			(*jenv)->DeleteLocalRef(jenv, jflowkind);
872 			if ((*jenv)->ExceptionCheck(jenv)) {
873 				WRAP_EXCEPTION(jenv);
874 				(*jenv)->DeleteLocalRef(jenv, jprobe);
875 				return (DTRACE_CONSUME_ABORT);
876 			}
877 		}
878 	}
879 
880 	/* Create ProbeData instance */
881 	jpdata = (*jenv)->NewObject(jenv, g_pdata_jc, g_pdatainit_jm,
882 	    epid, cpu, jprobe, jflow, nrecs);
883 	(*jenv)->DeleteLocalRef(jenv, jprobe);
884 	(*jenv)->DeleteLocalRef(jenv, jflow);
885 	if ((*jenv)->ExceptionCheck(jenv)) {
886 		WRAP_EXCEPTION(jenv);
887 		return (DTRACE_CONSUME_ABORT);
888 	}
889 
890 	/*
891 	 * Populate the ProbeData list of Java data elements in advance so we
892 	 * don't need to peek back in the record handler at libdtrace records
893 	 * that have already been consumed.  In the Java API, each ProbeData
894 	 * Record is generated by one D action, while in the native libdtrace
895 	 * there may be more than one probedata record (each a single data
896 	 * element) per D action.  For example PrintfRecord has multiple
897 	 * unformatted elements, each represented by a native probedata record,
898 	 * but combined by the API into a single PrintfRecord.
899 	 */
900 	for (i = 0; i < nrecs; ++i) {
901 		rec = &edesc->dtepd_rec[i];
902 		/*
903 		 * A statement that is not a D action, such as assignment to a
904 		 * variable, has no size.  Add a NULL placeholder to the scratch
905 		 * list of Java probedata elements in that case.
906 		 */
907 		jobj = NULL; /* initialize object reference to null */
908 		if (rec->dtrd_size > 0) {
909 			if (dtj_is_stack_action(rec->dtrd_action)) {
910 				jobj = dtj_new_probedata_stack_record(data,
911 				    rec, jc);
912 			} else {
913 				jobj = dtj_recdata(jc, rec->dtrd_size,
914 				    (data->dtpda_data + rec->dtrd_offset));
915 			}
916 			if ((*jenv)->ExceptionCheck(jenv)) {
917 				WRAP_EXCEPTION(jenv);
918 				(*jenv)->DeleteLocalRef(jenv, jpdata);
919 				return (DTRACE_CONSUME_ABORT);
920 			}
921 		}
922 
923 		(*jenv)->CallVoidMethod(jenv, jpdata, g_pdataadd_jm, jobj);
924 		(*jenv)->DeleteLocalRef(jenv, jobj);
925 		if ((*jenv)->ExceptionCheck(jenv)) {
926 			WRAP_EXCEPTION(jenv);
927 			(*jenv)->DeleteLocalRef(jenv, jpdata);
928 			return (DTRACE_CONSUME_ABORT);
929 		}
930 	}
931 
932 	if (jc->dtjj_probedata != NULL) {
933 		dtj_throw_illegal_state(jenv, "unfinished probedata");
934 		WRAP_EXCEPTION(jenv);
935 		(*jenv)->DeleteLocalRef(jenv, jpdata);
936 		return (DTRACE_CONSUME_ABORT);
937 	}
938 	jc->dtjj_probedata = jpdata;
939 
940 	/* Initialize per-consumer probedata fields */
941 	jc->dtjj_consumer->dtjc_probedata_rec_i = 0;
942 	jc->dtjj_consumer->dtjc_probedata_act = DTRACEACT_NONE;
943 	dtj_aggwalk_init(jc);
944 	if ((*jenv)->ExceptionCheck(jenv)) {
945 		WRAP_EXCEPTION(jenv);
946 		return (DTRACE_CONSUME_ABORT);
947 	}
948 
949 	return (DTRACE_CONSUME_THIS);
950 }
951 
952 /*
953  * This is the buffered output handler registered with dtrace_handle_buffered().
954  * It's purpose is to make the output of the libdtrace print routines available
955  * to this API, without writing any of it to a file (such as stdout).  This is
956  * needed for the stack(), ustack(), and jstack() actions to get human-readable
957  * stack values, since there is no public function in libdtrace to convert stack
958  * values to strings.  It is also used to get the formatted output of the D
959  * printf() and printa() actions.
960  *
961  * The bufhandler is called once for each output-producing, non-aggregating D
962  * action, such as trace() or printf(), and once for each libdtrace aggregation
963  * record (whether in response to the D printa() action, or the Consumer
964  * getAggregate() method).  In the simple printa() case that takes one
965  * aggregation and does not specify a format string, there is one libdtrace
966  * record per tuple element plus one for the corresponding value.  The complete
967  * tuple/value pair becomes a single AggregationRecord exported by the API.
968  * When multiple aggregations are passed to printa(), each tuple is associated
969  * with a list of values, one from each aggregation.  If a printa() format
970  * string does not specify placeholders for every aggregation value and tuple
971  * member, callbacks for those values and tuple members are omitted (and the
972  * data is omitted from the resulting PrintaRecord).
973  *
974  * Notes to characterize some non-obvious bufhandler behavior:
975  *
976  * 1. dtj_bufhandler() is never called with bufdata->dtbda_recdesc->dtrd_action
977  * DTRACEACT_PRINTA.  That action only appears in the probedata consumer
978  * functions dtj_chew() and dtj_chewrec() before the bufhandler is called with
979  * subsequent aggregation records.
980  *
981  * 2. If printa() specifies a format string argument, then the bufhandler is
982  * called only for those elements of the tuple/value pair that are included in
983  * the format string.  If a stack() tuple member is omitted from the format
984  * string, its human-readable representation will not be available to this API,
985  * so the stack frame array is also omitted from the resulting
986  * AggregationRecord.  The bufhandler is also called once for each string of
987  * characters surrounding printa() format string placeholders.  For example,
988  * "  %@d %d stack%k\n" results in the following callbacks:
989  *  - two spaces
990  *  - the aggregation value
991  *  - a single space
992  *  - the first tuple member (an integer)
993  *  - " stack"
994  *  - the second tuple member (a stack)
995  *  - a newline
996  * A NULL record (NULL dtbda_recdesc) distinguishes a callback with interstitial
997  * format string characters from a callback with a tuple member or aggregation
998  * value (which has a non-NULL recdesc).  The contents are also distinguished by
999  * the following flags:
1000  *  DTRACE_BUFDATA_AGGKEY
1001  *  DTRACE_BUFDATA_AGGVAL
1002  *  DTRACE_BUFDATA_AGGFORMAT
1003  *  DTRACE_BUFDATA_AGGLAST
1004  *
1005  * There is no final callback with the complete formatted string, so that must
1006  * be concatenated across multiple callbacks to the bufhandler.
1007  *
1008  * 3. bufdata->dtbda_probe->dtpda_data may be overwritten by libdtrace print
1009  * routines.  The address is cached in the dtj_chew() function in case it is
1010  * needed in the bufhandler.
1011  */
1012 static int
1013 /* ARGSUSED */
1014 dtj_bufhandler(const dtrace_bufdata_t *bufdata, void *arg)
1015 {
1016 	dtj_java_consumer_t *jc;
1017 	JNIEnv *jenv;
1018 	const dtrace_recdesc_t *rec;
1019 	dtrace_actkind_t act = DTRACEACT_NONE;
1020 	const char *s;
1021 
1022 	jobject jstr = NULL;
1023 
1024 	/*
1025 	 * Get the thread-specific java consumer.  The bufhandler needs access
1026 	 * to the correct JNI state specific to either the consumer loop or the
1027 	 * getAggregate() call (aggregation snapshots can be requested
1028 	 * asynchronously while the consumer loop generates PrintaRecords in
1029 	 * dtrace_work() for ConsumerListeners).
1030 	 */
1031 	jc = pthread_getspecific(g_dtj_consumer_key);
1032 	jenv = jc->dtjj_jenv;
1033 
1034 	/*
1035 	 * In at least one corner case (printa with multiple aggregations and a
1036 	 * format string that does not completely specify the tuple), returning
1037 	 * DTRACE_HANDLE_ABORT does not prevent a subsequent callback to this
1038 	 * bufhandler.  This check ensures that the invalid call is ignored.
1039 	 */
1040 	if ((*jenv)->ExceptionCheck(jenv)) {
1041 		return (DTRACE_HANDLE_ABORT);
1042 	}
1043 
1044 	if (bufdata->dtbda_aggdata) {
1045 		return (dtj_agghandler(bufdata, jc));
1046 	}
1047 
1048 	s = bufdata->dtbda_buffered;
1049 	if (s == NULL) {
1050 		return (DTRACE_HANDLE_OK);
1051 	}
1052 
1053 	rec = bufdata->dtbda_recdesc;
1054 	if (rec) {
1055 		act = rec->dtrd_action;
1056 	}
1057 
1058 	switch (act) {
1059 	case DTRACEACT_DIFEXPR:
1060 		/* trace() action */
1061 		break;
1062 	case DTRACEACT_PRINTF:
1063 		/*
1064 		 * Only the formatted string was not available to dtj_chewrec(),
1065 		 * so we attach that now.
1066 		 */
1067 		jstr = dtj_NewStringNative(jenv, s);
1068 		if ((*jenv)->ExceptionCheck(jenv)) {
1069 			WRAP_EXCEPTION(jenv);
1070 			return (DTRACE_HANDLE_ABORT);
1071 		}
1072 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
1073 		    g_pdataset_formatted_jm, jstr);
1074 		(*jenv)->DeleteLocalRef(jenv, jstr);
1075 		if ((*jenv)->ExceptionCheck(jenv)) {
1076 			WRAP_EXCEPTION(jenv);
1077 			return (DTRACE_HANDLE_ABORT);
1078 		}
1079 		break;
1080 	case DTRACEACT_STACK:
1081 	case DTRACEACT_USTACK:
1082 	case DTRACEACT_JSTACK:
1083 		/* stand-alone stack(), ustack(), or jstack() action */
1084 		jstr = (*jenv)->NewStringUTF(jenv, s);
1085 		if (!jstr) {
1086 			/* OutOfMemoryError pending */
1087 			return (DTRACE_HANDLE_ABORT);
1088 		}
1089 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
1090 		    g_pdataadd_stack_jm,
1091 		    jc->dtjj_consumer->dtjc_probedata_rec_i, jstr);
1092 		(*jenv)->DeleteLocalRef(jenv, jstr);
1093 		if ((*jenv)->ExceptionCheck(jenv)) {
1094 			WRAP_EXCEPTION(jenv);
1095 			return (DTRACE_HANDLE_ABORT);
1096 		}
1097 		break;
1098 	default:
1099 		/*
1100 		 * The record handler dtj_chewrec() defers nothing else to this
1101 		 * bufhandler.
1102 		 */
1103 		break;
1104 	}
1105 
1106 	return (DTRACE_HANDLE_OK);
1107 }
1108 
1109 static boolean_t
1110 dtj_is_stack_action(dtrace_actkind_t act)
1111 {
1112 	boolean_t stack_action;
1113 	switch (act) {
1114 	case DTRACEACT_STACK:
1115 	case DTRACEACT_USTACK:
1116 	case DTRACEACT_JSTACK:
1117 		stack_action = B_TRUE;
1118 		break;
1119 	default:
1120 		stack_action = B_FALSE;
1121 	}
1122 	return (stack_action);
1123 }
1124 
1125 /*
1126  * Called by get_aggregate() to clear only those aggregations specified by the
1127  * caller.
1128  */
1129 static int
1130 dtj_clear(const dtrace_aggdata_t *data, void *arg)
1131 {
1132 	dtj_java_consumer_t *jc = arg;
1133 	jboolean cleared = JNI_FALSE;
1134 
1135 	jstring jname = NULL;
1136 
1137 	if (jc->dtjj_aggregate_spec) {
1138 		JNIEnv *jenv = jc->dtjj_jenv;
1139 
1140 		dtrace_aggdesc_t *aggdesc = data->dtada_desc;
1141 
1142 		jname = (*jenv)->NewStringUTF(jenv, aggdesc->dtagd_name);
1143 		if (!jname) {
1144 			/* java exception pending */
1145 			return (DTRACE_AGGWALK_ABORT);
1146 		}
1147 
1148 		cleared = (*jenv)->CallBooleanMethod(jenv,
1149 		    jc->dtjj_aggregate_spec, g_aggspec_cleared_jm, jname);
1150 		(*jenv)->DeleteLocalRef(jenv, jname);
1151 		if ((*jenv)->ExceptionCheck(jenv)) {
1152 			WRAP_EXCEPTION(jenv);
1153 			return (DTRACE_AGGWALK_ABORT);
1154 		}
1155 	}
1156 
1157 	return (cleared ? DTRACE_AGGWALK_CLEAR : DTRACE_AGGWALK_NEXT);
1158 }
1159 
1160 static int64_t
1161 dtj_average(caddr_t addr, uint64_t normal)
1162 {
1163 	/* LINTED - alignment */
1164 	uint64_t *data = (uint64_t *)addr;
1165 
1166 	return (data[0] ?
1167 	    (long long)(data[1] / normal / data[0]) : 0);
1168 }
1169 
1170 static int64_t
1171 dtj_avg_total(caddr_t addr, uint64_t normal)
1172 {
1173 	/* LINTED - alignment */
1174 	uint64_t *data = (uint64_t *)addr;
1175 
1176 	return ((long long)(data[1] / normal));
1177 }
1178 
1179 static int64_t
1180 dtj_avg_count(caddr_t addr)
1181 {
1182 	/* LINTED - alignment */
1183 	uint64_t *data = (uint64_t *)addr;
1184 
1185 	return ((long long)data[0]);
1186 }
1187 
1188 static jobject
1189 dtj_new_probedata_stack_record(const dtrace_probedata_t *data,
1190     const dtrace_recdesc_t *rec, dtj_java_consumer_t *jc)
1191 {
1192 	caddr_t addr;
1193 
1194 	/* Get raw stack data */
1195 	addr = data->dtpda_data + rec->dtrd_offset;
1196 	return (dtj_new_stack_record(addr, rec, jc));
1197 }
1198 
1199 static jobject
1200 dtj_new_tuple_stack_record(const dtrace_aggdata_t *data,
1201     const dtrace_recdesc_t *rec, const char *s, dtj_java_consumer_t *jc)
1202 {
1203 	caddr_t addr;
1204 	JNIEnv *jenv = jc->dtjj_jenv;
1205 
1206 	jobjectArray frames = NULL;
1207 	jobject jobj = NULL; /* tuple element */
1208 	jstring jstr = NULL;
1209 
1210 	/* Get raw stack data */
1211 	addr = data->dtada_data + rec->dtrd_offset;
1212 	jobj = dtj_new_stack_record(addr, rec, jc);
1213 	if (!jobj) {
1214 		return (NULL); /* java exception pending */
1215 	}
1216 
1217 	jstr = dtj_NewStringNative(jenv, s);
1218 	if ((*jenv)->ExceptionCheck(jenv)) {
1219 		(*jenv)->DeleteLocalRef(jenv, jobj);
1220 		return (NULL);
1221 	}
1222 	frames = (*jenv)->CallStaticObjectMethod(jenv, g_stack_jc,
1223 	    g_parsestack_jsm, jstr);
1224 	(*jenv)->DeleteLocalRef(jenv, jstr);
1225 	if ((*jenv)->ExceptionCheck(jenv)) {
1226 		(*jenv)->DeleteLocalRef(jenv, jobj);
1227 		return (NULL);
1228 	}
1229 	dtj_attach_frames(jc, jobj, frames);
1230 	(*jenv)->DeleteLocalRef(jenv, frames);
1231 	if ((*jenv)->ExceptionCheck(jenv)) {
1232 		return (NULL);
1233 	}
1234 
1235 	return (jobj);
1236 }
1237 
1238 /* Caller must be holding per-consumer lock */
1239 static void
1240 dtj_aggwalk_init(dtj_java_consumer_t *jc)
1241 {
1242 	jc->dtjj_consumer->dtjc_aggid = -1;
1243 	jc->dtjj_consumer->dtjc_expected = -1;
1244 	if (jc->dtjj_tuple != NULL) {
1245 		/* assert without crashing */
1246 		dtj_throw_illegal_state(jc->dtjj_jenv,
1247 		    "stale aggregation tuple");
1248 	}
1249 }
1250 
1251 static jobject
1252 dtj_new_stack_record(caddr_t addr, const dtrace_recdesc_t *rec,
1253     dtj_java_consumer_t *jc)
1254 {
1255 	JNIEnv *jenv = jc->dtjj_jenv;
1256 
1257 	dtrace_actkind_t act;
1258 	uint64_t *pc;
1259 	pid_t pid = -1;
1260 	int size; /* size of raw bytes not including trailing zeros */
1261 	int i; /* index of last non-zero byte */
1262 
1263 	jbyteArray raw = NULL;
1264 	jobject stack = NULL; /* return value */
1265 
1266 	/* trim trailing zeros */
1267 	for (i = rec->dtrd_size - 1; (i >= 0) && !addr[i]; --i) {
1268 	}
1269 	size = (i + 1);
1270 	raw = (*jenv)->NewByteArray(jenv, size);
1271 	if (!raw) {
1272 		return (NULL); /* OutOfMemoryError pending */
1273 	}
1274 	(*jenv)->SetByteArrayRegion(jenv, raw, 0, size,
1275 	    (const jbyte *)addr);
1276 	if ((*jenv)->ExceptionCheck(jenv)) {
1277 		WRAP_EXCEPTION(jenv);
1278 		(*jenv)->DeleteLocalRef(jenv, raw);
1279 		return (NULL);
1280 	}
1281 
1282 	/* Create StackValueRecord instance from raw stack data */
1283 	act = rec->dtrd_action;
1284 	switch (act) {
1285 	case DTRACEACT_STACK:
1286 		stack = (*jenv)->NewObject(jenv, g_stack_jc,
1287 		    g_stackinit_jm, raw);
1288 		break;
1289 	case DTRACEACT_USTACK:
1290 	case DTRACEACT_JSTACK:
1291 		/* Get pid of user process */
1292 		pc = (uint64_t *)(uintptr_t)addr;
1293 		pid = (pid_t)*pc;
1294 		stack = (*jenv)->NewObject(jenv, g_ustack_jc,
1295 		    g_ustackinit_jm, pid, raw);
1296 		break;
1297 	default:
1298 		dtj_throw_illegal_argument(jenv,
1299 		    "Expected stack action, got %d\n", act);
1300 	}
1301 	(*jenv)->DeleteLocalRef(jenv, raw);
1302 	if ((*jenv)->ExceptionCheck(jenv)) {
1303 		WRAP_EXCEPTION(jenv);
1304 		return (NULL);
1305 	}
1306 	return (stack);
1307 }
1308 
1309 /*
1310  * Return NULL if java exception pending, otherwise return Distribution value.
1311  */
1312 static jobject
1313 dtj_new_distribution(const dtrace_aggdata_t *data, const dtrace_recdesc_t *rec,
1314     dtj_java_consumer_t *jc)
1315 {
1316 	JNIEnv *jenv = jc->dtjj_jenv;
1317 
1318 	jlongArray jbuckets = NULL;
1319 	jobject jdist = NULL; /* return value */
1320 
1321 	dtrace_actkind_t act = rec->dtrd_action;
1322 	/* LINTED - alignment */
1323 	int64_t *aggbuckets = (int64_t *)
1324 	    (data->dtada_data + rec->dtrd_offset);
1325 	size_t size = rec->dtrd_size;
1326 	int64_t value;
1327 	uint64_t normal = data->dtada_normal;
1328 	int64_t base, step;
1329 	int levels;
1330 	int n; /* number of buckets */
1331 
1332 	/* distribution */
1333 	if (act == DTRACEAGG_LQUANTIZE) {
1334 		/* first "bucket" used for range and step */
1335 		value = *aggbuckets++;
1336 		base = DTRACE_LQUANTIZE_BASE(value);
1337 		step = DTRACE_LQUANTIZE_STEP(value);
1338 		levels = DTRACE_LQUANTIZE_LEVELS(value);
1339 		size -= sizeof (int64_t); /* exclude non-bucket */
1340 		/*
1341 		 * Add one for the base bucket and one for the bucket of values
1342 		 * less than the base.
1343 		 */
1344 		n = levels + 2;
1345 	} else {
1346 		n = DTRACE_QUANTIZE_NBUCKETS;
1347 		levels = n - 1; /* levels excludes base */
1348 	}
1349 	if (size != (n * sizeof (uint64_t)) || n < 1) {
1350 		dtj_throw_illegal_state(jenv,
1351 		    "size mismatch: record %d, buckets %d", size,
1352 		    (n * sizeof (uint64_t)));
1353 		WRAP_EXCEPTION(jenv);
1354 		return (NULL);
1355 	}
1356 
1357 	jbuckets = (*jenv)->NewLongArray(jenv, n);
1358 	if (!jbuckets) {
1359 		return (NULL); /* exception pending */
1360 	}
1361 	if (n > 0) {
1362 		(*jenv)->SetLongArrayRegion(jenv, jbuckets, 0, n, aggbuckets);
1363 		/* check for ArrayIndexOutOfBounds */
1364 		if ((*jenv)->ExceptionCheck(jenv)) {
1365 			WRAP_EXCEPTION(jenv);
1366 			(*jenv)->DeleteLocalRef(jenv, jbuckets);
1367 			return (NULL);
1368 		}
1369 	}
1370 
1371 	if (act == DTRACEAGG_LQUANTIZE) {
1372 		/* Must pass 64-bit base and step or constructor gets junk. */
1373 		jdist = (*jenv)->NewObject(jenv, g_ldist_jc, g_ldistinit_jm,
1374 		    base, step, jbuckets);
1375 	} else {
1376 		jdist = (*jenv)->NewObject(jenv, g_dist_jc, g_distinit_jm,
1377 		    jbuckets);
1378 	}
1379 
1380 	(*jenv)->DeleteLocalRef(jenv, jbuckets);
1381 	if (!jdist) {
1382 		return (NULL); /* exception pending */
1383 	}
1384 
1385 	if (normal != 1) {
1386 		(*jenv)->CallVoidMethod(jenv, jdist, g_dist_normal_jm, normal);
1387 		if ((*jenv)->ExceptionCheck(jenv)) {
1388 			WRAP_EXCEPTION(jenv);
1389 			(*jenv)->DeleteLocalRef(jenv, jdist);
1390 			return (NULL);
1391 		}
1392 	}
1393 	return (jdist);
1394 }
1395 
1396 static void
1397 dtj_attach_frames(dtj_java_consumer_t *jc, jobject stack,
1398     jobjectArray frames)
1399 {
1400 	JNIEnv *jenv = jc->dtjj_jenv;
1401 
1402 	if ((*jenv)->IsInstanceOf(jenv, stack, g_stack_jc)) {
1403 		(*jenv)->CallVoidMethod(jenv, stack, g_stackset_frames_jm,
1404 		    frames);
1405 	} else if ((*jenv)->IsInstanceOf(jenv, stack, g_ustack_jc)) {
1406 		(*jenv)->CallVoidMethod(jenv, stack, g_ustackset_frames_jm,
1407 		    frames);
1408 	}
1409 }
1410 
1411 /*
1412  * Note: It is not valid to look outside the current libdtrace record in the
1413  * given aggdata (except to get the aggregation ID from the first record).
1414  *
1415  * Return DTRACE_HANDLE_ABORT if java exception pending, otherwise
1416  * DTRACE_HANDLE_OK.
1417  */
1418 static int
1419 dtj_agghandler(const dtrace_bufdata_t *bufdata, dtj_java_consumer_t *jc)
1420 {
1421 	JNIEnv *jenv = jc->dtjj_jenv;
1422 
1423 	const dtrace_aggdata_t *aggdata = bufdata->dtbda_aggdata;
1424 	const dtrace_aggdesc_t *aggdesc;
1425 	const dtrace_recdesc_t *rec = bufdata->dtbda_recdesc;
1426 	const char *s = bufdata->dtbda_buffered;
1427 	dtrace_actkind_t act = DTRACEACT_NONE;
1428 	int64_t aggid;
1429 
1430 	jobject jobj = NULL;
1431 
1432 	if (aggdata == NULL) {
1433 		/* Assert without crashing */
1434 		dtj_throw_illegal_state(jenv, "null aggdata");
1435 		WRAP_EXCEPTION(jenv);
1436 		return (DTRACE_HANDLE_ABORT);
1437 	}
1438 	aggdesc = aggdata->dtada_desc;
1439 
1440 	/*
1441 	 * Get the aggregation ID from the first record.
1442 	 */
1443 	/* LINTED - alignment */
1444 	aggid = *((int64_t *)(aggdata->dtada_data +
1445 	    aggdesc->dtagd_rec[0].dtrd_offset));
1446 	if (aggid < 0) {
1447 		/* Assert without crashing */
1448 		dtj_throw_illegal_argument(jenv, "negative aggregation ID");
1449 		WRAP_EXCEPTION(jenv);
1450 		return (DTRACE_HANDLE_ABORT);
1451 	}
1452 
1453 	if (jc->dtjj_consumer->dtjc_printa_snaptime) {
1454 		/* Append buffered output if this is a printa() callback. */
1455 		jstring jstr = dtj_NewStringNative(jenv, s);
1456 		if ((*jenv)->ExceptionCheck(jenv)) {
1457 			WRAP_EXCEPTION(jenv);
1458 			return (DTRACE_HANDLE_ABORT);
1459 		}
1460 		/*
1461 		 * StringBuffer append() returns a reference to the
1462 		 * StringBuffer; must not leak the returned reference.
1463 		 */
1464 		jobj = (*jenv)->CallObjectMethod(jenv,
1465 		    jc->dtjj_printa_buffer, g_buf_append_str_jm, jstr);
1466 		(*jenv)->DeleteLocalRef(jenv, jstr);
1467 		(*jenv)->DeleteLocalRef(jenv, jobj);
1468 		if ((*jenv)->ExceptionCheck(jenv)) {
1469 			WRAP_EXCEPTION(jenv);
1470 			return (DTRACE_HANDLE_ABORT);
1471 		}
1472 	} else {
1473 		/*
1474 		 * Test whether to include the aggregation if this is a
1475 		 * getAggregate() callback.  Optimization: perform the inclusion
1476 		 * test only when the aggregation has changed.
1477 		 */
1478 		if (aggid != jc->dtjj_consumer->dtjc_aggid) {
1479 			jc->dtjj_consumer->dtjc_included =
1480 			    dtj_is_included(aggdata, jc);
1481 			if ((*jenv)->ExceptionCheck(jenv)) {
1482 				WRAP_EXCEPTION(jenv);
1483 				return (DTRACE_HANDLE_ABORT);
1484 			}
1485 		}
1486 		if (!jc->dtjj_consumer->dtjc_included) {
1487 			return (DTRACE_HANDLE_OK);
1488 		}
1489 	}
1490 	jc->dtjj_consumer->dtjc_aggid = aggid;
1491 
1492 	/*
1493 	 * Determine the expected number of tuple members.  While it is not
1494 	 * technically valid to look outside the current record in the current
1495 	 * aggdata, this implementation does so without a known failure case.
1496 	 * Any method relying only on the current callback record makes riskier
1497 	 * assumptions and still does not cover every corner case (for example,
1498 	 * counting the records from index 1 up to and not including the index
1499 	 * of the current DTRACE_BUFDATA_AGGVAL record, which fails when a
1500 	 * format string specifies the value ahead of one or more tuple
1501 	 * elements).  Knowing that the calculation of the expected tuple size
1502 	 * is technically invalid (because it looks outside the current record),
1503 	 * we make the calculation at the earliest opportunity, before anything
1504 	 * might happen to invalidate any part of the aggdata.  It ought to be
1505 	 * safe in any case: dtrd_action and dtrd_size do not appear ever to be
1506 	 * overwritten, and dtrd_offset is not used outside the current record.
1507 	 *
1508 	 * It is possible (if the assumptions here ever prove untrue) that the
1509 	 * libdtrace buffered output handler may need to be enhanced to provide
1510 	 * the expected number of tuple members.
1511 	 */
1512 	if (jc->dtjj_consumer->dtjc_expected < 0) {
1513 		int r;
1514 		for (r = 1; r < aggdesc->dtagd_nrecs; ++r) {
1515 			act = aggdesc->dtagd_rec[r].dtrd_action;
1516 			if (DTRACEACT_ISAGG(act) ||
1517 			    aggdesc->dtagd_rec[r].dtrd_size == 0) {
1518 				break;
1519 			}
1520 		}
1521 		jc->dtjj_consumer->dtjc_expected = r - 1;
1522 	}
1523 
1524 	if (bufdata->dtbda_flags & DTRACE_BUFDATA_AGGKEY) {
1525 		/* record value is a tuple member */
1526 
1527 		if (jc->dtjj_tuple == NULL) {
1528 			jc->dtjj_tuple = (*jenv)->NewObject(jenv,
1529 			    g_tuple_jc, g_tupleinit_jm);
1530 			if (!jc->dtjj_tuple) {
1531 				/* java exception pending */
1532 				return (DTRACE_HANDLE_ABORT);
1533 			}
1534 		}
1535 
1536 		act = rec->dtrd_action;
1537 
1538 		switch (act) {
1539 		case DTRACEACT_STACK:
1540 		case DTRACEACT_USTACK:
1541 		case DTRACEACT_JSTACK:
1542 			jobj = dtj_new_tuple_stack_record(aggdata, rec, s, jc);
1543 			break;
1544 		default:
1545 			jobj = dtj_recdata(jc, rec->dtrd_size,
1546 			    (aggdata->dtada_data + rec->dtrd_offset));
1547 		}
1548 
1549 		if (!jobj) {
1550 			/* java exception pending */
1551 			return (DTRACE_HANDLE_ABORT);
1552 		}
1553 
1554 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_tuple,
1555 		    g_tupleadd_jm, jobj);
1556 		(*jenv)->DeleteLocalRef(jenv, jobj);
1557 		if ((*jenv)->ExceptionCheck(jenv)) {
1558 			WRAP_EXCEPTION(jenv);
1559 			return (DTRACE_HANDLE_ABORT);
1560 		}
1561 	} else if (bufdata->dtbda_flags & DTRACE_BUFDATA_AGGVAL) {
1562 		/*
1563 		 * Record value is that of an aggregating action.  The printa()
1564 		 * format string may place the tuple ahead of the aggregation
1565 		 * value(s), so we can't be sure we have the tuple until we get
1566 		 * the AGGLAST flag indicating the last callback associated with
1567 		 * the current tuple.  Save the aggregation value or values
1568 		 * (multiple values if more than one aggregation is passed to
1569 		 * printa()) until then.
1570 		 */
1571 		dtj_aggval_t *aggval;
1572 
1573 		jstring jvalue = NULL;
1574 
1575 		jvalue = dtj_new_aggval(jc, aggdata, rec);
1576 		if (!jvalue) {
1577 			/* java exception pending */
1578 			WRAP_EXCEPTION(jenv);
1579 			return (DTRACE_HANDLE_ABORT);
1580 		}
1581 		aggval = dtj_aggval_create(jenv, jvalue, aggdesc->dtagd_name,
1582 		    aggid);
1583 		if (!aggval) {
1584 			/* OutOfMemoryError pending */
1585 			(*jenv)->DeleteLocalRef(jenv, jvalue);
1586 			return (DTRACE_HANDLE_ABORT);
1587 		}
1588 		if (!dtj_list_add(jc->dtjj_aggval_list, aggval)) {
1589 			/* deletes jvalue reference */
1590 			dtj_aggval_destroy(aggval, jenv);
1591 			dtj_throw_out_of_memory(jenv, "Failed to add aggval");
1592 			return (DTRACE_HANDLE_ABORT);
1593 		}
1594 	}
1595 
1596 	if (bufdata->dtbda_flags & DTRACE_BUFDATA_AGGLAST) {
1597 		/* No more values associated with the current tuple. */
1598 
1599 		dtj_aggval_t *aggval;
1600 		uu_list_walk_t *itr;
1601 		int tuple_member_count;
1602 
1603 		jobject jrec = NULL;
1604 		jstring jname = NULL;
1605 
1606 		if (jc->dtjj_consumer->dtjc_expected == 0) {
1607 			/*
1608 			 * singleton aggregation declared in D with no square
1609 			 * brackets
1610 			 */
1611 			jc->dtjj_tuple = (*jenv)->GetStaticObjectField(jenv,
1612 			    g_tuple_jc, g_tuple_EMPTY_jsf);
1613 			if (jc->dtjj_tuple == NULL) {
1614 				dtj_throw_out_of_memory(jenv,
1615 				    "Failed to reference Tuple.EMPTY");
1616 				return (DTRACE_HANDLE_ABORT);
1617 			}
1618 		}
1619 
1620 		if (jc->dtjj_tuple == NULL) {
1621 			(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
1622 			    g_pdatainvalidate_printa_jm);
1623 		}
1624 
1625 		tuple_member_count = (*jenv)->CallIntMethod(jenv,
1626 		    jc->dtjj_tuple, g_tuplesize_jm);
1627 		if (tuple_member_count <
1628 		    jc->dtjj_consumer->dtjc_expected) {
1629 			(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
1630 			    g_pdatainvalidate_printa_jm);
1631 			(*jenv)->DeleteLocalRef(jenv, jc->dtjj_tuple);
1632 			jc->dtjj_tuple = NULL;
1633 		}
1634 
1635 		if (jc->dtjj_tuple == NULL) {
1636 			goto printa_output;
1637 		}
1638 
1639 		itr = uu_list_walk_start(jc->dtjj_aggval_list, 0);
1640 		while ((aggval = uu_list_walk_next(itr)) != NULL) {
1641 			/*
1642 			 * new AggregationRecord:  Combine the aggregation value
1643 			 * with the saved tuple and add it to the current
1644 			 * Aggregate or PrintaRecord.
1645 			 */
1646 			jrec = (*jenv)->NewObject(jenv, g_aggrec_jc,
1647 			    g_aggrecinit_jm, jc->dtjj_tuple,
1648 			    aggval->dtja_value);
1649 			(*jenv)->DeleteLocalRef(jenv, aggval->dtja_value);
1650 			aggval->dtja_value = NULL;
1651 			if (!jrec) {
1652 				/* java exception pending */
1653 				WRAP_EXCEPTION(jenv);
1654 				return (DTRACE_HANDLE_ABORT);
1655 			}
1656 
1657 			/* aggregation name */
1658 			jname = (*jenv)->NewStringUTF(jenv,
1659 			    aggval->dtja_aggname);
1660 			if (!jname) {
1661 				/* OutOfMemoryError pending */
1662 				(*jenv)->DeleteLocalRef(jenv, jrec);
1663 				return (DTRACE_HANDLE_ABORT);
1664 			}
1665 
1666 			/*
1667 			 * If the printa() format string specifies the value of
1668 			 * the aggregating action multiple times, PrintaRecord
1669 			 * ignores the attempt to add the duplicate record.
1670 			 */
1671 			if (jc->dtjj_consumer->dtjc_printa_snaptime) {
1672 				/* add to PrintaRecord */
1673 				(*jenv)->CallVoidMethod(jenv,
1674 				    jc->dtjj_probedata,
1675 				    g_pdataadd_aggrec_jm,
1676 				    jname, aggval->dtja_aggid, jrec);
1677 			} else {
1678 				/* add to Aggregate */
1679 				(*jenv)->CallVoidMethod(jenv,
1680 				    jc->dtjj_aggregate, g_aggaddrec_jm,
1681 				    jname, aggval->dtja_aggid, jrec);
1682 			}
1683 
1684 			(*jenv)->DeleteLocalRef(jenv, jrec);
1685 			(*jenv)->DeleteLocalRef(jenv, jname);
1686 			if ((*jenv)->ExceptionCheck(jenv)) {
1687 				WRAP_EXCEPTION(jenv);
1688 				return (DTRACE_HANDLE_ABORT);
1689 			}
1690 		}
1691 		uu_list_walk_end(itr);
1692 		dtj_list_clear(jc->dtjj_aggval_list, dtj_aggval_destroy,
1693 		    jenv);
1694 
1695 printa_output:
1696 		if (jc->dtjj_consumer->dtjc_printa_snaptime) {
1697 			/*
1698 			 * Get the formatted string associated with the current
1699 			 * tuple if this is a printa() callback.
1700 			 */
1701 			jstring jstr = (*jenv)->CallObjectMethod(jenv,
1702 			    jc->dtjj_printa_buffer, g_tostring_jm);
1703 			if ((*jenv)->ExceptionCheck(jenv)) {
1704 				WRAP_EXCEPTION(jenv);
1705 				return (DTRACE_HANDLE_ABORT);
1706 			}
1707 			/*
1708 			 * Clear the StringBuffer: this does not throw
1709 			 * exceptions.  Reuse the StringBuffer until the end of
1710 			 * the current probedata then dispose of it.
1711 			 */
1712 			(*jenv)->CallVoidMethod(jenv, jc->dtjj_printa_buffer,
1713 			    g_bufsetlen_jm, 0);
1714 			/* Add formatted string to PrintaRecord */
1715 			(*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
1716 			    g_pdataadd_printa_str_jm, jc->dtjj_tuple, jstr);
1717 			(*jenv)->DeleteLocalRef(jenv, jstr);
1718 			if ((*jenv)->ExceptionCheck(jenv)) {
1719 				WRAP_EXCEPTION(jenv);
1720 				return (DTRACE_HANDLE_ABORT);
1721 			}
1722 		}
1723 
1724 		(*jenv)->DeleteLocalRef(jenv, jc->dtjj_tuple);
1725 		jc->dtjj_tuple = NULL;
1726 		jc->dtjj_consumer->dtjc_expected = -1;
1727 	}
1728 
1729 	return (DTRACE_HANDLE_OK);
1730 }
1731 
1732 /*
1733  * Return B_TRUE if the aggregation is included, B_FALSE otherwise.  Only in the
1734  * latter case might there be an exception pending.
1735  */
1736 static boolean_t
1737 dtj_is_included(const dtrace_aggdata_t *data, dtj_java_consumer_t *jc)
1738 {
1739 	JNIEnv *jenv = jc->dtjj_jenv;
1740 
1741 	if (jc->dtjj_aggregate_spec) {
1742 		jboolean included;
1743 		jstring aggname = NULL;
1744 
1745 		const dtrace_aggdesc_t *aggdesc = data->dtada_desc;
1746 		aggname = (*jenv)->NewStringUTF(jenv, aggdesc->dtagd_name);
1747 		if (!aggname) {
1748 			/* java exception pending */
1749 			return (B_FALSE);
1750 		}
1751 
1752 		included = (*jenv)->CallBooleanMethod(jenv,
1753 		    jc->dtjj_aggregate_spec, g_aggspec_included_jm,
1754 		    aggname);
1755 		(*jenv)->DeleteLocalRef(jenv, aggname);
1756 		if ((*jenv)->ExceptionCheck(jenv)) {
1757 			WRAP_EXCEPTION(jenv);
1758 			return (B_FALSE);
1759 		}
1760 
1761 		return (included);
1762 	}
1763 
1764 	return (B_TRUE);
1765 }
1766 
1767 /*
1768  * Return NULL if a java exception is pending, otherwise return a new
1769  * AggregationValue instance.
1770  */
1771 static jobject
1772 dtj_new_aggval(dtj_java_consumer_t *jc, const dtrace_aggdata_t *data,
1773     const dtrace_recdesc_t *rec)
1774 {
1775 	JNIEnv *jenv = jc->dtjj_jenv;
1776 
1777 	jobject jvalue = NULL; /* return value */
1778 
1779 	dtrace_actkind_t act;
1780 	uint64_t normal;
1781 	caddr_t addr;
1782 	int64_t value;
1783 
1784 	act = rec->dtrd_action;
1785 	normal = data->dtada_normal;
1786 	addr = data->dtada_data + rec->dtrd_offset;
1787 	if (act == DTRACEAGG_AVG) {
1788 		value = dtj_average(addr, normal);
1789 	} else {
1790 		/* LINTED - alignment */
1791 		value = (*((int64_t *)addr)) / normal;
1792 	}
1793 
1794 	if (act == DTRACEAGG_QUANTIZE || act == DTRACEAGG_LQUANTIZE) {
1795 		jvalue = dtj_new_distribution(data, rec, jc);
1796 	} else {
1797 		switch (act) {
1798 		case DTRACEAGG_COUNT:
1799 			jvalue = (*jenv)->NewObject(jenv, g_aggcount_jc,
1800 			    g_aggcountinit_jm, value);
1801 			break;
1802 		case DTRACEAGG_SUM:
1803 			jvalue = (*jenv)->NewObject(jenv, g_aggsum_jc,
1804 			    g_aggsuminit_jm, value);
1805 			break;
1806 		case DTRACEAGG_AVG:
1807 			jvalue = (*jenv)->NewObject(jenv, g_aggavg_jc,
1808 			    g_aggavginit_jm, value, dtj_avg_total(addr,
1809 			    normal), dtj_avg_count(addr));
1810 			break;
1811 		case DTRACEAGG_MIN:
1812 			jvalue = (*jenv)->NewObject(jenv, g_aggmin_jc,
1813 			    g_aggmininit_jm, value);
1814 			break;
1815 		case DTRACEAGG_MAX:
1816 			jvalue = (*jenv)->NewObject(jenv, g_aggmax_jc,
1817 			    g_aggmaxinit_jm, value);
1818 			break;
1819 		default:
1820 			jvalue = NULL;
1821 			dtj_throw_illegal_argument(jenv,
1822 			    "unexpected aggregation action: %d", act);
1823 		}
1824 	}
1825 
1826 	return (jvalue);
1827 }
1828 
1829 /*
1830  * Stops the given consumer if it is running.  Throws DTraceException if
1831  * dtrace_stop() fails and no other exception is already pending.  Clears and
1832  * rethrows any pending exception in order to grab the global lock safely.
1833  */
1834 void
1835 dtj_stop(dtj_java_consumer_t *jc)
1836 {
1837 	JNIEnv *jenv;
1838 	int rc;
1839 	jthrowable e;
1840 
1841 	switch (jc->dtjj_consumer->dtjc_state) {
1842 	case DTJ_CONSUMER_GO:
1843 	case DTJ_CONSUMER_START:
1844 		break;
1845 	default:
1846 		return;
1847 	}
1848 
1849 	jenv = jc->dtjj_jenv;
1850 	e = (*jenv)->ExceptionOccurred(jenv);
1851 	if (e) {
1852 		(*jenv)->ExceptionClear(jenv);
1853 	}
1854 
1855 	(*jenv)->MonitorEnter(jenv, g_caller_jc);
1856 	if ((*jenv)->ExceptionCheck(jenv)) {
1857 		goto rethrow;
1858 	}
1859 
1860 	rc = dtrace_status(jc->dtjj_consumer->dtjc_dtp);
1861 	if (rc != DTRACE_STATUS_STOPPED) {
1862 		rc = dtrace_stop(jc->dtjj_consumer->dtjc_dtp);
1863 	}
1864 
1865 	(*jenv)->MonitorExit(jenv, g_caller_jc);
1866 	if ((*jenv)->ExceptionCheck(jenv)) {
1867 		goto rethrow;
1868 	}
1869 
1870 	if (rc == -1) {
1871 		(*jenv)->MonitorEnter(jenv, g_caller_jc);
1872 		if ((*jenv)->ExceptionCheck(jenv)) {
1873 			goto rethrow;
1874 		}
1875 		/* Do not wrap DTraceException */
1876 		dtj_throw_dtrace_exception(jc,
1877 		    "couldn't stop tracing: %s",
1878 		    dtrace_errmsg(jc->dtjj_consumer->dtjc_dtp,
1879 		    dtrace_errno(jc->dtjj_consumer->dtjc_dtp)));
1880 		/* safe to call with pending exception */
1881 		(*jenv)->MonitorExit(jenv, g_caller_jc);
1882 	} else {
1883 		jc->dtjj_consumer->dtjc_state = DTJ_CONSUMER_STOP;
1884 	}
1885 
1886 rethrow:
1887 	if (e) {
1888 		if ((*jenv)->ExceptionCheck(jenv)) {
1889 			/*
1890 			 * Favor earlier pending exception over
1891 			 * exception thrown in this function.
1892 			 */
1893 			(*jenv)->ExceptionClear(jenv);
1894 		}
1895 		(*jenv)->Throw(jenv, e);
1896 		(*jenv)->DeleteLocalRef(jenv, e);
1897 	}
1898 }
1899 
1900 /*
1901  * Return Aggregate instance, or null if java exception pending.
1902  */
1903 jobject
1904 dtj_get_aggregate(dtj_java_consumer_t *jc)
1905 {
1906 	JNIEnv *jenv = jc->dtjj_jenv;
1907 	hrtime_t snaptime;
1908 	int rc;
1909 
1910 	jobject aggregate = NULL;
1911 
1912 	/*
1913 	 * Aggregations must be snapped, walked, and cleared atomically,
1914 	 * otherwise clearing loses data accumulated since the most recent snap.
1915 	 * This per-consumer lock prevents dtrace_work() from snapping or
1916 	 * clearing aggregations while we're in the middle of this atomic
1917 	 * operation, so we continue to hold it until done clearing.
1918 	 */
1919 	(*jenv)->MonitorEnter(jenv, jc->dtjj_consumer_lock);
1920 	if ((*jenv)->ExceptionCheck(jenv)) {
1921 		WRAP_EXCEPTION(jenv);
1922 		return (NULL);
1923 	}
1924 
1925 	dtj_aggwalk_init(jc);
1926 	if ((*jenv)->ExceptionCheck(jenv)) {
1927 		WRAP_EXCEPTION(jenv);
1928 		/* release per-consumer lock */
1929 		(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
1930 		return (NULL);
1931 	}
1932 
1933 	/*
1934 	 * Snap aggregations
1935 	 *
1936 	 * We need to record the snaptime here for the caller.  Leaving it to
1937 	 * the caller to record the snaptime before calling getAggregate() may
1938 	 * be inaccurate because of the indeterminate delay waiting on the
1939 	 * consumer lock before calling dtrace_aggregate_snap().
1940 	 */
1941 	snaptime = gethrtime();
1942 	if (dtrace_aggregate_snap(jc->dtjj_consumer->dtjc_dtp) != 0) {
1943 		dtj_error_t e;
1944 		if (dtj_get_dtrace_error(jc, &e) == DTJ_OK) {
1945 			/* Do not wrap DTraceException */
1946 			dtj_throw_dtrace_exception(jc, e.dtje_message);
1947 		}
1948 		/* release per-consumer lock */
1949 		(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
1950 		return (NULL);
1951 	}
1952 
1953 	/* Create the Java representation of the aggregate snapshot. */
1954 	aggregate = (*jenv)->NewObject(jenv, g_agg_jc, g_agginit_jm,
1955 	    snaptime);
1956 	if ((*jenv)->ExceptionCheck(jenv)) {
1957 		WRAP_EXCEPTION(jenv);
1958 		/* release per-consumer lock */
1959 		(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
1960 		return (NULL);
1961 	}
1962 	jc->dtjj_aggregate = aggregate;
1963 
1964 	/*
1965 	 * Walk the aggregate, converting the data into Java Objects.  Traverse
1966 	 * in order by aggregation ID first and tuple second by using
1967 	 * dtrace_aggregate_walk_keysorted (uses varkeycmp).  We cannot do the
1968 	 * same for aggregations generated by the printa() action, since
1969 	 * dtrace_work() traverses aggregation data in the order determined by
1970 	 * the various "aggsort" options.  Functions used by both the consumer
1971 	 * loop and the competing getAggregate() thread must not depend on the
1972 	 * ordering of records by tuple key.
1973 	 *
1974 	 * It is impractical to hold the global lock around
1975 	 * dtrace_aggregate_print(), since it may take a long time (e.g. an
1976 	 * entire second) if it performs expensive conversions such as that
1977 	 * needed for user stack traces.  Most libdtrace functions are not
1978 	 * guaranteed to be MT-safe, even when each thread has its own dtrace
1979 	 * handle; or even if they are safe, there is no guarantee that future
1980 	 * changes may not make them unsafe.  Fortunately in this case, however,
1981 	 * only a per-consumer lock is necessary to avoid conflict with
1982 	 * dtrace_work() running in another thread (the consumer loop).
1983 	 */
1984 	rc = dtrace_aggregate_print(jc->dtjj_consumer->dtjc_dtp, NULL,
1985 	    dtrace_aggregate_walk_keysorted);
1986 	if ((*jenv)->ExceptionCheck(jenv)) {
1987 		WRAP_EXCEPTION(jenv);
1988 		/* release per-consumer lock */
1989 		(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
1990 		return (NULL);
1991 	}
1992 	if (rc != 0) {
1993 		dtj_error_t e;
1994 		if (dtj_get_dtrace_error(jc, &e) != DTJ_OK) {
1995 			/* release per-consumer lock */
1996 			(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
1997 			return (NULL);
1998 		}
1999 
2000 		if (e.dtje_number != EINTR) {
2001 			/* Do not wrap DTraceException */
2002 			dtj_throw_dtrace_exception(jc, e.dtje_message);
2003 			/* release per-consumer lock */
2004 			(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2005 			return (NULL);
2006 		}
2007 	}
2008 
2009 	dtj_aggwalk_init(jc);
2010 	if ((*jenv)->ExceptionCheck(jenv)) {
2011 		WRAP_EXCEPTION(jenv);
2012 		/* release per-consumer lock */
2013 		(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2014 		return (NULL);
2015 	}
2016 
2017 	/*
2018 	 * dtrace_aggregate_clear() clears all aggregations, and we need to
2019 	 * clear aggregations selectively.  It also fails to preserve the
2020 	 * lquantize() range and step size; using aggregate_walk() to clear
2021 	 * aggregations does not have this problem.
2022 	 */
2023 	rc = dtrace_aggregate_walk(jc->dtjj_consumer->dtjc_dtp, dtj_clear, jc);
2024 	if ((*jenv)->ExceptionCheck(jenv)) {
2025 		WRAP_EXCEPTION(jenv);
2026 		/* release per-consumer lock */
2027 		(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2028 		return (NULL);
2029 	}
2030 	if (rc != 0) {
2031 		dtj_error_t e;
2032 		if (dtj_get_dtrace_error(jc, &e) == DTJ_OK) {
2033 			/* Do not wrap DTraceException */
2034 			dtj_throw_dtrace_exception(jc, e.dtje_message);
2035 		}
2036 		/* release per-consumer lock */
2037 		(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2038 		return (NULL);
2039 	}
2040 
2041 	(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2042 	if ((*jenv)->ExceptionCheck(jenv)) {
2043 		WRAP_EXCEPTION(jenv);
2044 		return (NULL);
2045 	}
2046 
2047 	aggregate = jc->dtjj_aggregate;
2048 	jc->dtjj_aggregate = NULL;
2049 
2050 	return (aggregate);
2051 }
2052 
2053 /*
2054  * Process any requests, such as the setting of runtime options, enqueued during
2055  * dtrace_sleep().  A Java exception is pending if this function returns
2056  * DTJ_ERR.
2057  */
2058 static dtj_status_t
2059 dtj_process_requests(dtj_java_consumer_t *jc)
2060 {
2061 	dtj_request_t *r;
2062 	uu_list_t *list = jc->dtjj_consumer->dtjc_request_list;
2063 	pthread_mutex_t *list_lock = &jc->dtjj_consumer->
2064 	    dtjc_request_list_lock;
2065 	const char *opt;
2066 	const char *val;
2067 
2068 	(void) pthread_mutex_lock(list_lock);
2069 	while (!dtj_list_empty(list)) {
2070 		r = uu_list_first(list);
2071 		uu_list_remove(list, r);
2072 
2073 		switch (r->dtjr_type) {
2074 		case DTJ_REQUEST_OPTION:
2075 			opt = dtj_string_list_first(r->dtjr_args);
2076 			val = dtj_string_list_last(r->dtjr_args);
2077 			if (dtrace_setopt(jc->dtjj_consumer->dtjc_dtp, opt,
2078 			    val) == -1) {
2079 				/* Do not wrap DTraceException */
2080 				dtj_throw_dtrace_exception(jc,
2081 				    "failed to set %s: %s", opt,
2082 				    dtrace_errmsg(jc->dtjj_consumer->dtjc_dtp,
2083 				    dtrace_errno(jc->dtjj_consumer->dtjc_dtp)));
2084 				dtj_request_destroy(r, NULL);
2085 				(void) pthread_mutex_unlock(list_lock);
2086 				return (DTJ_ERR);
2087 			}
2088 			break;
2089 		}
2090 		dtj_request_destroy(r, NULL);
2091 	}
2092 	(void) pthread_mutex_unlock(list_lock);
2093 	return (DTJ_OK);
2094 }
2095 
2096 /*
2097  * Return DTJ_OK if the consumer loop is stopped normally by either the exit()
2098  * action or the Consumer stop() method.  Otherwise return DTJ_ERR if the
2099  * consumer loop terminates abnormally with an exception pending.
2100  */
2101 dtj_status_t
2102 dtj_consume(dtj_java_consumer_t *jc)
2103 {
2104 	JNIEnv *jenv = jc->dtjj_jenv;
2105 	dtrace_hdl_t *dtp = jc->dtjj_consumer->dtjc_dtp;
2106 	boolean_t done = B_FALSE;
2107 	dtj_error_t e;
2108 
2109 	do {
2110 		if (!jc->dtjj_consumer->dtjc_interrupt) {
2111 			dtrace_sleep(dtp);
2112 		}
2113 
2114 		if (jc->dtjj_consumer->dtjc_interrupt) {
2115 			done = B_TRUE;
2116 			dtj_stop(jc);
2117 			if ((*jenv)->ExceptionCheck(jenv)) {
2118 				/*
2119 				 * Exception left pending by Consumer
2120 				 * getAggregate() method.
2121 				 */
2122 				return (DTJ_ERR);
2123 			}
2124 		} else if (jc->dtjj_consumer->dtjc_process_list != NULL) {
2125 			int nprocs = uu_list_numnodes(jc->dtjj_consumer->
2126 			    dtjc_process_list);
2127 			if (jc->dtjj_consumer->dtjc_procs_ended == nprocs) {
2128 				done = B_TRUE;
2129 				dtj_stop(jc);
2130 			}
2131 		}
2132 
2133 		/*
2134 		 * Functions like dtrace_setopt() are not safe to call during
2135 		 * dtrace_sleep().  Check the request list every time we wake up
2136 		 * from dtrace_sleep().
2137 		 */
2138 		if (!done) {
2139 			if (dtj_process_requests(jc) != DTJ_OK) {
2140 				/* Do not wrap DTraceException */
2141 				return (DTJ_ERR);
2142 			}
2143 		}
2144 
2145 		/*
2146 		 * Use the per-consumer lock to avoid conflict with
2147 		 * get_aggregate() called from another thread.
2148 		 */
2149 		(*jenv)->MonitorEnter(jenv, jc->dtjj_consumer_lock);
2150 		if ((*jenv)->ExceptionCheck(jenv)) {
2151 			WRAP_EXCEPTION(jenv);
2152 			return (DTJ_ERR);
2153 		}
2154 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_caller,
2155 		    g_interval_began_jm);
2156 		if ((*jenv)->ExceptionCheck(jenv)) {
2157 			/* Don't wrap exception thrown from ConsumerListener */
2158 			(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2159 			return (DTJ_ERR);
2160 		}
2161 		jc->dtjj_consumer->dtjc_printa_snaptime = gethrtime();
2162 		switch (dtrace_work(dtp, NULL, dtj_chew, dtj_chewrec, jc)) {
2163 		case DTRACE_WORKSTATUS_DONE:
2164 			done = B_TRUE;
2165 			break;
2166 		case DTRACE_WORKSTATUS_OKAY:
2167 			break;
2168 		default:
2169 			/*
2170 			 * Check for a pending exception that got us to this
2171 			 * error workstatus case.
2172 			 */
2173 			if ((*jenv)->ExceptionCheck(jenv)) {
2174 				/*
2175 				 * Ensure valid initial state before releasing
2176 				 * the consumer lock
2177 				 */
2178 				jc->dtjj_consumer->dtjc_printa_snaptime = 0;
2179 				/* Do not wrap DTraceException */
2180 				/* Release per-consumer lock */
2181 				(*jenv)->MonitorExit(jenv,
2182 				    jc->dtjj_consumer_lock);
2183 				return (DTJ_ERR);
2184 			}
2185 
2186 			if (dtj_get_dtrace_error(jc, &e) != DTJ_OK) {
2187 				/* java exception pending */
2188 				jc->dtjj_consumer->dtjc_printa_snaptime = 0;
2189 				/* Release per-consumer lock */
2190 				(*jenv)->MonitorExit(jenv,
2191 				    jc->dtjj_consumer_lock);
2192 				return (DTJ_ERR);
2193 			}
2194 
2195 			if (e.dtje_number != EINTR) {
2196 				/* Do not wrap DTraceException */
2197 				dtj_throw_dtrace_exception(jc, e.dtje_message);
2198 				jc->dtjj_consumer->dtjc_printa_snaptime = 0;
2199 				/* Release per-consumer lock */
2200 				(*jenv)->MonitorExit(jenv,
2201 				    jc->dtjj_consumer_lock);
2202 				return (DTJ_ERR);
2203 			}
2204 		}
2205 		/*
2206 		 * Check for ConsumerException before doing anything else with
2207 		 * the JNIEnv.
2208 		 */
2209 		if ((*jenv)->ExceptionCheck(jenv)) {
2210 			/*
2211 			 * Do not wrap exception thrown from ConsumerListener.
2212 			 */
2213 			jc->dtjj_consumer->dtjc_printa_snaptime = 0;
2214 			/* Release per-consumer lock */
2215 			(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2216 			return (DTJ_ERR);
2217 		}
2218 		jc->dtjj_consumer->dtjc_printa_snaptime = 0;
2219 		/*
2220 		 * Notify ConsumerListeners the the dtrace_work() interval ended
2221 		 * before releasing the lock.
2222 		 */
2223 		(*jenv)->CallVoidMethod(jenv, jc->dtjj_caller,
2224 		    g_interval_ended_jm);
2225 		(*jenv)->MonitorExit(jenv, jc->dtjj_consumer_lock);
2226 		if ((*jenv)->ExceptionCheck(jenv)) {
2227 			/* Don't wrap exception thrown from ConsumerListener */
2228 			return (DTJ_ERR);
2229 		}
2230 
2231 		/*
2232 		 * Check for a temporarily cleared exception set by a handler
2233 		 * that could not safely leave the exception pending because it
2234 		 * could not return an abort signal.  Rethrow it now that it's
2235 		 * safe to do so (when it's possible to ensure that no JNI calls
2236 		 * will be made that are unsafe while an exception is pending).
2237 		 */
2238 		if (jc->dtjj_exception) {
2239 			(*jenv)->Throw(jenv, jc->dtjj_exception);
2240 			(*jenv)->DeleteLocalRef(jenv, jc->dtjj_exception);
2241 			jc->dtjj_exception = NULL;
2242 			return (DTJ_ERR);
2243 		}
2244 	} while (!done);
2245 
2246 	return (DTJ_OK);
2247 }
2248