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