xref: /onnv-gate/usr/src/cmd/latencytop/common/dwrapper.c (revision 10673:b22eb20aa9ca)
1*10673SKrishnendu.Sadhukhan@Sun.COM /*
2*10673SKrishnendu.Sadhukhan@Sun.COM  * CDDL HEADER START
3*10673SKrishnendu.Sadhukhan@Sun.COM  *
4*10673SKrishnendu.Sadhukhan@Sun.COM  * The contents of this file are subject to the terms of the
5*10673SKrishnendu.Sadhukhan@Sun.COM  * Common Development and Distribution License (the "License").
6*10673SKrishnendu.Sadhukhan@Sun.COM  * You may not use this file except in compliance with the License.
7*10673SKrishnendu.Sadhukhan@Sun.COM  *
8*10673SKrishnendu.Sadhukhan@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*10673SKrishnendu.Sadhukhan@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*10673SKrishnendu.Sadhukhan@Sun.COM  * See the License for the specific language governing permissions
11*10673SKrishnendu.Sadhukhan@Sun.COM  * and limitations under the License.
12*10673SKrishnendu.Sadhukhan@Sun.COM  *
13*10673SKrishnendu.Sadhukhan@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*10673SKrishnendu.Sadhukhan@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*10673SKrishnendu.Sadhukhan@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*10673SKrishnendu.Sadhukhan@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*10673SKrishnendu.Sadhukhan@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*10673SKrishnendu.Sadhukhan@Sun.COM  *
19*10673SKrishnendu.Sadhukhan@Sun.COM  * CDDL HEADER END
20*10673SKrishnendu.Sadhukhan@Sun.COM  */
21*10673SKrishnendu.Sadhukhan@Sun.COM /*
22*10673SKrishnendu.Sadhukhan@Sun.COM  * Copyright (c) 2008-2009, Intel Corporation.
23*10673SKrishnendu.Sadhukhan@Sun.COM  * All Rights Reserved.
24*10673SKrishnendu.Sadhukhan@Sun.COM  */
25*10673SKrishnendu.Sadhukhan@Sun.COM 
26*10673SKrishnendu.Sadhukhan@Sun.COM #include <unistd.h>
27*10673SKrishnendu.Sadhukhan@Sun.COM #include <stdio.h>
28*10673SKrishnendu.Sadhukhan@Sun.COM #include <dtrace.h>
29*10673SKrishnendu.Sadhukhan@Sun.COM #include <string.h>
30*10673SKrishnendu.Sadhukhan@Sun.COM #include <stdlib.h>
31*10673SKrishnendu.Sadhukhan@Sun.COM #include <memory.h>
32*10673SKrishnendu.Sadhukhan@Sun.COM #include <limits.h>
33*10673SKrishnendu.Sadhukhan@Sun.COM 
34*10673SKrishnendu.Sadhukhan@Sun.COM #include "latencytop.h"
35*10673SKrishnendu.Sadhukhan@Sun.COM 
36*10673SKrishnendu.Sadhukhan@Sun.COM static dtrace_hdl_t *g_dtp = NULL;	/* dtrace handle */
37*10673SKrishnendu.Sadhukhan@Sun.COM static pid_t pid_self = -1;		/* PID of our own process */
38*10673SKrishnendu.Sadhukhan@Sun.COM 
39*10673SKrishnendu.Sadhukhan@Sun.COM /*
40*10673SKrishnendu.Sadhukhan@Sun.COM  * Ignore sched if sched is not tracked.
41*10673SKrishnendu.Sadhukhan@Sun.COM  * Also ignore ourselves (i.e., latencytop).
42*10673SKrishnendu.Sadhukhan@Sun.COM  */
43*10673SKrishnendu.Sadhukhan@Sun.COM #define	SHOULD_IGNORE(pid)		\
44*10673SKrishnendu.Sadhukhan@Sun.COM 	((!g_config.lt_cfg_trace_sched && 0 == (pid)) || pid_self == (pid))
45*10673SKrishnendu.Sadhukhan@Sun.COM 
46*10673SKrishnendu.Sadhukhan@Sun.COM /*
47*10673SKrishnendu.Sadhukhan@Sun.COM  * Get an integer value from dtrace record.
48*10673SKrishnendu.Sadhukhan@Sun.COM  */
49*10673SKrishnendu.Sadhukhan@Sun.COM static uint64_t
50*10673SKrishnendu.Sadhukhan@Sun.COM rec_get_value(void *a, size_t b)
51*10673SKrishnendu.Sadhukhan@Sun.COM {
52*10673SKrishnendu.Sadhukhan@Sun.COM 	uint64_t ret = 0;
53*10673SKrishnendu.Sadhukhan@Sun.COM 
54*10673SKrishnendu.Sadhukhan@Sun.COM 	switch (b) {
55*10673SKrishnendu.Sadhukhan@Sun.COM 	case sizeof (uint64_t):
56*10673SKrishnendu.Sadhukhan@Sun.COM 		ret = *((uint64_t *)(a));
57*10673SKrishnendu.Sadhukhan@Sun.COM 		break;
58*10673SKrishnendu.Sadhukhan@Sun.COM 	case sizeof (uint32_t):
59*10673SKrishnendu.Sadhukhan@Sun.COM 		ret = *((uint32_t *)(a));
60*10673SKrishnendu.Sadhukhan@Sun.COM 		break;
61*10673SKrishnendu.Sadhukhan@Sun.COM 	case sizeof (uint16_t):
62*10673SKrishnendu.Sadhukhan@Sun.COM 		ret = *((uint16_t *)(a));
63*10673SKrishnendu.Sadhukhan@Sun.COM 		break;
64*10673SKrishnendu.Sadhukhan@Sun.COM 	case sizeof (uint8_t):
65*10673SKrishnendu.Sadhukhan@Sun.COM 		ret = *((uint8_t *)(a));
66*10673SKrishnendu.Sadhukhan@Sun.COM 		break;
67*10673SKrishnendu.Sadhukhan@Sun.COM 	default:
68*10673SKrishnendu.Sadhukhan@Sun.COM 		break;
69*10673SKrishnendu.Sadhukhan@Sun.COM 	}
70*10673SKrishnendu.Sadhukhan@Sun.COM 
71*10673SKrishnendu.Sadhukhan@Sun.COM 	return (ret);
72*10673SKrishnendu.Sadhukhan@Sun.COM }
73*10673SKrishnendu.Sadhukhan@Sun.COM 
74*10673SKrishnendu.Sadhukhan@Sun.COM /*
75*10673SKrishnendu.Sadhukhan@Sun.COM  * Callback to process aggregation lt_call_* (related to on/off cpu
76*10673SKrishnendu.Sadhukhan@Sun.COM  * activities) in the snapshot.
77*10673SKrishnendu.Sadhukhan@Sun.COM  */
78*10673SKrishnendu.Sadhukhan@Sun.COM static int
79*10673SKrishnendu.Sadhukhan@Sun.COM aggwalk_call(const dtrace_aggdata_t *data, lt_stat_type_t stat_type)
80*10673SKrishnendu.Sadhukhan@Sun.COM {
81*10673SKrishnendu.Sadhukhan@Sun.COM 	dtrace_aggdesc_t *aggdesc = data->dtada_desc;
82*10673SKrishnendu.Sadhukhan@Sun.COM 	dtrace_syminfo_t dts;
83*10673SKrishnendu.Sadhukhan@Sun.COM 	GElf_Sym sym;
84*10673SKrishnendu.Sadhukhan@Sun.COM 	caddr_t addr;
85*10673SKrishnendu.Sadhukhan@Sun.COM 	pid_t pid;
86*10673SKrishnendu.Sadhukhan@Sun.COM 	id_t tid;
87*10673SKrishnendu.Sadhukhan@Sun.COM 	unsigned int stack_depth;
88*10673SKrishnendu.Sadhukhan@Sun.COM 	unsigned int pc_size;
89*10673SKrishnendu.Sadhukhan@Sun.COM 	uint64_t pc;
90*10673SKrishnendu.Sadhukhan@Sun.COM 	uint64_t agg_value;
91*10673SKrishnendu.Sadhukhan@Sun.COM 	char *ptr = NULL;
92*10673SKrishnendu.Sadhukhan@Sun.COM 	char *buffer = NULL;
93*10673SKrishnendu.Sadhukhan@Sun.COM 	int ptrsize;
94*10673SKrishnendu.Sadhukhan@Sun.COM 	unsigned int buffersize;
95*10673SKrishnendu.Sadhukhan@Sun.COM 	char *tag = NULL;
96*10673SKrishnendu.Sadhukhan@Sun.COM 	unsigned int priority;
97*10673SKrishnendu.Sadhukhan@Sun.COM 	enum { REC_PID = 1, REC_TID, REC_STACK, REC_TAG, REC_PRIO, REC_AGG,
98*10673SKrishnendu.Sadhukhan@Sun.COM 	    NREC };
99*10673SKrishnendu.Sadhukhan@Sun.COM 
100*10673SKrishnendu.Sadhukhan@Sun.COM 	/* Check action type */
101*10673SKrishnendu.Sadhukhan@Sun.COM 	if ((aggdesc->dtagd_nrecs < NREC) ||
102*10673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_PID].dtrd_action != DTRACEACT_DIFEXPR) ||
103*10673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_TID].dtrd_action != DTRACEACT_DIFEXPR) ||
104*10673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_TAG].dtrd_action != DTRACEACT_DIFEXPR) ||
105*10673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_PRIO].dtrd_action != DTRACEACT_DIFEXPR) ||
106*10673SKrishnendu.Sadhukhan@Sun.COM 	    (!DTRACEACT_ISAGG(aggdesc->dtagd_rec[REC_AGG].dtrd_action)) ||
107*10673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_STACK].dtrd_action != DTRACEACT_STACK)) {
108*10673SKrishnendu.Sadhukhan@Sun.COM 
109*10673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
110*10673SKrishnendu.Sadhukhan@Sun.COM 	}
111*10673SKrishnendu.Sadhukhan@Sun.COM 
112*10673SKrishnendu.Sadhukhan@Sun.COM 	pid = rec_get_value(
113*10673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_PID].dtrd_offset,
114*10673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_PID].dtrd_size);
115*10673SKrishnendu.Sadhukhan@Sun.COM 
116*10673SKrishnendu.Sadhukhan@Sun.COM 	if (SHOULD_IGNORE(pid)) {
117*10673SKrishnendu.Sadhukhan@Sun.COM 		return (0);
118*10673SKrishnendu.Sadhukhan@Sun.COM 	}
119*10673SKrishnendu.Sadhukhan@Sun.COM 
120*10673SKrishnendu.Sadhukhan@Sun.COM 	tid = rec_get_value(
121*10673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_TID].dtrd_offset,
122*10673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_TID].dtrd_size);
123*10673SKrishnendu.Sadhukhan@Sun.COM 
124*10673SKrishnendu.Sadhukhan@Sun.COM 	/* Parse stack array from dtagd_rec */
125*10673SKrishnendu.Sadhukhan@Sun.COM 	stack_depth = aggdesc->dtagd_rec[REC_STACK].dtrd_arg;
126*10673SKrishnendu.Sadhukhan@Sun.COM 	pc_size = aggdesc->dtagd_rec[REC_STACK].dtrd_size / stack_depth;
127*10673SKrishnendu.Sadhukhan@Sun.COM 	addr = data->dtada_data + aggdesc->dtagd_rec[REC_STACK].dtrd_offset;
128*10673SKrishnendu.Sadhukhan@Sun.COM 	buffersize = (stack_depth * (2 * PATH_MAX + 2) + 1) * sizeof (char);
129*10673SKrishnendu.Sadhukhan@Sun.COM 	buffer = (char *)lt_malloc(buffersize);
130*10673SKrishnendu.Sadhukhan@Sun.COM 	ptr = buffer;
131*10673SKrishnendu.Sadhukhan@Sun.COM 	ptrsize = buffersize;
132*10673SKrishnendu.Sadhukhan@Sun.COM 
133*10673SKrishnendu.Sadhukhan@Sun.COM 	/* Print the stack */
134*10673SKrishnendu.Sadhukhan@Sun.COM 	while (stack_depth > 0) {
135*10673SKrishnendu.Sadhukhan@Sun.COM 		pc = rec_get_value(addr, pc_size);
136*10673SKrishnendu.Sadhukhan@Sun.COM 
137*10673SKrishnendu.Sadhukhan@Sun.COM 		if (pc == 0) {
138*10673SKrishnendu.Sadhukhan@Sun.COM 			break;
139*10673SKrishnendu.Sadhukhan@Sun.COM 		}
140*10673SKrishnendu.Sadhukhan@Sun.COM 
141*10673SKrishnendu.Sadhukhan@Sun.COM 		addr += pc_size;
142*10673SKrishnendu.Sadhukhan@Sun.COM 
143*10673SKrishnendu.Sadhukhan@Sun.COM 		if (dtrace_lookup_by_addr(g_dtp, pc, &sym, &dts) == 0) {
144*10673SKrishnendu.Sadhukhan@Sun.COM 			int len;
145*10673SKrishnendu.Sadhukhan@Sun.COM 			len = snprintf(ptr, ptrsize,
146*10673SKrishnendu.Sadhukhan@Sun.COM 			    "%s`%s ", dts.dts_object, dts.dts_name);
147*10673SKrishnendu.Sadhukhan@Sun.COM 			ptrsize -= len;
148*10673SKrishnendu.Sadhukhan@Sun.COM 
149*10673SKrishnendu.Sadhukhan@Sun.COM 			if (ptrsize <= 0) {
150*10673SKrishnendu.Sadhukhan@Sun.COM 				/*
151*10673SKrishnendu.Sadhukhan@Sun.COM 				 * snprintf returns "desired" length, so
152*10673SKrishnendu.Sadhukhan@Sun.COM 				 * reaching here means our buffer is full.
153*10673SKrishnendu.Sadhukhan@Sun.COM 				 * Move ptr to the last byte of the buffer and
154*10673SKrishnendu.Sadhukhan@Sun.COM 				 * break.
155*10673SKrishnendu.Sadhukhan@Sun.COM 				 */
156*10673SKrishnendu.Sadhukhan@Sun.COM 				ptr = &buffer[buffersize-1];
157*10673SKrishnendu.Sadhukhan@Sun.COM 				break;
158*10673SKrishnendu.Sadhukhan@Sun.COM 			} else {
159*10673SKrishnendu.Sadhukhan@Sun.COM 				ptr += len;
160*10673SKrishnendu.Sadhukhan@Sun.COM 			}
161*10673SKrishnendu.Sadhukhan@Sun.COM 		}
162*10673SKrishnendu.Sadhukhan@Sun.COM 	}
163*10673SKrishnendu.Sadhukhan@Sun.COM 
164*10673SKrishnendu.Sadhukhan@Sun.COM 	if (ptr != buffer) {
165*10673SKrishnendu.Sadhukhan@Sun.COM 		/*
166*10673SKrishnendu.Sadhukhan@Sun.COM 		 * We have printed something, so it is safe to remove
167*10673SKrishnendu.Sadhukhan@Sun.COM 		 * the last ' '.
168*10673SKrishnendu.Sadhukhan@Sun.COM 		 */
169*10673SKrishnendu.Sadhukhan@Sun.COM 		*(ptr-1) = '\0';
170*10673SKrishnendu.Sadhukhan@Sun.COM 	}
171*10673SKrishnendu.Sadhukhan@Sun.COM 
172*10673SKrishnendu.Sadhukhan@Sun.COM 	tag = (char *)data->dtada_data +
173*10673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_TAG].dtrd_offset;
174*10673SKrishnendu.Sadhukhan@Sun.COM 
175*10673SKrishnendu.Sadhukhan@Sun.COM 	priority = rec_get_value(
176*10673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_PRIO].dtrd_offset,
177*10673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_PRIO].dtrd_size);
178*10673SKrishnendu.Sadhukhan@Sun.COM 
179*10673SKrishnendu.Sadhukhan@Sun.COM 	agg_value = rec_get_value(
180*10673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_AGG].dtrd_offset,
181*10673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_AGG].dtrd_size);
182*10673SKrishnendu.Sadhukhan@Sun.COM 
183*10673SKrishnendu.Sadhukhan@Sun.COM 	lt_stat_update(pid, tid, buffer, tag, priority, stat_type, agg_value);
184*10673SKrishnendu.Sadhukhan@Sun.COM 
185*10673SKrishnendu.Sadhukhan@Sun.COM 	if (buffer != NULL)  {
186*10673SKrishnendu.Sadhukhan@Sun.COM 		free(buffer);
187*10673SKrishnendu.Sadhukhan@Sun.COM 	}
188*10673SKrishnendu.Sadhukhan@Sun.COM 
189*10673SKrishnendu.Sadhukhan@Sun.COM 	return (0);
190*10673SKrishnendu.Sadhukhan@Sun.COM }
191*10673SKrishnendu.Sadhukhan@Sun.COM 
192*10673SKrishnendu.Sadhukhan@Sun.COM /*
193*10673SKrishnendu.Sadhukhan@Sun.COM  * Callback to process aggregation lt_named_* (related to lock spinning etc.),
194*10673SKrishnendu.Sadhukhan@Sun.COM  * in the snapshot.
195*10673SKrishnendu.Sadhukhan@Sun.COM  */
196*10673SKrishnendu.Sadhukhan@Sun.COM static int
197*10673SKrishnendu.Sadhukhan@Sun.COM aggwalk_named(const dtrace_aggdata_t *data, lt_stat_type_t stat_type)
198*10673SKrishnendu.Sadhukhan@Sun.COM {
199*10673SKrishnendu.Sadhukhan@Sun.COM 	dtrace_aggdesc_t *aggdesc = data->dtada_desc;
200*10673SKrishnendu.Sadhukhan@Sun.COM 	pid_t pid;
201*10673SKrishnendu.Sadhukhan@Sun.COM 	id_t tid;
202*10673SKrishnendu.Sadhukhan@Sun.COM 	uint64_t agg_value;
203*10673SKrishnendu.Sadhukhan@Sun.COM 	int cause_id;
204*10673SKrishnendu.Sadhukhan@Sun.COM 	char *type = NULL;
205*10673SKrishnendu.Sadhukhan@Sun.COM 	enum { REC_PID = 1, REC_TID, REC_TYPE, REC_AGG, NREC };
206*10673SKrishnendu.Sadhukhan@Sun.COM 
207*10673SKrishnendu.Sadhukhan@Sun.COM 	/* Check action type */
208*10673SKrishnendu.Sadhukhan@Sun.COM 	if ((aggdesc->dtagd_nrecs < NREC) ||
209*10673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_PID].dtrd_action != DTRACEACT_DIFEXPR) ||
210*10673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_TID].dtrd_action != DTRACEACT_DIFEXPR) ||
211*10673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_TYPE].dtrd_action != DTRACEACT_DIFEXPR) ||
212*10673SKrishnendu.Sadhukhan@Sun.COM 	    (!DTRACEACT_ISAGG(aggdesc->dtagd_rec[REC_AGG].dtrd_action))) {
213*10673SKrishnendu.Sadhukhan@Sun.COM 
214*10673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
215*10673SKrishnendu.Sadhukhan@Sun.COM 	}
216*10673SKrishnendu.Sadhukhan@Sun.COM 
217*10673SKrishnendu.Sadhukhan@Sun.COM 	pid = rec_get_value(
218*10673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_PID].dtrd_offset,
219*10673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_PID].dtrd_size);
220*10673SKrishnendu.Sadhukhan@Sun.COM 
221*10673SKrishnendu.Sadhukhan@Sun.COM 	if (SHOULD_IGNORE(pid)) {
222*10673SKrishnendu.Sadhukhan@Sun.COM 		return (0);
223*10673SKrishnendu.Sadhukhan@Sun.COM 	}
224*10673SKrishnendu.Sadhukhan@Sun.COM 
225*10673SKrishnendu.Sadhukhan@Sun.COM 	tid = rec_get_value(
226*10673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_TID].dtrd_offset,
227*10673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_TID].dtrd_size);
228*10673SKrishnendu.Sadhukhan@Sun.COM 
229*10673SKrishnendu.Sadhukhan@Sun.COM 	type = (char *)data->dtada_data
230*10673SKrishnendu.Sadhukhan@Sun.COM 	    + aggdesc->dtagd_rec[REC_TYPE].dtrd_offset;
231*10673SKrishnendu.Sadhukhan@Sun.COM 	cause_id = lt_table_cause_from_name(type, 1, CAUSE_FLAG_SPECIAL);
232*10673SKrishnendu.Sadhukhan@Sun.COM 
233*10673SKrishnendu.Sadhukhan@Sun.COM 	agg_value = rec_get_value(
234*10673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_AGG].dtrd_offset,
235*10673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_AGG].dtrd_size);
236*10673SKrishnendu.Sadhukhan@Sun.COM 
237*10673SKrishnendu.Sadhukhan@Sun.COM 	lt_stat_update_cause(pid, tid, cause_id, stat_type, agg_value);
238*10673SKrishnendu.Sadhukhan@Sun.COM 
239*10673SKrishnendu.Sadhukhan@Sun.COM 	return (0);
240*10673SKrishnendu.Sadhukhan@Sun.COM 
241*10673SKrishnendu.Sadhukhan@Sun.COM }
242*10673SKrishnendu.Sadhukhan@Sun.COM 
243*10673SKrishnendu.Sadhukhan@Sun.COM /*
244*10673SKrishnendu.Sadhukhan@Sun.COM  * Callback to process aggregation lt_sync_* (related to synchronization
245*10673SKrishnendu.Sadhukhan@Sun.COM  * objects), in the snapshot.
246*10673SKrishnendu.Sadhukhan@Sun.COM  */
247*10673SKrishnendu.Sadhukhan@Sun.COM static int
248*10673SKrishnendu.Sadhukhan@Sun.COM aggwalk_sync(const dtrace_aggdata_t *data, lt_stat_type_t stat_type)
249*10673SKrishnendu.Sadhukhan@Sun.COM {
250*10673SKrishnendu.Sadhukhan@Sun.COM 	dtrace_aggdesc_t *aggdesc = data->dtada_desc;
251*10673SKrishnendu.Sadhukhan@Sun.COM 	pid_t pid;
252*10673SKrishnendu.Sadhukhan@Sun.COM 	id_t tid;
253*10673SKrishnendu.Sadhukhan@Sun.COM 	uint64_t agg_value;
254*10673SKrishnendu.Sadhukhan@Sun.COM 	int stype;
255*10673SKrishnendu.Sadhukhan@Sun.COM 	unsigned long long wchan;
256*10673SKrishnendu.Sadhukhan@Sun.COM 	enum { REC_PID = 1, REC_TID, REC_STYPE, REC_WCHAN, REC_AGG, NREC };
257*10673SKrishnendu.Sadhukhan@Sun.COM 
258*10673SKrishnendu.Sadhukhan@Sun.COM 	/* Check action type */
259*10673SKrishnendu.Sadhukhan@Sun.COM 	if ((aggdesc->dtagd_nrecs < NREC) ||
260*10673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_PID].dtrd_action != DTRACEACT_DIFEXPR) ||
261*10673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_TID].dtrd_action != DTRACEACT_DIFEXPR) ||
262*10673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_STYPE].dtrd_action != DTRACEACT_DIFEXPR) ||
263*10673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_WCHAN].dtrd_action != DTRACEACT_DIFEXPR) ||
264*10673SKrishnendu.Sadhukhan@Sun.COM 	    (!DTRACEACT_ISAGG(aggdesc->dtagd_rec[REC_AGG].dtrd_action))) {
265*10673SKrishnendu.Sadhukhan@Sun.COM 
266*10673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
267*10673SKrishnendu.Sadhukhan@Sun.COM 	}
268*10673SKrishnendu.Sadhukhan@Sun.COM 
269*10673SKrishnendu.Sadhukhan@Sun.COM 	pid = rec_get_value(
270*10673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_PID].dtrd_offset,
271*10673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_PID].dtrd_size);
272*10673SKrishnendu.Sadhukhan@Sun.COM 
273*10673SKrishnendu.Sadhukhan@Sun.COM 	if (SHOULD_IGNORE(pid)) {
274*10673SKrishnendu.Sadhukhan@Sun.COM 		return (0);
275*10673SKrishnendu.Sadhukhan@Sun.COM 	}
276*10673SKrishnendu.Sadhukhan@Sun.COM 
277*10673SKrishnendu.Sadhukhan@Sun.COM 	tid = rec_get_value(
278*10673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_TID].dtrd_offset,
279*10673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_TID].dtrd_size);
280*10673SKrishnendu.Sadhukhan@Sun.COM 
281*10673SKrishnendu.Sadhukhan@Sun.COM 	stype = rec_get_value(
282*10673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_STYPE].dtrd_offset,
283*10673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_STYPE].dtrd_size);
284*10673SKrishnendu.Sadhukhan@Sun.COM 
285*10673SKrishnendu.Sadhukhan@Sun.COM 	wchan = rec_get_value(
286*10673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_WCHAN].dtrd_offset,
287*10673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_WCHAN].dtrd_size);
288*10673SKrishnendu.Sadhukhan@Sun.COM 
289*10673SKrishnendu.Sadhukhan@Sun.COM 	agg_value = rec_get_value(
290*10673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_AGG].dtrd_offset,
291*10673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_AGG].dtrd_size);
292*10673SKrishnendu.Sadhukhan@Sun.COM 
293*10673SKrishnendu.Sadhukhan@Sun.COM 	lt_stat_update_sobj(pid, tid, stype, wchan, stat_type, agg_value);
294*10673SKrishnendu.Sadhukhan@Sun.COM 
295*10673SKrishnendu.Sadhukhan@Sun.COM 	return (0);
296*10673SKrishnendu.Sadhukhan@Sun.COM }
297*10673SKrishnendu.Sadhukhan@Sun.COM 
298*10673SKrishnendu.Sadhukhan@Sun.COM /*
299*10673SKrishnendu.Sadhukhan@Sun.COM  * Callback to process various aggregations in the snapshot. Called by
300*10673SKrishnendu.Sadhukhan@Sun.COM  * different aggwalk_* functions.
301*10673SKrishnendu.Sadhukhan@Sun.COM  */
302*10673SKrishnendu.Sadhukhan@Sun.COM /* ARGSUSED */
303*10673SKrishnendu.Sadhukhan@Sun.COM static int
304*10673SKrishnendu.Sadhukhan@Sun.COM aggwalk(const dtrace_aggdata_t *data, void *arg)
305*10673SKrishnendu.Sadhukhan@Sun.COM {
306*10673SKrishnendu.Sadhukhan@Sun.COM 	char *tmp;
307*10673SKrishnendu.Sadhukhan@Sun.COM 	char buffer[32];
308*10673SKrishnendu.Sadhukhan@Sun.COM 	lt_stat_type_t stat_type;
309*10673SKrishnendu.Sadhukhan@Sun.COM 	int (*func)(const dtrace_aggdata_t *, lt_stat_type_t);
310*10673SKrishnendu.Sadhukhan@Sun.COM 
311*10673SKrishnendu.Sadhukhan@Sun.COM 	(void) strncpy(buffer, data->dtada_desc->dtagd_name, sizeof (buffer));
312*10673SKrishnendu.Sadhukhan@Sun.COM 	buffer[sizeof (buffer) - 1] = '\0';
313*10673SKrishnendu.Sadhukhan@Sun.COM 	tmp = strtok(buffer, "_");
314*10673SKrishnendu.Sadhukhan@Sun.COM 
315*10673SKrishnendu.Sadhukhan@Sun.COM 	if (tmp == NULL || strcmp(tmp, "lt") != 0) {
316*10673SKrishnendu.Sadhukhan@Sun.COM 		goto done;
317*10673SKrishnendu.Sadhukhan@Sun.COM 	}
318*10673SKrishnendu.Sadhukhan@Sun.COM 
319*10673SKrishnendu.Sadhukhan@Sun.COM 	tmp = strtok(NULL, "_");
320*10673SKrishnendu.Sadhukhan@Sun.COM 
321*10673SKrishnendu.Sadhukhan@Sun.COM 	if (tmp == NULL) {
322*10673SKrishnendu.Sadhukhan@Sun.COM 		goto done;
323*10673SKrishnendu.Sadhukhan@Sun.COM 	} else if (strcmp(tmp, "call") == 0) {
324*10673SKrishnendu.Sadhukhan@Sun.COM 		func = aggwalk_call;
325*10673SKrishnendu.Sadhukhan@Sun.COM 	} else if (strcmp(tmp, "named") == 0) {
326*10673SKrishnendu.Sadhukhan@Sun.COM 		func = aggwalk_named;
327*10673SKrishnendu.Sadhukhan@Sun.COM 	} else if (strcmp(tmp, "sync") == 0) {
328*10673SKrishnendu.Sadhukhan@Sun.COM 		func = aggwalk_sync;
329*10673SKrishnendu.Sadhukhan@Sun.COM 	} else {
330*10673SKrishnendu.Sadhukhan@Sun.COM 		goto done;
331*10673SKrishnendu.Sadhukhan@Sun.COM 	}
332*10673SKrishnendu.Sadhukhan@Sun.COM 
333*10673SKrishnendu.Sadhukhan@Sun.COM 	tmp = strtok(NULL, "_");
334*10673SKrishnendu.Sadhukhan@Sun.COM 
335*10673SKrishnendu.Sadhukhan@Sun.COM 	if (tmp == NULL) {
336*10673SKrishnendu.Sadhukhan@Sun.COM 		goto done;
337*10673SKrishnendu.Sadhukhan@Sun.COM 	} else if (strcmp(tmp, "count") == 0) {
338*10673SKrishnendu.Sadhukhan@Sun.COM 		stat_type = LT_STAT_COUNT;
339*10673SKrishnendu.Sadhukhan@Sun.COM 	} else if (strcmp(tmp, "sum") == 0) {
340*10673SKrishnendu.Sadhukhan@Sun.COM 		stat_type = LT_STAT_SUM;
341*10673SKrishnendu.Sadhukhan@Sun.COM 	} else if (strcmp(tmp, "max") == 0) {
342*10673SKrishnendu.Sadhukhan@Sun.COM 		stat_type = LT_STAT_MAX;
343*10673SKrishnendu.Sadhukhan@Sun.COM 	} else {
344*10673SKrishnendu.Sadhukhan@Sun.COM 		goto done;
345*10673SKrishnendu.Sadhukhan@Sun.COM 	}
346*10673SKrishnendu.Sadhukhan@Sun.COM 
347*10673SKrishnendu.Sadhukhan@Sun.COM 	(void) func(data, stat_type);
348*10673SKrishnendu.Sadhukhan@Sun.COM 
349*10673SKrishnendu.Sadhukhan@Sun.COM done:
350*10673SKrishnendu.Sadhukhan@Sun.COM 	/* We have our data, so remove it from DTrace now */
351*10673SKrishnendu.Sadhukhan@Sun.COM 	return (DTRACE_AGGWALK_REMOVE);
352*10673SKrishnendu.Sadhukhan@Sun.COM }
353*10673SKrishnendu.Sadhukhan@Sun.COM 
354*10673SKrishnendu.Sadhukhan@Sun.COM /*
355*10673SKrishnendu.Sadhukhan@Sun.COM  * Callback to handle event caused by DTrace dropping data.
356*10673SKrishnendu.Sadhukhan@Sun.COM  */
357*10673SKrishnendu.Sadhukhan@Sun.COM /*ARGSUSED*/
358*10673SKrishnendu.Sadhukhan@Sun.COM static int
359*10673SKrishnendu.Sadhukhan@Sun.COM drop_handler(const dtrace_dropdata_t *data, void *user)
360*10673SKrishnendu.Sadhukhan@Sun.COM {
361*10673SKrishnendu.Sadhukhan@Sun.COM 	lt_display_error("Drop: %s\n", data->dtdda_msg);
362*10673SKrishnendu.Sadhukhan@Sun.COM 
363*10673SKrishnendu.Sadhukhan@Sun.COM 	/* Pretend nothing happened, so just continue */
364*10673SKrishnendu.Sadhukhan@Sun.COM 	return (DTRACE_HANDLE_OK);
365*10673SKrishnendu.Sadhukhan@Sun.COM }
366*10673SKrishnendu.Sadhukhan@Sun.COM 
367*10673SKrishnendu.Sadhukhan@Sun.COM #ifndef EMBED_CONFIGS
368*10673SKrishnendu.Sadhukhan@Sun.COM /*
369*10673SKrishnendu.Sadhukhan@Sun.COM  * Copy the content from a "real" file into a temp file.
370*10673SKrishnendu.Sadhukhan@Sun.COM  */
371*10673SKrishnendu.Sadhukhan@Sun.COM static int
372*10673SKrishnendu.Sadhukhan@Sun.COM copy_tmp_file(const char *src, FILE *dst)
373*10673SKrishnendu.Sadhukhan@Sun.COM {
374*10673SKrishnendu.Sadhukhan@Sun.COM 	FILE *tmp = NULL;
375*10673SKrishnendu.Sadhukhan@Sun.COM 	char buffer[256];
376*10673SKrishnendu.Sadhukhan@Sun.COM 	int bytes;
377*10673SKrishnendu.Sadhukhan@Sun.COM 
378*10673SKrishnendu.Sadhukhan@Sun.COM 	if ((tmp = fopen(src, "r")) == NULL) {
379*10673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
380*10673SKrishnendu.Sadhukhan@Sun.COM 	}
381*10673SKrishnendu.Sadhukhan@Sun.COM 
382*10673SKrishnendu.Sadhukhan@Sun.COM 	while ((bytes = fread(buffer, 1, sizeof (buffer), tmp)) > 0) {
383*10673SKrishnendu.Sadhukhan@Sun.COM 		if (fwrite(buffer, bytes, 1, dst) != 1) {
384*10673SKrishnendu.Sadhukhan@Sun.COM 			return (-1);
385*10673SKrishnendu.Sadhukhan@Sun.COM 		}
386*10673SKrishnendu.Sadhukhan@Sun.COM 	}
387*10673SKrishnendu.Sadhukhan@Sun.COM 
388*10673SKrishnendu.Sadhukhan@Sun.COM 	(void) fclose(tmp);
389*10673SKrishnendu.Sadhukhan@Sun.COM 
390*10673SKrishnendu.Sadhukhan@Sun.COM 	return (0);
391*10673SKrishnendu.Sadhukhan@Sun.COM }
392*10673SKrishnendu.Sadhukhan@Sun.COM #endif
393*10673SKrishnendu.Sadhukhan@Sun.COM 
394*10673SKrishnendu.Sadhukhan@Sun.COM /*
395*10673SKrishnendu.Sadhukhan@Sun.COM  * DTrace initialization. D script starts running when this function returns.
396*10673SKrishnendu.Sadhukhan@Sun.COM  */
397*10673SKrishnendu.Sadhukhan@Sun.COM int
398*10673SKrishnendu.Sadhukhan@Sun.COM lt_dtrace_init(void)
399*10673SKrishnendu.Sadhukhan@Sun.COM {
400*10673SKrishnendu.Sadhukhan@Sun.COM 	dtrace_prog_t *prog;
401*10673SKrishnendu.Sadhukhan@Sun.COM 	dtrace_proginfo_t info;
402*10673SKrishnendu.Sadhukhan@Sun.COM 	int err;
403*10673SKrishnendu.Sadhukhan@Sun.COM 	FILE *fp_script = NULL;
404*10673SKrishnendu.Sadhukhan@Sun.COM 
405*10673SKrishnendu.Sadhukhan@Sun.COM 	pid_self = getpid();
406*10673SKrishnendu.Sadhukhan@Sun.COM 
407*10673SKrishnendu.Sadhukhan@Sun.COM 	if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
408*10673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Cannot open dtrace library: %s\n",
409*10673SKrishnendu.Sadhukhan@Sun.COM 		    dtrace_errmsg(NULL, err));
410*10673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
411*10673SKrishnendu.Sadhukhan@Sun.COM 	}
412*10673SKrishnendu.Sadhukhan@Sun.COM 
413*10673SKrishnendu.Sadhukhan@Sun.COM 	if (dtrace_handle_drop(g_dtp, &drop_handler, NULL) == -1) {
414*10673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Cannot install DTrace handle: %s\n",
415*10673SKrishnendu.Sadhukhan@Sun.COM 		    dtrace_errmsg(NULL, err));
416*10673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
417*10673SKrishnendu.Sadhukhan@Sun.COM 	}
418*10673SKrishnendu.Sadhukhan@Sun.COM 
419*10673SKrishnendu.Sadhukhan@Sun.COM 	if (g_config.lt_cfg_enable_filter) {
420*10673SKrishnendu.Sadhukhan@Sun.COM 		if ((err = dtrace_setopt(g_dtp, "define",
421*10673SKrishnendu.Sadhukhan@Sun.COM 		    "ENABLE_FILTER")) != 0) {
422*10673SKrishnendu.Sadhukhan@Sun.COM 			lt_display_error(
423*10673SKrishnendu.Sadhukhan@Sun.COM 			    "Failed to set option ENABLE_FILTER.\n");
424*10673SKrishnendu.Sadhukhan@Sun.COM 			return (err);
425*10673SKrishnendu.Sadhukhan@Sun.COM 		}
426*10673SKrishnendu.Sadhukhan@Sun.COM 	}
427*10673SKrishnendu.Sadhukhan@Sun.COM 
428*10673SKrishnendu.Sadhukhan@Sun.COM 	if (g_config.lt_cfg_trace_syncobj) {
429*10673SKrishnendu.Sadhukhan@Sun.COM 		if ((err = dtrace_setopt(g_dtp, "define",
430*10673SKrishnendu.Sadhukhan@Sun.COM 		    "ENABLE_SYNCOBJ")) != 0) {
431*10673SKrishnendu.Sadhukhan@Sun.COM 			lt_display_error(
432*10673SKrishnendu.Sadhukhan@Sun.COM 			    "Failed to set option ENABLE_SYNCOBJ.\n");
433*10673SKrishnendu.Sadhukhan@Sun.COM 			return (err);
434*10673SKrishnendu.Sadhukhan@Sun.COM 		}
435*10673SKrishnendu.Sadhukhan@Sun.COM 	}
436*10673SKrishnendu.Sadhukhan@Sun.COM 
437*10673SKrishnendu.Sadhukhan@Sun.COM 	if (g_config.lt_cfg_trace_sched) {
438*10673SKrishnendu.Sadhukhan@Sun.COM 		if ((err = dtrace_setopt(g_dtp, "define",
439*10673SKrishnendu.Sadhukhan@Sun.COM 		    "ENABLE_SCHED")) != 0) {
440*10673SKrishnendu.Sadhukhan@Sun.COM 			lt_display_error(
441*10673SKrishnendu.Sadhukhan@Sun.COM 			    "Failed to set option ENABLE_SYNCOBJ.\n");
442*10673SKrishnendu.Sadhukhan@Sun.COM 			return (err);
443*10673SKrishnendu.Sadhukhan@Sun.COM 		}
444*10673SKrishnendu.Sadhukhan@Sun.COM 	}
445*10673SKrishnendu.Sadhukhan@Sun.COM 
446*10673SKrishnendu.Sadhukhan@Sun.COM 	if (g_config.lt_cfg_low_overhead_mode) {
447*10673SKrishnendu.Sadhukhan@Sun.COM 		if ((err = dtrace_setopt(g_dtp, "define",
448*10673SKrishnendu.Sadhukhan@Sun.COM 		    "ENABLE_LOW_OVERHEAD")) != 0) {
449*10673SKrishnendu.Sadhukhan@Sun.COM 			lt_display_error(
450*10673SKrishnendu.Sadhukhan@Sun.COM 			    "Failed to set option ENABLE_SYNCOBJ.\n");
451*10673SKrishnendu.Sadhukhan@Sun.COM 			return (err);
452*10673SKrishnendu.Sadhukhan@Sun.COM 		}
453*10673SKrishnendu.Sadhukhan@Sun.COM 	}
454*10673SKrishnendu.Sadhukhan@Sun.COM 
455*10673SKrishnendu.Sadhukhan@Sun.COM 	/* Create a temp file; libdtrace needs it for cpp(1) */
456*10673SKrishnendu.Sadhukhan@Sun.COM 	if ((fp_script = tmpfile()) == NULL) {
457*10673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Cannot create tmp file\n");
458*10673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
459*10673SKrishnendu.Sadhukhan@Sun.COM 	}
460*10673SKrishnendu.Sadhukhan@Sun.COM 
461*10673SKrishnendu.Sadhukhan@Sun.COM 	/* Copy the main D script into the temp file */
462*10673SKrishnendu.Sadhukhan@Sun.COM #ifdef EMBED_CONFIGS
463*10673SKrishnendu.Sadhukhan@Sun.COM 	if (fwrite(&latencytop_d_start,
464*10673SKrishnendu.Sadhukhan@Sun.COM 	    (size_t)(&latencytop_d_end - &latencytop_d_start), 1, fp_script)
465*10673SKrishnendu.Sadhukhan@Sun.COM 	    != 1) {
466*10673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Could not copy D script, fwrite() failed\n");
467*10673SKrishnendu.Sadhukhan@Sun.COM 		(void) fclose(fp_script);
468*10673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
469*10673SKrishnendu.Sadhukhan@Sun.COM 	}
470*10673SKrishnendu.Sadhukhan@Sun.COM #else
471*10673SKrishnendu.Sadhukhan@Sun.COM 	if (copy_tmp_file(DEFAULT_D_SCRIPT_NAME, fp_script) != 0) {
472*10673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Cannot open script file %s\n",
473*10673SKrishnendu.Sadhukhan@Sun.COM 		    DEFAULT_D_SCRIPT_NAME);
474*10673SKrishnendu.Sadhukhan@Sun.COM 		(void) fclose(fp_script);
475*10673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
476*10673SKrishnendu.Sadhukhan@Sun.COM 	}
477*10673SKrishnendu.Sadhukhan@Sun.COM #endif	/* EMBED_CONFIGS */
478*10673SKrishnendu.Sadhukhan@Sun.COM 
479*10673SKrishnendu.Sadhukhan@Sun.COM 	if (lt_table_append_trans(fp_script) != 0) {
480*10673SKrishnendu.Sadhukhan@Sun.COM 		(void) fclose(fp_script);
481*10673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
482*10673SKrishnendu.Sadhukhan@Sun.COM 	}
483*10673SKrishnendu.Sadhukhan@Sun.COM 
484*10673SKrishnendu.Sadhukhan@Sun.COM 	(void) fseek(fp_script, 0, SEEK_SET);
485*10673SKrishnendu.Sadhukhan@Sun.COM 
486*10673SKrishnendu.Sadhukhan@Sun.COM 	if ((prog = dtrace_program_fcompile(g_dtp, fp_script,
487*10673SKrishnendu.Sadhukhan@Sun.COM 	    DTRACE_C_CPP, 0, NULL)) == NULL) {
488*10673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Failed to compile D script.\n");
489*10673SKrishnendu.Sadhukhan@Sun.COM 		(void) fclose(fp_script);
490*10673SKrishnendu.Sadhukhan@Sun.COM 		return (dtrace_errno(g_dtp));
491*10673SKrishnendu.Sadhukhan@Sun.COM 	}
492*10673SKrishnendu.Sadhukhan@Sun.COM 
493*10673SKrishnendu.Sadhukhan@Sun.COM 	(void) fclose(fp_script);
494*10673SKrishnendu.Sadhukhan@Sun.COM 
495*10673SKrishnendu.Sadhukhan@Sun.COM 	/* Execute the D script */
496*10673SKrishnendu.Sadhukhan@Sun.COM 	if (dtrace_program_exec(g_dtp, prog, &info) == -1) {
497*10673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Failed to enable probes.\n");
498*10673SKrishnendu.Sadhukhan@Sun.COM 		return (dtrace_errno(g_dtp));
499*10673SKrishnendu.Sadhukhan@Sun.COM 	}
500*10673SKrishnendu.Sadhukhan@Sun.COM 
501*10673SKrishnendu.Sadhukhan@Sun.COM 	if (dtrace_go(g_dtp) != 0) {
502*10673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Failed to run D script.\n");
503*10673SKrishnendu.Sadhukhan@Sun.COM 		return (dtrace_errno(g_dtp));
504*10673SKrishnendu.Sadhukhan@Sun.COM 	}
505*10673SKrishnendu.Sadhukhan@Sun.COM 
506*10673SKrishnendu.Sadhukhan@Sun.COM 	return (0);
507*10673SKrishnendu.Sadhukhan@Sun.COM }
508*10673SKrishnendu.Sadhukhan@Sun.COM 
509*10673SKrishnendu.Sadhukhan@Sun.COM /*
510*10673SKrishnendu.Sadhukhan@Sun.COM  * Worker function to move aggregate data to user space. Called periodically
511*10673SKrishnendu.Sadhukhan@Sun.COM  * to prevent the kernel from running out of memory.
512*10673SKrishnendu.Sadhukhan@Sun.COM  */
513*10673SKrishnendu.Sadhukhan@Sun.COM int
514*10673SKrishnendu.Sadhukhan@Sun.COM lt_dtrace_work(int force)
515*10673SKrishnendu.Sadhukhan@Sun.COM {
516*10673SKrishnendu.Sadhukhan@Sun.COM 	static uint64_t last_snap = 0;
517*10673SKrishnendu.Sadhukhan@Sun.COM 	uint64_t now = lt_millisecond();
518*10673SKrishnendu.Sadhukhan@Sun.COM 
519*10673SKrishnendu.Sadhukhan@Sun.COM 	if (!force && now - last_snap < g_config.lt_cfg_snap_interval) {
520*10673SKrishnendu.Sadhukhan@Sun.COM 		return (last_snap + g_config.lt_cfg_snap_interval - now);
521*10673SKrishnendu.Sadhukhan@Sun.COM 	}
522*10673SKrishnendu.Sadhukhan@Sun.COM 
523*10673SKrishnendu.Sadhukhan@Sun.COM 	if (dtrace_status(g_dtp) == -1) {
524*10673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Failed when getting status: %s\n",
525*10673SKrishnendu.Sadhukhan@Sun.COM 		    dtrace_errmsg(g_dtp, dtrace_errno(g_dtp)));
526*10673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
527*10673SKrishnendu.Sadhukhan@Sun.COM 	}
528*10673SKrishnendu.Sadhukhan@Sun.COM 
529*10673SKrishnendu.Sadhukhan@Sun.COM 	if (dtrace_aggregate_snap(g_dtp) != 0) {
530*10673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Failed to snap aggregate: %s\n",
531*10673SKrishnendu.Sadhukhan@Sun.COM 		    dtrace_errmsg(g_dtp, dtrace_errno(g_dtp)));
532*10673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
533*10673SKrishnendu.Sadhukhan@Sun.COM 	}
534*10673SKrishnendu.Sadhukhan@Sun.COM 
535*10673SKrishnendu.Sadhukhan@Sun.COM 	last_snap = now;
536*10673SKrishnendu.Sadhukhan@Sun.COM 	return (0);
537*10673SKrishnendu.Sadhukhan@Sun.COM }
538*10673SKrishnendu.Sadhukhan@Sun.COM 
539*10673SKrishnendu.Sadhukhan@Sun.COM /*
540*10673SKrishnendu.Sadhukhan@Sun.COM  * Walk through dtrace aggregator and collect data for latencytop to display.
541*10673SKrishnendu.Sadhukhan@Sun.COM  * Called immediately before UI update.
542*10673SKrishnendu.Sadhukhan@Sun.COM  */
543*10673SKrishnendu.Sadhukhan@Sun.COM int
544*10673SKrishnendu.Sadhukhan@Sun.COM lt_dtrace_collect(void)
545*10673SKrishnendu.Sadhukhan@Sun.COM {
546*10673SKrishnendu.Sadhukhan@Sun.COM 	if (lt_dtrace_work(1) != 0) {
547*10673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
548*10673SKrishnendu.Sadhukhan@Sun.COM 	}
549*10673SKrishnendu.Sadhukhan@Sun.COM 
550*10673SKrishnendu.Sadhukhan@Sun.COM 	if (dtrace_aggregate_walk(g_dtp, aggwalk, NULL) != 0) {
551*10673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Failed to sort aggregate: %s\n",
552*10673SKrishnendu.Sadhukhan@Sun.COM 		    dtrace_errmsg(g_dtp, dtrace_errno(g_dtp)));
553*10673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
554*10673SKrishnendu.Sadhukhan@Sun.COM 	}
555*10673SKrishnendu.Sadhukhan@Sun.COM 
556*10673SKrishnendu.Sadhukhan@Sun.COM 	/*
557*10673SKrishnendu.Sadhukhan@Sun.COM 	 * Probably we don't need to clear again, because we have removed
558*10673SKrishnendu.Sadhukhan@Sun.COM 	 * everything. Paranoid ?
559*10673SKrishnendu.Sadhukhan@Sun.COM 	 */
560*10673SKrishnendu.Sadhukhan@Sun.COM 	dtrace_aggregate_clear(g_dtp);
561*10673SKrishnendu.Sadhukhan@Sun.COM 
562*10673SKrishnendu.Sadhukhan@Sun.COM 	return (0);
563*10673SKrishnendu.Sadhukhan@Sun.COM }
564*10673SKrishnendu.Sadhukhan@Sun.COM 
565*10673SKrishnendu.Sadhukhan@Sun.COM /*
566*10673SKrishnendu.Sadhukhan@Sun.COM  * dtrace clean up.
567*10673SKrishnendu.Sadhukhan@Sun.COM  */
568*10673SKrishnendu.Sadhukhan@Sun.COM void
569*10673SKrishnendu.Sadhukhan@Sun.COM lt_dtrace_deinit(void)
570*10673SKrishnendu.Sadhukhan@Sun.COM {
571*10673SKrishnendu.Sadhukhan@Sun.COM 	(void) dtrace_stop(g_dtp);
572*10673SKrishnendu.Sadhukhan@Sun.COM 	dtrace_close(g_dtp);
573*10673SKrishnendu.Sadhukhan@Sun.COM }
574