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
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.
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]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <mdb/mdb_modapi.h>
28 #include <mdb/mdb_ctf.h>
32 mdb_ctf_id_t request_enum
;
33 mdb_ctf_id_t response_enum
;
34 mdb_ctf_id_t ptr_type_enum
;
35 mdb_ctf_id_t thread_state_enum
;
37 hrtime_t max_time_seen
;
40 enum_lookup(char *out
, size_t size
, mdb_ctf_id_t id
, int val
,
41 const char *prefix
, const char *prefix2
)
44 size_t len
= strlen(prefix
);
45 size_t len2
= strlen(prefix2
);
47 if ((cp
= mdb_ctf_enum_name(id
, val
)) != NULL
) {
48 if (strncmp(cp
, prefix
, len
) == 0)
50 if (strncmp(cp
, prefix2
, len2
) == 0)
52 (void) strlcpy(out
, cp
, size
);
54 mdb_snprintf(out
, size
, "? (%d)", val
);
59 make_lower(char *out
, size_t sz
)
61 while (*out
!= 0 && sz
> 0) {
62 if (*out
>= 'A' && *out
<= 'Z')
71 configd_status(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
79 if (mdb_readvar(&num_servers
, "num_servers") == -1) {
80 mdb_warn("unable to read num_servers");
83 if (mdb_readvar(&num_started
, "num_started") == -1) {
84 mdb_warn("unable to read num_started");
88 "\nserver threads:\t%d running, %d starting\n\n", num_servers
,
89 num_started
- num_servers
);
91 if (mdb_walk_dcmd("configd_threads", "configd_thread", argc
,
93 mdb_warn("can't walk 'configd_threads'");
101 configd_thread(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
107 if (!(flags
& DCMD_ADDRSPEC
)) {
108 if (mdb_walk_dcmd("configd_threads", "configd_thread", argc
,
110 mdb_warn("can't walk 'configd_threads'");
119 if (DCMD_HDRSPEC(flags
)) {
120 mdb_printf("%<u>%-?s %5s %-12s %-12s %-?s %-?s %-?s%</u>\n",
121 "ADDR", "TID", "STATE", "PREV_STATE", "CLIENT", "CLIENTRQ",
125 if (mdb_vread(&t
, sizeof (t
), addr
) == -1) {
126 mdb_warn("failed to read thread_info_t at %p", addr
);
130 enum_lookup(state
, sizeof (state
), thread_state_enum
,
131 t
.ti_state
, "TI_", "");
132 make_lower(state
, sizeof (state
));
134 enum_lookup(oldstate
, sizeof (oldstate
), thread_state_enum
,
135 t
.ti_prev_state
, "TI_", "");
136 make_lower(oldstate
, sizeof (oldstate
));
138 mdb_printf("%0?p %5d %-12s %-12s %?p %?p %?p\n",
139 (void *)addr
, t
.ti_thread
, state
, oldstate
,
140 t
.ti_active_client
, t
.ti_client_request
, t
.ti_main_door_request
);
146 walk_thread_info_init(mdb_walk_state_t
*wsp
)
148 if (mdb_readvar(&wsp
->walk_addr
, "thread_list") == -1) {
149 mdb_warn("unable to read thread_list");
153 if (mdb_layered_walk("uu_list_node", wsp
) == -1) {
154 mdb_warn("couldn't walk 'uu_list_node'");
162 walk_thread_info_step(mdb_walk_state_t
*wsp
)
164 uintptr_t addr
= wsp
->walk_addr
;
167 if (mdb_vread(&ti
, sizeof (ti
), addr
) == -1) {
168 mdb_warn("unable to read thread_info_t at %p", addr
);
172 return (wsp
->walk_callback(addr
, &ti
, wsp
->walk_cbdata
));
176 request_log(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
178 request_log_entry_t cur
;
188 uintptr_t client
= 0;
189 uint64_t clientid
= 0;
192 int opt_v
= FALSE
; /* verbose */
194 if (!(flags
& DCMD_ADDRSPEC
)) {
195 if (mdb_walk_dcmd("configd_log", "configd_log", argc
,
197 mdb_warn("can't walk 'configd_log'");
203 if (mdb_getopts(argc
, argv
,
204 'c', MDB_OPT_UINTPTR
, &client
,
205 'i', MDB_OPT_UINT64
, &clientid
,
206 'n', MDB_OPT_UINTPTR
, &node
,
207 'v', MDB_OPT_SETBITS
, TRUE
, &opt_v
, NULL
) != argc
)
210 if (DCMD_HDRSPEC(flags
)) {
211 mdb_printf("%<u>%-?s %-4s %-14s %9s %-22s %-17s\n%</u>",
212 "ADDR", "THRD", "START", "DURATION", "REQUEST",
216 if (mdb_vread(&cur
, sizeof (cur
), addr
) == -1) {
217 mdb_warn("couldn't read log entry at %p", addr
);
222 * apply filters, if any.
224 if (clientid
!= 0 && clientid
!= cur
.rl_clientid
)
227 if (client
!= 0 && client
!= (uintptr_t)cur
.rl_client
)
231 for (idx
= 0; idx
< MIN(MAX_PTRS
, cur
.rl_num_ptrs
); idx
++) {
232 if ((uintptr_t)cur
.rl_ptrs
[idx
].rlp_data
== node
) {
233 node
= 0; /* found it */
241 enum_lookup(requstr
, sizeof (requstr
), request_enum
, cur
.rl_request
,
242 "REP_PROTOCOL_", "");
244 if (cur
.rl_end
!= 0) {
245 enum_lookup(respstr
, sizeof (respstr
), response_enum
,
246 cur
.rl_response
, "REP_PROTOCOL_", "FAIL_");
248 dur
= cur
.rl_end
- cur
.rl_start
;
249 dursec
= dur
/ NANOSEC
;
250 durnsec
= dur
% NANOSEC
;
253 mdb_snprintf(durstr
, sizeof (durstr
),
255 dursec
, durnsec
/ (NANOSEC
/ MICROSEC
));
256 else if (dursec
<= 9999)
257 mdb_snprintf(durstr
, sizeof (durstr
),
259 dursec
, NSEC2MSEC(durnsec
));
261 mdb_snprintf(durstr
, sizeof (durstr
),
264 (void) strcpy(durstr
, "-");
265 (void) strcpy(respstr
, "-");
268 if (max_time_seen
!= 0 && max_time_seen
>= cur
.rl_start
) {
269 dur
= max_time_seen
- cur
.rl_start
;
270 dursec
= dur
/ NANOSEC
;
271 durnsec
= dur
% NANOSEC
;
274 mdb_snprintf(stampstr
, sizeof (stampstr
),
275 "-%lld.%09lld", dursec
, durnsec
);
276 else if (dursec
<= 99999ULL)
277 mdb_snprintf(stampstr
, sizeof (stampstr
),
279 dursec
, durnsec
/ (NANOSEC
/ MICROSEC
));
280 else if (dursec
<= 99999999ULL)
281 mdb_snprintf(stampstr
, sizeof (stampstr
),
283 dursec
, NSEC2MSEC(durnsec
));
285 mdb_snprintf(stampstr
, sizeof (stampstr
),
288 (void) strcpy(stampstr
, "-");
291 mdb_printf("%0?x %4d T%13s %9s %-22s %-17s\n",
292 addr
, cur
.rl_tid
, stampstr
, durstr
, requstr
, respstr
);
295 mdb_printf("\tclient: %?p (%d)\tptrs: %d\tstamp: %llx\n",
296 cur
.rl_client
, cur
.rl_clientid
, cur
.rl_num_ptrs
,
298 for (idx
= 0; idx
< MIN(MAX_PTRS
, cur
.rl_num_ptrs
); idx
++) {
299 enum_lookup(typestr
, sizeof (typestr
), ptr_type_enum
,
300 cur
.rl_ptrs
[idx
].rlp_type
, "RC_PTR_TYPE_", "");
301 mdb_printf("\t\t%-7s %5d %?p %?p\n", typestr
,
302 cur
.rl_ptrs
[idx
].rlp_id
, cur
.rl_ptrs
[idx
].rlp_ptr
,
303 cur
.rl_ptrs
[idx
].rlp_data
);
310 struct request_log_walk
{
314 struct request_entry
{
321 * we want newer items at the top
324 request_entry_compare(const void *l
, const void *r
)
326 const struct request_entry
*lp
= l
;
327 const struct request_entry
*rp
= r
;
329 if (rp
->timestamp
== lp
->timestamp
)
333 * 0 timestamps go first.
335 if (rp
->timestamp
== 0)
337 if (lp
->timestamp
== 0)
340 if (lp
->timestamp
< rp
->timestamp
)
347 request_log_count_thread(uintptr_t addr
, thread_info_t
*tip
, uint_t
*arg
)
355 request_log_add_thread(uintptr_t addr
, thread_info_t
*tip
,
356 struct request_entry
**arg
)
358 if (max_time_seen
< tip
->ti_log
.rl_start
)
359 max_time_seen
= tip
->ti_log
.rl_start
;
361 if (max_time_seen
< tip
->ti_log
.rl_end
)
362 max_time_seen
= tip
->ti_log
.rl_end
;
364 if (tip
->ti_log
.rl_start
!= 0) {
365 if (tip
->ti_log
.rl_end
)
366 (*arg
)->timestamp
= tip
->ti_log
.rl_start
;
368 (*arg
)->timestamp
= 0; /* sort to the top */
370 (*arg
)->addr
= addr
+ offsetof(thread_info_t
, ti_log
);
377 request_log_walk_init(mdb_walk_state_t
*wsp
)
379 struct request_log_walk
*rlw
;
380 struct request_entry
*list
, *listp
;
386 request_log_entry_t
*base
;
387 request_log_entry_t cur
;
389 if (mdb_readvar(&base
, "request_log") == -1) {
390 mdb_warn("couldn't read 'request_log'");
393 if (mdb_readvar(&log_size
, "request_log_size") == -1) {
394 mdb_warn("couldn't read 'request_log_size'");
399 if (mdb_walk("configd_threads", (mdb_walk_cb_t
)request_log_count_thread
,
401 mdb_warn("couldn't walk 'configd_threads'");
405 list
= mdb_zalloc(sizeof (*list
) * size
, UM_SLEEP
);
408 if (mdb_walk("configd_threads", (mdb_walk_cb_t
)request_log_add_thread
,
410 mdb_warn("couldn't walk 'configd_threads'");
411 mdb_free(list
, sizeof (*list
) * size
);
416 for (idx
= 0; idx
< log_size
; idx
++) {
417 uintptr_t addr
= (uintptr_t)&base
[idx
];
418 if (mdb_vread(&cur
, sizeof (cur
), addr
) == -1) {
419 mdb_warn("couldn't read log entry at %p", addr
);
420 mdb_free(list
, sizeof (*list
) * size
);
424 if (max_time_seen
< cur
.rl_start
)
425 max_time_seen
= cur
.rl_start
;
427 if (max_time_seen
< cur
.rl_end
)
428 max_time_seen
= cur
.rl_end
;
430 if (cur
.rl_start
!= 0) {
431 list
[pos
].timestamp
= cur
.rl_start
;
432 list
[pos
].addr
= addr
;
436 qsort(list
, pos
, sizeof (*list
), &request_entry_compare
);
438 rlw
= mdb_zalloc(sizeof (*rlw
), UM_SLEEP
);
440 rlw
->rlw_count
= pos
;
442 rlw
->rlw_list
= list
;
444 wsp
->walk_data
= rlw
;
450 request_log_walk_step(mdb_walk_state_t
*wsp
)
452 struct request_log_walk
*rlw
= wsp
->walk_data
;
454 request_log_entry_t cur
;
456 if (rlw
->rlw_cur
>= rlw
->rlw_count
)
459 addr
= rlw
->rlw_list
[rlw
->rlw_cur
++].addr
;
461 if (mdb_vread(&cur
, sizeof (cur
), addr
) == -1) {
462 mdb_warn("couldn't read log entry at %p", addr
);
465 return (wsp
->walk_callback(addr
, &cur
, wsp
->walk_cbdata
));
469 request_log_walk_fini(mdb_walk_state_t
*wsp
)
471 struct request_log_walk
*rlw
= wsp
->walk_data
;
473 mdb_free(rlw
->rlw_list
, sizeof (*rlw
->rlw_list
) * rlw
->rlw_max
);
474 mdb_free(rlw
, sizeof (*rlw
));
477 static const mdb_dcmd_t dcmds
[] = {
478 { "configd_status", NULL
, "svc.configd status summary",
480 { "configd_thread", "?", "Print a thread_info_t tabularly",
482 { "configd_log", "?[-v] [-c clientptr] [-i clientid]",
483 "Print the request log, or a single entry", request_log
},
487 static const mdb_walker_t walkers
[] = {
488 { "configd_threads", "walks the thread_info_ts for all "
489 "threads", walk_thread_info_init
, walk_thread_info_step
},
490 { "configd_log", "walks the request_log_entry_ts",
491 request_log_walk_init
, request_log_walk_step
,
492 request_log_walk_fini
},
496 static const mdb_modinfo_t modinfo
= {
497 MDB_API_VERSION
, dcmds
, walkers
500 const mdb_modinfo_t
*
503 if (mdb_ctf_lookup_by_name("enum rep_protocol_requestid",
504 &request_enum
) == -1) {
505 mdb_warn("enum rep_protocol_requestid not found");
507 if (mdb_ctf_lookup_by_name("enum rep_protocol_responseid",
508 &response_enum
) == -1) {
509 mdb_warn("enum rep_protocol_responseid not found");
511 if (mdb_ctf_lookup_by_name("enum rc_ptr_type",
512 &ptr_type_enum
) == -1) {
513 mdb_warn("enum rc_ptr_type not found");
515 if (mdb_ctf_lookup_by_name("enum thread_state",
516 &thread_state_enum
) == -1) {
517 mdb_warn("enum thread_state not found");