xref: /illumos-gate/usr/src/lib/libc_db/common/thread_db.c (revision 4f364e7c95ee7fd9d5bbeddc1940e92405bb0e72)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <stddef.h>
30 #include <unistd.h>
31 #include <thr_uberdata.h>
32 #include <thread_db.h>
33 #include <libc_int.h>
34 
35 /*
36  * Private structures.
37  */
38 
39 typedef union {
40 	mutex_t		lock;
41 	rwlock_t	rwlock;
42 	sema_t		semaphore;
43 	cond_t		condition;
44 } td_so_un_t;
45 
46 struct td_thragent {
47 	rwlock_t	rwlock;
48 	struct ps_prochandle *ph_p;
49 	int		initialized;
50 	int		sync_tracking;
51 	int		model;
52 	int		primary_map;
53 	psaddr_t	bootstrap_addr;
54 	psaddr_t	uberdata_addr;
55 	psaddr_t	tdb_eventmask_addr;
56 	psaddr_t	tdb_register_sync_addr;
57 	psaddr_t	tdb_events[TD_MAX_EVENT_NUM - TD_MIN_EVENT_NUM + 1];
58 	psaddr_t	hash_table_addr;
59 	int		hash_size;
60 	lwpid_t		single_lwpid;
61 	psaddr_t	single_ulwp_addr;
62 };
63 
64 /*
65  * This is the name of the variable in libc that contains
66  * the uberdata address that we will need.
67  */
68 #define	TD_BOOTSTRAP_NAME	"_tdb_bootstrap"
69 /*
70  * This is the actual name of uberdata, used in the event
71  * that tdb_bootstrap has not yet been initialized.
72  */
73 #define	TD_UBERDATA_NAME	"_uberdata"
74 /*
75  * The library name should end with ".so.1", but older versions of
76  * dbx expect the unadorned name and malfunction if ".1" is specified.
77  * Unfortunately, if ".1" is not specified, mdb malfunctions when it
78  * is applied to another instance of itself (due to the presence of
79  * /usr/lib/mdb/proc/libc.so).  So we try it both ways.
80  */
81 #define	TD_LIBRARY_NAME		"libc.so"
82 #define	TD_LIBRARY_NAME_1	"libc.so.1"
83 
84 td_err_e __td_thr_get_info(td_thrhandle_t *th_p, td_thrinfo_t *ti_p);
85 
86 td_err_e __td_ta_thr_iter(td_thragent_t *ta_p, td_thr_iter_f *cb,
87 	void *cbdata_p, td_thr_state_e state, int ti_pri,
88 	sigset_t *ti_sigmask_p, unsigned ti_user_flags);
89 
90 /*
91  * Initialize threads debugging interface.
92  */
93 #pragma weak td_init = __td_init
94 td_err_e
95 __td_init()
96 {
97 	return (TD_OK);
98 }
99 
100 /*
101  * This function does nothing, and never did.
102  * But the symbol is in the ABI, so we can't delete it.
103  */
104 #pragma weak td_log = __td_log
105 void
106 __td_log()
107 {
108 }
109 
110 /*
111  * Short-cut to read just the hash table size from the process,
112  * to avoid repeatedly reading the full uberdata structure when
113  * dealing with a single-threaded process.
114  */
115 static uint_t
116 td_read_hash_size(td_thragent_t *ta_p)
117 {
118 	psaddr_t addr;
119 	uint_t hash_size;
120 
121 	switch (ta_p->initialized) {
122 	default:	/* uninitialized */
123 		return (0);
124 	case 1:		/* partially initialized */
125 		break;
126 	case 2:		/* fully initialized */
127 		return (ta_p->hash_size);
128 	}
129 
130 	if (ta_p->model == PR_MODEL_NATIVE) {
131 		addr = ta_p->uberdata_addr + offsetof(uberdata_t, hash_size);
132 	} else {
133 #if defined(_LP64) && defined(_SYSCALL32)
134 		addr = ta_p->uberdata_addr + offsetof(uberdata32_t, hash_size);
135 #else
136 		addr = 0;
137 #endif
138 	}
139 	if (ps_pdread(ta_p->ph_p, addr, &hash_size, sizeof (hash_size))
140 	    != PS_OK)
141 		return (0);
142 	return (hash_size);
143 }
144 
145 static td_err_e
146 td_read_uberdata(td_thragent_t *ta_p)
147 {
148 	struct ps_prochandle *ph_p = ta_p->ph_p;
149 
150 	if (ta_p->model == PR_MODEL_NATIVE) {
151 		uberdata_t uberdata;
152 
153 		if (ps_pdread(ph_p, ta_p->uberdata_addr,
154 		    &uberdata, sizeof (uberdata)) != PS_OK)
155 			return (TD_DBERR);
156 		ta_p->primary_map = uberdata.primary_map;
157 		ta_p->tdb_eventmask_addr = ta_p->uberdata_addr +
158 		    offsetof(uberdata_t, tdb.tdb_ev_global_mask);
159 		ta_p->tdb_register_sync_addr = ta_p->uberdata_addr +
160 		    offsetof(uberdata_t, uberflags.uf_tdb_register_sync);
161 		ta_p->hash_table_addr = (psaddr_t)uberdata.thr_hash_table;
162 		ta_p->hash_size = uberdata.hash_size;
163 		if (ps_pdread(ph_p, (psaddr_t)uberdata.tdb.tdb_events,
164 		    ta_p->tdb_events, sizeof (ta_p->tdb_events)) != PS_OK)
165 			return (TD_DBERR);
166 
167 	} else {
168 #if defined(_LP64) && defined(_SYSCALL32)
169 		uberdata32_t uberdata;
170 		caddr32_t tdb_events[TD_MAX_EVENT_NUM - TD_MIN_EVENT_NUM + 1];
171 		int i;
172 
173 		if (ps_pdread(ph_p, ta_p->uberdata_addr,
174 		    &uberdata, sizeof (uberdata)) != PS_OK)
175 			return (TD_DBERR);
176 		ta_p->primary_map = uberdata.primary_map;
177 		ta_p->tdb_eventmask_addr = ta_p->uberdata_addr +
178 		    offsetof(uberdata32_t, tdb.tdb_ev_global_mask);
179 		ta_p->tdb_register_sync_addr = ta_p->uberdata_addr +
180 		    offsetof(uberdata32_t, uberflags.uf_tdb_register_sync);
181 		ta_p->hash_table_addr = (psaddr_t)uberdata.thr_hash_table;
182 		ta_p->hash_size = uberdata.hash_size;
183 		if (ps_pdread(ph_p, (psaddr_t)uberdata.tdb.tdb_events,
184 		    tdb_events, sizeof (tdb_events)) != PS_OK)
185 			return (TD_DBERR);
186 		for (i = 0; i < TD_MAX_EVENT_NUM - TD_MIN_EVENT_NUM + 1; i++)
187 			ta_p->tdb_events[i] = tdb_events[i];
188 #else
189 		return (TD_DBERR);
190 #endif
191 	}
192 	if (ta_p->hash_size != 1) {	/* multi-threaded */
193 		ta_p->initialized = 2;
194 		ta_p->single_lwpid = 0;
195 		ta_p->single_ulwp_addr = NULL;
196 	} else {			/* single-threaded */
197 		ta_p->initialized = 1;
198 		/*
199 		 * Get the address and lwpid of the single thread/LWP.
200 		 * It may not be ulwp_one if this is a child of fork1().
201 		 */
202 		if (ta_p->model == PR_MODEL_NATIVE) {
203 			thr_hash_table_t head;
204 			lwpid_t lwpid = 0;
205 
206 			if (ps_pdread(ph_p, ta_p->hash_table_addr,
207 			    &head, sizeof (head)) != PS_OK)
208 				return (TD_DBERR);
209 			if ((psaddr_t)head.hash_bucket == NULL)
210 				ta_p->initialized = 0;
211 			else if (ps_pdread(ph_p, (psaddr_t)head.hash_bucket +
212 			    offsetof(ulwp_t, ul_lwpid),
213 			    &lwpid, sizeof (lwpid)) != PS_OK)
214 				return (TD_DBERR);
215 			ta_p->single_lwpid = lwpid;
216 			ta_p->single_ulwp_addr = (psaddr_t)head.hash_bucket;
217 		} else {
218 #if defined(_LP64) && defined(_SYSCALL32)
219 			thr_hash_table32_t head;
220 			lwpid_t lwpid = 0;
221 
222 			if (ps_pdread(ph_p, ta_p->hash_table_addr,
223 			    &head, sizeof (head)) != PS_OK)
224 				return (TD_DBERR);
225 			if ((psaddr_t)head.hash_bucket == NULL)
226 				ta_p->initialized = 0;
227 			else if (ps_pdread(ph_p, (psaddr_t)head.hash_bucket +
228 			    offsetof(ulwp32_t, ul_lwpid),
229 			    &lwpid, sizeof (lwpid)) != PS_OK)
230 				return (TD_DBERR);
231 			ta_p->single_lwpid = lwpid;
232 			ta_p->single_ulwp_addr = (psaddr_t)head.hash_bucket;
233 #else
234 			return (TD_DBERR);
235 #endif
236 		}
237 	}
238 	if (!ta_p->primary_map)
239 		ta_p->initialized = 0;
240 	return (TD_OK);
241 }
242 
243 static td_err_e
244 td_read_bootstrap_data(td_thragent_t *ta_p)
245 {
246 	struct ps_prochandle *ph_p = ta_p->ph_p;
247 	psaddr_t bootstrap_addr;
248 	psaddr_t uberdata_addr;
249 	ps_err_e db_return;
250 	td_err_e return_val;
251 	int do_1;
252 
253 	switch (ta_p->initialized) {
254 	case 2:			/* fully initialized */
255 		return (TD_OK);
256 	case 1:			/* partially initialized */
257 		if (td_read_hash_size(ta_p) == 1)
258 			return (TD_OK);
259 		return (td_read_uberdata(ta_p));
260 	}
261 
262 	/*
263 	 * Uninitialized -- do the startup work.
264 	 * We set ta_p->initialized to -1 to cut off recursive calls
265 	 * into libc_db by code in the provider of ps_pglobal_lookup().
266 	 */
267 	do_1 = 0;
268 	ta_p->initialized = -1;
269 	db_return = ps_pglobal_lookup(ph_p, TD_LIBRARY_NAME,
270 	    TD_BOOTSTRAP_NAME, &bootstrap_addr);
271 	if (db_return == PS_NOSYM) {
272 		do_1 = 1;
273 		db_return = ps_pglobal_lookup(ph_p, TD_LIBRARY_NAME_1,
274 		    TD_BOOTSTRAP_NAME, &bootstrap_addr);
275 	}
276 	if (db_return == PS_NOSYM)	/* libc is not linked yet */
277 		return (TD_NOLIBTHREAD);
278 	if (db_return != PS_OK)
279 		return (TD_ERR);
280 	db_return = ps_pglobal_lookup(ph_p,
281 	    do_1? TD_LIBRARY_NAME_1 : TD_LIBRARY_NAME,
282 	    TD_UBERDATA_NAME, &uberdata_addr);
283 	if (db_return == PS_NOSYM)	/* libc is not linked yet */
284 		return (TD_NOLIBTHREAD);
285 	if (db_return != PS_OK)
286 		return (TD_ERR);
287 
288 	/*
289 	 * Read the uberdata address into the thread agent structure.
290 	 */
291 	if (ta_p->model == PR_MODEL_NATIVE) {
292 		psaddr_t psaddr;
293 		if (ps_pdread(ph_p, bootstrap_addr,
294 		    &psaddr, sizeof (psaddr)) != PS_OK)
295 			return (TD_DBERR);
296 		if ((ta_p->bootstrap_addr = psaddr) == NULL)
297 			psaddr = uberdata_addr;
298 		else if (ps_pdread(ph_p, psaddr,
299 		    &psaddr, sizeof (psaddr)) != PS_OK)
300 			return (TD_DBERR);
301 		if (psaddr == NULL) {
302 			/* primary linkmap in the tgt is not initialized */
303 			ta_p->bootstrap_addr = NULL;
304 			psaddr = uberdata_addr;
305 		}
306 		ta_p->uberdata_addr = psaddr;
307 	} else {
308 #if defined(_LP64) && defined(_SYSCALL32)
309 		caddr32_t psaddr;
310 		if (ps_pdread(ph_p, bootstrap_addr,
311 		    &psaddr, sizeof (psaddr)) != PS_OK)
312 			return (TD_DBERR);
313 		if ((ta_p->bootstrap_addr = (psaddr_t)psaddr) == NULL)
314 			psaddr = (caddr32_t)uberdata_addr;
315 		else if (ps_pdread(ph_p, (psaddr_t)psaddr,
316 		    &psaddr, sizeof (psaddr)) != PS_OK)
317 			return (TD_DBERR);
318 		if (psaddr == NULL) {
319 			/* primary linkmap in the tgt is not initialized */
320 			ta_p->bootstrap_addr = NULL;
321 			psaddr = (caddr32_t)uberdata_addr;
322 		}
323 		ta_p->uberdata_addr = (psaddr_t)psaddr;
324 #else
325 		return (TD_DBERR);
326 #endif	/* _SYSCALL32 */
327 	}
328 
329 	if ((return_val = td_read_uberdata(ta_p)) != TD_OK)
330 		return (return_val);
331 	if (ta_p->bootstrap_addr == NULL)
332 		ta_p->initialized = 0;
333 	return (TD_OK);
334 }
335 
336 #pragma weak ps_kill
337 #pragma weak ps_lrolltoaddr
338 
339 /*
340  * Allocate a new agent process handle ("thread agent").
341  */
342 #pragma weak td_ta_new = __td_ta_new
343 td_err_e
344 __td_ta_new(struct ps_prochandle *ph_p, td_thragent_t **ta_pp)
345 {
346 	td_thragent_t *ta_p;
347 	int model;
348 	td_err_e return_val = TD_OK;
349 
350 	if (ph_p == NULL)
351 		return (TD_BADPH);
352 	if (ta_pp == NULL)
353 		return (TD_ERR);
354 	*ta_pp = NULL;
355 	if (ps_pstop(ph_p) != PS_OK)
356 		return (TD_DBERR);
357 	/*
358 	 * ps_pdmodel might not be defined if this is an older client.
359 	 * Make it a weak symbol and test if it exists before calling.
360 	 */
361 #pragma weak ps_pdmodel
362 	if (ps_pdmodel == NULL) {
363 		model = PR_MODEL_NATIVE;
364 	} else if (ps_pdmodel(ph_p, &model) != PS_OK) {
365 		(void) ps_pcontinue(ph_p);
366 		return (TD_ERR);
367 	}
368 	if ((ta_p = malloc(sizeof (*ta_p))) == NULL) {
369 		(void) ps_pcontinue(ph_p);
370 		return (TD_MALLOC);
371 	}
372 
373 	/*
374 	 * Initialize the agent process handle.
375 	 * Pick up the symbol value we need from the target process.
376 	 */
377 	(void) memset(ta_p, 0, sizeof (*ta_p));
378 	ta_p->ph_p = ph_p;
379 	(void) rwlock_init(&ta_p->rwlock, USYNC_THREAD, NULL);
380 	ta_p->model = model;
381 	return_val = td_read_bootstrap_data(ta_p);
382 
383 	/*
384 	 * Because the old libthread_db enabled lock tracking by default,
385 	 * we must also do it.  However, we do it only if the application
386 	 * provides the ps_kill() and ps_lrolltoaddr() interfaces.
387 	 * (dbx provides the ps_kill() and ps_lrolltoaddr() interfaces.)
388 	 */
389 	if (return_val == TD_OK && ps_kill != NULL && ps_lrolltoaddr != NULL) {
390 		register_sync_t oldenable;
391 		register_sync_t enable = REGISTER_SYNC_ENABLE;
392 		psaddr_t psaddr = ta_p->tdb_register_sync_addr;
393 
394 		if (ps_pdread(ph_p, psaddr,
395 		    &oldenable, sizeof (oldenable)) != PS_OK)
396 			return_val = TD_DBERR;
397 		else if (oldenable != REGISTER_SYNC_OFF ||
398 		    ps_pdwrite(ph_p, psaddr,
399 		    &enable, sizeof (enable)) != PS_OK) {
400 			/*
401 			 * Lock tracking was already enabled or we
402 			 * failed to enable it, probably because we
403 			 * are examining a core file.  In either case
404 			 * set the sync_tracking flag non-zero to
405 			 * indicate that we should not attempt to
406 			 * disable lock tracking when we delete the
407 			 * agent process handle in td_ta_delete().
408 			 */
409 			ta_p->sync_tracking = 1;
410 		}
411 	}
412 
413 	if (return_val == TD_OK)
414 		*ta_pp = ta_p;
415 	else
416 		free(ta_p);
417 
418 	(void) ps_pcontinue(ph_p);
419 	return (return_val);
420 }
421 
422 /*
423  * Utility function to grab the readers lock and return the prochandle,
424  * given an agent process handle.  Performs standard error checking.
425  * Returns non-NULL with the lock held, or NULL with the lock not held.
426  */
427 static struct ps_prochandle *
428 ph_lock_ta(td_thragent_t *ta_p, td_err_e *err)
429 {
430 	struct ps_prochandle *ph_p = NULL;
431 	td_err_e error;
432 
433 	if (ta_p == NULL || ta_p->initialized == -1) {
434 		*err = TD_BADTA;
435 	} else if (rw_rdlock(&ta_p->rwlock) != 0) {	/* can't happen? */
436 		*err = TD_BADTA;
437 	} else if ((ph_p = ta_p->ph_p) == NULL) {
438 		(void) rw_unlock(&ta_p->rwlock);
439 		*err = TD_BADPH;
440 	} else if (ta_p->initialized != 2 &&
441 	    (error = td_read_bootstrap_data(ta_p)) != TD_OK) {
442 		(void) rw_unlock(&ta_p->rwlock);
443 		ph_p = NULL;
444 		*err = error;
445 	} else {
446 		*err = TD_OK;
447 	}
448 
449 	return (ph_p);
450 }
451 
452 /*
453  * Utility function to grab the readers lock and return the prochandle,
454  * given an agent thread handle.  Performs standard error checking.
455  * Returns non-NULL with the lock held, or NULL with the lock not held.
456  */
457 static struct ps_prochandle *
458 ph_lock_th(const td_thrhandle_t *th_p, td_err_e *err)
459 {
460 	if (th_p == NULL || th_p->th_unique == NULL) {
461 		*err = TD_BADTH;
462 		return (NULL);
463 	}
464 	return (ph_lock_ta(th_p->th_ta_p, err));
465 }
466 
467 /*
468  * Utility function to grab the readers lock and return the prochandle,
469  * given a synchronization object handle.  Performs standard error checking.
470  * Returns non-NULL with the lock held, or NULL with the lock not held.
471  */
472 static struct ps_prochandle *
473 ph_lock_sh(const td_synchandle_t *sh_p, td_err_e *err)
474 {
475 	if (sh_p == NULL || sh_p->sh_unique == NULL) {
476 		*err = TD_BADSH;
477 		return (NULL);
478 	}
479 	return (ph_lock_ta(sh_p->sh_ta_p, err));
480 }
481 
482 /*
483  * Unlock the agent process handle obtained from ph_lock_*().
484  */
485 static void
486 ph_unlock(td_thragent_t *ta_p)
487 {
488 	(void) rw_unlock(&ta_p->rwlock);
489 }
490 
491 /*
492  * De-allocate an agent process handle,
493  * releasing all related resources.
494  *
495  * XXX -- This is hopelessly broken ---
496  * Storage for thread agent is not deallocated.  The prochandle
497  * in the thread agent is set to NULL so that future uses of
498  * the thread agent can be detected and an error value returned.
499  * All functions in the external user interface that make
500  * use of the thread agent are expected
501  * to check for a NULL prochandle in the thread agent.
502  * All such functions are also expected to obtain a
503  * reader lock on the thread agent while it is using it.
504  */
505 #pragma weak td_ta_delete = __td_ta_delete
506 td_err_e
507 __td_ta_delete(td_thragent_t *ta_p)
508 {
509 	struct ps_prochandle *ph_p;
510 
511 	/*
512 	 * This is the only place we grab the writer lock.
513 	 * We are going to NULL out the prochandle.
514 	 */
515 	if (ta_p == NULL || rw_wrlock(&ta_p->rwlock) != 0)
516 		return (TD_BADTA);
517 	if ((ph_p = ta_p->ph_p) == NULL) {
518 		(void) rw_unlock(&ta_p->rwlock);
519 		return (TD_BADPH);
520 	}
521 	/*
522 	 * If synch. tracking was disabled when td_ta_new() was called and
523 	 * if td_ta_sync_tracking_enable() was never called, then disable
524 	 * synch. tracking (it was enabled by default in td_ta_new()).
525 	 */
526 	if (ta_p->sync_tracking == 0 &&
527 	    ps_kill != NULL && ps_lrolltoaddr != NULL) {
528 		register_sync_t enable = REGISTER_SYNC_DISABLE;
529 
530 		(void) ps_pdwrite(ph_p, ta_p->tdb_register_sync_addr,
531 		    &enable, sizeof (enable));
532 	}
533 	ta_p->ph_p = NULL;
534 	(void) rw_unlock(&ta_p->rwlock);
535 	return (TD_OK);
536 }
537 
538 /*
539  * Map an agent process handle to a client prochandle.
540  * Currently unused by dbx.
541  */
542 #pragma weak td_ta_get_ph = __td_ta_get_ph
543 td_err_e
544 __td_ta_get_ph(td_thragent_t *ta_p, struct ps_prochandle **ph_pp)
545 {
546 	td_err_e return_val;
547 
548 	if (ph_pp != NULL)	/* protect stupid callers */
549 		*ph_pp = NULL;
550 	if (ph_pp == NULL)
551 		return (TD_ERR);
552 	if ((*ph_pp = ph_lock_ta(ta_p, &return_val)) == NULL)
553 		return (return_val);
554 	ph_unlock(ta_p);
555 	return (TD_OK);
556 }
557 
558 /*
559  * Set the process's suggested concurrency level.
560  * This is a no-op in a one-level model.
561  * Currently unused by dbx.
562  */
563 #pragma weak td_ta_setconcurrency = __td_ta_setconcurrency
564 /* ARGSUSED1 */
565 td_err_e
566 __td_ta_setconcurrency(const td_thragent_t *ta_p, int level)
567 {
568 	if (ta_p == NULL)
569 		return (TD_BADTA);
570 	if (ta_p->ph_p == NULL)
571 		return (TD_BADPH);
572 	return (TD_OK);
573 }
574 
575 /*
576  * Get the number of threads in the process.
577  */
578 #pragma weak td_ta_get_nthreads = __td_ta_get_nthreads
579 td_err_e
580 __td_ta_get_nthreads(td_thragent_t *ta_p, int *nthread_p)
581 {
582 	struct ps_prochandle *ph_p;
583 	td_err_e return_val;
584 	int nthreads;
585 	int nzombies;
586 	psaddr_t nthreads_addr;
587 	psaddr_t nzombies_addr;
588 
589 	if (ta_p->model == PR_MODEL_NATIVE) {
590 		nthreads_addr = ta_p->uberdata_addr +
591 		    offsetof(uberdata_t, nthreads);
592 		nzombies_addr = ta_p->uberdata_addr +
593 		    offsetof(uberdata_t, nzombies);
594 	} else {
595 #if defined(_LP64) && defined(_SYSCALL32)
596 		nthreads_addr = ta_p->uberdata_addr +
597 		    offsetof(uberdata32_t, nthreads);
598 		nzombies_addr = ta_p->uberdata_addr +
599 		    offsetof(uberdata32_t, nzombies);
600 #else
601 		nthreads_addr = 0;
602 		nzombies_addr = 0;
603 #endif	/* _SYSCALL32 */
604 	}
605 
606 	if (nthread_p == NULL)
607 		return (TD_ERR);
608 	if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL)
609 		return (return_val);
610 	if (ps_pdread(ph_p, nthreads_addr, &nthreads, sizeof (int)) != PS_OK)
611 		return_val = TD_DBERR;
612 	if (ps_pdread(ph_p, nzombies_addr, &nzombies, sizeof (int)) != PS_OK)
613 		return_val = TD_DBERR;
614 	ph_unlock(ta_p);
615 	if (return_val == TD_OK)
616 		*nthread_p = nthreads + nzombies;
617 	return (return_val);
618 }
619 
620 typedef struct {
621 	thread_t	tid;
622 	int		found;
623 	td_thrhandle_t	th;
624 } td_mapper_param_t;
625 
626 /*
627  * Check the value in data against the thread id.
628  * If it matches, return 1 to terminate iterations.
629  * This function is used by td_ta_map_id2thr() to map a tid to a thread handle.
630  */
631 static int
632 td_mapper_id2thr(td_thrhandle_t *th_p, td_mapper_param_t *data)
633 {
634 	td_thrinfo_t ti;
635 
636 	if (__td_thr_get_info(th_p, &ti) == TD_OK &&
637 	    data->tid == ti.ti_tid) {
638 		data->found = 1;
639 		data->th = *th_p;
640 		return (1);
641 	}
642 	return (0);
643 }
644 
645 /*
646  * Given a thread identifier, return the corresponding thread handle.
647  */
648 #pragma weak td_ta_map_id2thr = __td_ta_map_id2thr
649 td_err_e
650 __td_ta_map_id2thr(td_thragent_t *ta_p, thread_t tid,
651 	td_thrhandle_t *th_p)
652 {
653 	td_err_e		return_val;
654 	td_mapper_param_t	data;
655 
656 	if (th_p != NULL &&	/* optimize for a single thread */
657 	    ta_p != NULL &&
658 	    ta_p->initialized == 1 &&
659 	    (td_read_hash_size(ta_p) == 1 ||
660 	    td_read_uberdata(ta_p) == TD_OK) &&
661 	    ta_p->initialized == 1 &&
662 	    ta_p->single_lwpid == tid) {
663 		th_p->th_ta_p = ta_p;
664 		if ((th_p->th_unique = ta_p->single_ulwp_addr) == 0)
665 			return (TD_NOTHR);
666 		return (TD_OK);
667 	}
668 
669 	/*
670 	 * LOCKING EXCEPTION - Locking is not required here because
671 	 * the locking and checking will be done in __td_ta_thr_iter.
672 	 */
673 
674 	if (ta_p == NULL)
675 		return (TD_BADTA);
676 	if (th_p == NULL)
677 		return (TD_BADTH);
678 	if (tid == 0)
679 		return (TD_NOTHR);
680 
681 	data.tid = tid;
682 	data.found = 0;
683 	return_val = __td_ta_thr_iter(ta_p,
684 	    (td_thr_iter_f *)td_mapper_id2thr, (void *)&data,
685 	    TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
686 	    TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
687 	if (return_val == TD_OK) {
688 		if (data.found == 0)
689 			return_val = TD_NOTHR;
690 		else
691 			*th_p = data.th;
692 	}
693 
694 	return (return_val);
695 }
696 
697 /*
698  * Map the address of a synchronization object to a sync. object handle.
699  */
700 #pragma weak td_ta_map_addr2sync = __td_ta_map_addr2sync
701 td_err_e
702 __td_ta_map_addr2sync(td_thragent_t *ta_p, psaddr_t addr, td_synchandle_t *sh_p)
703 {
704 	struct ps_prochandle *ph_p;
705 	td_err_e return_val;
706 	uint16_t sync_magic;
707 
708 	if (sh_p == NULL)
709 		return (TD_BADSH);
710 	if (addr == NULL)
711 		return (TD_ERR);
712 	if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL)
713 		return (return_val);
714 	/*
715 	 * Check the magic number of the sync. object to make sure it's valid.
716 	 * The magic number is at the same offset for all sync. objects.
717 	 */
718 	if (ps_pdread(ph_p, (psaddr_t)&((mutex_t *)addr)->mutex_magic,
719 	    &sync_magic, sizeof (sync_magic)) != PS_OK) {
720 		ph_unlock(ta_p);
721 		return (TD_BADSH);
722 	}
723 	ph_unlock(ta_p);
724 	if (sync_magic != MUTEX_MAGIC && sync_magic != COND_MAGIC &&
725 	    sync_magic != SEMA_MAGIC && sync_magic != RWL_MAGIC)
726 		return (TD_BADSH);
727 	/*
728 	 * Just fill in the appropriate fields of the sync. handle.
729 	 */
730 	sh_p->sh_ta_p = (td_thragent_t *)ta_p;
731 	sh_p->sh_unique = addr;
732 	return (TD_OK);
733 }
734 
735 /*
736  * Iterate over the set of global TSD keys.
737  * The call back function is called with three arguments,
738  * a key, a pointer to the destructor function, and the cbdata pointer.
739  * Currently unused by dbx.
740  */
741 #pragma weak td_ta_tsd_iter = __td_ta_tsd_iter
742 td_err_e
743 __td_ta_tsd_iter(td_thragent_t *ta_p, td_key_iter_f *cb, void *cbdata_p)
744 {
745 	struct ps_prochandle *ph_p;
746 	td_err_e	return_val;
747 	int		key;
748 	int		numkeys;
749 	psaddr_t	dest_addr;
750 	psaddr_t	*destructors = NULL;
751 	PFrV		destructor;
752 
753 	if (cb == NULL)
754 		return (TD_ERR);
755 	if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL)
756 		return (return_val);
757 	if (ps_pstop(ph_p) != PS_OK) {
758 		ph_unlock(ta_p);
759 		return (TD_DBERR);
760 	}
761 
762 	if (ta_p->model == PR_MODEL_NATIVE) {
763 		tsd_metadata_t tsdm;
764 
765 		if (ps_pdread(ph_p,
766 		    ta_p->uberdata_addr + offsetof(uberdata_t, tsd_metadata),
767 		    &tsdm, sizeof (tsdm)) != PS_OK)
768 			return_val = TD_DBERR;
769 		else {
770 			numkeys = tsdm.tsdm_nused;
771 			dest_addr = (psaddr_t)tsdm.tsdm_destro;
772 			if (numkeys > 0)
773 				destructors =
774 				    malloc(numkeys * sizeof (psaddr_t));
775 		}
776 	} else {
777 #if defined(_LP64) && defined(_SYSCALL32)
778 		tsd_metadata32_t tsdm;
779 
780 		if (ps_pdread(ph_p,
781 		    ta_p->uberdata_addr + offsetof(uberdata32_t, tsd_metadata),
782 		    &tsdm, sizeof (tsdm)) != PS_OK)
783 			return_val = TD_DBERR;
784 		else {
785 			numkeys = tsdm.tsdm_nused;
786 			dest_addr = (psaddr_t)tsdm.tsdm_destro;
787 			if (numkeys > 0)
788 				destructors =
789 				    malloc(numkeys * sizeof (caddr32_t));
790 		}
791 #else
792 		return_val = TD_DBERR;
793 #endif	/* _SYSCALL32 */
794 	}
795 
796 	if (return_val != TD_OK || numkeys <= 0) {
797 		(void) ps_pcontinue(ph_p);
798 		ph_unlock(ta_p);
799 		return (return_val);
800 	}
801 
802 	if (destructors == NULL)
803 		return_val = TD_MALLOC;
804 	else if (ta_p->model == PR_MODEL_NATIVE) {
805 		if (ps_pdread(ph_p, dest_addr,
806 		    destructors, numkeys * sizeof (psaddr_t)) != PS_OK)
807 			return_val = TD_DBERR;
808 		else {
809 			for (key = 1; key < numkeys; key++) {
810 				destructor = (PFrV)destructors[key];
811 				if (destructor != TSD_UNALLOCATED &&
812 				    (*cb)(key, destructor, cbdata_p))
813 					break;
814 			}
815 		}
816 #if defined(_LP64) && defined(_SYSCALL32)
817 	} else {
818 		caddr32_t *destructors32 = (caddr32_t *)destructors;
819 		caddr32_t destruct32;
820 
821 		if (ps_pdread(ph_p, dest_addr,
822 		    destructors32, numkeys * sizeof (caddr32_t)) != PS_OK)
823 			return_val = TD_DBERR;
824 		else {
825 			for (key = 1; key < numkeys; key++) {
826 				destruct32 = destructors32[key];
827 				if ((destruct32 !=
828 				    (caddr32_t)(uintptr_t)TSD_UNALLOCATED) &&
829 				    (*cb)(key, (PFrV)(uintptr_t)destruct32,
830 				    cbdata_p))
831 					break;
832 			}
833 		}
834 #endif	/* _SYSCALL32 */
835 	}
836 
837 	if (destructors)
838 		free(destructors);
839 	(void) ps_pcontinue(ph_p);
840 	ph_unlock(ta_p);
841 	return (return_val);
842 }
843 
844 int
845 sigequalset(const sigset_t *s1, const sigset_t *s2)
846 {
847 	return (
848 	    s1->__sigbits[0] == s2->__sigbits[0] &&
849 	    s1->__sigbits[1] == s2->__sigbits[1] &&
850 	    s1->__sigbits[2] == s2->__sigbits[2] &&
851 	    s1->__sigbits[3] == s2->__sigbits[3]);
852 }
853 
854 /*
855  * Description:
856  *   Iterate over all threads. For each thread call
857  * the function pointed to by "cb" with a pointer
858  * to a thread handle, and a pointer to data which
859  * can be NULL. Only call td_thr_iter_f() on threads
860  * which match the properties of state, ti_pri,
861  * ti_sigmask_p, and ti_user_flags.  If cb returns
862  * a non-zero value, terminate iterations.
863  *
864  * Input:
865  *   *ta_p - thread agent
866  *   *cb - call back function defined by user.
867  * td_thr_iter_f() takes a thread handle and
868  * cbdata_p as a parameter.
869  *   cbdata_p - parameter for td_thr_iter_f().
870  *
871  *   state - state of threads of interest.  A value of
872  * TD_THR_ANY_STATE from enum td_thr_state_e
873  * does not restrict iterations by state.
874  *   ti_pri - lower bound of priorities of threads of
875  * interest.  A value of TD_THR_LOWEST_PRIORITY
876  * defined in thread_db.h does not restrict
877  * iterations by priority.  A thread with priority
878  * less than ti_pri will NOT be passed to the callback
879  * function.
880  *   ti_sigmask_p - signal mask of threads of interest.
881  * A value of TD_SIGNO_MASK defined in thread_db.h
882  * does not restrict iterations by signal mask.
883  *   ti_user_flags - user flags of threads of interest.  A
884  * value of TD_THR_ANY_USER_FLAGS defined in thread_db.h
885  * does not restrict iterations by user flags.
886  */
887 #pragma weak td_ta_thr_iter = __td_ta_thr_iter
888 td_err_e
889 __td_ta_thr_iter(td_thragent_t *ta_p, td_thr_iter_f *cb,
890 	void *cbdata_p, td_thr_state_e state, int ti_pri,
891 	sigset_t *ti_sigmask_p, unsigned ti_user_flags)
892 {
893 	struct ps_prochandle *ph_p;
894 	psaddr_t	first_lwp_addr;
895 	psaddr_t	first_zombie_addr;
896 	psaddr_t	curr_lwp_addr;
897 	psaddr_t	next_lwp_addr;
898 	td_thrhandle_t	th;
899 	ps_err_e	db_return;
900 	ps_err_e	db_return2;
901 	td_err_e	return_val;
902 
903 	if (cb == NULL)
904 		return (TD_ERR);
905 	/*
906 	 * If state is not within bound, short circuit.
907 	 */
908 	if (state < TD_THR_ANY_STATE || state > TD_THR_STOPPED_ASLEEP)
909 		return (TD_OK);
910 
911 	if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL)
912 		return (return_val);
913 	if (ps_pstop(ph_p) != PS_OK) {
914 		ph_unlock(ta_p);
915 		return (TD_DBERR);
916 	}
917 
918 	/*
919 	 * For each ulwp_t in the circular linked lists pointed
920 	 * to by "all_lwps" and "all_zombies":
921 	 * (1) Filter each thread.
922 	 * (2) Create the thread_object for each thread that passes.
923 	 * (3) Call the call back function on each thread.
924 	 */
925 
926 	if (ta_p->model == PR_MODEL_NATIVE) {
927 		db_return = ps_pdread(ph_p,
928 		    ta_p->uberdata_addr + offsetof(uberdata_t, all_lwps),
929 		    &first_lwp_addr, sizeof (first_lwp_addr));
930 		db_return2 = ps_pdread(ph_p,
931 		    ta_p->uberdata_addr + offsetof(uberdata_t, all_zombies),
932 		    &first_zombie_addr, sizeof (first_zombie_addr));
933 	} else {
934 #if defined(_LP64) && defined(_SYSCALL32)
935 		caddr32_t addr32;
936 
937 		db_return = ps_pdread(ph_p,
938 		    ta_p->uberdata_addr + offsetof(uberdata32_t, all_lwps),
939 		    &addr32, sizeof (addr32));
940 		first_lwp_addr = addr32;
941 		db_return2 = ps_pdread(ph_p,
942 		    ta_p->uberdata_addr + offsetof(uberdata32_t, all_zombies),
943 		    &addr32, sizeof (addr32));
944 		first_zombie_addr = addr32;
945 #else	/* _SYSCALL32 */
946 		db_return = PS_ERR;
947 		db_return2 = PS_ERR;
948 #endif	/* _SYSCALL32 */
949 	}
950 	if (db_return == PS_OK)
951 		db_return = db_return2;
952 
953 	/*
954 	 * If first_lwp_addr and first_zombie_addr are both NULL,
955 	 * libc must not yet be initialized or all threads have
956 	 * exited.  Return TD_NOTHR and all will be well.
957 	 */
958 	if (db_return == PS_OK &&
959 	    first_lwp_addr == NULL && first_zombie_addr == NULL) {
960 		(void) ps_pcontinue(ph_p);
961 		ph_unlock(ta_p);
962 		return (TD_NOTHR);
963 	}
964 	if (db_return != PS_OK) {
965 		(void) ps_pcontinue(ph_p);
966 		ph_unlock(ta_p);
967 		return (TD_DBERR);
968 	}
969 
970 	/*
971 	 * Run down the lists of all living and dead lwps.
972 	 */
973 	if (first_lwp_addr == NULL)
974 		first_lwp_addr = first_zombie_addr;
975 	curr_lwp_addr = first_lwp_addr;
976 	for (;;) {
977 		td_thr_state_e ts_state;
978 		int userpri;
979 		unsigned userflags;
980 		sigset_t mask;
981 
982 		/*
983 		 * Read the ulwp struct.
984 		 */
985 		if (ta_p->model == PR_MODEL_NATIVE) {
986 			ulwp_t ulwp;
987 
988 			if (ps_pdread(ph_p, curr_lwp_addr,
989 			    &ulwp, sizeof (ulwp)) != PS_OK &&
990 			    ((void) memset(&ulwp, 0, sizeof (ulwp)),
991 			    ps_pdread(ph_p, curr_lwp_addr,
992 			    &ulwp, REPLACEMENT_SIZE)) != PS_OK) {
993 				return_val = TD_DBERR;
994 				break;
995 			}
996 			next_lwp_addr = (psaddr_t)ulwp.ul_forw;
997 
998 			ts_state = ulwp.ul_dead? TD_THR_ZOMBIE :
999 			    ulwp.ul_stop? TD_THR_STOPPED :
1000 			    ulwp.ul_wchan? TD_THR_SLEEP :
1001 			    TD_THR_ACTIVE;
1002 			userpri = ulwp.ul_pri;
1003 			userflags = ulwp.ul_usropts;
1004 			if (ulwp.ul_dead)
1005 				(void) sigemptyset(&mask);
1006 			else
1007 				mask = *(sigset_t *)&ulwp.ul_sigmask;
1008 		} else {
1009 #if defined(_LP64) && defined(_SYSCALL32)
1010 			ulwp32_t ulwp;
1011 
1012 			if (ps_pdread(ph_p, curr_lwp_addr,
1013 			    &ulwp, sizeof (ulwp)) != PS_OK &&
1014 			    ((void) memset(&ulwp, 0, sizeof (ulwp)),
1015 			    ps_pdread(ph_p, curr_lwp_addr,
1016 			    &ulwp, REPLACEMENT_SIZE32)) != PS_OK) {
1017 				return_val = TD_DBERR;
1018 				break;
1019 			}
1020 			next_lwp_addr = (psaddr_t)ulwp.ul_forw;
1021 
1022 			ts_state = ulwp.ul_dead? TD_THR_ZOMBIE :
1023 			    ulwp.ul_stop? TD_THR_STOPPED :
1024 			    ulwp.ul_wchan? TD_THR_SLEEP :
1025 			    TD_THR_ACTIVE;
1026 			userpri = ulwp.ul_pri;
1027 			userflags = ulwp.ul_usropts;
1028 			if (ulwp.ul_dead)
1029 				(void) sigemptyset(&mask);
1030 			else
1031 				mask = *(sigset_t *)&ulwp.ul_sigmask;
1032 #else	/* _SYSCALL32 */
1033 			return_val = TD_ERR;
1034 			break;
1035 #endif	/* _SYSCALL32 */
1036 		}
1037 
1038 		/*
1039 		 * Filter on state, priority, sigmask, and user flags.
1040 		 */
1041 
1042 		if ((state != ts_state) &&
1043 		    (state != TD_THR_ANY_STATE))
1044 			goto advance;
1045 
1046 		if (ti_pri > userpri)
1047 			goto advance;
1048 
1049 		if (ti_sigmask_p != TD_SIGNO_MASK &&
1050 		    !sigequalset(ti_sigmask_p, &mask))
1051 			goto advance;
1052 
1053 		if (ti_user_flags != userflags &&
1054 		    ti_user_flags != (unsigned)TD_THR_ANY_USER_FLAGS)
1055 			goto advance;
1056 
1057 		/*
1058 		 * Call back - break if the return
1059 		 * from the call back is non-zero.
1060 		 */
1061 		th.th_ta_p = (td_thragent_t *)ta_p;
1062 		th.th_unique = curr_lwp_addr;
1063 		if ((*cb)(&th, cbdata_p))
1064 			break;
1065 
1066 advance:
1067 		if ((curr_lwp_addr = next_lwp_addr) == first_lwp_addr) {
1068 			/*
1069 			 * Switch to the zombie list, unless it is NULL
1070 			 * or we have already been doing the zombie list,
1071 			 * in which case terminate the loop.
1072 			 */
1073 			if (first_zombie_addr == NULL ||
1074 			    first_lwp_addr == first_zombie_addr)
1075 				break;
1076 			curr_lwp_addr = first_lwp_addr = first_zombie_addr;
1077 		}
1078 	}
1079 
1080 	(void) ps_pcontinue(ph_p);
1081 	ph_unlock(ta_p);
1082 	return (return_val);
1083 }
1084 
1085 /*
1086  * Enable or disable process synchronization object tracking.
1087  * Currently unused by dbx.
1088  */
1089 #pragma weak td_ta_sync_tracking_enable = __td_ta_sync_tracking_enable
1090 td_err_e
1091 __td_ta_sync_tracking_enable(td_thragent_t *ta_p, int onoff)
1092 {
1093 	struct ps_prochandle *ph_p;
1094 	td_err_e return_val;
1095 	register_sync_t enable;
1096 
1097 	if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL)
1098 		return (return_val);
1099 	/*
1100 	 * Values of tdb_register_sync in the victim process:
1101 	 *	REGISTER_SYNC_ENABLE	enables registration of synch objects
1102 	 *	REGISTER_SYNC_DISABLE	disables registration of synch objects
1103 	 * These cause the table to be cleared and tdb_register_sync set to:
1104 	 *	REGISTER_SYNC_ON	registration in effect
1105 	 *	REGISTER_SYNC_OFF	registration not in effect
1106 	 */
1107 	enable = onoff? REGISTER_SYNC_ENABLE : REGISTER_SYNC_DISABLE;
1108 	if (ps_pdwrite(ph_p, ta_p->tdb_register_sync_addr,
1109 	    &enable, sizeof (enable)) != PS_OK)
1110 		return_val = TD_DBERR;
1111 	/*
1112 	 * Remember that this interface was called (see td_ta_delete()).
1113 	 */
1114 	ta_p->sync_tracking = 1;
1115 	ph_unlock(ta_p);
1116 	return (return_val);
1117 }
1118 
1119 /*
1120  * Iterate over all known synchronization variables.
1121  * It is very possible that the list generated is incomplete,
1122  * because the iterator can only find synchronization variables
1123  * that have been registered by the process since synchronization
1124  * object registration was enabled.
1125  * The call back function cb is called for each synchronization
1126  * variable with two arguments: a pointer to the synchronization
1127  * handle and the passed-in argument cbdata.
1128  * If cb returns a non-zero value, iterations are terminated.
1129  */
1130 #pragma weak td_ta_sync_iter = __td_ta_sync_iter
1131 td_err_e
1132 __td_ta_sync_iter(td_thragent_t *ta_p, td_sync_iter_f *cb, void *cbdata)
1133 {
1134 	struct ps_prochandle *ph_p;
1135 	td_err_e	return_val;
1136 	int		i;
1137 	register_sync_t	enable;
1138 	psaddr_t	next_desc;
1139 	tdb_sync_stats_t sync_stats;
1140 	td_synchandle_t	synchandle;
1141 	psaddr_t	psaddr;
1142 	void		*vaddr;
1143 	uint64_t	*sync_addr_hash = NULL;
1144 
1145 	if (cb == NULL)
1146 		return (TD_ERR);
1147 	if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL)
1148 		return (return_val);
1149 	if (ps_pstop(ph_p) != PS_OK) {
1150 		ph_unlock(ta_p);
1151 		return (TD_DBERR);
1152 	}
1153 	if (ps_pdread(ph_p, ta_p->tdb_register_sync_addr,
1154 	    &enable, sizeof (enable)) != PS_OK) {
1155 		return_val = TD_DBERR;
1156 		goto out;
1157 	}
1158 	if (enable != REGISTER_SYNC_ON)
1159 		goto out;
1160 
1161 	/*
1162 	 * First read the hash table.
1163 	 * The hash table is large; allocate with mmap().
1164 	 */
1165 	if ((vaddr = mmap(NULL, TDB_HASH_SIZE * sizeof (uint64_t),
1166 	    PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, (off_t)0))
1167 	    == MAP_FAILED) {
1168 		return_val = TD_MALLOC;
1169 		goto out;
1170 	}
1171 	sync_addr_hash = vaddr;
1172 
1173 	if (ta_p->model == PR_MODEL_NATIVE) {
1174 		if (ps_pdread(ph_p, ta_p->uberdata_addr +
1175 		    offsetof(uberdata_t, tdb.tdb_sync_addr_hash),
1176 		    &psaddr, sizeof (&psaddr)) != PS_OK) {
1177 			return_val = TD_DBERR;
1178 			goto out;
1179 		}
1180 	} else {
1181 #ifdef  _SYSCALL32
1182 		caddr32_t addr;
1183 
1184 		if (ps_pdread(ph_p, ta_p->uberdata_addr +
1185 		    offsetof(uberdata32_t, tdb.tdb_sync_addr_hash),
1186 		    &addr, sizeof (addr)) != PS_OK) {
1187 			return_val = TD_DBERR;
1188 			goto out;
1189 		}
1190 		psaddr = addr;
1191 #else
1192 		return_val = TD_ERR;
1193 		goto out;
1194 #endif /* _SYSCALL32 */
1195 	}
1196 
1197 	if (psaddr == NULL)
1198 		goto out;
1199 	if (ps_pdread(ph_p, psaddr, sync_addr_hash,
1200 	    TDB_HASH_SIZE * sizeof (uint64_t)) != PS_OK) {
1201 		return_val = TD_DBERR;
1202 		goto out;
1203 	}
1204 
1205 	/*
1206 	 * Now scan the hash table.
1207 	 */
1208 	for (i = 0; i < TDB_HASH_SIZE; i++) {
1209 		for (next_desc = (psaddr_t)sync_addr_hash[i];
1210 		    next_desc != NULL;
1211 		    next_desc = (psaddr_t)sync_stats.next) {
1212 			if (ps_pdread(ph_p, next_desc,
1213 			    &sync_stats, sizeof (sync_stats)) != PS_OK) {
1214 				return_val = TD_DBERR;
1215 				goto out;
1216 			}
1217 			if (sync_stats.un.type == TDB_NONE) {
1218 				/* not registered since registration enabled */
1219 				continue;
1220 			}
1221 			synchandle.sh_ta_p = ta_p;
1222 			synchandle.sh_unique = (psaddr_t)sync_stats.sync_addr;
1223 			if ((*cb)(&synchandle, cbdata) != 0)
1224 				goto out;
1225 		}
1226 	}
1227 
1228 out:
1229 	if (sync_addr_hash != NULL)
1230 		(void) munmap((void *)sync_addr_hash,
1231 		    TDB_HASH_SIZE * sizeof (uint64_t));
1232 	(void) ps_pcontinue(ph_p);
1233 	ph_unlock(ta_p);
1234 	return (return_val);
1235 }
1236 
1237 /*
1238  * Enable process statistics collection.
1239  */
1240 #pragma weak td_ta_enable_stats = __td_ta_enable_stats
1241 /* ARGSUSED */
1242 td_err_e
1243 __td_ta_enable_stats(const td_thragent_t *ta_p, int onoff)
1244 {
1245 	return (TD_NOCAPAB);
1246 }
1247 
1248 /*
1249  * Reset process statistics.
1250  */
1251 #pragma weak td_ta_reset_stats = __td_ta_reset_stats
1252 /* ARGSUSED */
1253 td_err_e
1254 __td_ta_reset_stats(const td_thragent_t *ta_p)
1255 {
1256 	return (TD_NOCAPAB);
1257 }
1258 
1259 /*
1260  * Read process statistics.
1261  */
1262 #pragma weak td_ta_get_stats = __td_ta_get_stats
1263 /* ARGSUSED */
1264 td_err_e
1265 __td_ta_get_stats(const td_thragent_t *ta_p, td_ta_stats_t *tstats)
1266 {
1267 	return (TD_NOCAPAB);
1268 }
1269 
1270 /*
1271  * Transfer information from lwp struct to thread information struct.
1272  * XXX -- lots of this needs cleaning up.
1273  */
1274 static void
1275 td_thr2to(td_thragent_t *ta_p, psaddr_t ts_addr,
1276 	ulwp_t *ulwp, td_thrinfo_t *ti_p)
1277 {
1278 	lwpid_t lwpid;
1279 
1280 	if ((lwpid = ulwp->ul_lwpid) == 0)
1281 		lwpid = 1;
1282 	(void) memset(ti_p, 0, sizeof (*ti_p));
1283 	ti_p->ti_ta_p = ta_p;
1284 	ti_p->ti_user_flags = ulwp->ul_usropts;
1285 	ti_p->ti_tid = lwpid;
1286 	ti_p->ti_exitval = ulwp->ul_rval;
1287 	ti_p->ti_startfunc = (psaddr_t)ulwp->ul_startpc;
1288 	if (!ulwp->ul_dead) {
1289 		/*
1290 		 * The bloody fools got this backwards!
1291 		 */
1292 		ti_p->ti_stkbase = (psaddr_t)ulwp->ul_stktop;
1293 		ti_p->ti_stksize = ulwp->ul_stksiz;
1294 	}
1295 	ti_p->ti_ro_area = ts_addr;
1296 	ti_p->ti_ro_size = ulwp->ul_replace?
1297 	    REPLACEMENT_SIZE : sizeof (ulwp_t);
1298 	ti_p->ti_state = ulwp->ul_dead? TD_THR_ZOMBIE :
1299 	    ulwp->ul_stop? TD_THR_STOPPED :
1300 	    ulwp->ul_wchan? TD_THR_SLEEP :
1301 	    TD_THR_ACTIVE;
1302 	ti_p->ti_db_suspended = 0;
1303 	ti_p->ti_type = TD_THR_USER;
1304 	ti_p->ti_sp = ulwp->ul_sp;
1305 	ti_p->ti_flags = 0;
1306 	ti_p->ti_pri = ulwp->ul_pri;
1307 	ti_p->ti_lid = lwpid;
1308 	if (!ulwp->ul_dead)
1309 		ti_p->ti_sigmask = ulwp->ul_sigmask;
1310 	ti_p->ti_traceme = 0;
1311 	ti_p->ti_preemptflag = 0;
1312 	ti_p->ti_pirecflag = 0;
1313 	(void) sigemptyset(&ti_p->ti_pending);
1314 	ti_p->ti_events = ulwp->ul_td_evbuf.eventmask;
1315 }
1316 
1317 #if defined(_LP64) && defined(_SYSCALL32)
1318 static void
1319 td_thr2to32(td_thragent_t *ta_p, psaddr_t ts_addr,
1320 	ulwp32_t *ulwp, td_thrinfo_t *ti_p)
1321 {
1322 	lwpid_t lwpid;
1323 
1324 	if ((lwpid = ulwp->ul_lwpid) == 0)
1325 		lwpid = 1;
1326 	(void) memset(ti_p, 0, sizeof (*ti_p));
1327 	ti_p->ti_ta_p = ta_p;
1328 	ti_p->ti_user_flags = ulwp->ul_usropts;
1329 	ti_p->ti_tid = lwpid;
1330 	ti_p->ti_exitval = (void *)(uintptr_t)ulwp->ul_rval;
1331 	ti_p->ti_startfunc = (psaddr_t)ulwp->ul_startpc;
1332 	if (!ulwp->ul_dead) {
1333 		/*
1334 		 * The bloody fools got this backwards!
1335 		 */
1336 		ti_p->ti_stkbase = (psaddr_t)ulwp->ul_stktop;
1337 		ti_p->ti_stksize = ulwp->ul_stksiz;
1338 	}
1339 	ti_p->ti_ro_area = ts_addr;
1340 	ti_p->ti_ro_size = ulwp->ul_replace?
1341 	    REPLACEMENT_SIZE32 : sizeof (ulwp32_t);
1342 	ti_p->ti_state = ulwp->ul_dead? TD_THR_ZOMBIE :
1343 	    ulwp->ul_stop? TD_THR_STOPPED :
1344 	    ulwp->ul_wchan? TD_THR_SLEEP :
1345 	    TD_THR_ACTIVE;
1346 	ti_p->ti_db_suspended = 0;
1347 	ti_p->ti_type = TD_THR_USER;
1348 	ti_p->ti_sp = (uint32_t)ulwp->ul_sp;
1349 	ti_p->ti_flags = 0;
1350 	ti_p->ti_pri = ulwp->ul_pri;
1351 	ti_p->ti_lid = lwpid;
1352 	if (!ulwp->ul_dead)
1353 		ti_p->ti_sigmask = *(sigset_t *)&ulwp->ul_sigmask;
1354 	ti_p->ti_traceme = 0;
1355 	ti_p->ti_preemptflag = 0;
1356 	ti_p->ti_pirecflag = 0;
1357 	(void) sigemptyset(&ti_p->ti_pending);
1358 	ti_p->ti_events = ulwp->ul_td_evbuf.eventmask;
1359 }
1360 #endif	/* _SYSCALL32 */
1361 
1362 /*
1363  * Get thread information.
1364  */
1365 #pragma weak td_thr_get_info = __td_thr_get_info
1366 td_err_e
1367 __td_thr_get_info(td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
1368 {
1369 	struct ps_prochandle *ph_p;
1370 	td_thragent_t	*ta_p;
1371 	td_err_e	return_val;
1372 	psaddr_t	psaddr;
1373 
1374 	if (ti_p == NULL)
1375 		return (TD_ERR);
1376 	(void) memset(ti_p, NULL, sizeof (*ti_p));
1377 
1378 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
1379 		return (return_val);
1380 	ta_p = th_p->th_ta_p;
1381 	if (ps_pstop(ph_p) != PS_OK) {
1382 		ph_unlock(ta_p);
1383 		return (TD_DBERR);
1384 	}
1385 
1386 	/*
1387 	 * Read the ulwp struct from the process.
1388 	 * Transfer the ulwp struct to the thread information struct.
1389 	 */
1390 	psaddr = th_p->th_unique;
1391 	if (ta_p->model == PR_MODEL_NATIVE) {
1392 		ulwp_t ulwp;
1393 
1394 		if (ps_pdread(ph_p, psaddr, &ulwp, sizeof (ulwp)) != PS_OK &&
1395 		    ((void) memset(&ulwp, 0, sizeof (ulwp)),
1396 		    ps_pdread(ph_p, psaddr, &ulwp, REPLACEMENT_SIZE)) != PS_OK)
1397 			return_val = TD_DBERR;
1398 		else
1399 			td_thr2to(ta_p, psaddr, &ulwp, ti_p);
1400 	} else {
1401 #if defined(_LP64) && defined(_SYSCALL32)
1402 		ulwp32_t ulwp;
1403 
1404 		if (ps_pdread(ph_p, psaddr, &ulwp, sizeof (ulwp)) != PS_OK &&
1405 		    ((void) memset(&ulwp, 0, sizeof (ulwp)),
1406 		    ps_pdread(ph_p, psaddr, &ulwp, REPLACEMENT_SIZE32)) !=
1407 		    PS_OK)
1408 			return_val = TD_DBERR;
1409 		else
1410 			td_thr2to32(ta_p, psaddr, &ulwp, ti_p);
1411 #else
1412 		return_val = TD_ERR;
1413 #endif	/* _SYSCALL32 */
1414 	}
1415 
1416 	(void) ps_pcontinue(ph_p);
1417 	ph_unlock(ta_p);
1418 	return (return_val);
1419 }
1420 
1421 /*
1422  * Given a process and an event number, return information about
1423  * an address in the process or at which a breakpoint can be set
1424  * to monitor the event.
1425  */
1426 #pragma weak td_ta_event_addr = __td_ta_event_addr
1427 td_err_e
1428 __td_ta_event_addr(td_thragent_t *ta_p, td_event_e event, td_notify_t *notify_p)
1429 {
1430 	if (ta_p == NULL)
1431 		return (TD_BADTA);
1432 	if (event < TD_MIN_EVENT_NUM || event > TD_MAX_EVENT_NUM)
1433 		return (TD_NOEVENT);
1434 	if (notify_p == NULL)
1435 		return (TD_ERR);
1436 
1437 	notify_p->type = NOTIFY_BPT;
1438 	notify_p->u.bptaddr = ta_p->tdb_events[event - TD_MIN_EVENT_NUM];
1439 
1440 	return (TD_OK);
1441 }
1442 
1443 /*
1444  * Add the events in eventset 2 to eventset 1.
1445  */
1446 static void
1447 eventsetaddset(td_thr_events_t *event1_p, td_thr_events_t *event2_p)
1448 {
1449 	int	i;
1450 
1451 	for (i = 0; i < TD_EVENTSIZE; i++)
1452 		event1_p->event_bits[i] |= event2_p->event_bits[i];
1453 }
1454 
1455 /*
1456  * Delete the events in eventset 2 from eventset 1.
1457  */
1458 static void
1459 eventsetdelset(td_thr_events_t *event1_p, td_thr_events_t *event2_p)
1460 {
1461 	int	i;
1462 
1463 	for (i = 0; i < TD_EVENTSIZE; i++)
1464 		event1_p->event_bits[i] &= ~event2_p->event_bits[i];
1465 }
1466 
1467 /*
1468  * Either add or delete the given event set from a thread's event mask.
1469  */
1470 static td_err_e
1471 mod_eventset(td_thrhandle_t *th_p, td_thr_events_t *events, int onoff)
1472 {
1473 	struct ps_prochandle *ph_p;
1474 	td_err_e	return_val = TD_OK;
1475 	char		enable;
1476 	td_thr_events_t	evset;
1477 	psaddr_t	psaddr_evset;
1478 	psaddr_t	psaddr_enab;
1479 
1480 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
1481 		return (return_val);
1482 	if (th_p->th_ta_p->model == PR_MODEL_NATIVE) {
1483 		ulwp_t *ulwp = (ulwp_t *)th_p->th_unique;
1484 		psaddr_evset = (psaddr_t)&ulwp->ul_td_evbuf.eventmask;
1485 		psaddr_enab = (psaddr_t)&ulwp->ul_td_events_enable;
1486 	} else {
1487 #if defined(_LP64) && defined(_SYSCALL32)
1488 		ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique;
1489 		psaddr_evset = (psaddr_t)&ulwp->ul_td_evbuf.eventmask;
1490 		psaddr_enab = (psaddr_t)&ulwp->ul_td_events_enable;
1491 #else
1492 		ph_unlock(th_p->th_ta_p);
1493 		return (TD_ERR);
1494 #endif	/* _SYSCALL32 */
1495 	}
1496 	if (ps_pstop(ph_p) != PS_OK) {
1497 		ph_unlock(th_p->th_ta_p);
1498 		return (TD_DBERR);
1499 	}
1500 
1501 	if (ps_pdread(ph_p, psaddr_evset, &evset, sizeof (evset)) != PS_OK)
1502 		return_val = TD_DBERR;
1503 	else {
1504 		if (onoff)
1505 			eventsetaddset(&evset, events);
1506 		else
1507 			eventsetdelset(&evset, events);
1508 		if (ps_pdwrite(ph_p, psaddr_evset, &evset, sizeof (evset))
1509 		    != PS_OK)
1510 			return_val = TD_DBERR;
1511 		else {
1512 			enable = 0;
1513 			if (td_eventismember(&evset, TD_EVENTS_ENABLE))
1514 				enable = 1;
1515 			if (ps_pdwrite(ph_p, psaddr_enab,
1516 			    &enable, sizeof (enable)) != PS_OK)
1517 				return_val = TD_DBERR;
1518 		}
1519 	}
1520 
1521 	(void) ps_pcontinue(ph_p);
1522 	ph_unlock(th_p->th_ta_p);
1523 	return (return_val);
1524 }
1525 
1526 /*
1527  * Enable or disable tracing for a given thread.  Tracing
1528  * is filtered based on the event mask of each thread.  Tracing
1529  * can be turned on/off for the thread without changing thread
1530  * event mask.
1531  * Currently unused by dbx.
1532  */
1533 #pragma weak td_thr_event_enable = __td_thr_event_enable
1534 td_err_e
1535 __td_thr_event_enable(td_thrhandle_t *th_p, int onoff)
1536 {
1537 	td_thr_events_t	evset;
1538 
1539 	td_event_emptyset(&evset);
1540 	td_event_addset(&evset, TD_EVENTS_ENABLE);
1541 	return (mod_eventset(th_p, &evset, onoff));
1542 }
1543 
1544 /*
1545  * Set event mask to enable event. event is turned on in
1546  * event mask for thread.  If a thread encounters an event
1547  * for which its event mask is on, notification will be sent
1548  * to the debugger.
1549  * Addresses for each event are provided to the
1550  * debugger.  It is assumed that a breakpoint of some type will
1551  * be placed at that address.  If the event mask for the thread
1552  * is on, the instruction at the address will be executed.
1553  * Otherwise, the instruction will be skipped.
1554  */
1555 #pragma weak td_thr_set_event = __td_thr_set_event
1556 td_err_e
1557 __td_thr_set_event(td_thrhandle_t *th_p, td_thr_events_t *events)
1558 {
1559 	return (mod_eventset(th_p, events, 1));
1560 }
1561 
1562 /*
1563  * Enable or disable a set of events in the process-global event mask,
1564  * depending on the value of onoff.
1565  */
1566 static td_err_e
1567 td_ta_mod_event(td_thragent_t *ta_p, td_thr_events_t *events, int onoff)
1568 {
1569 	struct ps_prochandle *ph_p;
1570 	td_thr_events_t targ_eventset;
1571 	td_err_e	return_val;
1572 
1573 	if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL)
1574 		return (return_val);
1575 	if (ps_pstop(ph_p) != PS_OK) {
1576 		ph_unlock(ta_p);
1577 		return (TD_DBERR);
1578 	}
1579 	if (ps_pdread(ph_p, ta_p->tdb_eventmask_addr,
1580 	    &targ_eventset, sizeof (targ_eventset)) != PS_OK)
1581 		return_val = TD_DBERR;
1582 	else {
1583 		if (onoff)
1584 			eventsetaddset(&targ_eventset, events);
1585 		else
1586 			eventsetdelset(&targ_eventset, events);
1587 		if (ps_pdwrite(ph_p, ta_p->tdb_eventmask_addr,
1588 		    &targ_eventset, sizeof (targ_eventset)) != PS_OK)
1589 			return_val = TD_DBERR;
1590 	}
1591 	(void) ps_pcontinue(ph_p);
1592 	ph_unlock(ta_p);
1593 	return (return_val);
1594 }
1595 
1596 /*
1597  * Enable a set of events in the process-global event mask.
1598  */
1599 #pragma weak td_ta_set_event = __td_ta_set_event
1600 td_err_e
1601 __td_ta_set_event(td_thragent_t *ta_p, td_thr_events_t *events)
1602 {
1603 	return (td_ta_mod_event(ta_p, events, 1));
1604 }
1605 
1606 /*
1607  * Set event mask to disable the given event set; these events are cleared
1608  * from the event mask of the thread.  Events that occur for a thread
1609  * with the event masked off will not cause notification to be
1610  * sent to the debugger (see td_thr_set_event for fuller description).
1611  */
1612 #pragma weak td_thr_clear_event = __td_thr_clear_event
1613 td_err_e
1614 __td_thr_clear_event(td_thrhandle_t *th_p, td_thr_events_t *events)
1615 {
1616 	return (mod_eventset(th_p, events, 0));
1617 }
1618 
1619 /*
1620  * Disable a set of events in the process-global event mask.
1621  */
1622 #pragma weak td_ta_clear_event = __td_ta_clear_event
1623 td_err_e
1624 __td_ta_clear_event(td_thragent_t *ta_p, td_thr_events_t *events)
1625 {
1626 	return (td_ta_mod_event(ta_p, events, 0));
1627 }
1628 
1629 /*
1630  * This function returns the most recent event message, if any,
1631  * associated with a thread.  Given a thread handle, return the message
1632  * corresponding to the event encountered by the thread.  Only one
1633  * message per thread is saved.  Messages from earlier events are lost
1634  * when later events occur.
1635  */
1636 #pragma weak td_thr_event_getmsg = __td_thr_event_getmsg
1637 td_err_e
1638 __td_thr_event_getmsg(td_thrhandle_t *th_p, td_event_msg_t *msg)
1639 {
1640 	struct ps_prochandle *ph_p;
1641 	td_err_e	return_val = TD_OK;
1642 	psaddr_t	psaddr;
1643 
1644 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
1645 		return (return_val);
1646 	if (ps_pstop(ph_p) != PS_OK) {
1647 		ph_unlock(th_p->th_ta_p);
1648 		return (TD_BADTA);
1649 	}
1650 	if (th_p->th_ta_p->model == PR_MODEL_NATIVE) {
1651 		ulwp_t *ulwp = (ulwp_t *)th_p->th_unique;
1652 		td_evbuf_t evbuf;
1653 
1654 		psaddr = (psaddr_t)&ulwp->ul_td_evbuf;
1655 		if (ps_pdread(ph_p, psaddr, &evbuf, sizeof (evbuf)) != PS_OK) {
1656 			return_val = TD_DBERR;
1657 		} else if (evbuf.eventnum == TD_EVENT_NONE) {
1658 			return_val = TD_NOEVENT;
1659 		} else {
1660 			msg->event = evbuf.eventnum;
1661 			msg->th_p = (td_thrhandle_t *)th_p;
1662 			msg->msg.data = (uintptr_t)evbuf.eventdata;
1663 			/* "Consume" the message */
1664 			evbuf.eventnum = TD_EVENT_NONE;
1665 			evbuf.eventdata = NULL;
1666 			if (ps_pdwrite(ph_p, psaddr, &evbuf, sizeof (evbuf))
1667 			    != PS_OK)
1668 				return_val = TD_DBERR;
1669 		}
1670 	} else {
1671 #if defined(_LP64) && defined(_SYSCALL32)
1672 		ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique;
1673 		td_evbuf32_t evbuf;
1674 
1675 		psaddr = (psaddr_t)&ulwp->ul_td_evbuf;
1676 		if (ps_pdread(ph_p, psaddr, &evbuf, sizeof (evbuf)) != PS_OK) {
1677 			return_val = TD_DBERR;
1678 		} else if (evbuf.eventnum == TD_EVENT_NONE) {
1679 			return_val = TD_NOEVENT;
1680 		} else {
1681 			msg->event = evbuf.eventnum;
1682 			msg->th_p = (td_thrhandle_t *)th_p;
1683 			msg->msg.data = (uintptr_t)evbuf.eventdata;
1684 			/* "Consume" the message */
1685 			evbuf.eventnum = TD_EVENT_NONE;
1686 			evbuf.eventdata = NULL;
1687 			if (ps_pdwrite(ph_p, psaddr, &evbuf, sizeof (evbuf))
1688 			    != PS_OK)
1689 				return_val = TD_DBERR;
1690 		}
1691 #else
1692 		return_val = TD_ERR;
1693 #endif	/* _SYSCALL32 */
1694 	}
1695 
1696 	(void) ps_pcontinue(ph_p);
1697 	ph_unlock(th_p->th_ta_p);
1698 	return (return_val);
1699 }
1700 
1701 /*
1702  * The callback function td_ta_event_getmsg uses when looking for
1703  * a thread with an event.  A thin wrapper around td_thr_event_getmsg.
1704  */
1705 static int
1706 event_msg_cb(const td_thrhandle_t *th_p, void *arg)
1707 {
1708 	static td_thrhandle_t th;
1709 	td_event_msg_t *msg = arg;
1710 
1711 	if (__td_thr_event_getmsg((td_thrhandle_t *)th_p, msg) == TD_OK) {
1712 		/*
1713 		 * Got an event, stop iterating.
1714 		 *
1715 		 * Because of past mistakes in interface definition,
1716 		 * we are forced to pass back a static local variable
1717 		 * for the thread handle because th_p is a pointer
1718 		 * to a local variable in __td_ta_thr_iter().
1719 		 * Grr...
1720 		 */
1721 		th = *th_p;
1722 		msg->th_p = &th;
1723 		return (1);
1724 	}
1725 	return (0);
1726 }
1727 
1728 /*
1729  * This function is just like td_thr_event_getmsg, except that it is
1730  * passed a process handle rather than a thread handle, and returns
1731  * an event message for some thread in the process that has an event
1732  * message pending.  If no thread has an event message pending, this
1733  * routine returns TD_NOEVENT.  Thus, all pending event messages may
1734  * be collected from a process by repeatedly calling this routine
1735  * until it returns TD_NOEVENT.
1736  */
1737 #pragma weak td_ta_event_getmsg = __td_ta_event_getmsg
1738 td_err_e
1739 __td_ta_event_getmsg(td_thragent_t *ta_p, td_event_msg_t *msg)
1740 {
1741 	td_err_e return_val;
1742 
1743 	if (ta_p == NULL)
1744 		return (TD_BADTA);
1745 	if (ta_p->ph_p == NULL)
1746 		return (TD_BADPH);
1747 	if (msg == NULL)
1748 		return (TD_ERR);
1749 	msg->event = TD_EVENT_NONE;
1750 	if ((return_val = __td_ta_thr_iter(ta_p, event_msg_cb, msg,
1751 	    TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK,
1752 	    TD_THR_ANY_USER_FLAGS)) != TD_OK)
1753 		return (return_val);
1754 	if (msg->event == TD_EVENT_NONE)
1755 		return (TD_NOEVENT);
1756 	return (TD_OK);
1757 }
1758 
1759 static lwpid_t
1760 thr_to_lwpid(const td_thrhandle_t *th_p)
1761 {
1762 	struct ps_prochandle *ph_p = th_p->th_ta_p->ph_p;
1763 	lwpid_t lwpid;
1764 
1765 	/*
1766 	 * The caller holds the prochandle lock
1767 	 * and has already verfied everything.
1768 	 */
1769 	if (th_p->th_ta_p->model == PR_MODEL_NATIVE) {
1770 		ulwp_t *ulwp = (ulwp_t *)th_p->th_unique;
1771 
1772 		if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_lwpid,
1773 		    &lwpid, sizeof (lwpid)) != PS_OK)
1774 			lwpid = 0;
1775 		else if (lwpid == 0)
1776 			lwpid = 1;
1777 	} else {
1778 #if defined(_LP64) && defined(_SYSCALL32)
1779 		ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique;
1780 
1781 		if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_lwpid,
1782 		    &lwpid, sizeof (lwpid)) != PS_OK)
1783 			lwpid = 0;
1784 		else if (lwpid == 0)
1785 			lwpid = 1;
1786 #else
1787 		lwpid = 0;
1788 #endif	/* _SYSCALL32 */
1789 	}
1790 
1791 	return (lwpid);
1792 }
1793 
1794 /*
1795  * Suspend a thread.
1796  * XXX: What does this mean in a one-level model?
1797  */
1798 #pragma weak td_thr_dbsuspend = __td_thr_dbsuspend
1799 td_err_e
1800 __td_thr_dbsuspend(const td_thrhandle_t *th_p)
1801 {
1802 	struct ps_prochandle *ph_p;
1803 	td_err_e return_val;
1804 
1805 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
1806 		return (return_val);
1807 	if (ps_lstop(ph_p, thr_to_lwpid(th_p)) != PS_OK)
1808 		return_val = TD_DBERR;
1809 	ph_unlock(th_p->th_ta_p);
1810 	return (return_val);
1811 }
1812 
1813 /*
1814  * Resume a suspended thread.
1815  * XXX: What does this mean in a one-level model?
1816  */
1817 #pragma weak td_thr_dbresume = __td_thr_dbresume
1818 td_err_e
1819 __td_thr_dbresume(const td_thrhandle_t *th_p)
1820 {
1821 	struct ps_prochandle *ph_p;
1822 	td_err_e return_val;
1823 
1824 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
1825 		return (return_val);
1826 	if (ps_lcontinue(ph_p, thr_to_lwpid(th_p)) != PS_OK)
1827 		return_val = TD_DBERR;
1828 	ph_unlock(th_p->th_ta_p);
1829 	return (return_val);
1830 }
1831 
1832 /*
1833  * Set a thread's signal mask.
1834  * Currently unused by dbx.
1835  */
1836 #pragma weak td_thr_sigsetmask = __td_thr_sigsetmask
1837 /* ARGSUSED */
1838 td_err_e
1839 __td_thr_sigsetmask(const td_thrhandle_t *th_p, const sigset_t ti_sigmask)
1840 {
1841 	return (TD_NOCAPAB);
1842 }
1843 
1844 /*
1845  * Set a thread's "signals-pending" set.
1846  * Currently unused by dbx.
1847  */
1848 #pragma weak td_thr_setsigpending = __td_thr_setsigpending
1849 /* ARGSUSED */
1850 td_err_e
1851 __td_thr_setsigpending(const td_thrhandle_t *th_p,
1852 	uchar_t ti_pending_flag, const sigset_t ti_pending)
1853 {
1854 	return (TD_NOCAPAB);
1855 }
1856 
1857 /*
1858  * Get a thread's general register set.
1859  */
1860 #pragma weak td_thr_getgregs = __td_thr_getgregs
1861 td_err_e
1862 __td_thr_getgregs(td_thrhandle_t *th_p, prgregset_t regset)
1863 {
1864 	struct ps_prochandle *ph_p;
1865 	td_err_e return_val;
1866 
1867 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
1868 		return (return_val);
1869 	if (ps_pstop(ph_p) != PS_OK) {
1870 		ph_unlock(th_p->th_ta_p);
1871 		return (TD_DBERR);
1872 	}
1873 
1874 	if (ps_lgetregs(ph_p, thr_to_lwpid(th_p), regset) != PS_OK)
1875 		return_val = TD_DBERR;
1876 
1877 	(void) ps_pcontinue(ph_p);
1878 	ph_unlock(th_p->th_ta_p);
1879 	return (return_val);
1880 }
1881 
1882 /*
1883  * Set a thread's general register set.
1884  */
1885 #pragma weak td_thr_setgregs = __td_thr_setgregs
1886 td_err_e
1887 __td_thr_setgregs(td_thrhandle_t *th_p, const prgregset_t regset)
1888 {
1889 	struct ps_prochandle *ph_p;
1890 	td_err_e return_val;
1891 
1892 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
1893 		return (return_val);
1894 	if (ps_pstop(ph_p) != PS_OK) {
1895 		ph_unlock(th_p->th_ta_p);
1896 		return (TD_DBERR);
1897 	}
1898 
1899 	if (ps_lsetregs(ph_p, thr_to_lwpid(th_p), regset) != PS_OK)
1900 		return_val = TD_DBERR;
1901 
1902 	(void) ps_pcontinue(ph_p);
1903 	ph_unlock(th_p->th_ta_p);
1904 	return (return_val);
1905 }
1906 
1907 /*
1908  * Get a thread's floating-point register set.
1909  */
1910 #pragma weak td_thr_getfpregs = __td_thr_getfpregs
1911 td_err_e
1912 __td_thr_getfpregs(td_thrhandle_t *th_p, prfpregset_t *fpregset)
1913 {
1914 	struct ps_prochandle *ph_p;
1915 	td_err_e return_val;
1916 
1917 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
1918 		return (return_val);
1919 	if (ps_pstop(ph_p) != PS_OK) {
1920 		ph_unlock(th_p->th_ta_p);
1921 		return (TD_DBERR);
1922 	}
1923 
1924 	if (ps_lgetfpregs(ph_p, thr_to_lwpid(th_p), fpregset) != PS_OK)
1925 		return_val = TD_DBERR;
1926 
1927 	(void) ps_pcontinue(ph_p);
1928 	ph_unlock(th_p->th_ta_p);
1929 	return (return_val);
1930 }
1931 
1932 /*
1933  * Set a thread's floating-point register set.
1934  */
1935 #pragma weak td_thr_setfpregs = __td_thr_setfpregs
1936 td_err_e
1937 __td_thr_setfpregs(td_thrhandle_t *th_p, const prfpregset_t *fpregset)
1938 {
1939 	struct ps_prochandle *ph_p;
1940 	td_err_e return_val;
1941 
1942 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
1943 		return (return_val);
1944 	if (ps_pstop(ph_p) != PS_OK) {
1945 		ph_unlock(th_p->th_ta_p);
1946 		return (TD_DBERR);
1947 	}
1948 
1949 	if (ps_lsetfpregs(ph_p, thr_to_lwpid(th_p), fpregset) != PS_OK)
1950 		return_val = TD_DBERR;
1951 
1952 	(void) ps_pcontinue(ph_p);
1953 	ph_unlock(th_p->th_ta_p);
1954 	return (return_val);
1955 }
1956 
1957 /*
1958  * Get the size of the extra state register set for this architecture.
1959  * Currently unused by dbx.
1960  */
1961 #pragma weak td_thr_getxregsize = __td_thr_getxregsize
1962 /* ARGSUSED */
1963 td_err_e
1964 __td_thr_getxregsize(td_thrhandle_t *th_p, int *xregsize)
1965 {
1966 #if defined(__sparc)
1967 	struct ps_prochandle *ph_p;
1968 	td_err_e return_val;
1969 
1970 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
1971 		return (return_val);
1972 	if (ps_pstop(ph_p) != PS_OK) {
1973 		ph_unlock(th_p->th_ta_p);
1974 		return (TD_DBERR);
1975 	}
1976 
1977 	if (ps_lgetxregsize(ph_p, thr_to_lwpid(th_p), xregsize) != PS_OK)
1978 		return_val = TD_DBERR;
1979 
1980 	(void) ps_pcontinue(ph_p);
1981 	ph_unlock(th_p->th_ta_p);
1982 	return (return_val);
1983 #else	/* __sparc */
1984 	return (TD_NOXREGS);
1985 #endif	/* __sparc */
1986 }
1987 
1988 /*
1989  * Get a thread's extra state register set.
1990  */
1991 #pragma weak td_thr_getxregs = __td_thr_getxregs
1992 /* ARGSUSED */
1993 td_err_e
1994 __td_thr_getxregs(td_thrhandle_t *th_p, void *xregset)
1995 {
1996 #if defined(__sparc)
1997 	struct ps_prochandle *ph_p;
1998 	td_err_e return_val;
1999 
2000 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
2001 		return (return_val);
2002 	if (ps_pstop(ph_p) != PS_OK) {
2003 		ph_unlock(th_p->th_ta_p);
2004 		return (TD_DBERR);
2005 	}
2006 
2007 	if (ps_lgetxregs(ph_p, thr_to_lwpid(th_p), (caddr_t)xregset) != PS_OK)
2008 		return_val = TD_DBERR;
2009 
2010 	(void) ps_pcontinue(ph_p);
2011 	ph_unlock(th_p->th_ta_p);
2012 	return (return_val);
2013 #else	/* __sparc */
2014 	return (TD_NOXREGS);
2015 #endif	/* __sparc */
2016 }
2017 
2018 /*
2019  * Set a thread's extra state register set.
2020  */
2021 #pragma weak td_thr_setxregs = __td_thr_setxregs
2022 /* ARGSUSED */
2023 td_err_e
2024 __td_thr_setxregs(td_thrhandle_t *th_p, const void *xregset)
2025 {
2026 #if defined(__sparc)
2027 	struct ps_prochandle *ph_p;
2028 	td_err_e return_val;
2029 
2030 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
2031 		return (return_val);
2032 	if (ps_pstop(ph_p) != PS_OK) {
2033 		ph_unlock(th_p->th_ta_p);
2034 		return (TD_DBERR);
2035 	}
2036 
2037 	if (ps_lsetxregs(ph_p, thr_to_lwpid(th_p), (caddr_t)xregset) != PS_OK)
2038 		return_val = TD_DBERR;
2039 
2040 	(void) ps_pcontinue(ph_p);
2041 	ph_unlock(th_p->th_ta_p);
2042 	return (return_val);
2043 #else	/* __sparc */
2044 	return (TD_NOXREGS);
2045 #endif	/* __sparc */
2046 }
2047 
2048 struct searcher {
2049 	psaddr_t	addr;
2050 	int		status;
2051 };
2052 
2053 /*
2054  * Check the struct thread address in *th_p again first
2055  * value in "data".  If value in data is found, set second value
2056  * in "data" to 1 and return 1 to terminate iterations.
2057  * This function is used by td_thr_validate() to verify that
2058  * a thread handle is valid.
2059  */
2060 static int
2061 td_searcher(const td_thrhandle_t *th_p, void *data)
2062 {
2063 	struct searcher *searcher_data = (struct searcher *)data;
2064 
2065 	if (searcher_data->addr == th_p->th_unique) {
2066 		searcher_data->status = 1;
2067 		return (1);
2068 	}
2069 	return (0);
2070 }
2071 
2072 /*
2073  * Validate the thread handle.  Check that
2074  * a thread exists in the thread agent/process that
2075  * corresponds to thread with handle *th_p.
2076  * Currently unused by dbx.
2077  */
2078 #pragma weak td_thr_validate = __td_thr_validate
2079 td_err_e
2080 __td_thr_validate(const td_thrhandle_t *th_p)
2081 {
2082 	td_err_e return_val;
2083 	struct searcher searcher_data = {0, 0};
2084 
2085 	if (th_p == NULL)
2086 		return (TD_BADTH);
2087 	if (th_p->th_unique == NULL || th_p->th_ta_p == NULL)
2088 		return (TD_BADTH);
2089 
2090 	/*
2091 	 * LOCKING EXCEPTION - Locking is not required
2092 	 * here because no use of the thread agent is made (other
2093 	 * than the sanity check) and checking of the thread
2094 	 * agent will be done in __td_ta_thr_iter.
2095 	 */
2096 
2097 	searcher_data.addr = th_p->th_unique;
2098 	return_val = __td_ta_thr_iter(th_p->th_ta_p,
2099 	    td_searcher, &searcher_data,
2100 	    TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
2101 	    TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
2102 
2103 	if (return_val == TD_OK && searcher_data.status == 0)
2104 		return_val = TD_NOTHR;
2105 
2106 	return (return_val);
2107 }
2108 
2109 /*
2110  * Get a thread's private binding to a given thread specific
2111  * data(TSD) key(see thr_getspecific(3T).  If the thread doesn't
2112  * have a binding for a particular key, then NULL is returned.
2113  */
2114 #pragma weak td_thr_tsd = __td_thr_tsd
2115 td_err_e
2116 __td_thr_tsd(td_thrhandle_t *th_p, thread_key_t key, void **data_pp)
2117 {
2118 	struct ps_prochandle *ph_p;
2119 	td_thragent_t	*ta_p;
2120 	td_err_e	return_val;
2121 	int		maxkey;
2122 	int		nkey;
2123 	psaddr_t	tsd_paddr;
2124 
2125 	if (data_pp == NULL)
2126 		return (TD_ERR);
2127 	*data_pp = NULL;
2128 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
2129 		return (return_val);
2130 	ta_p = th_p->th_ta_p;
2131 	if (ps_pstop(ph_p) != PS_OK) {
2132 		ph_unlock(ta_p);
2133 		return (TD_DBERR);
2134 	}
2135 
2136 	if (ta_p->model == PR_MODEL_NATIVE) {
2137 		ulwp_t *ulwp = (ulwp_t *)th_p->th_unique;
2138 		tsd_metadata_t tsdm;
2139 		tsd_t stsd;
2140 
2141 		if (ps_pdread(ph_p,
2142 		    ta_p->uberdata_addr + offsetof(uberdata_t, tsd_metadata),
2143 		    &tsdm, sizeof (tsdm)) != PS_OK)
2144 			return_val = TD_DBERR;
2145 		else if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_stsd,
2146 		    &tsd_paddr, sizeof (tsd_paddr)) != PS_OK)
2147 			return_val = TD_DBERR;
2148 		else if (tsd_paddr != NULL &&
2149 		    ps_pdread(ph_p, tsd_paddr, &stsd, sizeof (stsd)) != PS_OK)
2150 			return_val = TD_DBERR;
2151 		else {
2152 			maxkey = tsdm.tsdm_nused;
2153 			nkey = tsd_paddr == NULL ? TSD_NFAST : stsd.tsd_nalloc;
2154 
2155 			if (key < TSD_NFAST)
2156 				tsd_paddr = (psaddr_t)&ulwp->ul_ftsd[0];
2157 		}
2158 	} else {
2159 #if defined(_LP64) && defined(_SYSCALL32)
2160 		ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique;
2161 		tsd_metadata32_t tsdm;
2162 		tsd32_t stsd;
2163 		caddr32_t addr;
2164 
2165 		if (ps_pdread(ph_p,
2166 		    ta_p->uberdata_addr + offsetof(uberdata32_t, tsd_metadata),
2167 		    &tsdm, sizeof (tsdm)) != PS_OK)
2168 			return_val = TD_DBERR;
2169 		else if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_stsd,
2170 		    &addr, sizeof (addr)) != PS_OK)
2171 			return_val = TD_DBERR;
2172 		else if (addr != NULL &&
2173 		    ps_pdread(ph_p, addr, &stsd, sizeof (stsd)) != PS_OK)
2174 			return_val = TD_DBERR;
2175 		else {
2176 			maxkey = tsdm.tsdm_nused;
2177 			nkey = addr == NULL ? TSD_NFAST : stsd.tsd_nalloc;
2178 
2179 			if (key < TSD_NFAST) {
2180 				tsd_paddr = (psaddr_t)&ulwp->ul_ftsd[0];
2181 			} else {
2182 				tsd_paddr = addr;
2183 			}
2184 		}
2185 #else
2186 		return_val = TD_ERR;
2187 #endif	/* _SYSCALL32 */
2188 	}
2189 
2190 	if (return_val == TD_OK && (key < 1 || key >= maxkey))
2191 		return_val = TD_NOTSD;
2192 	if (return_val != TD_OK || key >= nkey) {
2193 		/* NULL has already been stored in data_pp */
2194 		(void) ps_pcontinue(ph_p);
2195 		ph_unlock(ta_p);
2196 		return (return_val);
2197 	}
2198 
2199 	/*
2200 	 * Read the value from the thread's tsd array.
2201 	 */
2202 	if (ta_p->model == PR_MODEL_NATIVE) {
2203 		void *value;
2204 
2205 		if (ps_pdread(ph_p, tsd_paddr + key * sizeof (void *),
2206 		    &value, sizeof (value)) != PS_OK)
2207 			return_val = TD_DBERR;
2208 		else
2209 			*data_pp = value;
2210 #if defined(_LP64) && defined(_SYSCALL32)
2211 	} else {
2212 		caddr32_t value32;
2213 
2214 		if (ps_pdread(ph_p, tsd_paddr + key * sizeof (caddr32_t),
2215 		    &value32, sizeof (value32)) != PS_OK)
2216 			return_val = TD_DBERR;
2217 		else
2218 			*data_pp = (void *)(uintptr_t)value32;
2219 #endif	/* _SYSCALL32 */
2220 	}
2221 
2222 	(void) ps_pcontinue(ph_p);
2223 	ph_unlock(ta_p);
2224 	return (return_val);
2225 }
2226 
2227 /*
2228  * Get the base address of a thread's thread local storage (TLS) block
2229  * for the module (executable or shared object) identified by 'moduleid'.
2230  */
2231 #pragma weak td_thr_tlsbase = __td_thr_tlsbase
2232 td_err_e
2233 __td_thr_tlsbase(td_thrhandle_t *th_p, ulong_t moduleid, psaddr_t *base)
2234 {
2235 	struct ps_prochandle *ph_p;
2236 	td_thragent_t	*ta_p;
2237 	td_err_e	return_val;
2238 
2239 	if (base == NULL)
2240 		return (TD_ERR);
2241 	*base = NULL;
2242 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
2243 		return (return_val);
2244 	ta_p = th_p->th_ta_p;
2245 	if (ps_pstop(ph_p) != PS_OK) {
2246 		ph_unlock(ta_p);
2247 		return (TD_DBERR);
2248 	}
2249 
2250 	if (ta_p->model == PR_MODEL_NATIVE) {
2251 		ulwp_t *ulwp = (ulwp_t *)th_p->th_unique;
2252 		tls_metadata_t tls_metadata;
2253 		TLS_modinfo tlsmod;
2254 		tls_t tls;
2255 
2256 		if (ps_pdread(ph_p,
2257 		    ta_p->uberdata_addr + offsetof(uberdata_t, tls_metadata),
2258 		    &tls_metadata, sizeof (tls_metadata)) != PS_OK)
2259 			return_val = TD_DBERR;
2260 		else if (moduleid >= tls_metadata.tls_modinfo.tls_size)
2261 			return_val = TD_NOTLS;
2262 		else if (ps_pdread(ph_p,
2263 		    (psaddr_t)((TLS_modinfo *)
2264 		    tls_metadata.tls_modinfo.tls_data + moduleid),
2265 		    &tlsmod, sizeof (tlsmod)) != PS_OK)
2266 			return_val = TD_DBERR;
2267 		else if (tlsmod.tm_memsz == 0)
2268 			return_val = TD_NOTLS;
2269 		else if (tlsmod.tm_flags & TM_FLG_STATICTLS)
2270 			*base = (psaddr_t)ulwp - tlsmod.tm_stattlsoffset;
2271 		else if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_tls,
2272 		    &tls, sizeof (tls)) != PS_OK)
2273 			return_val = TD_DBERR;
2274 		else if (moduleid >= tls.tls_size)
2275 			return_val = TD_TLSDEFER;
2276 		else if (ps_pdread(ph_p,
2277 		    (psaddr_t)((tls_t *)tls.tls_data + moduleid),
2278 		    &tls, sizeof (tls)) != PS_OK)
2279 			return_val = TD_DBERR;
2280 		else if (tls.tls_size == 0)
2281 			return_val = TD_TLSDEFER;
2282 		else
2283 			*base = (psaddr_t)tls.tls_data;
2284 	} else {
2285 #if defined(_LP64) && defined(_SYSCALL32)
2286 		ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique;
2287 		tls_metadata32_t tls_metadata;
2288 		TLS_modinfo32 tlsmod;
2289 		tls32_t tls;
2290 
2291 		if (ps_pdread(ph_p,
2292 		    ta_p->uberdata_addr + offsetof(uberdata32_t, tls_metadata),
2293 		    &tls_metadata, sizeof (tls_metadata)) != PS_OK)
2294 			return_val = TD_DBERR;
2295 		else if (moduleid >= tls_metadata.tls_modinfo.tls_size)
2296 			return_val = TD_NOTLS;
2297 		else if (ps_pdread(ph_p,
2298 		    (psaddr_t)((TLS_modinfo32 *)
2299 		    (uintptr_t)tls_metadata.tls_modinfo.tls_data + moduleid),
2300 		    &tlsmod, sizeof (tlsmod)) != PS_OK)
2301 			return_val = TD_DBERR;
2302 		else if (tlsmod.tm_memsz == 0)
2303 			return_val = TD_NOTLS;
2304 		else if (tlsmod.tm_flags & TM_FLG_STATICTLS)
2305 			*base = (psaddr_t)ulwp - tlsmod.tm_stattlsoffset;
2306 		else if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_tls,
2307 		    &tls, sizeof (tls)) != PS_OK)
2308 			return_val = TD_DBERR;
2309 		else if (moduleid >= tls.tls_size)
2310 			return_val = TD_TLSDEFER;
2311 		else if (ps_pdread(ph_p,
2312 		    (psaddr_t)((tls32_t *)(uintptr_t)tls.tls_data + moduleid),
2313 		    &tls, sizeof (tls)) != PS_OK)
2314 			return_val = TD_DBERR;
2315 		else if (tls.tls_size == 0)
2316 			return_val = TD_TLSDEFER;
2317 		else
2318 			*base = (psaddr_t)tls.tls_data;
2319 #else
2320 		return_val = TD_ERR;
2321 #endif	/* _SYSCALL32 */
2322 	}
2323 
2324 	(void) ps_pcontinue(ph_p);
2325 	ph_unlock(ta_p);
2326 	return (return_val);
2327 }
2328 
2329 /*
2330  * Change a thread's priority to the value specified by ti_pri.
2331  * Currently unused by dbx.
2332  */
2333 #pragma weak td_thr_setprio = __td_thr_setprio
2334 /* ARGSUSED */
2335 td_err_e
2336 __td_thr_setprio(td_thrhandle_t *th_p, int ti_pri)
2337 {
2338 	return (TD_NOCAPAB);
2339 }
2340 
2341 /*
2342  * This structure links td_thr_lockowner and the lowner_cb callback function.
2343  */
2344 typedef struct {
2345 	td_sync_iter_f	*owner_cb;
2346 	void		*owner_cb_arg;
2347 	td_thrhandle_t	*th_p;
2348 } lowner_cb_ctl_t;
2349 
2350 static int
2351 lowner_cb(const td_synchandle_t *sh_p, void *arg)
2352 {
2353 	lowner_cb_ctl_t *ocb = arg;
2354 	int trunc = 0;
2355 	union {
2356 		rwlock_t rwl;
2357 		mutex_t mx;
2358 	} rw_m;
2359 
2360 	if (ps_pdread(sh_p->sh_ta_p->ph_p, sh_p->sh_unique,
2361 	    &rw_m, sizeof (rw_m)) != PS_OK) {
2362 		trunc = 1;
2363 		if (ps_pdread(sh_p->sh_ta_p->ph_p, sh_p->sh_unique,
2364 		    &rw_m.mx, sizeof (rw_m.mx)) != PS_OK)
2365 			return (0);
2366 	}
2367 	if (rw_m.mx.mutex_magic == MUTEX_MAGIC &&
2368 	    rw_m.mx.mutex_owner == ocb->th_p->th_unique)
2369 		return ((ocb->owner_cb)(sh_p, ocb->owner_cb_arg));
2370 	if (!trunc && rw_m.rwl.magic == RWL_MAGIC) {
2371 		mutex_t *rwlock = &rw_m.rwl.mutex;
2372 		if (rwlock->mutex_owner == ocb->th_p->th_unique)
2373 			return ((ocb->owner_cb)(sh_p, ocb->owner_cb_arg));
2374 	}
2375 	return (0);
2376 }
2377 
2378 /*
2379  * Iterate over the set of locks owned by a specified thread.
2380  * If cb returns a non-zero value, terminate iterations.
2381  */
2382 #pragma weak td_thr_lockowner = __td_thr_lockowner
2383 td_err_e
2384 __td_thr_lockowner(const td_thrhandle_t *th_p, td_sync_iter_f *cb,
2385 	void *cb_data)
2386 {
2387 	td_thragent_t	*ta_p;
2388 	td_err_e	return_val;
2389 	lowner_cb_ctl_t	lcb;
2390 
2391 	/*
2392 	 * Just sanity checks.
2393 	 */
2394 	if (ph_lock_th((td_thrhandle_t *)th_p, &return_val) == NULL)
2395 		return (return_val);
2396 	ta_p = th_p->th_ta_p;
2397 	ph_unlock(ta_p);
2398 
2399 	lcb.owner_cb = cb;
2400 	lcb.owner_cb_arg = cb_data;
2401 	lcb.th_p = (td_thrhandle_t *)th_p;
2402 	return (__td_ta_sync_iter(ta_p, lowner_cb, &lcb));
2403 }
2404 
2405 /*
2406  * If a thread is asleep on a synchronization variable,
2407  * then get the synchronization handle.
2408  */
2409 #pragma weak td_thr_sleepinfo = __td_thr_sleepinfo
2410 td_err_e
2411 __td_thr_sleepinfo(const td_thrhandle_t *th_p, td_synchandle_t *sh_p)
2412 {
2413 	struct ps_prochandle *ph_p;
2414 	td_err_e	return_val = TD_OK;
2415 	uintptr_t	wchan;
2416 
2417 	if (sh_p == NULL)
2418 		return (TD_ERR);
2419 	if ((ph_p = ph_lock_th((td_thrhandle_t *)th_p, &return_val)) == NULL)
2420 		return (return_val);
2421 
2422 	/*
2423 	 * No need to stop the process for a simple read.
2424 	 */
2425 	if (th_p->th_ta_p->model == PR_MODEL_NATIVE) {
2426 		ulwp_t *ulwp = (ulwp_t *)th_p->th_unique;
2427 
2428 		if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_wchan,
2429 		    &wchan, sizeof (wchan)) != PS_OK)
2430 			return_val = TD_DBERR;
2431 	} else {
2432 #if defined(_LP64) && defined(_SYSCALL32)
2433 		ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique;
2434 		caddr32_t wchan32;
2435 
2436 		if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_wchan,
2437 		    &wchan32, sizeof (wchan32)) != PS_OK)
2438 			return_val = TD_DBERR;
2439 		wchan = wchan32;
2440 #else
2441 		return_val = TD_ERR;
2442 #endif	/* _SYSCALL32 */
2443 	}
2444 
2445 	if (return_val != TD_OK || wchan == NULL) {
2446 		sh_p->sh_ta_p = NULL;
2447 		sh_p->sh_unique = NULL;
2448 		if (return_val == TD_OK)
2449 			return_val = TD_ERR;
2450 	} else {
2451 		sh_p->sh_ta_p = th_p->th_ta_p;
2452 		sh_p->sh_unique = (psaddr_t)wchan;
2453 	}
2454 
2455 	ph_unlock(th_p->th_ta_p);
2456 	return (return_val);
2457 }
2458 
2459 /*
2460  * Which thread is running on an lwp?
2461  */
2462 #pragma weak td_ta_map_lwp2thr = __td_ta_map_lwp2thr
2463 td_err_e
2464 __td_ta_map_lwp2thr(td_thragent_t *ta_p, lwpid_t lwpid,
2465 	td_thrhandle_t *th_p)
2466 {
2467 	return (__td_ta_map_id2thr(ta_p, lwpid, th_p));
2468 }
2469 
2470 /*
2471  * Common code for td_sync_get_info() and td_sync_get_stats()
2472  */
2473 static td_err_e
2474 sync_get_info_common(const td_synchandle_t *sh_p, struct ps_prochandle *ph_p,
2475 	td_syncinfo_t *si_p)
2476 {
2477 	int trunc = 0;
2478 	td_so_un_t generic_so;
2479 
2480 	/*
2481 	 * Determine the sync. object type; a little type fudgery here.
2482 	 * First attempt to read the whole union.  If that fails, attempt
2483 	 * to read just the condvar.  A condvar is the smallest sync. object.
2484 	 */
2485 	if (ps_pdread(ph_p, sh_p->sh_unique,
2486 	    &generic_so, sizeof (generic_so)) != PS_OK) {
2487 		trunc = 1;
2488 		if (ps_pdread(ph_p, sh_p->sh_unique, &generic_so.condition,
2489 		    sizeof (generic_so.condition)) != PS_OK)
2490 			return (TD_DBERR);
2491 	}
2492 
2493 	switch (generic_so.condition.cond_magic) {
2494 	case MUTEX_MAGIC:
2495 		if (trunc && ps_pdread(ph_p, sh_p->sh_unique,
2496 		    &generic_so.lock, sizeof (generic_so.lock)) != PS_OK)
2497 			return (TD_DBERR);
2498 		si_p->si_type = TD_SYNC_MUTEX;
2499 		si_p->si_shared_type =
2500 		    (generic_so.lock.mutex_type & USYNC_PROCESS);
2501 		(void) memcpy(si_p->si_flags, &generic_so.lock.mutex_flag,
2502 		    sizeof (generic_so.lock.mutex_flag));
2503 		si_p->si_state.mutex_locked =
2504 		    (generic_so.lock.mutex_lockw != 0);
2505 		si_p->si_size = sizeof (generic_so.lock);
2506 		si_p->si_has_waiters = generic_so.lock.mutex_waiters;
2507 		si_p->si_rcount = generic_so.lock.mutex_rcount;
2508 		si_p->si_prioceiling = generic_so.lock.mutex_ceiling;
2509 		if (si_p->si_state.mutex_locked) {
2510 			if (si_p->si_shared_type & USYNC_PROCESS)
2511 				si_p->si_ownerpid =
2512 				    generic_so.lock.mutex_ownerpid;
2513 			si_p->si_owner.th_ta_p = sh_p->sh_ta_p;
2514 			si_p->si_owner.th_unique = generic_so.lock.mutex_owner;
2515 		}
2516 		break;
2517 	case COND_MAGIC:
2518 		si_p->si_type = TD_SYNC_COND;
2519 		si_p->si_shared_type =
2520 		    (generic_so.condition.cond_type & USYNC_PROCESS);
2521 		(void) memcpy(si_p->si_flags, generic_so.condition.flags.flag,
2522 		    sizeof (generic_so.condition.flags.flag));
2523 		si_p->si_size = sizeof (generic_so.condition);
2524 		si_p->si_has_waiters =
2525 		    (generic_so.condition.cond_waiters_user |
2526 		    generic_so.condition.cond_waiters_kernel)? 1 : 0;
2527 		break;
2528 	case SEMA_MAGIC:
2529 		if (trunc && ps_pdread(ph_p, sh_p->sh_unique,
2530 		    &generic_so.semaphore, sizeof (generic_so.semaphore))
2531 		    != PS_OK)
2532 			return (TD_DBERR);
2533 		si_p->si_type = TD_SYNC_SEMA;
2534 		si_p->si_shared_type =
2535 		    (generic_so.semaphore.type & USYNC_PROCESS);
2536 		si_p->si_state.sem_count = generic_so.semaphore.count;
2537 		si_p->si_size = sizeof (generic_so.semaphore);
2538 		si_p->si_has_waiters =
2539 		    ((lwp_sema_t *)&generic_so.semaphore)->flags[7];
2540 		/* this is useless but the old interface provided it */
2541 		si_p->si_data = (psaddr_t)generic_so.semaphore.count;
2542 		break;
2543 	case RWL_MAGIC:
2544 	{
2545 		uint32_t rwstate;
2546 
2547 		if (trunc && ps_pdread(ph_p, sh_p->sh_unique,
2548 		    &generic_so.rwlock, sizeof (generic_so.rwlock)) != PS_OK)
2549 			return (TD_DBERR);
2550 		si_p->si_type = TD_SYNC_RWLOCK;
2551 		si_p->si_shared_type =
2552 		    (generic_so.rwlock.rwlock_type & USYNC_PROCESS);
2553 		si_p->si_size = sizeof (generic_so.rwlock);
2554 
2555 		rwstate = (uint32_t)generic_so.rwlock.rwlock_readers;
2556 		if (rwstate & URW_WRITE_LOCKED) {
2557 			si_p->si_state.nreaders = -1;
2558 			si_p->si_is_wlock = 1;
2559 			si_p->si_owner.th_ta_p = sh_p->sh_ta_p;
2560 			si_p->si_owner.th_unique =
2561 			    generic_so.rwlock.rwlock_owner;
2562 			if (si_p->si_shared_type & USYNC_PROCESS)
2563 				si_p->si_ownerpid =
2564 				    generic_so.rwlock.rwlock_ownerpid;
2565 		} else {
2566 			si_p->si_state.nreaders = (rwstate & URW_READERS_MASK);
2567 		}
2568 		si_p->si_has_waiters = ((rwstate & URW_HAS_WAITERS) != 0);
2569 
2570 		/* this is useless but the old interface provided it */
2571 		si_p->si_data = (psaddr_t)generic_so.rwlock.readers;
2572 		break;
2573 	}
2574 	default:
2575 		return (TD_BADSH);
2576 	}
2577 
2578 	si_p->si_ta_p = sh_p->sh_ta_p;
2579 	si_p->si_sv_addr = sh_p->sh_unique;
2580 	return (TD_OK);
2581 }
2582 
2583 /*
2584  * Given a synchronization handle, fill in the
2585  * information for the synchronization variable into *si_p.
2586  */
2587 #pragma weak td_sync_get_info = __td_sync_get_info
2588 td_err_e
2589 __td_sync_get_info(const td_synchandle_t *sh_p, td_syncinfo_t *si_p)
2590 {
2591 	struct ps_prochandle *ph_p;
2592 	td_err_e return_val;
2593 
2594 	if (si_p == NULL)
2595 		return (TD_ERR);
2596 	(void) memset(si_p, 0, sizeof (*si_p));
2597 	if ((ph_p = ph_lock_sh(sh_p, &return_val)) == NULL)
2598 		return (return_val);
2599 	if (ps_pstop(ph_p) != PS_OK) {
2600 		ph_unlock(sh_p->sh_ta_p);
2601 		return (TD_DBERR);
2602 	}
2603 
2604 	return_val = sync_get_info_common(sh_p, ph_p, si_p);
2605 
2606 	(void) ps_pcontinue(ph_p);
2607 	ph_unlock(sh_p->sh_ta_p);
2608 	return (return_val);
2609 }
2610 
2611 static uint_t
2612 tdb_addr_hash64(uint64_t addr)
2613 {
2614 	uint64_t value60 = (addr >> 4);
2615 	uint32_t value30 = (value60 >> 30) ^ (value60 & 0x3fffffff);
2616 	return ((value30 >> 15) ^ (value30 & 0x7fff));
2617 }
2618 
2619 static uint_t
2620 tdb_addr_hash32(uint64_t addr)
2621 {
2622 	uint32_t value30 = (addr >> 2);		/* 30 bits */
2623 	return ((value30 >> 15) ^ (value30 & 0x7fff));
2624 }
2625 
2626 static td_err_e
2627 read_sync_stats(td_thragent_t *ta_p, psaddr_t hash_table,
2628 	psaddr_t sync_obj_addr, tdb_sync_stats_t *sync_stats)
2629 {
2630 	psaddr_t next_desc;
2631 	uint64_t first;
2632 	uint_t ix;
2633 
2634 	/*
2635 	 * Compute the hash table index from the synch object's address.
2636 	 */
2637 	if (ta_p->model == PR_MODEL_LP64)
2638 		ix = tdb_addr_hash64(sync_obj_addr);
2639 	else
2640 		ix = tdb_addr_hash32(sync_obj_addr);
2641 
2642 	/*
2643 	 * Get the address of the first element in the linked list.
2644 	 */
2645 	if (ps_pdread(ta_p->ph_p, hash_table + ix * sizeof (uint64_t),
2646 	    &first, sizeof (first)) != PS_OK)
2647 		return (TD_DBERR);
2648 
2649 	/*
2650 	 * Search the linked list for an entry for the synch object..
2651 	 */
2652 	for (next_desc = (psaddr_t)first; next_desc != NULL;
2653 	    next_desc = (psaddr_t)sync_stats->next) {
2654 		if (ps_pdread(ta_p->ph_p, next_desc,
2655 		    sync_stats, sizeof (*sync_stats)) != PS_OK)
2656 			return (TD_DBERR);
2657 		if (sync_stats->sync_addr == sync_obj_addr)
2658 			return (TD_OK);
2659 	}
2660 
2661 	(void) memset(sync_stats, 0, sizeof (*sync_stats));
2662 	return (TD_OK);
2663 }
2664 
2665 /*
2666  * Given a synchronization handle, fill in the
2667  * statistics for the synchronization variable into *ss_p.
2668  */
2669 #pragma weak td_sync_get_stats = __td_sync_get_stats
2670 td_err_e
2671 __td_sync_get_stats(const td_synchandle_t *sh_p, td_syncstats_t *ss_p)
2672 {
2673 	struct ps_prochandle *ph_p;
2674 	td_thragent_t *ta_p;
2675 	td_err_e return_val;
2676 	register_sync_t enable;
2677 	psaddr_t hashaddr;
2678 	tdb_sync_stats_t sync_stats;
2679 	size_t ix;
2680 
2681 	if (ss_p == NULL)
2682 		return (TD_ERR);
2683 	(void) memset(ss_p, 0, sizeof (*ss_p));
2684 	if ((ph_p = ph_lock_sh(sh_p, &return_val)) == NULL)
2685 		return (return_val);
2686 	ta_p = sh_p->sh_ta_p;
2687 	if (ps_pstop(ph_p) != PS_OK) {
2688 		ph_unlock(ta_p);
2689 		return (TD_DBERR);
2690 	}
2691 
2692 	if ((return_val = sync_get_info_common(sh_p, ph_p, &ss_p->ss_info))
2693 	    != TD_OK) {
2694 		if (return_val != TD_BADSH)
2695 			goto out;
2696 		/* we can correct TD_BADSH */
2697 		(void) memset(&ss_p->ss_info, 0, sizeof (ss_p->ss_info));
2698 		ss_p->ss_info.si_ta_p = sh_p->sh_ta_p;
2699 		ss_p->ss_info.si_sv_addr = sh_p->sh_unique;
2700 		/* we correct si_type and si_size below */
2701 		return_val = TD_OK;
2702 	}
2703 	if (ps_pdread(ph_p, ta_p->tdb_register_sync_addr,
2704 	    &enable, sizeof (enable)) != PS_OK) {
2705 		return_val = TD_DBERR;
2706 		goto out;
2707 	}
2708 	if (enable != REGISTER_SYNC_ON)
2709 		goto out;
2710 
2711 	/*
2712 	 * Get the address of the hash table in the target process.
2713 	 */
2714 	if (ta_p->model == PR_MODEL_NATIVE) {
2715 		if (ps_pdread(ph_p, ta_p->uberdata_addr +
2716 		    offsetof(uberdata_t, tdb.tdb_sync_addr_hash),
2717 		    &hashaddr, sizeof (&hashaddr)) != PS_OK) {
2718 			return_val = TD_DBERR;
2719 			goto out;
2720 		}
2721 	} else {
2722 #if defined(_LP64) && defined(_SYSCALL32)
2723 		caddr32_t addr;
2724 
2725 		if (ps_pdread(ph_p, ta_p->uberdata_addr +
2726 		    offsetof(uberdata32_t, tdb.tdb_sync_addr_hash),
2727 		    &addr, sizeof (addr)) != PS_OK) {
2728 			return_val = TD_DBERR;
2729 			goto out;
2730 		}
2731 		hashaddr = addr;
2732 #else
2733 		return_val = TD_ERR;
2734 		goto out;
2735 #endif	/* _SYSCALL32 */
2736 	}
2737 
2738 	if (hashaddr == 0)
2739 		return_val = TD_BADSH;
2740 	else
2741 		return_val = read_sync_stats(ta_p, hashaddr,
2742 		    sh_p->sh_unique, &sync_stats);
2743 	if (return_val != TD_OK)
2744 		goto out;
2745 
2746 	/*
2747 	 * We have the hash table entry.  Transfer the data to
2748 	 * the td_syncstats_t structure provided by the caller.
2749 	 */
2750 	switch (sync_stats.un.type) {
2751 	case TDB_MUTEX:
2752 	{
2753 		td_mutex_stats_t *msp = &ss_p->ss_un.mutex;
2754 
2755 		ss_p->ss_info.si_type = TD_SYNC_MUTEX;
2756 		ss_p->ss_info.si_size = sizeof (mutex_t);
2757 		msp->mutex_lock =
2758 		    sync_stats.un.mutex.mutex_lock;
2759 		msp->mutex_sleep =
2760 		    sync_stats.un.mutex.mutex_sleep;
2761 		msp->mutex_sleep_time =
2762 		    sync_stats.un.mutex.mutex_sleep_time;
2763 		msp->mutex_hold_time =
2764 		    sync_stats.un.mutex.mutex_hold_time;
2765 		msp->mutex_try =
2766 		    sync_stats.un.mutex.mutex_try;
2767 		msp->mutex_try_fail =
2768 		    sync_stats.un.mutex.mutex_try_fail;
2769 		if (sync_stats.sync_addr >= ta_p->hash_table_addr &&
2770 		    (ix = sync_stats.sync_addr - ta_p->hash_table_addr)
2771 		    < ta_p->hash_size * sizeof (thr_hash_table_t))
2772 			msp->mutex_internal =
2773 			    ix / sizeof (thr_hash_table_t) + 1;
2774 		break;
2775 	}
2776 	case TDB_COND:
2777 	{
2778 		td_cond_stats_t *csp = &ss_p->ss_un.cond;
2779 
2780 		ss_p->ss_info.si_type = TD_SYNC_COND;
2781 		ss_p->ss_info.si_size = sizeof (cond_t);
2782 		csp->cond_wait =
2783 		    sync_stats.un.cond.cond_wait;
2784 		csp->cond_timedwait =
2785 		    sync_stats.un.cond.cond_timedwait;
2786 		csp->cond_wait_sleep_time =
2787 		    sync_stats.un.cond.cond_wait_sleep_time;
2788 		csp->cond_timedwait_sleep_time =
2789 		    sync_stats.un.cond.cond_timedwait_sleep_time;
2790 		csp->cond_timedwait_timeout =
2791 		    sync_stats.un.cond.cond_timedwait_timeout;
2792 		csp->cond_signal =
2793 		    sync_stats.un.cond.cond_signal;
2794 		csp->cond_broadcast =
2795 		    sync_stats.un.cond.cond_broadcast;
2796 		if (sync_stats.sync_addr >= ta_p->hash_table_addr &&
2797 		    (ix = sync_stats.sync_addr - ta_p->hash_table_addr)
2798 		    < ta_p->hash_size * sizeof (thr_hash_table_t))
2799 			csp->cond_internal =
2800 			    ix / sizeof (thr_hash_table_t) + 1;
2801 		break;
2802 	}
2803 	case TDB_RWLOCK:
2804 	{
2805 		td_rwlock_stats_t *rwsp = &ss_p->ss_un.rwlock;
2806 
2807 		ss_p->ss_info.si_type = TD_SYNC_RWLOCK;
2808 		ss_p->ss_info.si_size = sizeof (rwlock_t);
2809 		rwsp->rw_rdlock =
2810 		    sync_stats.un.rwlock.rw_rdlock;
2811 		rwsp->rw_rdlock_try =
2812 		    sync_stats.un.rwlock.rw_rdlock_try;
2813 		rwsp->rw_rdlock_try_fail =
2814 		    sync_stats.un.rwlock.rw_rdlock_try_fail;
2815 		rwsp->rw_wrlock =
2816 		    sync_stats.un.rwlock.rw_wrlock;
2817 		rwsp->rw_wrlock_hold_time =
2818 		    sync_stats.un.rwlock.rw_wrlock_hold_time;
2819 		rwsp->rw_wrlock_try =
2820 		    sync_stats.un.rwlock.rw_wrlock_try;
2821 		rwsp->rw_wrlock_try_fail =
2822 		    sync_stats.un.rwlock.rw_wrlock_try_fail;
2823 		break;
2824 	}
2825 	case TDB_SEMA:
2826 	{
2827 		td_sema_stats_t *ssp = &ss_p->ss_un.sema;
2828 
2829 		ss_p->ss_info.si_type = TD_SYNC_SEMA;
2830 		ss_p->ss_info.si_size = sizeof (sema_t);
2831 		ssp->sema_wait =
2832 		    sync_stats.un.sema.sema_wait;
2833 		ssp->sema_wait_sleep =
2834 		    sync_stats.un.sema.sema_wait_sleep;
2835 		ssp->sema_wait_sleep_time =
2836 		    sync_stats.un.sema.sema_wait_sleep_time;
2837 		ssp->sema_trywait =
2838 		    sync_stats.un.sema.sema_trywait;
2839 		ssp->sema_trywait_fail =
2840 		    sync_stats.un.sema.sema_trywait_fail;
2841 		ssp->sema_post =
2842 		    sync_stats.un.sema.sema_post;
2843 		ssp->sema_max_count =
2844 		    sync_stats.un.sema.sema_max_count;
2845 		ssp->sema_min_count =
2846 		    sync_stats.un.sema.sema_min_count;
2847 		break;
2848 	}
2849 	default:
2850 		return_val = TD_BADSH;
2851 		break;
2852 	}
2853 
2854 out:
2855 	(void) ps_pcontinue(ph_p);
2856 	ph_unlock(ta_p);
2857 	return (return_val);
2858 }
2859 
2860 /*
2861  * Change the state of a synchronization variable.
2862  *	1) mutex lock state set to value
2863  *	2) semaphore's count set to value
2864  *	3) writer's lock set by value < 0
2865  *	4) reader's lock number of readers set to value >= 0
2866  * Currently unused by dbx.
2867  */
2868 #pragma weak td_sync_setstate = __td_sync_setstate
2869 td_err_e
2870 __td_sync_setstate(const td_synchandle_t *sh_p, long lvalue)
2871 {
2872 	struct ps_prochandle *ph_p;
2873 	int		trunc = 0;
2874 	td_err_e	return_val;
2875 	td_so_un_t	generic_so;
2876 	uint32_t	*rwstate;
2877 	int		value = (int)lvalue;
2878 
2879 	if ((ph_p = ph_lock_sh(sh_p, &return_val)) == NULL)
2880 		return (return_val);
2881 	if (ps_pstop(ph_p) != PS_OK) {
2882 		ph_unlock(sh_p->sh_ta_p);
2883 		return (TD_DBERR);
2884 	}
2885 
2886 	/*
2887 	 * Read the synch. variable information.
2888 	 * First attempt to read the whole union and if that fails
2889 	 * fall back to reading only the smallest member, the condvar.
2890 	 */
2891 	if (ps_pdread(ph_p, sh_p->sh_unique, &generic_so,
2892 	    sizeof (generic_so)) != PS_OK) {
2893 		trunc = 1;
2894 		if (ps_pdread(ph_p, sh_p->sh_unique, &generic_so.condition,
2895 		    sizeof (generic_so.condition)) != PS_OK) {
2896 			(void) ps_pcontinue(ph_p);
2897 			ph_unlock(sh_p->sh_ta_p);
2898 			return (TD_DBERR);
2899 		}
2900 	}
2901 
2902 	/*
2903 	 * Set the new value in the sync. variable, read the synch. variable
2904 	 * information. from the process, reset its value and write it back.
2905 	 */
2906 	switch (generic_so.condition.mutex_magic) {
2907 	case MUTEX_MAGIC:
2908 		if (trunc && ps_pdread(ph_p, sh_p->sh_unique,
2909 		    &generic_so.lock, sizeof (generic_so.lock)) != PS_OK) {
2910 			return_val = TD_DBERR;
2911 			break;
2912 		}
2913 		generic_so.lock.mutex_lockw = (uint8_t)value;
2914 		if (ps_pdwrite(ph_p, sh_p->sh_unique, &generic_so.lock,
2915 		    sizeof (generic_so.lock)) != PS_OK)
2916 			return_val = TD_DBERR;
2917 		break;
2918 	case SEMA_MAGIC:
2919 		if (trunc && ps_pdread(ph_p, sh_p->sh_unique,
2920 		    &generic_so.semaphore, sizeof (generic_so.semaphore))
2921 		    != PS_OK) {
2922 			return_val = TD_DBERR;
2923 			break;
2924 		}
2925 		generic_so.semaphore.count = value;
2926 		if (ps_pdwrite(ph_p, sh_p->sh_unique, &generic_so.semaphore,
2927 		    sizeof (generic_so.semaphore)) != PS_OK)
2928 			return_val = TD_DBERR;
2929 		break;
2930 	case COND_MAGIC:
2931 		/* Operation not supported on a condition variable */
2932 		return_val = TD_ERR;
2933 		break;
2934 	case RWL_MAGIC:
2935 		if (trunc && ps_pdread(ph_p, sh_p->sh_unique,
2936 		    &generic_so.rwlock, sizeof (generic_so.rwlock)) != PS_OK) {
2937 			return_val = TD_DBERR;
2938 			break;
2939 		}
2940 		rwstate = (uint32_t *)&generic_so.rwlock.readers;
2941 		*rwstate &= URW_HAS_WAITERS;
2942 		if (value < 0)
2943 			*rwstate |= URW_WRITE_LOCKED;
2944 		else
2945 			*rwstate |= (value & URW_READERS_MASK);
2946 		if (ps_pdwrite(ph_p, sh_p->sh_unique, &generic_so.rwlock,
2947 		    sizeof (generic_so.rwlock)) != PS_OK)
2948 			return_val = TD_DBERR;
2949 		break;
2950 	default:
2951 		/* Bad sync. object type */
2952 		return_val = TD_BADSH;
2953 		break;
2954 	}
2955 
2956 	(void) ps_pcontinue(ph_p);
2957 	ph_unlock(sh_p->sh_ta_p);
2958 	return (return_val);
2959 }
2960 
2961 typedef struct {
2962 	td_thr_iter_f	*waiter_cb;
2963 	psaddr_t	sync_obj_addr;
2964 	uint16_t	sync_magic;
2965 	void		*waiter_cb_arg;
2966 	td_err_e	errcode;
2967 } waiter_cb_ctl_t;
2968 
2969 static int
2970 waiters_cb(const td_thrhandle_t *th_p, void *arg)
2971 {
2972 	td_thragent_t	*ta_p = th_p->th_ta_p;
2973 	struct ps_prochandle *ph_p = ta_p->ph_p;
2974 	waiter_cb_ctl_t	*wcb = arg;
2975 	caddr_t		wchan;
2976 
2977 	if (ta_p->model == PR_MODEL_NATIVE) {
2978 		ulwp_t *ulwp = (ulwp_t *)th_p->th_unique;
2979 
2980 		if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_wchan,
2981 		    &wchan, sizeof (wchan)) != PS_OK) {
2982 			wcb->errcode = TD_DBERR;
2983 			return (1);
2984 		}
2985 	} else {
2986 #if defined(_LP64) && defined(_SYSCALL32)
2987 		ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique;
2988 		caddr32_t wchan32;
2989 
2990 		if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_wchan,
2991 		    &wchan32, sizeof (wchan32)) != PS_OK) {
2992 			wcb->errcode = TD_DBERR;
2993 			return (1);
2994 		}
2995 		wchan = (caddr_t)(uintptr_t)wchan32;
2996 #else
2997 		wcb->errcode = TD_ERR;
2998 		return (1);
2999 #endif	/* _SYSCALL32 */
3000 	}
3001 
3002 	if (wchan == NULL)
3003 		return (0);
3004 
3005 	if (wchan == (caddr_t)wcb->sync_obj_addr)
3006 		return ((*wcb->waiter_cb)(th_p, wcb->waiter_cb_arg));
3007 
3008 	return (0);
3009 }
3010 
3011 /*
3012  * For a given synchronization variable, iterate over the
3013  * set of waiting threads.  The call back function is passed
3014  * two parameters, a pointer to a thread handle and a pointer
3015  * to extra call back data.
3016  */
3017 #pragma weak td_sync_waiters = __td_sync_waiters
3018 td_err_e
3019 __td_sync_waiters(const td_synchandle_t *sh_p, td_thr_iter_f *cb, void *cb_data)
3020 {
3021 	struct ps_prochandle *ph_p;
3022 	waiter_cb_ctl_t	wcb;
3023 	td_err_e	return_val;
3024 
3025 	if ((ph_p = ph_lock_sh(sh_p, &return_val)) == NULL)
3026 		return (return_val);
3027 	if (ps_pdread(ph_p,
3028 	    (psaddr_t)&((mutex_t *)sh_p->sh_unique)->mutex_magic,
3029 	    (caddr_t)&wcb.sync_magic, sizeof (wcb.sync_magic)) != PS_OK) {
3030 		ph_unlock(sh_p->sh_ta_p);
3031 		return (TD_DBERR);
3032 	}
3033 	ph_unlock(sh_p->sh_ta_p);
3034 
3035 	switch (wcb.sync_magic) {
3036 	case MUTEX_MAGIC:
3037 	case COND_MAGIC:
3038 	case SEMA_MAGIC:
3039 	case RWL_MAGIC:
3040 		break;
3041 	default:
3042 		return (TD_BADSH);
3043 	}
3044 
3045 	wcb.waiter_cb = cb;
3046 	wcb.sync_obj_addr = sh_p->sh_unique;
3047 	wcb.waiter_cb_arg = cb_data;
3048 	wcb.errcode = TD_OK;
3049 	return_val = __td_ta_thr_iter(sh_p->sh_ta_p, waiters_cb, &wcb,
3050 	    TD_THR_SLEEP, TD_THR_LOWEST_PRIORITY,
3051 	    TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
3052 
3053 	if (return_val != TD_OK)
3054 		return (return_val);
3055 
3056 	return (wcb.errcode);
3057 }
3058