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