xref: /onnv-gate/usr/src/cmd/latencytop/common/dwrapper.c (revision 11789:6c7658a179ca)
110673SKrishnendu.Sadhukhan@Sun.COM /*
210673SKrishnendu.Sadhukhan@Sun.COM  * CDDL HEADER START
310673SKrishnendu.Sadhukhan@Sun.COM  *
410673SKrishnendu.Sadhukhan@Sun.COM  * The contents of this file are subject to the terms of the
510673SKrishnendu.Sadhukhan@Sun.COM  * Common Development and Distribution License (the "License").
610673SKrishnendu.Sadhukhan@Sun.COM  * You may not use this file except in compliance with the License.
710673SKrishnendu.Sadhukhan@Sun.COM  *
810673SKrishnendu.Sadhukhan@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910673SKrishnendu.Sadhukhan@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1010673SKrishnendu.Sadhukhan@Sun.COM  * See the License for the specific language governing permissions
1110673SKrishnendu.Sadhukhan@Sun.COM  * and limitations under the License.
1210673SKrishnendu.Sadhukhan@Sun.COM  *
1310673SKrishnendu.Sadhukhan@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1410673SKrishnendu.Sadhukhan@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510673SKrishnendu.Sadhukhan@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1610673SKrishnendu.Sadhukhan@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1710673SKrishnendu.Sadhukhan@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1810673SKrishnendu.Sadhukhan@Sun.COM  *
1910673SKrishnendu.Sadhukhan@Sun.COM  * CDDL HEADER END
2010673SKrishnendu.Sadhukhan@Sun.COM  */
2110673SKrishnendu.Sadhukhan@Sun.COM /*
2210673SKrishnendu.Sadhukhan@Sun.COM  * Copyright (c) 2008-2009, Intel Corporation.
2310673SKrishnendu.Sadhukhan@Sun.COM  * All Rights Reserved.
2410673SKrishnendu.Sadhukhan@Sun.COM  */
2510673SKrishnendu.Sadhukhan@Sun.COM 
2610673SKrishnendu.Sadhukhan@Sun.COM #include <unistd.h>
2710673SKrishnendu.Sadhukhan@Sun.COM #include <stdio.h>
2810673SKrishnendu.Sadhukhan@Sun.COM #include <dtrace.h>
2910673SKrishnendu.Sadhukhan@Sun.COM #include <string.h>
3010673SKrishnendu.Sadhukhan@Sun.COM #include <stdlib.h>
3110673SKrishnendu.Sadhukhan@Sun.COM #include <memory.h>
3210673SKrishnendu.Sadhukhan@Sun.COM #include <limits.h>
3310673SKrishnendu.Sadhukhan@Sun.COM 
3410673SKrishnendu.Sadhukhan@Sun.COM #include "latencytop.h"
3510673SKrishnendu.Sadhukhan@Sun.COM 
3610673SKrishnendu.Sadhukhan@Sun.COM static dtrace_hdl_t *g_dtp = NULL;	/* dtrace handle */
3710673SKrishnendu.Sadhukhan@Sun.COM static pid_t pid_self = -1;		/* PID of our own process */
3810673SKrishnendu.Sadhukhan@Sun.COM 
3910673SKrishnendu.Sadhukhan@Sun.COM /*
4010673SKrishnendu.Sadhukhan@Sun.COM  * Ignore sched if sched is not tracked.
4110673SKrishnendu.Sadhukhan@Sun.COM  * Also ignore ourselves (i.e., latencytop).
4210673SKrishnendu.Sadhukhan@Sun.COM  */
4310673SKrishnendu.Sadhukhan@Sun.COM #define	SHOULD_IGNORE(pid)		\
4410673SKrishnendu.Sadhukhan@Sun.COM 	((!g_config.lt_cfg_trace_sched && 0 == (pid)) || pid_self == (pid))
4510673SKrishnendu.Sadhukhan@Sun.COM 
4610673SKrishnendu.Sadhukhan@Sun.COM /*
4710673SKrishnendu.Sadhukhan@Sun.COM  * Get an integer value from dtrace record.
4810673SKrishnendu.Sadhukhan@Sun.COM  */
4910673SKrishnendu.Sadhukhan@Sun.COM static uint64_t
rec_get_value(void * a,size_t b)5010673SKrishnendu.Sadhukhan@Sun.COM rec_get_value(void *a, size_t b)
5110673SKrishnendu.Sadhukhan@Sun.COM {
5210673SKrishnendu.Sadhukhan@Sun.COM 	uint64_t ret = 0;
5310673SKrishnendu.Sadhukhan@Sun.COM 
5410673SKrishnendu.Sadhukhan@Sun.COM 	switch (b) {
5510673SKrishnendu.Sadhukhan@Sun.COM 	case sizeof (uint64_t):
5610673SKrishnendu.Sadhukhan@Sun.COM 		ret = *((uint64_t *)(a));
5710673SKrishnendu.Sadhukhan@Sun.COM 		break;
5810673SKrishnendu.Sadhukhan@Sun.COM 	case sizeof (uint32_t):
5910673SKrishnendu.Sadhukhan@Sun.COM 		ret = *((uint32_t *)(a));
6010673SKrishnendu.Sadhukhan@Sun.COM 		break;
6110673SKrishnendu.Sadhukhan@Sun.COM 	case sizeof (uint16_t):
6210673SKrishnendu.Sadhukhan@Sun.COM 		ret = *((uint16_t *)(a));
6310673SKrishnendu.Sadhukhan@Sun.COM 		break;
6410673SKrishnendu.Sadhukhan@Sun.COM 	case sizeof (uint8_t):
6510673SKrishnendu.Sadhukhan@Sun.COM 		ret = *((uint8_t *)(a));
6610673SKrishnendu.Sadhukhan@Sun.COM 		break;
6710673SKrishnendu.Sadhukhan@Sun.COM 	default:
6810673SKrishnendu.Sadhukhan@Sun.COM 		break;
6910673SKrishnendu.Sadhukhan@Sun.COM 	}
7010673SKrishnendu.Sadhukhan@Sun.COM 
7110673SKrishnendu.Sadhukhan@Sun.COM 	return (ret);
7210673SKrishnendu.Sadhukhan@Sun.COM }
7310673SKrishnendu.Sadhukhan@Sun.COM 
7410673SKrishnendu.Sadhukhan@Sun.COM /*
7510673SKrishnendu.Sadhukhan@Sun.COM  * Callback to process aggregation lt_call_* (related to on/off cpu
7610673SKrishnendu.Sadhukhan@Sun.COM  * activities) in the snapshot.
7710673SKrishnendu.Sadhukhan@Sun.COM  */
7810673SKrishnendu.Sadhukhan@Sun.COM static int
aggwalk_call(const dtrace_aggdata_t * data,lt_stat_type_t stat_type)7910673SKrishnendu.Sadhukhan@Sun.COM aggwalk_call(const dtrace_aggdata_t *data, lt_stat_type_t stat_type)
8010673SKrishnendu.Sadhukhan@Sun.COM {
8110673SKrishnendu.Sadhukhan@Sun.COM 	dtrace_aggdesc_t *aggdesc = data->dtada_desc;
8210673SKrishnendu.Sadhukhan@Sun.COM 	dtrace_syminfo_t dts;
8310673SKrishnendu.Sadhukhan@Sun.COM 	GElf_Sym sym;
8410673SKrishnendu.Sadhukhan@Sun.COM 	caddr_t addr;
8510673SKrishnendu.Sadhukhan@Sun.COM 	pid_t pid;
8610673SKrishnendu.Sadhukhan@Sun.COM 	id_t tid;
8710673SKrishnendu.Sadhukhan@Sun.COM 	unsigned int stack_depth;
8810673SKrishnendu.Sadhukhan@Sun.COM 	unsigned int pc_size;
8910673SKrishnendu.Sadhukhan@Sun.COM 	uint64_t pc;
9010673SKrishnendu.Sadhukhan@Sun.COM 	uint64_t agg_value;
9110673SKrishnendu.Sadhukhan@Sun.COM 	char *ptr = NULL;
9210673SKrishnendu.Sadhukhan@Sun.COM 	char *buffer = NULL;
9310673SKrishnendu.Sadhukhan@Sun.COM 	int ptrsize;
9410673SKrishnendu.Sadhukhan@Sun.COM 	unsigned int buffersize;
9510673SKrishnendu.Sadhukhan@Sun.COM 	char *tag = NULL;
9610673SKrishnendu.Sadhukhan@Sun.COM 	unsigned int priority;
9710673SKrishnendu.Sadhukhan@Sun.COM 	enum { REC_PID = 1, REC_TID, REC_STACK, REC_TAG, REC_PRIO, REC_AGG,
9810673SKrishnendu.Sadhukhan@Sun.COM 	    NREC };
9910673SKrishnendu.Sadhukhan@Sun.COM 
10010673SKrishnendu.Sadhukhan@Sun.COM 	/* Check action type */
10110673SKrishnendu.Sadhukhan@Sun.COM 	if ((aggdesc->dtagd_nrecs < NREC) ||
10210673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_PID].dtrd_action != DTRACEACT_DIFEXPR) ||
10310673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_TID].dtrd_action != DTRACEACT_DIFEXPR) ||
10410673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_TAG].dtrd_action != DTRACEACT_DIFEXPR) ||
10510673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_PRIO].dtrd_action != DTRACEACT_DIFEXPR) ||
10610673SKrishnendu.Sadhukhan@Sun.COM 	    (!DTRACEACT_ISAGG(aggdesc->dtagd_rec[REC_AGG].dtrd_action)) ||
10710673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_STACK].dtrd_action != DTRACEACT_STACK)) {
10810673SKrishnendu.Sadhukhan@Sun.COM 
10910673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
11010673SKrishnendu.Sadhukhan@Sun.COM 	}
11110673SKrishnendu.Sadhukhan@Sun.COM 
11210673SKrishnendu.Sadhukhan@Sun.COM 	pid = rec_get_value(
11310673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_PID].dtrd_offset,
11410673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_PID].dtrd_size);
11510673SKrishnendu.Sadhukhan@Sun.COM 
11610673SKrishnendu.Sadhukhan@Sun.COM 	if (SHOULD_IGNORE(pid)) {
11710673SKrishnendu.Sadhukhan@Sun.COM 		return (0);
11810673SKrishnendu.Sadhukhan@Sun.COM 	}
11910673SKrishnendu.Sadhukhan@Sun.COM 
12010673SKrishnendu.Sadhukhan@Sun.COM 	tid = rec_get_value(
12110673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_TID].dtrd_offset,
12210673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_TID].dtrd_size);
12310673SKrishnendu.Sadhukhan@Sun.COM 
12410673SKrishnendu.Sadhukhan@Sun.COM 	/* Parse stack array from dtagd_rec */
12510673SKrishnendu.Sadhukhan@Sun.COM 	stack_depth = aggdesc->dtagd_rec[REC_STACK].dtrd_arg;
12610673SKrishnendu.Sadhukhan@Sun.COM 	pc_size = aggdesc->dtagd_rec[REC_STACK].dtrd_size / stack_depth;
12710673SKrishnendu.Sadhukhan@Sun.COM 	addr = data->dtada_data + aggdesc->dtagd_rec[REC_STACK].dtrd_offset;
12810673SKrishnendu.Sadhukhan@Sun.COM 	buffersize = (stack_depth * (2 * PATH_MAX + 2) + 1) * sizeof (char);
12910673SKrishnendu.Sadhukhan@Sun.COM 	buffer = (char *)lt_malloc(buffersize);
13010673SKrishnendu.Sadhukhan@Sun.COM 	ptr = buffer;
13110673SKrishnendu.Sadhukhan@Sun.COM 	ptrsize = buffersize;
13210673SKrishnendu.Sadhukhan@Sun.COM 
13310673SKrishnendu.Sadhukhan@Sun.COM 	/* Print the stack */
13410673SKrishnendu.Sadhukhan@Sun.COM 	while (stack_depth > 0) {
13510673SKrishnendu.Sadhukhan@Sun.COM 		pc = rec_get_value(addr, pc_size);
13610673SKrishnendu.Sadhukhan@Sun.COM 
13710673SKrishnendu.Sadhukhan@Sun.COM 		if (pc == 0) {
13810673SKrishnendu.Sadhukhan@Sun.COM 			break;
13910673SKrishnendu.Sadhukhan@Sun.COM 		}
14010673SKrishnendu.Sadhukhan@Sun.COM 
14110673SKrishnendu.Sadhukhan@Sun.COM 		addr += pc_size;
14210673SKrishnendu.Sadhukhan@Sun.COM 
14310673SKrishnendu.Sadhukhan@Sun.COM 		if (dtrace_lookup_by_addr(g_dtp, pc, &sym, &dts) == 0) {
14410673SKrishnendu.Sadhukhan@Sun.COM 			int len;
14510673SKrishnendu.Sadhukhan@Sun.COM 			len = snprintf(ptr, ptrsize,
14610673SKrishnendu.Sadhukhan@Sun.COM 			    "%s`%s ", dts.dts_object, dts.dts_name);
14710673SKrishnendu.Sadhukhan@Sun.COM 			ptrsize -= len;
14810673SKrishnendu.Sadhukhan@Sun.COM 
14910673SKrishnendu.Sadhukhan@Sun.COM 			if (ptrsize <= 0) {
15010673SKrishnendu.Sadhukhan@Sun.COM 				/*
15110673SKrishnendu.Sadhukhan@Sun.COM 				 * snprintf returns "desired" length, so
15210673SKrishnendu.Sadhukhan@Sun.COM 				 * reaching here means our buffer is full.
15310673SKrishnendu.Sadhukhan@Sun.COM 				 * Move ptr to the last byte of the buffer and
15410673SKrishnendu.Sadhukhan@Sun.COM 				 * break.
15510673SKrishnendu.Sadhukhan@Sun.COM 				 */
15610673SKrishnendu.Sadhukhan@Sun.COM 				ptr = &buffer[buffersize-1];
15710673SKrishnendu.Sadhukhan@Sun.COM 				break;
15810673SKrishnendu.Sadhukhan@Sun.COM 			} else {
15910673SKrishnendu.Sadhukhan@Sun.COM 				ptr += len;
16010673SKrishnendu.Sadhukhan@Sun.COM 			}
16110673SKrishnendu.Sadhukhan@Sun.COM 		}
16210673SKrishnendu.Sadhukhan@Sun.COM 	}
16310673SKrishnendu.Sadhukhan@Sun.COM 
16410673SKrishnendu.Sadhukhan@Sun.COM 	if (ptr != buffer) {
16510673SKrishnendu.Sadhukhan@Sun.COM 		/*
16610673SKrishnendu.Sadhukhan@Sun.COM 		 * We have printed something, so it is safe to remove
16710673SKrishnendu.Sadhukhan@Sun.COM 		 * the last ' '.
16810673SKrishnendu.Sadhukhan@Sun.COM 		 */
16910673SKrishnendu.Sadhukhan@Sun.COM 		*(ptr-1) = '\0';
17010673SKrishnendu.Sadhukhan@Sun.COM 	}
17110673SKrishnendu.Sadhukhan@Sun.COM 
17210673SKrishnendu.Sadhukhan@Sun.COM 	tag = (char *)data->dtada_data +
17310673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_TAG].dtrd_offset;
17410673SKrishnendu.Sadhukhan@Sun.COM 
17510673SKrishnendu.Sadhukhan@Sun.COM 	priority = rec_get_value(
17610673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_PRIO].dtrd_offset,
17710673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_PRIO].dtrd_size);
17810673SKrishnendu.Sadhukhan@Sun.COM 
17910673SKrishnendu.Sadhukhan@Sun.COM 	agg_value = rec_get_value(
18010673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_AGG].dtrd_offset,
18110673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_AGG].dtrd_size);
18210673SKrishnendu.Sadhukhan@Sun.COM 
18310673SKrishnendu.Sadhukhan@Sun.COM 	lt_stat_update(pid, tid, buffer, tag, priority, stat_type, agg_value);
18410673SKrishnendu.Sadhukhan@Sun.COM 
18510673SKrishnendu.Sadhukhan@Sun.COM 	if (buffer != NULL)  {
18610673SKrishnendu.Sadhukhan@Sun.COM 		free(buffer);
18710673SKrishnendu.Sadhukhan@Sun.COM 	}
18810673SKrishnendu.Sadhukhan@Sun.COM 
18910673SKrishnendu.Sadhukhan@Sun.COM 	return (0);
19010673SKrishnendu.Sadhukhan@Sun.COM }
19110673SKrishnendu.Sadhukhan@Sun.COM 
19210673SKrishnendu.Sadhukhan@Sun.COM /*
19310673SKrishnendu.Sadhukhan@Sun.COM  * Callback to process aggregation lt_named_* (related to lock spinning etc.),
19410673SKrishnendu.Sadhukhan@Sun.COM  * in the snapshot.
19510673SKrishnendu.Sadhukhan@Sun.COM  */
19610673SKrishnendu.Sadhukhan@Sun.COM static int
aggwalk_named(const dtrace_aggdata_t * data,lt_stat_type_t stat_type)19710673SKrishnendu.Sadhukhan@Sun.COM aggwalk_named(const dtrace_aggdata_t *data, lt_stat_type_t stat_type)
19810673SKrishnendu.Sadhukhan@Sun.COM {
19910673SKrishnendu.Sadhukhan@Sun.COM 	dtrace_aggdesc_t *aggdesc = data->dtada_desc;
20010673SKrishnendu.Sadhukhan@Sun.COM 	pid_t pid;
20110673SKrishnendu.Sadhukhan@Sun.COM 	id_t tid;
20210673SKrishnendu.Sadhukhan@Sun.COM 	uint64_t agg_value;
20310673SKrishnendu.Sadhukhan@Sun.COM 	int cause_id;
20410673SKrishnendu.Sadhukhan@Sun.COM 	char *type = NULL;
20510673SKrishnendu.Sadhukhan@Sun.COM 	enum { REC_PID = 1, REC_TID, REC_TYPE, REC_AGG, NREC };
20610673SKrishnendu.Sadhukhan@Sun.COM 
20710673SKrishnendu.Sadhukhan@Sun.COM 	/* Check action type */
20810673SKrishnendu.Sadhukhan@Sun.COM 	if ((aggdesc->dtagd_nrecs < NREC) ||
20910673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_PID].dtrd_action != DTRACEACT_DIFEXPR) ||
21010673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_TID].dtrd_action != DTRACEACT_DIFEXPR) ||
21110673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_TYPE].dtrd_action != DTRACEACT_DIFEXPR) ||
21210673SKrishnendu.Sadhukhan@Sun.COM 	    (!DTRACEACT_ISAGG(aggdesc->dtagd_rec[REC_AGG].dtrd_action))) {
21310673SKrishnendu.Sadhukhan@Sun.COM 
21410673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
21510673SKrishnendu.Sadhukhan@Sun.COM 	}
21610673SKrishnendu.Sadhukhan@Sun.COM 
21710673SKrishnendu.Sadhukhan@Sun.COM 	pid = rec_get_value(
21810673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_PID].dtrd_offset,
21910673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_PID].dtrd_size);
22010673SKrishnendu.Sadhukhan@Sun.COM 
22110673SKrishnendu.Sadhukhan@Sun.COM 	if (SHOULD_IGNORE(pid)) {
22210673SKrishnendu.Sadhukhan@Sun.COM 		return (0);
22310673SKrishnendu.Sadhukhan@Sun.COM 	}
22410673SKrishnendu.Sadhukhan@Sun.COM 
22510673SKrishnendu.Sadhukhan@Sun.COM 	tid = rec_get_value(
22610673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_TID].dtrd_offset,
22710673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_TID].dtrd_size);
22810673SKrishnendu.Sadhukhan@Sun.COM 
22910673SKrishnendu.Sadhukhan@Sun.COM 	type = (char *)data->dtada_data
23010673SKrishnendu.Sadhukhan@Sun.COM 	    + aggdesc->dtagd_rec[REC_TYPE].dtrd_offset;
23110673SKrishnendu.Sadhukhan@Sun.COM 	cause_id = lt_table_cause_from_name(type, 1, CAUSE_FLAG_SPECIAL);
23210673SKrishnendu.Sadhukhan@Sun.COM 
23310673SKrishnendu.Sadhukhan@Sun.COM 	agg_value = rec_get_value(
23410673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_AGG].dtrd_offset,
23510673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_AGG].dtrd_size);
23610673SKrishnendu.Sadhukhan@Sun.COM 
23710673SKrishnendu.Sadhukhan@Sun.COM 	lt_stat_update_cause(pid, tid, cause_id, stat_type, agg_value);
23810673SKrishnendu.Sadhukhan@Sun.COM 
23910673SKrishnendu.Sadhukhan@Sun.COM 	return (0);
24010673SKrishnendu.Sadhukhan@Sun.COM 
24110673SKrishnendu.Sadhukhan@Sun.COM }
24210673SKrishnendu.Sadhukhan@Sun.COM 
24310673SKrishnendu.Sadhukhan@Sun.COM /*
24410673SKrishnendu.Sadhukhan@Sun.COM  * Callback to process aggregation lt_sync_* (related to synchronization
24510673SKrishnendu.Sadhukhan@Sun.COM  * objects), in the snapshot.
24610673SKrishnendu.Sadhukhan@Sun.COM  */
24710673SKrishnendu.Sadhukhan@Sun.COM static int
aggwalk_sync(const dtrace_aggdata_t * data,lt_stat_type_t stat_type)24810673SKrishnendu.Sadhukhan@Sun.COM aggwalk_sync(const dtrace_aggdata_t *data, lt_stat_type_t stat_type)
24910673SKrishnendu.Sadhukhan@Sun.COM {
25010673SKrishnendu.Sadhukhan@Sun.COM 	dtrace_aggdesc_t *aggdesc = data->dtada_desc;
25110673SKrishnendu.Sadhukhan@Sun.COM 	pid_t pid;
25210673SKrishnendu.Sadhukhan@Sun.COM 	id_t tid;
25310673SKrishnendu.Sadhukhan@Sun.COM 	uint64_t agg_value;
25410673SKrishnendu.Sadhukhan@Sun.COM 	int stype;
25510673SKrishnendu.Sadhukhan@Sun.COM 	unsigned long long wchan;
25610673SKrishnendu.Sadhukhan@Sun.COM 	enum { REC_PID = 1, REC_TID, REC_STYPE, REC_WCHAN, REC_AGG, NREC };
25710673SKrishnendu.Sadhukhan@Sun.COM 
25810673SKrishnendu.Sadhukhan@Sun.COM 	/* Check action type */
25910673SKrishnendu.Sadhukhan@Sun.COM 	if ((aggdesc->dtagd_nrecs < NREC) ||
26010673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_PID].dtrd_action != DTRACEACT_DIFEXPR) ||
26110673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_TID].dtrd_action != DTRACEACT_DIFEXPR) ||
26210673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_STYPE].dtrd_action != DTRACEACT_DIFEXPR) ||
26310673SKrishnendu.Sadhukhan@Sun.COM 	    (aggdesc->dtagd_rec[REC_WCHAN].dtrd_action != DTRACEACT_DIFEXPR) ||
26410673SKrishnendu.Sadhukhan@Sun.COM 	    (!DTRACEACT_ISAGG(aggdesc->dtagd_rec[REC_AGG].dtrd_action))) {
26510673SKrishnendu.Sadhukhan@Sun.COM 
26610673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
26710673SKrishnendu.Sadhukhan@Sun.COM 	}
26810673SKrishnendu.Sadhukhan@Sun.COM 
26910673SKrishnendu.Sadhukhan@Sun.COM 	pid = rec_get_value(
27010673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_PID].dtrd_offset,
27110673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_PID].dtrd_size);
27210673SKrishnendu.Sadhukhan@Sun.COM 
27310673SKrishnendu.Sadhukhan@Sun.COM 	if (SHOULD_IGNORE(pid)) {
27410673SKrishnendu.Sadhukhan@Sun.COM 		return (0);
27510673SKrishnendu.Sadhukhan@Sun.COM 	}
27610673SKrishnendu.Sadhukhan@Sun.COM 
27710673SKrishnendu.Sadhukhan@Sun.COM 	tid = rec_get_value(
27810673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_TID].dtrd_offset,
27910673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_TID].dtrd_size);
28010673SKrishnendu.Sadhukhan@Sun.COM 
28110673SKrishnendu.Sadhukhan@Sun.COM 	stype = rec_get_value(
28210673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_STYPE].dtrd_offset,
28310673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_STYPE].dtrd_size);
28410673SKrishnendu.Sadhukhan@Sun.COM 
28510673SKrishnendu.Sadhukhan@Sun.COM 	wchan = rec_get_value(
28610673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_WCHAN].dtrd_offset,
28710673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_WCHAN].dtrd_size);
28810673SKrishnendu.Sadhukhan@Sun.COM 
28910673SKrishnendu.Sadhukhan@Sun.COM 	agg_value = rec_get_value(
29010673SKrishnendu.Sadhukhan@Sun.COM 	    data->dtada_data + aggdesc->dtagd_rec[REC_AGG].dtrd_offset,
29110673SKrishnendu.Sadhukhan@Sun.COM 	    aggdesc->dtagd_rec[REC_AGG].dtrd_size);
29210673SKrishnendu.Sadhukhan@Sun.COM 
29310673SKrishnendu.Sadhukhan@Sun.COM 	lt_stat_update_sobj(pid, tid, stype, wchan, stat_type, agg_value);
29410673SKrishnendu.Sadhukhan@Sun.COM 
29510673SKrishnendu.Sadhukhan@Sun.COM 	return (0);
29610673SKrishnendu.Sadhukhan@Sun.COM }
29710673SKrishnendu.Sadhukhan@Sun.COM 
29810673SKrishnendu.Sadhukhan@Sun.COM /*
29910673SKrishnendu.Sadhukhan@Sun.COM  * Callback to process various aggregations in the snapshot. Called by
30010673SKrishnendu.Sadhukhan@Sun.COM  * different aggwalk_* functions.
30110673SKrishnendu.Sadhukhan@Sun.COM  */
30210673SKrishnendu.Sadhukhan@Sun.COM /* ARGSUSED */
30310673SKrishnendu.Sadhukhan@Sun.COM static int
aggwalk(const dtrace_aggdata_t * data,void * arg)30410673SKrishnendu.Sadhukhan@Sun.COM aggwalk(const dtrace_aggdata_t *data, void *arg)
30510673SKrishnendu.Sadhukhan@Sun.COM {
30610673SKrishnendu.Sadhukhan@Sun.COM 	char *tmp;
30710673SKrishnendu.Sadhukhan@Sun.COM 	char buffer[32];
30810673SKrishnendu.Sadhukhan@Sun.COM 	lt_stat_type_t stat_type;
30910673SKrishnendu.Sadhukhan@Sun.COM 	int (*func)(const dtrace_aggdata_t *, lt_stat_type_t);
31010673SKrishnendu.Sadhukhan@Sun.COM 
31110673SKrishnendu.Sadhukhan@Sun.COM 	(void) strncpy(buffer, data->dtada_desc->dtagd_name, sizeof (buffer));
31210673SKrishnendu.Sadhukhan@Sun.COM 	buffer[sizeof (buffer) - 1] = '\0';
31310673SKrishnendu.Sadhukhan@Sun.COM 	tmp = strtok(buffer, "_");
31410673SKrishnendu.Sadhukhan@Sun.COM 
31510673SKrishnendu.Sadhukhan@Sun.COM 	if (tmp == NULL || strcmp(tmp, "lt") != 0) {
31610673SKrishnendu.Sadhukhan@Sun.COM 		goto done;
31710673SKrishnendu.Sadhukhan@Sun.COM 	}
31810673SKrishnendu.Sadhukhan@Sun.COM 
31910673SKrishnendu.Sadhukhan@Sun.COM 	tmp = strtok(NULL, "_");
32010673SKrishnendu.Sadhukhan@Sun.COM 
32110673SKrishnendu.Sadhukhan@Sun.COM 	if (tmp == NULL) {
32210673SKrishnendu.Sadhukhan@Sun.COM 		goto done;
32310673SKrishnendu.Sadhukhan@Sun.COM 	} else if (strcmp(tmp, "call") == 0) {
32410673SKrishnendu.Sadhukhan@Sun.COM 		func = aggwalk_call;
32510673SKrishnendu.Sadhukhan@Sun.COM 	} else if (strcmp(tmp, "named") == 0) {
32610673SKrishnendu.Sadhukhan@Sun.COM 		func = aggwalk_named;
32710673SKrishnendu.Sadhukhan@Sun.COM 	} else if (strcmp(tmp, "sync") == 0) {
32810673SKrishnendu.Sadhukhan@Sun.COM 		func = aggwalk_sync;
32910673SKrishnendu.Sadhukhan@Sun.COM 	} else {
33010673SKrishnendu.Sadhukhan@Sun.COM 		goto done;
33110673SKrishnendu.Sadhukhan@Sun.COM 	}
33210673SKrishnendu.Sadhukhan@Sun.COM 
33310673SKrishnendu.Sadhukhan@Sun.COM 	tmp = strtok(NULL, "_");
33410673SKrishnendu.Sadhukhan@Sun.COM 
33510673SKrishnendu.Sadhukhan@Sun.COM 	if (tmp == NULL) {
33610673SKrishnendu.Sadhukhan@Sun.COM 		goto done;
33710673SKrishnendu.Sadhukhan@Sun.COM 	} else if (strcmp(tmp, "count") == 0) {
33810673SKrishnendu.Sadhukhan@Sun.COM 		stat_type = LT_STAT_COUNT;
33910673SKrishnendu.Sadhukhan@Sun.COM 	} else if (strcmp(tmp, "sum") == 0) {
34010673SKrishnendu.Sadhukhan@Sun.COM 		stat_type = LT_STAT_SUM;
34110673SKrishnendu.Sadhukhan@Sun.COM 	} else if (strcmp(tmp, "max") == 0) {
34210673SKrishnendu.Sadhukhan@Sun.COM 		stat_type = LT_STAT_MAX;
34310673SKrishnendu.Sadhukhan@Sun.COM 	} else {
34410673SKrishnendu.Sadhukhan@Sun.COM 		goto done;
34510673SKrishnendu.Sadhukhan@Sun.COM 	}
34610673SKrishnendu.Sadhukhan@Sun.COM 
34710673SKrishnendu.Sadhukhan@Sun.COM 	(void) func(data, stat_type);
34810673SKrishnendu.Sadhukhan@Sun.COM 
34910673SKrishnendu.Sadhukhan@Sun.COM done:
35010673SKrishnendu.Sadhukhan@Sun.COM 	/* We have our data, so remove it from DTrace now */
35110673SKrishnendu.Sadhukhan@Sun.COM 	return (DTRACE_AGGWALK_REMOVE);
35210673SKrishnendu.Sadhukhan@Sun.COM }
35310673SKrishnendu.Sadhukhan@Sun.COM 
35410673SKrishnendu.Sadhukhan@Sun.COM /*
35510673SKrishnendu.Sadhukhan@Sun.COM  * Callback to handle event caused by DTrace dropping data.
35610673SKrishnendu.Sadhukhan@Sun.COM  */
35710673SKrishnendu.Sadhukhan@Sun.COM /*ARGSUSED*/
35810673SKrishnendu.Sadhukhan@Sun.COM static int
drop_handler(const dtrace_dropdata_t * data,void * user)35910673SKrishnendu.Sadhukhan@Sun.COM drop_handler(const dtrace_dropdata_t *data, void *user)
36010673SKrishnendu.Sadhukhan@Sun.COM {
36110673SKrishnendu.Sadhukhan@Sun.COM 	lt_display_error("Drop: %s\n", data->dtdda_msg);
36210883SKrishnendu.Sadhukhan@Sun.COM 	lt_drop_detected = B_TRUE;
36310673SKrishnendu.Sadhukhan@Sun.COM 
36410673SKrishnendu.Sadhukhan@Sun.COM 	/* Pretend nothing happened, so just continue */
36510673SKrishnendu.Sadhukhan@Sun.COM 	return (DTRACE_HANDLE_OK);
36610673SKrishnendu.Sadhukhan@Sun.COM }
36710673SKrishnendu.Sadhukhan@Sun.COM 
36810673SKrishnendu.Sadhukhan@Sun.COM #ifndef EMBED_CONFIGS
36910673SKrishnendu.Sadhukhan@Sun.COM /*
37010673SKrishnendu.Sadhukhan@Sun.COM  * Copy the content from a "real" file into a temp file.
37110673SKrishnendu.Sadhukhan@Sun.COM  */
37210673SKrishnendu.Sadhukhan@Sun.COM static int
copy_tmp_file(const char * src,FILE * dst)37310673SKrishnendu.Sadhukhan@Sun.COM copy_tmp_file(const char *src, FILE *dst)
37410673SKrishnendu.Sadhukhan@Sun.COM {
37510673SKrishnendu.Sadhukhan@Sun.COM 	FILE *tmp = NULL;
37610673SKrishnendu.Sadhukhan@Sun.COM 	char buffer[256];
37710673SKrishnendu.Sadhukhan@Sun.COM 	int bytes;
37810673SKrishnendu.Sadhukhan@Sun.COM 
37910673SKrishnendu.Sadhukhan@Sun.COM 	if ((tmp = fopen(src, "r")) == NULL) {
38010673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
38110673SKrishnendu.Sadhukhan@Sun.COM 	}
38210673SKrishnendu.Sadhukhan@Sun.COM 
38310673SKrishnendu.Sadhukhan@Sun.COM 	while ((bytes = fread(buffer, 1, sizeof (buffer), tmp)) > 0) {
38410673SKrishnendu.Sadhukhan@Sun.COM 		if (fwrite(buffer, bytes, 1, dst) != 1) {
38510673SKrishnendu.Sadhukhan@Sun.COM 			return (-1);
38610673SKrishnendu.Sadhukhan@Sun.COM 		}
38710673SKrishnendu.Sadhukhan@Sun.COM 	}
38810673SKrishnendu.Sadhukhan@Sun.COM 
38910673SKrishnendu.Sadhukhan@Sun.COM 	(void) fclose(tmp);
39010673SKrishnendu.Sadhukhan@Sun.COM 
39110673SKrishnendu.Sadhukhan@Sun.COM 	return (0);
39210673SKrishnendu.Sadhukhan@Sun.COM }
39310673SKrishnendu.Sadhukhan@Sun.COM #endif
39410673SKrishnendu.Sadhukhan@Sun.COM 
39510673SKrishnendu.Sadhukhan@Sun.COM /*
39610673SKrishnendu.Sadhukhan@Sun.COM  * DTrace initialization. D script starts running when this function returns.
39710673SKrishnendu.Sadhukhan@Sun.COM  */
39810673SKrishnendu.Sadhukhan@Sun.COM int
lt_dtrace_init(void)39910673SKrishnendu.Sadhukhan@Sun.COM lt_dtrace_init(void)
40010673SKrishnendu.Sadhukhan@Sun.COM {
40110673SKrishnendu.Sadhukhan@Sun.COM 	dtrace_prog_t *prog;
40210673SKrishnendu.Sadhukhan@Sun.COM 	dtrace_proginfo_t info;
40310673SKrishnendu.Sadhukhan@Sun.COM 	int err;
40410673SKrishnendu.Sadhukhan@Sun.COM 	FILE *fp_script = NULL;
405*11789SKrishnendu.Sadhukhan@Sun.COM 	char tmp[64];
40610673SKrishnendu.Sadhukhan@Sun.COM 
40710673SKrishnendu.Sadhukhan@Sun.COM 	pid_self = getpid();
40810673SKrishnendu.Sadhukhan@Sun.COM 
40910673SKrishnendu.Sadhukhan@Sun.COM 	if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) {
41010673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Cannot open dtrace library: %s\n",
41110673SKrishnendu.Sadhukhan@Sun.COM 		    dtrace_errmsg(NULL, err));
41210673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
41310673SKrishnendu.Sadhukhan@Sun.COM 	}
41410673SKrishnendu.Sadhukhan@Sun.COM 
41510673SKrishnendu.Sadhukhan@Sun.COM 	if (dtrace_handle_drop(g_dtp, &drop_handler, NULL) == -1) {
41610673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Cannot install DTrace handle: %s\n",
41710673SKrishnendu.Sadhukhan@Sun.COM 		    dtrace_errmsg(NULL, err));
41810673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
41910673SKrishnendu.Sadhukhan@Sun.COM 	}
42010673SKrishnendu.Sadhukhan@Sun.COM 
42110673SKrishnendu.Sadhukhan@Sun.COM 	if (g_config.lt_cfg_enable_filter) {
42210673SKrishnendu.Sadhukhan@Sun.COM 		if ((err = dtrace_setopt(g_dtp, "define",
42310673SKrishnendu.Sadhukhan@Sun.COM 		    "ENABLE_FILTER")) != 0) {
42410673SKrishnendu.Sadhukhan@Sun.COM 			lt_display_error(
42510673SKrishnendu.Sadhukhan@Sun.COM 			    "Failed to set option ENABLE_FILTER.\n");
42610673SKrishnendu.Sadhukhan@Sun.COM 			return (err);
42710673SKrishnendu.Sadhukhan@Sun.COM 		}
42810673SKrishnendu.Sadhukhan@Sun.COM 	}
42910673SKrishnendu.Sadhukhan@Sun.COM 
43010673SKrishnendu.Sadhukhan@Sun.COM 	if (g_config.lt_cfg_trace_syncobj) {
43110673SKrishnendu.Sadhukhan@Sun.COM 		if ((err = dtrace_setopt(g_dtp, "define",
43210673SKrishnendu.Sadhukhan@Sun.COM 		    "ENABLE_SYNCOBJ")) != 0) {
43310673SKrishnendu.Sadhukhan@Sun.COM 			lt_display_error(
43410673SKrishnendu.Sadhukhan@Sun.COM 			    "Failed to set option ENABLE_SYNCOBJ.\n");
43510673SKrishnendu.Sadhukhan@Sun.COM 			return (err);
43610673SKrishnendu.Sadhukhan@Sun.COM 		}
43710673SKrishnendu.Sadhukhan@Sun.COM 	}
43810673SKrishnendu.Sadhukhan@Sun.COM 
43910673SKrishnendu.Sadhukhan@Sun.COM 	if (g_config.lt_cfg_trace_sched) {
44010673SKrishnendu.Sadhukhan@Sun.COM 		if ((err = dtrace_setopt(g_dtp, "define",
44110673SKrishnendu.Sadhukhan@Sun.COM 		    "ENABLE_SCHED")) != 0) {
44210673SKrishnendu.Sadhukhan@Sun.COM 			lt_display_error(
443*11789SKrishnendu.Sadhukhan@Sun.COM 			    "Failed to set option ENABLE_SCHED.\n");
444*11789SKrishnendu.Sadhukhan@Sun.COM 			return (err);
445*11789SKrishnendu.Sadhukhan@Sun.COM 		}
446*11789SKrishnendu.Sadhukhan@Sun.COM 	}
447*11789SKrishnendu.Sadhukhan@Sun.COM 
448*11789SKrishnendu.Sadhukhan@Sun.COM 	if (g_config.lt_cfg_trace_pid != 0) {
449*11789SKrishnendu.Sadhukhan@Sun.COM 		(void) snprintf(tmp, sizeof (tmp), "TRACE_PID=%u",
450*11789SKrishnendu.Sadhukhan@Sun.COM 		    g_config.lt_cfg_trace_pid);
451*11789SKrishnendu.Sadhukhan@Sun.COM 		if ((err = dtrace_setopt(g_dtp, "define", tmp)) != 0) {
452*11789SKrishnendu.Sadhukhan@Sun.COM 			lt_display_error(
453*11789SKrishnendu.Sadhukhan@Sun.COM 			    "Failed to set option TRACE_PID.\n");
454*11789SKrishnendu.Sadhukhan@Sun.COM 			return (err);
455*11789SKrishnendu.Sadhukhan@Sun.COM 		}
456*11789SKrishnendu.Sadhukhan@Sun.COM 	}
457*11789SKrishnendu.Sadhukhan@Sun.COM 
458*11789SKrishnendu.Sadhukhan@Sun.COM 	if (g_config.lt_cfg_trace_pgid != 0) {
459*11789SKrishnendu.Sadhukhan@Sun.COM 		(void) snprintf(tmp, sizeof (tmp), "TRACE_PGID=%u",
460*11789SKrishnendu.Sadhukhan@Sun.COM 		    g_config.lt_cfg_trace_pgid);
461*11789SKrishnendu.Sadhukhan@Sun.COM 		if ((err = dtrace_setopt(g_dtp, "define", tmp)) != 0) {
462*11789SKrishnendu.Sadhukhan@Sun.COM 			lt_display_error(
463*11789SKrishnendu.Sadhukhan@Sun.COM 			    "Failed to set option TRACE_PGID.\n");
46410673SKrishnendu.Sadhukhan@Sun.COM 			return (err);
46510673SKrishnendu.Sadhukhan@Sun.COM 		}
46610673SKrishnendu.Sadhukhan@Sun.COM 	}
46710673SKrishnendu.Sadhukhan@Sun.COM 
46810673SKrishnendu.Sadhukhan@Sun.COM 	if (g_config.lt_cfg_low_overhead_mode) {
46910673SKrishnendu.Sadhukhan@Sun.COM 		if ((err = dtrace_setopt(g_dtp, "define",
47010673SKrishnendu.Sadhukhan@Sun.COM 		    "ENABLE_LOW_OVERHEAD")) != 0) {
47110673SKrishnendu.Sadhukhan@Sun.COM 			lt_display_error(
472*11789SKrishnendu.Sadhukhan@Sun.COM 			    "Failed to set option ENABLE_LOW_OVERHEAD.\n");
47310673SKrishnendu.Sadhukhan@Sun.COM 			return (err);
47410673SKrishnendu.Sadhukhan@Sun.COM 		}
47510673SKrishnendu.Sadhukhan@Sun.COM 	}
47610673SKrishnendu.Sadhukhan@Sun.COM 
47710673SKrishnendu.Sadhukhan@Sun.COM 	/* Create a temp file; libdtrace needs it for cpp(1) */
47810673SKrishnendu.Sadhukhan@Sun.COM 	if ((fp_script = tmpfile()) == NULL) {
47910673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Cannot create tmp file\n");
48010673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
48110673SKrishnendu.Sadhukhan@Sun.COM 	}
48210673SKrishnendu.Sadhukhan@Sun.COM 
48310673SKrishnendu.Sadhukhan@Sun.COM 	/* Copy the main D script into the temp file */
48410673SKrishnendu.Sadhukhan@Sun.COM #ifdef EMBED_CONFIGS
48510673SKrishnendu.Sadhukhan@Sun.COM 	if (fwrite(&latencytop_d_start,
48610673SKrishnendu.Sadhukhan@Sun.COM 	    (size_t)(&latencytop_d_end - &latencytop_d_start), 1, fp_script)
48710673SKrishnendu.Sadhukhan@Sun.COM 	    != 1) {
48810673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Could not copy D script, fwrite() failed\n");
48910673SKrishnendu.Sadhukhan@Sun.COM 		(void) fclose(fp_script);
49010673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
49110673SKrishnendu.Sadhukhan@Sun.COM 	}
49210673SKrishnendu.Sadhukhan@Sun.COM #else
49310673SKrishnendu.Sadhukhan@Sun.COM 	if (copy_tmp_file(DEFAULT_D_SCRIPT_NAME, fp_script) != 0) {
49410673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Cannot open script file %s\n",
49510673SKrishnendu.Sadhukhan@Sun.COM 		    DEFAULT_D_SCRIPT_NAME);
49610673SKrishnendu.Sadhukhan@Sun.COM 		(void) fclose(fp_script);
49710673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
49810673SKrishnendu.Sadhukhan@Sun.COM 	}
49910673SKrishnendu.Sadhukhan@Sun.COM #endif	/* EMBED_CONFIGS */
50010673SKrishnendu.Sadhukhan@Sun.COM 
50110673SKrishnendu.Sadhukhan@Sun.COM 	if (lt_table_append_trans(fp_script) != 0) {
50210673SKrishnendu.Sadhukhan@Sun.COM 		(void) fclose(fp_script);
50310673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
50410673SKrishnendu.Sadhukhan@Sun.COM 	}
50510673SKrishnendu.Sadhukhan@Sun.COM 
50610673SKrishnendu.Sadhukhan@Sun.COM 	(void) fseek(fp_script, 0, SEEK_SET);
50710673SKrishnendu.Sadhukhan@Sun.COM 
50810673SKrishnendu.Sadhukhan@Sun.COM 	if ((prog = dtrace_program_fcompile(g_dtp, fp_script,
50910673SKrishnendu.Sadhukhan@Sun.COM 	    DTRACE_C_CPP, 0, NULL)) == NULL) {
51010673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Failed to compile D script.\n");
51110673SKrishnendu.Sadhukhan@Sun.COM 		(void) fclose(fp_script);
51210673SKrishnendu.Sadhukhan@Sun.COM 		return (dtrace_errno(g_dtp));
51310673SKrishnendu.Sadhukhan@Sun.COM 	}
51410673SKrishnendu.Sadhukhan@Sun.COM 
51510673SKrishnendu.Sadhukhan@Sun.COM 	(void) fclose(fp_script);
51610673SKrishnendu.Sadhukhan@Sun.COM 
51710673SKrishnendu.Sadhukhan@Sun.COM 	/* Execute the D script */
51810673SKrishnendu.Sadhukhan@Sun.COM 	if (dtrace_program_exec(g_dtp, prog, &info) == -1) {
51910673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Failed to enable probes.\n");
52010673SKrishnendu.Sadhukhan@Sun.COM 		return (dtrace_errno(g_dtp));
52110673SKrishnendu.Sadhukhan@Sun.COM 	}
52210673SKrishnendu.Sadhukhan@Sun.COM 
52310673SKrishnendu.Sadhukhan@Sun.COM 	if (dtrace_go(g_dtp) != 0) {
52410673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Failed to run D script.\n");
52510673SKrishnendu.Sadhukhan@Sun.COM 		return (dtrace_errno(g_dtp));
52610673SKrishnendu.Sadhukhan@Sun.COM 	}
52710673SKrishnendu.Sadhukhan@Sun.COM 
52810673SKrishnendu.Sadhukhan@Sun.COM 	return (0);
52910673SKrishnendu.Sadhukhan@Sun.COM }
53010673SKrishnendu.Sadhukhan@Sun.COM 
53110673SKrishnendu.Sadhukhan@Sun.COM /*
53210673SKrishnendu.Sadhukhan@Sun.COM  * Worker function to move aggregate data to user space. Called periodically
53310673SKrishnendu.Sadhukhan@Sun.COM  * to prevent the kernel from running out of memory.
53410673SKrishnendu.Sadhukhan@Sun.COM  */
53510673SKrishnendu.Sadhukhan@Sun.COM int
lt_dtrace_work(int force)53610673SKrishnendu.Sadhukhan@Sun.COM lt_dtrace_work(int force)
53710673SKrishnendu.Sadhukhan@Sun.COM {
53810673SKrishnendu.Sadhukhan@Sun.COM 	static uint64_t last_snap = 0;
53910673SKrishnendu.Sadhukhan@Sun.COM 	uint64_t now = lt_millisecond();
54010673SKrishnendu.Sadhukhan@Sun.COM 
54110673SKrishnendu.Sadhukhan@Sun.COM 	if (!force && now - last_snap < g_config.lt_cfg_snap_interval) {
54210673SKrishnendu.Sadhukhan@Sun.COM 		return (last_snap + g_config.lt_cfg_snap_interval - now);
54310673SKrishnendu.Sadhukhan@Sun.COM 	}
54410673SKrishnendu.Sadhukhan@Sun.COM 
54510673SKrishnendu.Sadhukhan@Sun.COM 	if (dtrace_status(g_dtp) == -1) {
54610673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Failed when getting status: %s\n",
54710673SKrishnendu.Sadhukhan@Sun.COM 		    dtrace_errmsg(g_dtp, dtrace_errno(g_dtp)));
54810673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
54910673SKrishnendu.Sadhukhan@Sun.COM 	}
55010673SKrishnendu.Sadhukhan@Sun.COM 
55110673SKrishnendu.Sadhukhan@Sun.COM 	if (dtrace_aggregate_snap(g_dtp) != 0) {
55210673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Failed to snap aggregate: %s\n",
55310673SKrishnendu.Sadhukhan@Sun.COM 		    dtrace_errmsg(g_dtp, dtrace_errno(g_dtp)));
55410673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
55510673SKrishnendu.Sadhukhan@Sun.COM 	}
55610673SKrishnendu.Sadhukhan@Sun.COM 
55710673SKrishnendu.Sadhukhan@Sun.COM 	last_snap = now;
55810673SKrishnendu.Sadhukhan@Sun.COM 	return (0);
55910673SKrishnendu.Sadhukhan@Sun.COM }
56010673SKrishnendu.Sadhukhan@Sun.COM 
56110673SKrishnendu.Sadhukhan@Sun.COM /*
56210673SKrishnendu.Sadhukhan@Sun.COM  * Walk through dtrace aggregator and collect data for latencytop to display.
56310673SKrishnendu.Sadhukhan@Sun.COM  * Called immediately before UI update.
56410673SKrishnendu.Sadhukhan@Sun.COM  */
56510673SKrishnendu.Sadhukhan@Sun.COM int
lt_dtrace_collect(void)56610673SKrishnendu.Sadhukhan@Sun.COM lt_dtrace_collect(void)
56710673SKrishnendu.Sadhukhan@Sun.COM {
56810673SKrishnendu.Sadhukhan@Sun.COM 	if (lt_dtrace_work(1) != 0) {
56910673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
57010673SKrishnendu.Sadhukhan@Sun.COM 	}
57110673SKrishnendu.Sadhukhan@Sun.COM 
57210673SKrishnendu.Sadhukhan@Sun.COM 	if (dtrace_aggregate_walk(g_dtp, aggwalk, NULL) != 0) {
57310673SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("Failed to sort aggregate: %s\n",
57410673SKrishnendu.Sadhukhan@Sun.COM 		    dtrace_errmsg(g_dtp, dtrace_errno(g_dtp)));
57510673SKrishnendu.Sadhukhan@Sun.COM 		return (-1);
57610673SKrishnendu.Sadhukhan@Sun.COM 	}
57710673SKrishnendu.Sadhukhan@Sun.COM 
57810673SKrishnendu.Sadhukhan@Sun.COM 	/*
57910673SKrishnendu.Sadhukhan@Sun.COM 	 * Probably we don't need to clear again, because we have removed
58010673SKrishnendu.Sadhukhan@Sun.COM 	 * everything. Paranoid ?
58110673SKrishnendu.Sadhukhan@Sun.COM 	 */
58210673SKrishnendu.Sadhukhan@Sun.COM 	dtrace_aggregate_clear(g_dtp);
58310673SKrishnendu.Sadhukhan@Sun.COM 
58410673SKrishnendu.Sadhukhan@Sun.COM 	return (0);
58510673SKrishnendu.Sadhukhan@Sun.COM }
58610673SKrishnendu.Sadhukhan@Sun.COM 
58710673SKrishnendu.Sadhukhan@Sun.COM /*
58810673SKrishnendu.Sadhukhan@Sun.COM  * dtrace clean up.
58910673SKrishnendu.Sadhukhan@Sun.COM  */
59010883SKrishnendu.Sadhukhan@Sun.COM int
lt_dtrace_deinit(void)59110673SKrishnendu.Sadhukhan@Sun.COM lt_dtrace_deinit(void)
59210673SKrishnendu.Sadhukhan@Sun.COM {
59310883SKrishnendu.Sadhukhan@Sun.COM 	int ret = 0;
59410883SKrishnendu.Sadhukhan@Sun.COM 
59510883SKrishnendu.Sadhukhan@Sun.COM 	if (dtrace_stop(g_dtp) != 0) {
59610883SKrishnendu.Sadhukhan@Sun.COM 		lt_display_error("dtrace_stop failed: %s\n",
59710883SKrishnendu.Sadhukhan@Sun.COM 		    dtrace_errmsg(g_dtp, dtrace_errno(g_dtp)));
59810883SKrishnendu.Sadhukhan@Sun.COM 		ret = -1;
59910883SKrishnendu.Sadhukhan@Sun.COM 	}
60010883SKrishnendu.Sadhukhan@Sun.COM 
60110673SKrishnendu.Sadhukhan@Sun.COM 	dtrace_close(g_dtp);
60210883SKrishnendu.Sadhukhan@Sun.COM 
60310883SKrishnendu.Sadhukhan@Sun.COM 	return (ret);
60410673SKrishnendu.Sadhukhan@Sun.COM }
605