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