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