xref: /titanic_52/usr/src/cmd/tnf/tnfdump/cooked.c (revision 8d483882aa3390058094b043f3d62187b5d1de03)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  *	Copyright (c) 1994, by Sun Microsytems, Inc.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <sys/mman.h>
33 #include <stdio.h>
34 #include <stdarg.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <tnf/tnf.h>
38 #include <errno.h>
39 #include <libintl.h>
40 
41 #include "state.h"
42 
43 #define	STREQ(s1, s2, n)	(strncmp(s1, s2, n) == 0)
44 
45 #define	IS_64BIT(kind)	((1 << kind) &	\
46 				((1 << TNF_K_UINT64) | (1 << TNF_K_INT64)))
47 
48 #define	PROBE_TYPE	"tnf_probe_type"
49 
50 static void print_event			(entry_t *ent);
51 static void insert_event		(tnf_datum_t, tnf_datum_t);
52 static void describe_c_brief		(tnf_datum_t);
53 static void describe_target		(tnf_datum_t);
54 static void describe_c_struct		(tnf_datum_t);
55 static void describe_probe_type		(tnf_datum_t);
56 static void describe_event		(tnf_datum_t, tnf_datum_t, hrtime_t);
57 
58 static hrtime_t		base_time = 0;
59 
60 void
61 print_c_header(void)
62 {
63 	(void) printf("%16s %16s %5s %5s %10s %3s %-25s %s\n",
64 		"----------------", "----------------", "-----", "-----",
65 		"----------", "---", "-------------------------",
66 		"------------------------");
67 	(void) printf("%16s %16s %5s %5s %10s %3s %-25s %s\n",
68 		"Elapsed (ms)", "Delta (ms)", "PID", "LWPID",
69 		"   TID    ", "CPU", "Probe Name", "Data / Description . . .");
70 	(void) printf("%16s %16s %5s %5s %10s %3s %-25s %s\n",
71 		"----------------", "----------------", "-----", "-----",
72 		"----------", "---", "-------------------------",
73 		"------------------------");
74 }
75 
76 static void
77 print_event(entry_t *ent)
78 {
79 	tnf_datum_t	evt, sched;
80 	hrtime_t	normalized_time;
81 
82 	evt = ent->record;
83 	sched = tnf_get_tag_arg(evt);
84 	if (sched == TNF_DATUM_NULL) {
85 		/*
86 		 * should never happen because it had a schedule
87 		 * record earlier
88 		 */
89 		fail(0, gettext("event without a schedule record"));
90 	}
91 	normalized_time = ent->time - base_time;
92 	describe_event(evt, sched, normalized_time);
93 }
94 
95 void
96 print_sorted_events(void)
97 {
98 	entry_t 	*ent;
99 
100 	table_sort();
101 	ent = table_get_entry_indexed(0);
102 	if (ent) {
103 		base_time = ent->time;
104 	}
105 	table_print(&print_event);
106 }
107 
108 void
109 describe_c_record(tnf_datum_t datum)
110 {
111 	char		*name_str;
112 	tnf_datum_t	schedule_rec;
113 
114 	switch (tnf_get_kind(datum)) {
115 
116 	case TNF_K_STRUCT:
117 		/* print only event records */
118 		schedule_rec = tnf_get_tag_arg(datum);
119 		if (schedule_rec != TNF_DATUM_NULL) {
120 			/* event record */
121 			insert_event(datum, schedule_rec);
122 		}
123 		break;
124 	case TNF_K_STRING:
125 	case TNF_K_ARRAY:
126 		/* Skip arrays at top level */
127 		break;
128 	case TNF_K_TYPE:
129 		name_str = tnf_get_type_name(datum);
130 		/* REMIND: filter based on property */
131 		if (STREQ(name_str, PROBE_TYPE, strlen(name_str)))
132 			describe_probe_type(datum);
133 		break;
134 	default:
135 		fail(0, gettext("illegal record at %x (%d)"),
136 			tnf_get_raw(datum), tnf_get_kind(datum));
137 		break;
138 	}
139 
140 }
141 
142 static void
143 describe_probe_type(tnf_datum_t datum)
144 {
145 	unsigned 	n, i;
146 	char 		*slotname;
147 	size_t		slot_len;
148 
149 	n = tnf_get_slot_count(datum);
150 #if 0
151 	/* print the OUTPUT PAD */
152 	(void) printf("%16s %14s %5s %5s %8s %3s %-25s",
153 			"-", "-", "-", "-", "-", "-", "-");
154 #endif
155 	(void) printf("probe\t");
156 	for (i = 0; i < n; i++) {
157 		slotname = tnf_get_slot_name(datum, i);
158 		slot_len = strlen(slotname);
159 
160 		/* print all fields except ... */
161 		if ((!STREQ(slotname, TNF_N_TAG, slot_len)) &&
162 			(!STREQ(slotname, TNF_N_PROPERTIES, slot_len)) &&
163 			(!STREQ(slotname, TNF_N_SLOT_TYPES, slot_len)) &&
164 			(!STREQ(slotname, TNF_N_TYPE_SIZE, slot_len)) &&
165 			(!STREQ(slotname, TNF_N_SLOT_NAMES, slot_len))) {
166 				(void) printf(" ");
167 				(void) printf("%s: ", slotname);
168 				describe_c_brief(tnf_get_slot_indexed(datum,
169 							i));
170 		}
171 	}
172 	(void) printf("\n");
173 }
174 
175 static void
176 insert_event(tnf_datum_t datum, tnf_datum_t schedule_rec)
177 {
178 	tnf_datum_t	temp;
179 	hrtime_t	evt_time;
180 	unsigned	time_delta = 0;
181 	entry_t		element;
182 
183 	temp = tnf_get_slot_named(schedule_rec, TNF_N_TIME_BASE);
184 	evt_time = tnf_get_int64(temp);
185 	temp = tnf_get_slot_named(datum, TNF_N_TIME_DELTA);
186 	time_delta = (unsigned) tnf_get_int32(temp);
187 	evt_time = evt_time + time_delta;
188 
189 	element.time = evt_time;
190 	element.record = datum;
191 	table_insert(&element);
192 }
193 
194 #define	K_TID	"tnf_kthread_id"
195 #define	CPUID	"cpuid"
196 
197 static void
198 describe_event(tnf_datum_t datum, tnf_datum_t schedule_rec, hrtime_t evt_time)
199 {
200 	unsigned 	n, i;
201 	char 		*slotname, *eventname, *tidtype;
202 	tnf_datum_t	temp;
203 	int		lwpid = 0, pid = 0;
204 	int		start_slots = 0;
205 	static hrtime_t	last_time = 0;
206 	unsigned long long	tid = 0;
207 
208 	temp = tnf_get_slot_named(schedule_rec, TNF_N_TID);
209 	if (IS_64BIT(tnf_get_kind(temp))) {
210 		tid = tnf_get_int64(temp);
211 	} else {
212 		tid = (unsigned int)tnf_get_int32(temp);
213 	}
214 	tidtype = tnf_get_type_name(temp);
215 
216 	temp = tnf_get_slot_named(schedule_rec, TNF_N_LWPID);
217 	lwpid = tnf_get_int32(temp);
218 	temp = tnf_get_slot_named(schedule_rec, TNF_N_PID);
219 	pid = tnf_get_int32(temp);
220 
221 	/* XXX should use TNF_N_KERNEL_SCHEDULE, TNF_N_USER_SCHEDULE */
222 	if (strcmp(tidtype, K_TID) == 0) {
223 		int 	cpuid;
224 		/* XXX Assumes cpuid always exists in kernel schedule */
225 		cpuid = tnf_get_int32(tnf_get_slot_named(schedule_rec, CPUID));
226 		/* print the OUTPUT schedule record for Kernel case */
227 		(void) printf("%16.6f %16.6f %5u %5u 0x%-8llx %3d",
228 			evt_time / 1000000.0,
229 			(evt_time - last_time)/1000000.0,
230 			pid, lwpid, tid, cpuid);
231 	} else {
232 		/* print the OUTPUT schedule record */
233 		(void) printf("%16.6f %16.6f %5u %5u %10llu %3s",
234 			evt_time / 1000000.0,
235 			(evt_time - last_time)/1000000.0,
236 			pid, lwpid, tid, "-");
237 	}
238 	/* print the tag */
239 	eventname = tnf_type_get_name(tnf_get_slot_named(datum, TNF_N_TAG));
240 	(void) printf(" %-25s", eventname);
241 
242 	/* heuristic - start of data is after TIME_DELTA field */
243 	start_slots = tnf_get_slot_index(datum, TNF_N_TIME_DELTA);
244 	start_slots++;
245 
246 	n = tnf_get_slot_count(datum);
247 
248 	/* print the rest of the fields */
249 	for (i = start_slots; i < n; i++) {
250 		(void) printf(" ");
251 		slotname = tnf_get_slot_name(datum, i);
252 		(void) printf("%s: ", slotname);
253 		describe_target(tnf_get_slot_indexed(datum, i));
254 	}
255 	(void) printf("\n");
256 	last_time = evt_time;
257 }
258 
259 static void
260 describe_c_struct(tnf_datum_t datum)
261 {
262 	unsigned 	n, i, tag_index;
263 	char 		*slotname;
264 
265 	n = tnf_get_slot_count(datum);
266 
267 	/* print the tag */
268 	(void) printf(" ");
269 	(void) printf("%s: ", "type");
270 	describe_c_brief(tnf_get_slot_named(datum, TNF_N_TAG));
271 	tag_index = tnf_get_slot_index(datum, TNF_N_TAG);
272 
273 	for (i = 0; i < n; i++) {
274 		/* print the rest of the members */
275 		if (i != tag_index) {
276 			(void) printf(" ");
277 			slotname = tnf_get_slot_name(datum, i);
278 			(void) printf("%s: ", slotname);
279 			describe_target(tnf_get_slot_indexed(datum, i));
280 		}
281 	}
282 }
283 
284 static void
285 describe_c_brief(tnf_datum_t datum)
286 {
287 	if (datum == TNF_DATUM_NULL) /* allowed */
288 		(void) printf("0x%-8x <NULL>", 0);
289 
290 	else if (tnf_is_scalar(datum))
291 		describe_scalar(datum);
292 
293 	else if (tnf_is_record(datum)) {
294 
295 		switch (tnf_get_kind(datum)) {
296 		case TNF_K_TYPE:
297 			(void) printf("%s", tnf_type_get_name(datum));
298 			break;
299 		case TNF_K_STRING:
300 			(void) printf("\"%s\"", tnf_get_chars(datum));
301 			break;
302 		default:
303 			(void) printf("<%s>", tnf_get_type_name(datum));
304 		}
305 	} else
306 		fail(0, gettext("inline aggregate slots/elements unhandled"));
307 }
308 
309 static void
310 describe_target(tnf_datum_t datum)
311 {
312 	if (datum == TNF_DATUM_NULL) /* allowed */
313 		(void) printf("0x%-8x <NULL>", 0);
314 
315 	else if (tnf_is_scalar(datum))
316 		describe_scalar(datum);
317 
318 	else if (tnf_is_record(datum)) {
319 
320 		switch (tnf_get_kind(datum)) {
321 		case TNF_K_STRUCT:
322 			(void) printf("{");
323 			describe_c_struct(datum);
324 			(void) printf(" }");
325 			break;
326 		case TNF_K_TYPE:
327 			(void) printf("%s", tnf_type_get_name(datum));
328 			break;
329 		case TNF_K_STRING:
330 			(void) printf("\"%s\"", tnf_get_chars(datum));
331 			break;
332 		default:
333 			(void) printf("<%s>", tnf_get_type_name(datum));
334 		}
335 	} else
336 		fail(0, gettext("inline aggregate slots/elements unhandled"));
337 }
338