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 #pragma ident "%Z%%M% %I% %E% SMI"
30 * "Resident" part of TNF -- this has to be around even when the
31 * driver is not loaded.
35 #include <sys/types.h>
36 #include <sys/systm.h>
37 #include <sys/thread.h>
41 #include <sys/msacct.h>
42 #include <sys/tnf_com.h>
43 #include <sys/tnf_writer.h>
44 #include <sys/tnf_probe.h>
46 #include <sys/debug.h>
47 #include <sys/modctl.h>
51 #include "tnf_types.h"
52 #include "tnf_trace.h"
58 #define TNF_PC_COUNT 8
65 * TNF kernel probe management externs
67 extern tnf_probe_control_t
*__tnf_probe_list_head
;
68 extern tnf_tag_data_t
*__tnf_tag_list_head
;
69 extern int tnf_changed_probe_list
;
72 * This makes the state of the TNFW_B_STOPPED bit externally visible
75 volatile int tnf_tracing_active
= 0;
78 * The trace buffer pointer
83 * Stub definitions for tag data pointers
86 /* tnf_writer module */
87 tnf_tag_data_t
*tnf_inline_tag_data
= NULL
;
88 tnf_tag_data_t
*tnf_tagged_tag_data
= NULL
;
89 tnf_tag_data_t
*tnf_scalar_tag_data
= NULL
;
90 tnf_tag_data_t
*tnf_char_tag_data
= NULL
;
91 tnf_tag_data_t
*tnf_int8_tag_data
= NULL
;
92 tnf_tag_data_t
*tnf_uint8_tag_data
= NULL
;
93 tnf_tag_data_t
*tnf_int16_tag_data
= NULL
;
94 tnf_tag_data_t
*tnf_uint16_tag_data
= NULL
;
95 tnf_tag_data_t
*tnf_int32_tag_data
= NULL
;
96 tnf_tag_data_t
*tnf_uint32_tag_data
= NULL
;
97 tnf_tag_data_t
*tnf_int64_tag_data
= NULL
;
98 tnf_tag_data_t
*tnf_uint64_tag_data
= NULL
;
99 tnf_tag_data_t
*tnf_float32_tag_data
= NULL
;
100 tnf_tag_data_t
*tnf_float64_tag_data
= NULL
;
101 tnf_tag_data_t
*tnf_array_tag_data
= NULL
;
102 tnf_tag_data_t
*tnf_string_tag_data
= NULL
;
103 tnf_tag_data_t
*tnf_type_array_tag_data
= NULL
;
104 tnf_tag_data_t
*tnf_name_array_tag_data
= NULL
;
105 tnf_tag_data_t
*tnf_derived_tag_data
= NULL
;
106 tnf_tag_data_t
*tnf_align_tag_data
= NULL
;
107 tnf_tag_data_t
*tnf_derived_base_tag_data
= NULL
;
108 tnf_tag_data_t
*tnf_element_type_tag_data
= NULL
;
109 tnf_tag_data_t
*tnf_header_size_tag_data
= NULL
;
110 tnf_tag_data_t
*tnf_name_tag_data
= NULL
;
111 tnf_tag_data_t
*tnf_opaque_tag_data
= NULL
;
112 tnf_tag_data_t
*tnf_properties_tag_data
= NULL
;
113 tnf_tag_data_t
*tnf_self_size_tag_data
= NULL
;
114 tnf_tag_data_t
*tnf_size_tag_data
= NULL
;
115 tnf_tag_data_t
*tnf_slot_names_tag_data
= NULL
;
116 tnf_tag_data_t
*tnf_slot_types_tag_data
= NULL
;
117 tnf_tag_data_t
*tnf_tag_tag_data
= NULL
;
118 tnf_tag_data_t
*tnf_tag_arg_tag_data
= NULL
;
119 tnf_tag_data_t
*tnf_type_size_tag_data
= NULL
;
120 tnf_tag_data_t
*tnf_struct_tag_data
= NULL
;
121 tnf_tag_data_t
*tnf_file_header_tag_data
= NULL
;
122 tnf_tag_data_t
*tnf_block_header_tag_data
= NULL
;
123 tnf_tag_data_t
*tnf_type_tag_data
= NULL
;
124 tnf_tag_data_t
*tnf_array_type_tag_data
= NULL
;
125 tnf_tag_data_t
*tnf_derived_type_tag_data
= NULL
;
126 tnf_tag_data_t
*tnf_scalar_type_tag_data
= NULL
;
127 tnf_tag_data_t
*tnf_struct_type_tag_data
= NULL
;
129 /* tnf_trace module */
130 tnf_tag_data_t
*tnf_probe_event_tag_data
= NULL
;
131 tnf_tag_data_t
*tnf_time_base_tag_data
= NULL
;
132 tnf_tag_data_t
*tnf_time_delta_tag_data
= NULL
;
133 tnf_tag_data_t
*tnf_pid_tag_data
= NULL
;
134 tnf_tag_data_t
*tnf_lwpid_tag_data
= NULL
;
135 tnf_tag_data_t
*tnf_kthread_id_tag_data
= NULL
;
136 tnf_tag_data_t
*tnf_cpuid_tag_data
= NULL
;
137 tnf_tag_data_t
*tnf_device_tag_data
= NULL
;
138 tnf_tag_data_t
*tnf_symbol_tag_data
= NULL
;
139 tnf_tag_data_t
*tnf_symbols_tag_data
= NULL
;
140 tnf_tag_data_t
*tnf_sysnum_tag_data
= NULL
;
141 tnf_tag_data_t
*tnf_microstate_tag_data
= NULL
;
142 tnf_tag_data_t
*tnf_offset_tag_data
= NULL
;
143 tnf_tag_data_t
*tnf_fault_type_tag_data
= NULL
;
144 tnf_tag_data_t
*tnf_seg_access_tag_data
= NULL
;
145 tnf_tag_data_t
*tnf_bioflags_tag_data
= NULL
;
146 tnf_tag_data_t
*tnf_diskaddr_tag_data
= NULL
;
147 tnf_tag_data_t
*tnf_kernel_schedule_tag_data
= NULL
;
149 tnf_tag_data_t
*tnf_probe_type_tag_data
= NULL
;
151 /* Exported properties */
152 tnf_tag_data_t
***tnf_user_struct_properties
= NULL
;
155 * tnf_thread_create()
156 * Called from thread_create() to initialize thread's tracing state.
157 * XXX Do this when tracing is first turned on
161 tnf_thread_create(kthread_t
*t
)
163 /* If the allocation fails, this thread doesn't trace */
164 t
->t_tnf_tpdp
= kmem_zalloc(sizeof (tnf_ops_t
), KM_NOSLEEP
);
166 TNF_PROBE_3(thread_create
, "thread", /* CSTYLED */,
167 tnf_kthread_id
, tid
, t
,
168 tnf_pid
, pid
, ttoproc(t
)->p_pid
,
169 tnf_symbol
, start_pc
, t
->t_startpc
);
174 * Called from thread_exit() and lwp_exit() if thread has a tpdp.
175 * From this point on, we're off the allthreads list
179 tnf_thread_exit(void)
182 tnf_block_header_t
*block
;
184 TNF_PROBE_0(thread_exit
, "thread", /* CSTYLED */);
185 /* LINTED pointer cast may result in improper alignment */
186 ops
= (tnf_ops_t
*)curthread
->t_tnf_tpdp
;
188 * Mark ops as busy from now on, so it will never be used
189 * again. If we fail on the busy lock, the buffer
190 * deallocation code is cleaning our ops, so we don't need to
191 * do anything. If we get the lock and the buffer exists,
192 * release all blocks we hold. Once we're off allthreads,
193 * the deallocator will not examine our ops.
197 LOCK_INIT_HELD(&ops
->busy
);
198 if (tnf_buf
!= NULL
) {
199 /* Release any A-locks held */
200 block
= ops
->wcb
.tnfw_w_pos
.tnfw_w_block
;
201 ops
->wcb
.tnfw_w_pos
.tnfw_w_block
= NULL
;
203 lock_clear(&block
->A_lock
);
204 block
= ops
->wcb
.tnfw_w_tag_pos
.tnfw_w_block
;
205 ops
->wcb
.tnfw_w_tag_pos
.tnfw_w_block
= NULL
;
207 lock_clear(&block
->A_lock
);
212 * Called from thread_free() if thread has tpdp.
216 tnf_thread_free(kthread_t
*t
)
219 /* LINTED pointer cast may result in improper alignment */
220 ops
= (tnf_ops_t
*)t
->t_tnf_tpdp
;
221 t
->t_tnf_tpdp
= NULL
;
222 kmem_free(ops
, sizeof (*ops
));
227 * Probe wrapper called when tracing is enabled and a thread is
228 * placed on some dispatch queue.
232 tnf_thread_queue(kthread_t
*t
, cpu_t
*cp
, pri_t tpri
)
234 TNF_PROBE_4(thread_queue
, "dispatcher", /* CSTYLED */,
235 tnf_kthread_id
, tid
, t
,
236 tnf_cpuid
, cpuid
, cp
->cpu_id
,
237 tnf_long
, priority
, tpri
,
238 tnf_ulong
, queue_length
,
239 /* cp->cpu_disp->disp_q[tpri].dq_sruncnt */
240 cp
->cpu_disp
->disp_nrunnable
);
242 TNF_PROBE_2(thread_state
, "thread", /* CSTYLED */,
243 tnf_kthread_id
, tid
, t
,
244 tnf_microstate
, state
, LMS_WAIT_CPU
);
248 * pcstack(): fill in, NULL-terminate and return pc stack.
256 n
= getpcstack(pcs
, TNF_PC_COUNT
);
262 * tnf_thread_switch()
263 * Probe wrapper called when tracing enabled and curthread is about to
264 * switch to the next thread.
265 * XXX Simple sleepstate and runstate calculations
268 #define SLPSTATE(t, ts) \
269 (((ts) == TS_STOPPED) ? LMS_STOPPED : \
270 ((t)->t_wchan0 ? LMS_USER_LOCK : LMS_SLEEP))
272 #define RUNSTATE(next, lwp) \
273 ((((lwp = ttolwp(next)) != NULL) && \
274 lwp->lwp_state == LWP_USER) ? \
275 LMS_USER : LMS_SYSTEM)
278 tnf_thread_switch(kthread_t
*next
)
285 pc_t pcs
[TNF_PC_COUNT
+ 1];
291 * If we're a zombie, borrow idle thread's tpdp. This lets
292 * the driver decide whether the buffer is busy by examining
293 * allthreads (idle threads are always on the list).
295 if ((borrow
= (ts
== TS_ZOMB
)) != 0) {
296 ztpdp
= t
->t_tnf_tpdp
;
297 t
->t_tnf_tpdp
= CPU
->cpu_idle_thread
->t_tnf_tpdp
;
302 * If we're blocked, test the blockage probe
304 if (ts
== TS_SLEEP
&& t
->t_wchan
)
306 TNF_PROBE_2(thread_block
, "synch", /* CSTYLED */,
307 tnf_opaque
, reason
, t
->t_wchan
,
308 tnf_symbols
, stack
, (pc_t
*)pcstack(pcs
));
309 #else /* defined(__sparc) */
310 TNF_PROBE_2(thread_block
, "synch", /* CSTYLED */,
311 tnf_opaque
, reason
, t
->t_wchan
,
312 tnf_symbols
, stack
, (tnf_opaque_t
*)pcstack(pcs
));
313 #endif /* defined(__sparc) */
316 * Record outgoing thread's state
317 * Kernel thread ID is implicit in schedule record
318 * supress lint: cast from 32-bit integer to 8-bit integer
319 * tnf_microstate_t = tnf_uint8_t
323 TNF_PROBE_1(thread_state
, "thread", /* CSTYLED */,
324 tnf_microstate
, state
, SLPSTATE(t
, ts
));
326 TNF_PROBE_1(thread_state
, "thread", /* CSTYLED */,
327 tnf_microstate
, state
, SLPSTATE(t
, ts
));
332 * Record incoming thread's state
334 * supress lint: cast from 32-bit integer to 8-bit integer
335 * tnf_microstate_t = tnf_uint8_t
339 TNF_PROBE_2(thread_state
, "thread", /* CSTYLED */,
340 tnf_kthread_id
, tid
, next
,
341 tnf_microstate
, state
, RUNSTATE(next
, lwp
));
343 TNF_PROBE_2(thread_state
, "thread", /* CSTYLED */,
344 tnf_kthread_id
, tid
, next
,
345 tnf_microstate
, state
, RUNSTATE(next
, lwp
));
349 * If we borrowed idle thread's tpdp above, restore the zombies
350 * tpdp so that it will be freed from tnf_thread_free().
353 t
->t_tnf_tpdp
= ztpdp
;
360 * tnf_mod_load (and tnf_mod_unload), when called from a client module's _init
361 * (and _fini) entry points are insufficient mechanisms for maintaining the
362 * consistency of __tnf_probe_list_head and __tnf_tag_list_head whenever that
363 * module is loaded or unloaded. The problem occurs because loading a module,
364 * at which time the modules probes are linked into the two lists, and
365 * installing that module are separate operations. This means that it is
366 * possible for a module to be loaded, not installed, and unloaded without
367 * calling _init and _fini. If the module contains TNF probes, the probe and
368 * tag lists will contain references to data addresses freed when the module
371 * The implemented solution for maintaining the lists is to perform the
372 * unsplicing when the module is unloaded. (Splicing into the lists, "probe
373 * discovery", is done when krtld processes relocation references when it
374 * loads the module; this information is not available for subsequent
375 * operations on the module.
385 tnf_mod_unload(struct modlinkage
*mlp
)