xref: /onnv-gate/usr/src/lib/libc/inc/tdb_agent.h (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #ifndef	_TDB_AGENT_H
28*0Sstevel@tonic-gate #define	_TDB_AGENT_H
29*0Sstevel@tonic-gate 
30*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
31*0Sstevel@tonic-gate 
32*0Sstevel@tonic-gate /*
33*0Sstevel@tonic-gate  * Thread debug agent control structures.
34*0Sstevel@tonic-gate  *
35*0Sstevel@tonic-gate  * This is an implementation-specific header file that is shared
36*0Sstevel@tonic-gate  * between libc and libc_db.  It is NOT a public header file
37*0Sstevel@tonic-gate  * and must never be installed in /usr/include
38*0Sstevel@tonic-gate  */
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate #include <thread_db.h>
41*0Sstevel@tonic-gate 
42*0Sstevel@tonic-gate #ifdef __cplusplus
43*0Sstevel@tonic-gate extern "C" {
44*0Sstevel@tonic-gate #endif
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate /*
47*0Sstevel@tonic-gate  * The structure containing per-thread event data.
48*0Sstevel@tonic-gate  */
49*0Sstevel@tonic-gate typedef struct {
50*0Sstevel@tonic-gate 	td_thr_events_t	eventmask;	/* Which events are enabled? */
51*0Sstevel@tonic-gate 	td_event_e	eventnum;	/* Most recent enabled event */
52*0Sstevel@tonic-gate 	void		*eventdata;	/* Param. for most recent event */
53*0Sstevel@tonic-gate } td_evbuf_t;
54*0Sstevel@tonic-gate 
55*0Sstevel@tonic-gate #ifdef _SYSCALL32
56*0Sstevel@tonic-gate typedef struct {
57*0Sstevel@tonic-gate 	td_thr_events_t	eventmask;	/* Which events are enabled? */
58*0Sstevel@tonic-gate 	td_event_e	eventnum;	/* Most recent enabled event */
59*0Sstevel@tonic-gate 	caddr32_t	eventdata;	/* Param. for most recent event */
60*0Sstevel@tonic-gate } td_evbuf32_t;
61*0Sstevel@tonic-gate #endif /* _SYSCALL32 */
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate /*
65*0Sstevel@tonic-gate  * All of these structures are constrained to have a size of 48 bytes.
66*0Sstevel@tonic-gate  * This is so that two 8-byte pointers can be inserted at the front to
67*0Sstevel@tonic-gate  * make up a complete tdb_sync_stats_t structure of exactly 64 bytes.
68*0Sstevel@tonic-gate  * The 'type' element of each structure identifies the type of the union,
69*0Sstevel@tonic-gate  * with values from the following defines.
70*0Sstevel@tonic-gate  */
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate #define	TDB_NONE	0
73*0Sstevel@tonic-gate #define	TDB_MUTEX	1
74*0Sstevel@tonic-gate #define	TDB_COND	2
75*0Sstevel@tonic-gate #define	TDB_RWLOCK	3
76*0Sstevel@tonic-gate #define	TDB_SEMA	4
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate typedef struct {
79*0Sstevel@tonic-gate 	uint16_t	type;
80*0Sstevel@tonic-gate 	uint16_t	unused;
81*0Sstevel@tonic-gate 	uint_t		mutex_lock;
82*0Sstevel@tonic-gate 	hrtime_t	mutex_hold_time;
83*0Sstevel@tonic-gate 	hrtime_t	mutex_sleep_time;
84*0Sstevel@tonic-gate 	uint_t		mutex_sleep;
85*0Sstevel@tonic-gate 	uint_t		mutex_try;
86*0Sstevel@tonic-gate 	uint_t		mutex_try_fail;
87*0Sstevel@tonic-gate 	uint_t		mutex_pad[1];
88*0Sstevel@tonic-gate 	hrtime_t	mutex_begin_hold;
89*0Sstevel@tonic-gate } tdb_mutex_stats_t;
90*0Sstevel@tonic-gate 
91*0Sstevel@tonic-gate typedef struct {
92*0Sstevel@tonic-gate 	uint16_t	type;
93*0Sstevel@tonic-gate 	uint16_t	unused;
94*0Sstevel@tonic-gate 	uint_t		cond_wait;
95*0Sstevel@tonic-gate 	uint_t		cond_timedwait;
96*0Sstevel@tonic-gate 	uint_t		cond_timedwait_timeout;
97*0Sstevel@tonic-gate 	hrtime_t	cond_wait_sleep_time;
98*0Sstevel@tonic-gate 	hrtime_t	cond_timedwait_sleep_time;
99*0Sstevel@tonic-gate 	uint_t		cond_signal;
100*0Sstevel@tonic-gate 	uint_t		cond_broadcast;
101*0Sstevel@tonic-gate 	uint_t		cond_pad[2];
102*0Sstevel@tonic-gate } tdb_cond_stats_t;
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate typedef struct {
105*0Sstevel@tonic-gate 	uint16_t	type;
106*0Sstevel@tonic-gate 	uint16_t	unused;
107*0Sstevel@tonic-gate 	uint_t		rw_rdlock;
108*0Sstevel@tonic-gate 	/* rw_rdlock_sleep is the reader cv's cond_wait count */
109*0Sstevel@tonic-gate 	/* rw_rdlock_sleep_time is the reader cv's cond_wait_sleep_time */
110*0Sstevel@tonic-gate 	uint_t		rw_rdlock_try;
111*0Sstevel@tonic-gate 	uint_t		rw_rdlock_try_fail;
112*0Sstevel@tonic-gate 	uint_t		rw_pad[1];
113*0Sstevel@tonic-gate 	uint_t		rw_wrlock;
114*0Sstevel@tonic-gate 	/* rw_wrlock_sleep is the writer cv's cond_wait count */
115*0Sstevel@tonic-gate 	/* rw_wrlock_sleep_time is the writer cv's cond_wait_sleep_time */
116*0Sstevel@tonic-gate 	hrtime_t	rw_wrlock_hold_time;
117*0Sstevel@tonic-gate 	uint_t		rw_wrlock_try;
118*0Sstevel@tonic-gate 	uint_t		rw_wrlock_try_fail;
119*0Sstevel@tonic-gate 	hrtime_t	rw_wrlock_begin_hold;
120*0Sstevel@tonic-gate } tdb_rwlock_stats_t;
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate typedef struct {
123*0Sstevel@tonic-gate 	uint16_t	type;
124*0Sstevel@tonic-gate 	uint16_t	unused;
125*0Sstevel@tonic-gate 	uint_t		sema_post;
126*0Sstevel@tonic-gate 	uint_t		sema_wait;
127*0Sstevel@tonic-gate 	uint_t		sema_wait_sleep;
128*0Sstevel@tonic-gate 	hrtime_t	sema_wait_sleep_time;
129*0Sstevel@tonic-gate 	uint_t		sema_trywait;
130*0Sstevel@tonic-gate 	uint_t		sema_trywait_fail;
131*0Sstevel@tonic-gate 	uint_t		sema_max_count;
132*0Sstevel@tonic-gate 	uint_t		sema_min_count;
133*0Sstevel@tonic-gate 	uint_t		sema_pad[2];
134*0Sstevel@tonic-gate } tdb_sema_stats_t;
135*0Sstevel@tonic-gate 
136*0Sstevel@tonic-gate /*
137*0Sstevel@tonic-gate  * An entry in the sync. object hash table.
138*0Sstevel@tonic-gate  */
139*0Sstevel@tonic-gate typedef struct {
140*0Sstevel@tonic-gate 	uint64_t	next;
141*0Sstevel@tonic-gate 	uint64_t	sync_addr;
142*0Sstevel@tonic-gate 	union {
143*0Sstevel@tonic-gate 		uint16_t		type;
144*0Sstevel@tonic-gate 		tdb_mutex_stats_t	mutex;
145*0Sstevel@tonic-gate 		tdb_cond_stats_t	cond;
146*0Sstevel@tonic-gate 		tdb_rwlock_stats_t	rwlock;
147*0Sstevel@tonic-gate 		tdb_sema_stats_t	sema;
148*0Sstevel@tonic-gate 	} un;
149*0Sstevel@tonic-gate } tdb_sync_stats_t;
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate /* peg count values at UINT_MAX */
152*0Sstevel@tonic-gate #define	tdb_incr(x)	(((x) != UINT_MAX)? (x)++ : 0)
153*0Sstevel@tonic-gate 
154*0Sstevel@tonic-gate /*
155*0Sstevel@tonic-gate  * The tdb_register_sync variable is set to REGISTER_SYNC_ENABLE by a
156*0Sstevel@tonic-gate  * debugger to enable synchronization object registration.
157*0Sstevel@tonic-gate  * Thereafter, synchronization primitives call tdb_sync_obj_register()
158*0Sstevel@tonic-gate  * to put their synchronization objects in the registration hash table.
159*0Sstevel@tonic-gate  * In this state, the first call to tdb_sync_obj_register() empties the
160*0Sstevel@tonic-gate  * hash table and sets tdb_register_sync to REGISTER_SYNC_ON.
161*0Sstevel@tonic-gate  *
162*0Sstevel@tonic-gate  * The tdb_register_sync variable is set to REGISTER_SYNC_DISABLE by a
163*0Sstevel@tonic-gate  * debugger to disable synchronization object registration.
164*0Sstevel@tonic-gate  * In this state, the first call to tdb_sync_obj_register() empties the
165*0Sstevel@tonic-gate  * hash table and sets tdb_register_sync to REGISTER_SYNC_OFF.
166*0Sstevel@tonic-gate  * Thereafter, synchronization primitives do not call tdb_sync_obj_register().
167*0Sstevel@tonic-gate  *
168*0Sstevel@tonic-gate  * Sync object *_destroy() functions always call tdb_sync_obj_deregister().
169*0Sstevel@tonic-gate  */
170*0Sstevel@tonic-gate typedef	uint8_t	register_sync_t;
171*0Sstevel@tonic-gate #define	REGISTER_SYNC_OFF	0	/* registration is off */
172*0Sstevel@tonic-gate #define	REGISTER_SYNC_ON	1	/* registration is on */
173*0Sstevel@tonic-gate #define	REGISTER_SYNC_DISABLE	2	/* request to disable registration */
174*0Sstevel@tonic-gate #define	REGISTER_SYNC_ENABLE	3	/* request to enable registration */
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate extern	tdb_sync_stats_t	*tdb_sync_obj_register(void *, int *);
177*0Sstevel@tonic-gate extern	void			tdb_sync_obj_deregister(void *);
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate /*
180*0Sstevel@tonic-gate  * Definitions for acquiring pointers to synch object statistics blocks
181*0Sstevel@tonic-gate  * contained in the synchronization object registration hash table.
182*0Sstevel@tonic-gate  */
183*0Sstevel@tonic-gate extern	tdb_mutex_stats_t	*tdb_mutex_stats(mutex_t *);
184*0Sstevel@tonic-gate extern	tdb_cond_stats_t	*tdb_cond_stats(cond_t *);
185*0Sstevel@tonic-gate extern	tdb_rwlock_stats_t	*tdb_rwlock_stats(rwlock_t *);
186*0Sstevel@tonic-gate extern	tdb_sema_stats_t	*tdb_sema_stats(sema_t *);
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate #define	REGISTER_SYNC(udp)	(udp)->uberflags.uf_tdb_register_sync
189*0Sstevel@tonic-gate 
190*0Sstevel@tonic-gate #define	MUTEX_STATS(mp, udp)	\
191*0Sstevel@tonic-gate 		(REGISTER_SYNC(udp)? tdb_mutex_stats(mp): NULL)
192*0Sstevel@tonic-gate #define	COND_STATS(cvp, udp)	\
193*0Sstevel@tonic-gate 		(REGISTER_SYNC(udp)? tdb_cond_stats(cvp): NULL)
194*0Sstevel@tonic-gate #define	RWLOCK_STATS(rwlp, udp)	\
195*0Sstevel@tonic-gate 		(REGISTER_SYNC(udp)? tdb_rwlock_stats(rwlp): NULL)
196*0Sstevel@tonic-gate #define	SEMA_STATS(sp, udp)	\
197*0Sstevel@tonic-gate 		(REGISTER_SYNC(udp)? tdb_sema_stats(sp): NULL)
198*0Sstevel@tonic-gate 
199*0Sstevel@tonic-gate /*
200*0Sstevel@tonic-gate  * Parameters of the synchronization object registration hash table.
201*0Sstevel@tonic-gate  */
202*0Sstevel@tonic-gate #define	TDB_HASH_SHIFT	15	/* 32K hash table entries */
203*0Sstevel@tonic-gate #define	TDB_HASH_SIZE	(1 << TDB_HASH_SHIFT)
204*0Sstevel@tonic-gate #define	TDB_HASH_MASK	(TDB_HASH_SIZE - 1)
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate /*
207*0Sstevel@tonic-gate  * uberdata.tdb_hash_lock protects all synchronization object
208*0Sstevel@tonic-gate  * hash table data structures.
209*0Sstevel@tonic-gate  * uberdata.tdb_hash_lock_stats is a special tdb_sync_stats structure
210*0Sstevel@tonic-gate  * reserved for tdb_hash_lock.
211*0Sstevel@tonic-gate  */
212*0Sstevel@tonic-gate 
213*0Sstevel@tonic-gate typedef	void (*tdb_ev_func_t)(void);
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate /*
216*0Sstevel@tonic-gate  * Uberdata for thread debug interfaces (known to libc_db).
217*0Sstevel@tonic-gate  */
218*0Sstevel@tonic-gate typedef struct {
219*0Sstevel@tonic-gate 	/*
220*0Sstevel@tonic-gate 	 * Pointer to the hash table of sync_addr_t descriptors.
221*0Sstevel@tonic-gate 	 * This holds the addresses of all of the synchronization variables
222*0Sstevel@tonic-gate 	 * that the library has seen since tracking was enabled by a debugger.
223*0Sstevel@tonic-gate 	 */
224*0Sstevel@tonic-gate 	uint64_t		*tdb_sync_addr_hash;
225*0Sstevel@tonic-gate 	/*
226*0Sstevel@tonic-gate 	 * The number of entries in the hash table.
227*0Sstevel@tonic-gate 	 */
228*0Sstevel@tonic-gate 	uint_t			tdb_register_count;
229*0Sstevel@tonic-gate 	int			tdb_hash_alloc_failed;
230*0Sstevel@tonic-gate 	/*
231*0Sstevel@tonic-gate 	 * The free list of sync_addr_t descriptors.
232*0Sstevel@tonic-gate 	 * When the free list is used up, it is replenished using mmap().
233*0Sstevel@tonic-gate 	 * sync_addr_t descriptors are never freed, though they may be
234*0Sstevel@tonic-gate 	 * removed from the hash table and returned to the free list.
235*0Sstevel@tonic-gate 	 */
236*0Sstevel@tonic-gate 	tdb_sync_stats_t	*tdb_sync_addr_free;
237*0Sstevel@tonic-gate 	tdb_sync_stats_t	*tdb_sync_addr_last;
238*0Sstevel@tonic-gate 	size_t			tdb_sync_alloc;
239*0Sstevel@tonic-gate 	/*
240*0Sstevel@tonic-gate 	 * The set of globally enabled events to report to libc_db.
241*0Sstevel@tonic-gate 	 */
242*0Sstevel@tonic-gate 	td_thr_events_t		tdb_ev_global_mask;
243*0Sstevel@tonic-gate 	/*
244*0Sstevel@tonic-gate 	 * The array of event function pointers.
245*0Sstevel@tonic-gate 	 */
246*0Sstevel@tonic-gate 	const tdb_ev_func_t	*tdb_events;
247*0Sstevel@tonic-gate } tdb_t;
248*0Sstevel@tonic-gate 
249*0Sstevel@tonic-gate #ifdef _SYSCALL32
250*0Sstevel@tonic-gate typedef struct {
251*0Sstevel@tonic-gate 	caddr32_t	tdb_sync_addr_hash;
252*0Sstevel@tonic-gate 	uint_t		tdb_register_count;
253*0Sstevel@tonic-gate 	int		tdb_hash_alloc_failed;
254*0Sstevel@tonic-gate 	caddr32_t	tdb_sync_addr_free;
255*0Sstevel@tonic-gate 	caddr32_t	tdb_sync_addr_last;
256*0Sstevel@tonic-gate 	size32_t	tdb_sync_alloc;
257*0Sstevel@tonic-gate 	td_thr_events_t	tdb_ev_global_mask;
258*0Sstevel@tonic-gate 	caddr32_t	tdb_events;
259*0Sstevel@tonic-gate } tdb32_t;
260*0Sstevel@tonic-gate #endif /* _SYSCALL32 */
261*0Sstevel@tonic-gate 
262*0Sstevel@tonic-gate /*
263*0Sstevel@tonic-gate  * This will have to change if event numbers exceed 31.
264*0Sstevel@tonic-gate  * Note that we only test tdb_ev_global_mask.event_bits[0] below.
265*0Sstevel@tonic-gate  */
266*0Sstevel@tonic-gate #define	__td_event_report(ulwp, event, udp)				\
267*0Sstevel@tonic-gate 	(((ulwp)->ul_td_events_enable &&				\
268*0Sstevel@tonic-gate 	td_eventismember(&(ulwp)->ul_td_evbuf.eventmask, (event))) ||	\
269*0Sstevel@tonic-gate 	((udp)->tdb.tdb_ev_global_mask.event_bits[0] &&			\
270*0Sstevel@tonic-gate 	td_eventismember(&(udp)->tdb.tdb_ev_global_mask, (event))))
271*0Sstevel@tonic-gate 
272*0Sstevel@tonic-gate /*
273*0Sstevel@tonic-gate  * Event "reporting" functions.  A thread reports an event by calling
274*0Sstevel@tonic-gate  * one of these empty functions; a debugger can set a breakpoint
275*0Sstevel@tonic-gate  * at the address of any of these functions to determine that an
276*0Sstevel@tonic-gate  * event is being reported.
277*0Sstevel@tonic-gate  */
278*0Sstevel@tonic-gate extern const tdb_ev_func_t tdb_events[TD_MAX_EVENT_NUM - TD_MIN_EVENT_NUM + 1];
279*0Sstevel@tonic-gate 
280*0Sstevel@tonic-gate #define	tdb_event(event, udp)		\
281*0Sstevel@tonic-gate 	(*(udp)->tdb.tdb_events[(event) - TD_MIN_EVENT_NUM])()
282*0Sstevel@tonic-gate 
283*0Sstevel@tonic-gate #ifdef __cplusplus
284*0Sstevel@tonic-gate }
285*0Sstevel@tonic-gate #endif
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate #endif	/* _TDB_AGENT_H */
288