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