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