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