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 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 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 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 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 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 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); 362*10883SKrishnendu.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 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 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; 40510673SKrishnendu.Sadhukhan@Sun.COM 40610673SKrishnendu.Sadhukhan@Sun.COM pid_self = getpid(); 40710673SKrishnendu.Sadhukhan@Sun.COM 40810673SKrishnendu.Sadhukhan@Sun.COM if ((g_dtp = dtrace_open(DTRACE_VERSION, 0, &err)) == NULL) { 40910673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Cannot open dtrace library: %s\n", 41010673SKrishnendu.Sadhukhan@Sun.COM dtrace_errmsg(NULL, err)); 41110673SKrishnendu.Sadhukhan@Sun.COM return (-1); 41210673SKrishnendu.Sadhukhan@Sun.COM } 41310673SKrishnendu.Sadhukhan@Sun.COM 41410673SKrishnendu.Sadhukhan@Sun.COM if (dtrace_handle_drop(g_dtp, &drop_handler, NULL) == -1) { 41510673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Cannot install DTrace handle: %s\n", 41610673SKrishnendu.Sadhukhan@Sun.COM dtrace_errmsg(NULL, err)); 41710673SKrishnendu.Sadhukhan@Sun.COM return (-1); 41810673SKrishnendu.Sadhukhan@Sun.COM } 41910673SKrishnendu.Sadhukhan@Sun.COM 42010673SKrishnendu.Sadhukhan@Sun.COM if (g_config.lt_cfg_enable_filter) { 42110673SKrishnendu.Sadhukhan@Sun.COM if ((err = dtrace_setopt(g_dtp, "define", 42210673SKrishnendu.Sadhukhan@Sun.COM "ENABLE_FILTER")) != 0) { 42310673SKrishnendu.Sadhukhan@Sun.COM lt_display_error( 42410673SKrishnendu.Sadhukhan@Sun.COM "Failed to set option ENABLE_FILTER.\n"); 42510673SKrishnendu.Sadhukhan@Sun.COM return (err); 42610673SKrishnendu.Sadhukhan@Sun.COM } 42710673SKrishnendu.Sadhukhan@Sun.COM } 42810673SKrishnendu.Sadhukhan@Sun.COM 42910673SKrishnendu.Sadhukhan@Sun.COM if (g_config.lt_cfg_trace_syncobj) { 43010673SKrishnendu.Sadhukhan@Sun.COM if ((err = dtrace_setopt(g_dtp, "define", 43110673SKrishnendu.Sadhukhan@Sun.COM "ENABLE_SYNCOBJ")) != 0) { 43210673SKrishnendu.Sadhukhan@Sun.COM lt_display_error( 43310673SKrishnendu.Sadhukhan@Sun.COM "Failed to set option ENABLE_SYNCOBJ.\n"); 43410673SKrishnendu.Sadhukhan@Sun.COM return (err); 43510673SKrishnendu.Sadhukhan@Sun.COM } 43610673SKrishnendu.Sadhukhan@Sun.COM } 43710673SKrishnendu.Sadhukhan@Sun.COM 43810673SKrishnendu.Sadhukhan@Sun.COM if (g_config.lt_cfg_trace_sched) { 43910673SKrishnendu.Sadhukhan@Sun.COM if ((err = dtrace_setopt(g_dtp, "define", 44010673SKrishnendu.Sadhukhan@Sun.COM "ENABLE_SCHED")) != 0) { 44110673SKrishnendu.Sadhukhan@Sun.COM lt_display_error( 44210673SKrishnendu.Sadhukhan@Sun.COM "Failed to set option ENABLE_SYNCOBJ.\n"); 44310673SKrishnendu.Sadhukhan@Sun.COM return (err); 44410673SKrishnendu.Sadhukhan@Sun.COM } 44510673SKrishnendu.Sadhukhan@Sun.COM } 44610673SKrishnendu.Sadhukhan@Sun.COM 44710673SKrishnendu.Sadhukhan@Sun.COM if (g_config.lt_cfg_low_overhead_mode) { 44810673SKrishnendu.Sadhukhan@Sun.COM if ((err = dtrace_setopt(g_dtp, "define", 44910673SKrishnendu.Sadhukhan@Sun.COM "ENABLE_LOW_OVERHEAD")) != 0) { 45010673SKrishnendu.Sadhukhan@Sun.COM lt_display_error( 45110673SKrishnendu.Sadhukhan@Sun.COM "Failed to set option ENABLE_SYNCOBJ.\n"); 45210673SKrishnendu.Sadhukhan@Sun.COM return (err); 45310673SKrishnendu.Sadhukhan@Sun.COM } 45410673SKrishnendu.Sadhukhan@Sun.COM } 45510673SKrishnendu.Sadhukhan@Sun.COM 45610673SKrishnendu.Sadhukhan@Sun.COM /* Create a temp file; libdtrace needs it for cpp(1) */ 45710673SKrishnendu.Sadhukhan@Sun.COM if ((fp_script = tmpfile()) == NULL) { 45810673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Cannot create tmp file\n"); 45910673SKrishnendu.Sadhukhan@Sun.COM return (-1); 46010673SKrishnendu.Sadhukhan@Sun.COM } 46110673SKrishnendu.Sadhukhan@Sun.COM 46210673SKrishnendu.Sadhukhan@Sun.COM /* Copy the main D script into the temp file */ 46310673SKrishnendu.Sadhukhan@Sun.COM #ifdef EMBED_CONFIGS 46410673SKrishnendu.Sadhukhan@Sun.COM if (fwrite(&latencytop_d_start, 46510673SKrishnendu.Sadhukhan@Sun.COM (size_t)(&latencytop_d_end - &latencytop_d_start), 1, fp_script) 46610673SKrishnendu.Sadhukhan@Sun.COM != 1) { 46710673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Could not copy D script, fwrite() failed\n"); 46810673SKrishnendu.Sadhukhan@Sun.COM (void) fclose(fp_script); 46910673SKrishnendu.Sadhukhan@Sun.COM return (-1); 47010673SKrishnendu.Sadhukhan@Sun.COM } 47110673SKrishnendu.Sadhukhan@Sun.COM #else 47210673SKrishnendu.Sadhukhan@Sun.COM if (copy_tmp_file(DEFAULT_D_SCRIPT_NAME, fp_script) != 0) { 47310673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Cannot open script file %s\n", 47410673SKrishnendu.Sadhukhan@Sun.COM DEFAULT_D_SCRIPT_NAME); 47510673SKrishnendu.Sadhukhan@Sun.COM (void) fclose(fp_script); 47610673SKrishnendu.Sadhukhan@Sun.COM return (-1); 47710673SKrishnendu.Sadhukhan@Sun.COM } 47810673SKrishnendu.Sadhukhan@Sun.COM #endif /* EMBED_CONFIGS */ 47910673SKrishnendu.Sadhukhan@Sun.COM 48010673SKrishnendu.Sadhukhan@Sun.COM if (lt_table_append_trans(fp_script) != 0) { 48110673SKrishnendu.Sadhukhan@Sun.COM (void) fclose(fp_script); 48210673SKrishnendu.Sadhukhan@Sun.COM return (-1); 48310673SKrishnendu.Sadhukhan@Sun.COM } 48410673SKrishnendu.Sadhukhan@Sun.COM 48510673SKrishnendu.Sadhukhan@Sun.COM (void) fseek(fp_script, 0, SEEK_SET); 48610673SKrishnendu.Sadhukhan@Sun.COM 48710673SKrishnendu.Sadhukhan@Sun.COM if ((prog = dtrace_program_fcompile(g_dtp, fp_script, 48810673SKrishnendu.Sadhukhan@Sun.COM DTRACE_C_CPP, 0, NULL)) == NULL) { 48910673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Failed to compile D script.\n"); 49010673SKrishnendu.Sadhukhan@Sun.COM (void) fclose(fp_script); 49110673SKrishnendu.Sadhukhan@Sun.COM return (dtrace_errno(g_dtp)); 49210673SKrishnendu.Sadhukhan@Sun.COM } 49310673SKrishnendu.Sadhukhan@Sun.COM 49410673SKrishnendu.Sadhukhan@Sun.COM (void) fclose(fp_script); 49510673SKrishnendu.Sadhukhan@Sun.COM 49610673SKrishnendu.Sadhukhan@Sun.COM /* Execute the D script */ 49710673SKrishnendu.Sadhukhan@Sun.COM if (dtrace_program_exec(g_dtp, prog, &info) == -1) { 49810673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Failed to enable probes.\n"); 49910673SKrishnendu.Sadhukhan@Sun.COM return (dtrace_errno(g_dtp)); 50010673SKrishnendu.Sadhukhan@Sun.COM } 50110673SKrishnendu.Sadhukhan@Sun.COM 50210673SKrishnendu.Sadhukhan@Sun.COM if (dtrace_go(g_dtp) != 0) { 50310673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Failed to run D script.\n"); 50410673SKrishnendu.Sadhukhan@Sun.COM return (dtrace_errno(g_dtp)); 50510673SKrishnendu.Sadhukhan@Sun.COM } 50610673SKrishnendu.Sadhukhan@Sun.COM 50710673SKrishnendu.Sadhukhan@Sun.COM return (0); 50810673SKrishnendu.Sadhukhan@Sun.COM } 50910673SKrishnendu.Sadhukhan@Sun.COM 51010673SKrishnendu.Sadhukhan@Sun.COM /* 51110673SKrishnendu.Sadhukhan@Sun.COM * Worker function to move aggregate data to user space. Called periodically 51210673SKrishnendu.Sadhukhan@Sun.COM * to prevent the kernel from running out of memory. 51310673SKrishnendu.Sadhukhan@Sun.COM */ 51410673SKrishnendu.Sadhukhan@Sun.COM int 51510673SKrishnendu.Sadhukhan@Sun.COM lt_dtrace_work(int force) 51610673SKrishnendu.Sadhukhan@Sun.COM { 51710673SKrishnendu.Sadhukhan@Sun.COM static uint64_t last_snap = 0; 51810673SKrishnendu.Sadhukhan@Sun.COM uint64_t now = lt_millisecond(); 51910673SKrishnendu.Sadhukhan@Sun.COM 52010673SKrishnendu.Sadhukhan@Sun.COM if (!force && now - last_snap < g_config.lt_cfg_snap_interval) { 52110673SKrishnendu.Sadhukhan@Sun.COM return (last_snap + g_config.lt_cfg_snap_interval - now); 52210673SKrishnendu.Sadhukhan@Sun.COM } 52310673SKrishnendu.Sadhukhan@Sun.COM 52410673SKrishnendu.Sadhukhan@Sun.COM if (dtrace_status(g_dtp) == -1) { 52510673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Failed when getting status: %s\n", 52610673SKrishnendu.Sadhukhan@Sun.COM dtrace_errmsg(g_dtp, dtrace_errno(g_dtp))); 52710673SKrishnendu.Sadhukhan@Sun.COM return (-1); 52810673SKrishnendu.Sadhukhan@Sun.COM } 52910673SKrishnendu.Sadhukhan@Sun.COM 53010673SKrishnendu.Sadhukhan@Sun.COM if (dtrace_aggregate_snap(g_dtp) != 0) { 53110673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Failed to snap aggregate: %s\n", 53210673SKrishnendu.Sadhukhan@Sun.COM dtrace_errmsg(g_dtp, dtrace_errno(g_dtp))); 53310673SKrishnendu.Sadhukhan@Sun.COM return (-1); 53410673SKrishnendu.Sadhukhan@Sun.COM } 53510673SKrishnendu.Sadhukhan@Sun.COM 53610673SKrishnendu.Sadhukhan@Sun.COM last_snap = now; 53710673SKrishnendu.Sadhukhan@Sun.COM return (0); 53810673SKrishnendu.Sadhukhan@Sun.COM } 53910673SKrishnendu.Sadhukhan@Sun.COM 54010673SKrishnendu.Sadhukhan@Sun.COM /* 54110673SKrishnendu.Sadhukhan@Sun.COM * Walk through dtrace aggregator and collect data for latencytop to display. 54210673SKrishnendu.Sadhukhan@Sun.COM * Called immediately before UI update. 54310673SKrishnendu.Sadhukhan@Sun.COM */ 54410673SKrishnendu.Sadhukhan@Sun.COM int 54510673SKrishnendu.Sadhukhan@Sun.COM lt_dtrace_collect(void) 54610673SKrishnendu.Sadhukhan@Sun.COM { 54710673SKrishnendu.Sadhukhan@Sun.COM if (lt_dtrace_work(1) != 0) { 54810673SKrishnendu.Sadhukhan@Sun.COM return (-1); 54910673SKrishnendu.Sadhukhan@Sun.COM } 55010673SKrishnendu.Sadhukhan@Sun.COM 55110673SKrishnendu.Sadhukhan@Sun.COM if (dtrace_aggregate_walk(g_dtp, aggwalk, NULL) != 0) { 55210673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Failed to sort 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 /* 55810673SKrishnendu.Sadhukhan@Sun.COM * Probably we don't need to clear again, because we have removed 55910673SKrishnendu.Sadhukhan@Sun.COM * everything. Paranoid ? 56010673SKrishnendu.Sadhukhan@Sun.COM */ 56110673SKrishnendu.Sadhukhan@Sun.COM dtrace_aggregate_clear(g_dtp); 56210673SKrishnendu.Sadhukhan@Sun.COM 56310673SKrishnendu.Sadhukhan@Sun.COM return (0); 56410673SKrishnendu.Sadhukhan@Sun.COM } 56510673SKrishnendu.Sadhukhan@Sun.COM 56610673SKrishnendu.Sadhukhan@Sun.COM /* 56710673SKrishnendu.Sadhukhan@Sun.COM * dtrace clean up. 56810673SKrishnendu.Sadhukhan@Sun.COM */ 569*10883SKrishnendu.Sadhukhan@Sun.COM int 57010673SKrishnendu.Sadhukhan@Sun.COM lt_dtrace_deinit(void) 57110673SKrishnendu.Sadhukhan@Sun.COM { 572*10883SKrishnendu.Sadhukhan@Sun.COM int ret = 0; 573*10883SKrishnendu.Sadhukhan@Sun.COM 574*10883SKrishnendu.Sadhukhan@Sun.COM if (dtrace_stop(g_dtp) != 0) { 575*10883SKrishnendu.Sadhukhan@Sun.COM lt_display_error("dtrace_stop failed: %s\n", 576*10883SKrishnendu.Sadhukhan@Sun.COM dtrace_errmsg(g_dtp, dtrace_errno(g_dtp))); 577*10883SKrishnendu.Sadhukhan@Sun.COM ret = -1; 578*10883SKrishnendu.Sadhukhan@Sun.COM } 579*10883SKrishnendu.Sadhukhan@Sun.COM 58010673SKrishnendu.Sadhukhan@Sun.COM dtrace_close(g_dtp); 581*10883SKrishnendu.Sadhukhan@Sun.COM 582*10883SKrishnendu.Sadhukhan@Sun.COM return (ret); 58310673SKrishnendu.Sadhukhan@Sun.COM } 584