Home | History | Annotate | Download | only in inc
      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
     43 extern "C" {
     44 #endif
     45 
     46 /*
     47  * The structure containing per-thread event data.
     48  */
     49 typedef 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
     56 typedef 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 
     78 typedef 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 
     91 typedef 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 
    104 typedef 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 
    122 typedef 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  */
    139 typedef 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  */
    170 typedef	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 
    176 extern	tdb_sync_stats_t	*tdb_sync_obj_register(void *, int *);
    177 extern	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  */
    183 extern	tdb_mutex_stats_t	*tdb_mutex_stats(mutex_t *);
    184 extern	tdb_cond_stats_t	*tdb_cond_stats(cond_t *);
    185 extern	tdb_rwlock_stats_t	*tdb_rwlock_stats(rwlock_t *);
    186 extern	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 
    213 typedef	void (*tdb_ev_func_t)(void);
    214 
    215 /*
    216  * Uberdata for thread debug interfaces (known to libc_db).
    217  */
    218 typedef 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
    250 typedef 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  */
    278 extern 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