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