17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
541efec22Sraf  * Common Development and Distribution License (the "License").
641efec22Sraf  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
2141efec22Sraf 
227c478bd9Sstevel@tonic-gate /*
23d4204c85Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
27cd8037eeSBryan Cantrill /*
28cd8037eeSBryan Cantrill  * Copyright (c) 2014, Joyent, Inc. All rights reserved.
29*ed093b41SRobert Mustacchi  * Copyright 2023 Oxide Computer Company
30cd8037eeSBryan Cantrill  */
31cd8037eeSBryan Cantrill 
327c478bd9Sstevel@tonic-gate #include <stdio.h>
337c478bd9Sstevel@tonic-gate #include <stdlib.h>
347c478bd9Sstevel@tonic-gate #include <stddef.h>
357c478bd9Sstevel@tonic-gate #include <unistd.h>
367c478bd9Sstevel@tonic-gate #include <thr_uberdata.h>
377c478bd9Sstevel@tonic-gate #include <thread_db.h>
387c478bd9Sstevel@tonic-gate #include <libc_int.h>
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate /*
417c478bd9Sstevel@tonic-gate  * Private structures.
427c478bd9Sstevel@tonic-gate  */
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate typedef union {
457c478bd9Sstevel@tonic-gate 	mutex_t		lock;
467c478bd9Sstevel@tonic-gate 	rwlock_t	rwlock;
477c478bd9Sstevel@tonic-gate 	sema_t		semaphore;
487c478bd9Sstevel@tonic-gate 	cond_t		condition;
497c478bd9Sstevel@tonic-gate } td_so_un_t;
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate struct td_thragent {
527c478bd9Sstevel@tonic-gate 	rwlock_t	rwlock;
537c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
547c478bd9Sstevel@tonic-gate 	int		initialized;
557c478bd9Sstevel@tonic-gate 	int		sync_tracking;
567c478bd9Sstevel@tonic-gate 	int		model;
577c478bd9Sstevel@tonic-gate 	int		primary_map;
587c478bd9Sstevel@tonic-gate 	psaddr_t	bootstrap_addr;
597c478bd9Sstevel@tonic-gate 	psaddr_t	uberdata_addr;
607c478bd9Sstevel@tonic-gate 	psaddr_t	tdb_eventmask_addr;
617c478bd9Sstevel@tonic-gate 	psaddr_t	tdb_register_sync_addr;
627c478bd9Sstevel@tonic-gate 	psaddr_t	tdb_events[TD_MAX_EVENT_NUM - TD_MIN_EVENT_NUM + 1];
637c478bd9Sstevel@tonic-gate 	psaddr_t	hash_table_addr;
647c478bd9Sstevel@tonic-gate 	int		hash_size;
657c478bd9Sstevel@tonic-gate 	lwpid_t		single_lwpid;
667c478bd9Sstevel@tonic-gate 	psaddr_t	single_ulwp_addr;
677c478bd9Sstevel@tonic-gate };
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate  * This is the name of the variable in libc that contains
717c478bd9Sstevel@tonic-gate  * the uberdata address that we will need.
727c478bd9Sstevel@tonic-gate  */
737c478bd9Sstevel@tonic-gate #define	TD_BOOTSTRAP_NAME	"_tdb_bootstrap"
747c478bd9Sstevel@tonic-gate /*
757c478bd9Sstevel@tonic-gate  * This is the actual name of uberdata, used in the event
767c478bd9Sstevel@tonic-gate  * that tdb_bootstrap has not yet been initialized.
777c478bd9Sstevel@tonic-gate  */
787c478bd9Sstevel@tonic-gate #define	TD_UBERDATA_NAME	"_uberdata"
797c478bd9Sstevel@tonic-gate /*
807c478bd9Sstevel@tonic-gate  * The library name should end with ".so.1", but older versions of
817c478bd9Sstevel@tonic-gate  * dbx expect the unadorned name and malfunction if ".1" is specified.
827c478bd9Sstevel@tonic-gate  * Unfortunately, if ".1" is not specified, mdb malfunctions when it
837c478bd9Sstevel@tonic-gate  * is applied to another instance of itself (due to the presence of
847c478bd9Sstevel@tonic-gate  * /usr/lib/mdb/proc/libc.so).  So we try it both ways.
857c478bd9Sstevel@tonic-gate  */
867c478bd9Sstevel@tonic-gate #define	TD_LIBRARY_NAME		"libc.so"
877c478bd9Sstevel@tonic-gate #define	TD_LIBRARY_NAME_1	"libc.so.1"
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate td_err_e __td_thr_get_info(td_thrhandle_t *th_p, td_thrinfo_t *ti_p);
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate td_err_e __td_ta_thr_iter(td_thragent_t *ta_p, td_thr_iter_f *cb,
927c478bd9Sstevel@tonic-gate 	void *cbdata_p, td_thr_state_e state, int ti_pri,
937c478bd9Sstevel@tonic-gate 	sigset_t *ti_sigmask_p, unsigned ti_user_flags);
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate /*
967c478bd9Sstevel@tonic-gate  * Initialize threads debugging interface.
977c478bd9Sstevel@tonic-gate  */
987c478bd9Sstevel@tonic-gate #pragma weak td_init = __td_init
997c478bd9Sstevel@tonic-gate td_err_e
__td_init()1007c478bd9Sstevel@tonic-gate __td_init()
1017c478bd9Sstevel@tonic-gate {
1027c478bd9Sstevel@tonic-gate 	return (TD_OK);
1037c478bd9Sstevel@tonic-gate }
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate /*
1067c478bd9Sstevel@tonic-gate  * This function does nothing, and never did.
1077c478bd9Sstevel@tonic-gate  * But the symbol is in the ABI, so we can't delete it.
1087c478bd9Sstevel@tonic-gate  */
1097c478bd9Sstevel@tonic-gate #pragma weak td_log = __td_log
1107c478bd9Sstevel@tonic-gate void
__td_log()1117c478bd9Sstevel@tonic-gate __td_log()
1127c478bd9Sstevel@tonic-gate {
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate /*
1167c478bd9Sstevel@tonic-gate  * Short-cut to read just the hash table size from the process,
1177c478bd9Sstevel@tonic-gate  * to avoid repeatedly reading the full uberdata structure when
1187c478bd9Sstevel@tonic-gate  * dealing with a single-threaded process.
1197c478bd9Sstevel@tonic-gate  */
1207c478bd9Sstevel@tonic-gate static uint_t
td_read_hash_size(td_thragent_t * ta_p)1217c478bd9Sstevel@tonic-gate td_read_hash_size(td_thragent_t *ta_p)
1227c478bd9Sstevel@tonic-gate {
1237c478bd9Sstevel@tonic-gate 	psaddr_t addr;
1247c478bd9Sstevel@tonic-gate 	uint_t hash_size;
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 	switch (ta_p->initialized) {
1277c478bd9Sstevel@tonic-gate 	default:	/* uninitialized */
1287c478bd9Sstevel@tonic-gate 		return (0);
1297c478bd9Sstevel@tonic-gate 	case 1:		/* partially initialized */
1307c478bd9Sstevel@tonic-gate 		break;
1317c478bd9Sstevel@tonic-gate 	case 2:		/* fully initialized */
1327c478bd9Sstevel@tonic-gate 		return (ta_p->hash_size);
1337c478bd9Sstevel@tonic-gate 	}
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	if (ta_p->model == PR_MODEL_NATIVE) {
1367c478bd9Sstevel@tonic-gate 		addr = ta_p->uberdata_addr + offsetof(uberdata_t, hash_size);
1377c478bd9Sstevel@tonic-gate 	} else {
1387c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
1397c478bd9Sstevel@tonic-gate 		addr = ta_p->uberdata_addr + offsetof(uberdata32_t, hash_size);
1407c478bd9Sstevel@tonic-gate #else
1417c478bd9Sstevel@tonic-gate 		addr = 0;
1427c478bd9Sstevel@tonic-gate #endif
1437c478bd9Sstevel@tonic-gate 	}
1447c478bd9Sstevel@tonic-gate 	if (ps_pdread(ta_p->ph_p, addr, &hash_size, sizeof (hash_size))
1457c478bd9Sstevel@tonic-gate 	    != PS_OK)
1467c478bd9Sstevel@tonic-gate 		return (0);
1477c478bd9Sstevel@tonic-gate 	return (hash_size);
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate static td_err_e
td_read_uberdata(td_thragent_t * ta_p)1517c478bd9Sstevel@tonic-gate td_read_uberdata(td_thragent_t *ta_p)
1527c478bd9Sstevel@tonic-gate {
1537c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p = ta_p->ph_p;
154cd8037eeSBryan Cantrill 	int i;
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	if (ta_p->model == PR_MODEL_NATIVE) {
1577c478bd9Sstevel@tonic-gate 		uberdata_t uberdata;
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, ta_p->uberdata_addr,
1607c478bd9Sstevel@tonic-gate 		    &uberdata, sizeof (uberdata)) != PS_OK)
1617c478bd9Sstevel@tonic-gate 			return (TD_DBERR);
1627c478bd9Sstevel@tonic-gate 		ta_p->primary_map = uberdata.primary_map;
1637c478bd9Sstevel@tonic-gate 		ta_p->tdb_eventmask_addr = ta_p->uberdata_addr +
164d4204c85Sraf 		    offsetof(uberdata_t, tdb.tdb_ev_global_mask);
1657c478bd9Sstevel@tonic-gate 		ta_p->tdb_register_sync_addr = ta_p->uberdata_addr +
166d4204c85Sraf 		    offsetof(uberdata_t, uberflags.uf_tdb_register_sync);
1677c478bd9Sstevel@tonic-gate 		ta_p->hash_table_addr = (psaddr_t)uberdata.thr_hash_table;
1687c478bd9Sstevel@tonic-gate 		ta_p->hash_size = uberdata.hash_size;
1697c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, (psaddr_t)uberdata.tdb.tdb_events,
1707c478bd9Sstevel@tonic-gate 		    ta_p->tdb_events, sizeof (ta_p->tdb_events)) != PS_OK)
1717c478bd9Sstevel@tonic-gate 			return (TD_DBERR);
1727c478bd9Sstevel@tonic-gate 	} else {
1737c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
1747c478bd9Sstevel@tonic-gate 		uberdata32_t uberdata;
1757c478bd9Sstevel@tonic-gate 		caddr32_t tdb_events[TD_MAX_EVENT_NUM - TD_MIN_EVENT_NUM + 1];
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, ta_p->uberdata_addr,
1787c478bd9Sstevel@tonic-gate 		    &uberdata, sizeof (uberdata)) != PS_OK)
1797c478bd9Sstevel@tonic-gate 			return (TD_DBERR);
1807c478bd9Sstevel@tonic-gate 		ta_p->primary_map = uberdata.primary_map;
1817c478bd9Sstevel@tonic-gate 		ta_p->tdb_eventmask_addr = ta_p->uberdata_addr +
182d4204c85Sraf 		    offsetof(uberdata32_t, tdb.tdb_ev_global_mask);
1837c478bd9Sstevel@tonic-gate 		ta_p->tdb_register_sync_addr = ta_p->uberdata_addr +
184d4204c85Sraf 		    offsetof(uberdata32_t, uberflags.uf_tdb_register_sync);
1857c478bd9Sstevel@tonic-gate 		ta_p->hash_table_addr = (psaddr_t)uberdata.thr_hash_table;
1867c478bd9Sstevel@tonic-gate 		ta_p->hash_size = uberdata.hash_size;
1877c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, (psaddr_t)uberdata.tdb.tdb_events,
1887c478bd9Sstevel@tonic-gate 		    tdb_events, sizeof (tdb_events)) != PS_OK)
1897c478bd9Sstevel@tonic-gate 			return (TD_DBERR);
1907c478bd9Sstevel@tonic-gate 		for (i = 0; i < TD_MAX_EVENT_NUM - TD_MIN_EVENT_NUM + 1; i++)
1917c478bd9Sstevel@tonic-gate 			ta_p->tdb_events[i] = tdb_events[i];
1927c478bd9Sstevel@tonic-gate #else
1937c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
1947c478bd9Sstevel@tonic-gate #endif
1957c478bd9Sstevel@tonic-gate 	}
196cd8037eeSBryan Cantrill 
197cd8037eeSBryan Cantrill 	/*
198cd8037eeSBryan Cantrill 	 * Unfortunately, we are (implicitly) assuming that our uberdata
199cd8037eeSBryan Cantrill 	 * definition precisely matches that of our target.  If this is not
200cd8037eeSBryan Cantrill 	 * true (that is, if we're examining a core file from a foreign
201cd8037eeSBryan Cantrill 	 * system that has a different definition of uberdata), the failure
202cd8037eeSBryan Cantrill 	 * modes can be frustratingly non-explicit.  In an effort to catch
203cd8037eeSBryan Cantrill 	 * this upon initialization (when the debugger may still be able to
204cd8037eeSBryan Cantrill 	 * opt for another thread model or may be able to fail explicitly), we
205cd8037eeSBryan Cantrill 	 * check that each of our tdb_events points to valid memory (these are
206cd8037eeSBryan Cantrill 	 * putatively text upon which a breakpoint can be issued), with the
207cd8037eeSBryan Cantrill 	 * hope that this is enough of a self-consistency check to lead to
208cd8037eeSBryan Cantrill 	 * explicit failure on a mismatch.
209cd8037eeSBryan Cantrill 	 */
210cd8037eeSBryan Cantrill 	for (i = 0; i < TD_MAX_EVENT_NUM - TD_MIN_EVENT_NUM + 1; i++) {
211cd8037eeSBryan Cantrill 		uint8_t check;
212cd8037eeSBryan Cantrill 
213cd8037eeSBryan Cantrill 		if (ps_pdread(ph_p, (psaddr_t)ta_p->tdb_events[i],
214cd8037eeSBryan Cantrill 		    &check, sizeof (check)) != PS_OK) {
215cd8037eeSBryan Cantrill 			return (TD_DBERR);
216cd8037eeSBryan Cantrill 		}
217cd8037eeSBryan Cantrill 	}
218cd8037eeSBryan Cantrill 
2197c478bd9Sstevel@tonic-gate 	if (ta_p->hash_size != 1) {	/* multi-threaded */
2207c478bd9Sstevel@tonic-gate 		ta_p->initialized = 2;
2217c478bd9Sstevel@tonic-gate 		ta_p->single_lwpid = 0;
222c3e74f84SToomas Soome 		ta_p->single_ulwp_addr = 0;
2237c478bd9Sstevel@tonic-gate 	} else {			/* single-threaded */
2247c478bd9Sstevel@tonic-gate 		ta_p->initialized = 1;
2257c478bd9Sstevel@tonic-gate 		/*
2267c478bd9Sstevel@tonic-gate 		 * Get the address and lwpid of the single thread/LWP.
2277c478bd9Sstevel@tonic-gate 		 * It may not be ulwp_one if this is a child of fork1().
2287c478bd9Sstevel@tonic-gate 		 */
2297c478bd9Sstevel@tonic-gate 		if (ta_p->model == PR_MODEL_NATIVE) {
2307c478bd9Sstevel@tonic-gate 			thr_hash_table_t head;
2317c478bd9Sstevel@tonic-gate 			lwpid_t lwpid = 0;
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 			if (ps_pdread(ph_p, ta_p->hash_table_addr,
2347c478bd9Sstevel@tonic-gate 			    &head, sizeof (head)) != PS_OK)
2357c478bd9Sstevel@tonic-gate 				return (TD_DBERR);
236c3e74f84SToomas Soome 			if ((psaddr_t)head.hash_bucket == 0)
2377c478bd9Sstevel@tonic-gate 				ta_p->initialized = 0;
2387c478bd9Sstevel@tonic-gate 			else if (ps_pdread(ph_p, (psaddr_t)head.hash_bucket +
2397c478bd9Sstevel@tonic-gate 			    offsetof(ulwp_t, ul_lwpid),
2407c478bd9Sstevel@tonic-gate 			    &lwpid, sizeof (lwpid)) != PS_OK)
2417c478bd9Sstevel@tonic-gate 				return (TD_DBERR);
2427c478bd9Sstevel@tonic-gate 			ta_p->single_lwpid = lwpid;
2437c478bd9Sstevel@tonic-gate 			ta_p->single_ulwp_addr = (psaddr_t)head.hash_bucket;
2447c478bd9Sstevel@tonic-gate 		} else {
2457c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
2467c478bd9Sstevel@tonic-gate 			thr_hash_table32_t head;
2477c478bd9Sstevel@tonic-gate 			lwpid_t lwpid = 0;
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 			if (ps_pdread(ph_p, ta_p->hash_table_addr,
2507c478bd9Sstevel@tonic-gate 			    &head, sizeof (head)) != PS_OK)
2517c478bd9Sstevel@tonic-gate 				return (TD_DBERR);
252c3e74f84SToomas Soome 			if ((psaddr_t)head.hash_bucket == 0)
2537c478bd9Sstevel@tonic-gate 				ta_p->initialized = 0;
2547c478bd9Sstevel@tonic-gate 			else if (ps_pdread(ph_p, (psaddr_t)head.hash_bucket +
2557c478bd9Sstevel@tonic-gate 			    offsetof(ulwp32_t, ul_lwpid),
2567c478bd9Sstevel@tonic-gate 			    &lwpid, sizeof (lwpid)) != PS_OK)
2577c478bd9Sstevel@tonic-gate 				return (TD_DBERR);
2587c478bd9Sstevel@tonic-gate 			ta_p->single_lwpid = lwpid;
2597c478bd9Sstevel@tonic-gate 			ta_p->single_ulwp_addr = (psaddr_t)head.hash_bucket;
2607c478bd9Sstevel@tonic-gate #else
2617c478bd9Sstevel@tonic-gate 			return (TD_DBERR);
2627c478bd9Sstevel@tonic-gate #endif
2637c478bd9Sstevel@tonic-gate 		}
2647c478bd9Sstevel@tonic-gate 	}
2657c478bd9Sstevel@tonic-gate 	if (!ta_p->primary_map)
2667c478bd9Sstevel@tonic-gate 		ta_p->initialized = 0;
2677c478bd9Sstevel@tonic-gate 	return (TD_OK);
2687c478bd9Sstevel@tonic-gate }
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate static td_err_e
td_read_bootstrap_data(td_thragent_t * ta_p)2717c478bd9Sstevel@tonic-gate td_read_bootstrap_data(td_thragent_t *ta_p)
2727c478bd9Sstevel@tonic-gate {
2737c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p = ta_p->ph_p;
2747c478bd9Sstevel@tonic-gate 	psaddr_t bootstrap_addr;
2757c478bd9Sstevel@tonic-gate 	psaddr_t uberdata_addr;
2767c478bd9Sstevel@tonic-gate 	ps_err_e db_return;
2777c478bd9Sstevel@tonic-gate 	td_err_e return_val;
2787c478bd9Sstevel@tonic-gate 	int do_1;
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	switch (ta_p->initialized) {
2817c478bd9Sstevel@tonic-gate 	case 2:			/* fully initialized */
2827c478bd9Sstevel@tonic-gate 		return (TD_OK);
2837c478bd9Sstevel@tonic-gate 	case 1:			/* partially initialized */
2847c478bd9Sstevel@tonic-gate 		if (td_read_hash_size(ta_p) == 1)
2857c478bd9Sstevel@tonic-gate 			return (TD_OK);
2867c478bd9Sstevel@tonic-gate 		return (td_read_uberdata(ta_p));
2877c478bd9Sstevel@tonic-gate 	}
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	/*
2907c478bd9Sstevel@tonic-gate 	 * Uninitialized -- do the startup work.
2917c478bd9Sstevel@tonic-gate 	 * We set ta_p->initialized to -1 to cut off recursive calls
2927c478bd9Sstevel@tonic-gate 	 * into libc_db by code in the provider of ps_pglobal_lookup().
2937c478bd9Sstevel@tonic-gate 	 */
2947c478bd9Sstevel@tonic-gate 	do_1 = 0;
2957c478bd9Sstevel@tonic-gate 	ta_p->initialized = -1;
2967c478bd9Sstevel@tonic-gate 	db_return = ps_pglobal_lookup(ph_p, TD_LIBRARY_NAME,
2977c478bd9Sstevel@tonic-gate 	    TD_BOOTSTRAP_NAME, &bootstrap_addr);
2987c478bd9Sstevel@tonic-gate 	if (db_return == PS_NOSYM) {
2997c478bd9Sstevel@tonic-gate 		do_1 = 1;
3007c478bd9Sstevel@tonic-gate 		db_return = ps_pglobal_lookup(ph_p, TD_LIBRARY_NAME_1,
3017c478bd9Sstevel@tonic-gate 		    TD_BOOTSTRAP_NAME, &bootstrap_addr);
3027c478bd9Sstevel@tonic-gate 	}
3037c478bd9Sstevel@tonic-gate 	if (db_return == PS_NOSYM)	/* libc is not linked yet */
3047c478bd9Sstevel@tonic-gate 		return (TD_NOLIBTHREAD);
3057c478bd9Sstevel@tonic-gate 	if (db_return != PS_OK)
3067c478bd9Sstevel@tonic-gate 		return (TD_ERR);
3077c478bd9Sstevel@tonic-gate 	db_return = ps_pglobal_lookup(ph_p,
3087c478bd9Sstevel@tonic-gate 	    do_1? TD_LIBRARY_NAME_1 : TD_LIBRARY_NAME,
3097c478bd9Sstevel@tonic-gate 	    TD_UBERDATA_NAME, &uberdata_addr);
3107c478bd9Sstevel@tonic-gate 	if (db_return == PS_NOSYM)	/* libc is not linked yet */
3117c478bd9Sstevel@tonic-gate 		return (TD_NOLIBTHREAD);
3127c478bd9Sstevel@tonic-gate 	if (db_return != PS_OK)
3137c478bd9Sstevel@tonic-gate 		return (TD_ERR);
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	/*
3167c478bd9Sstevel@tonic-gate 	 * Read the uberdata address into the thread agent structure.
3177c478bd9Sstevel@tonic-gate 	 */
3187c478bd9Sstevel@tonic-gate 	if (ta_p->model == PR_MODEL_NATIVE) {
3197c478bd9Sstevel@tonic-gate 		psaddr_t psaddr;
3207c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, bootstrap_addr,
3217c478bd9Sstevel@tonic-gate 		    &psaddr, sizeof (psaddr)) != PS_OK)
3227c478bd9Sstevel@tonic-gate 			return (TD_DBERR);
323c3e74f84SToomas Soome 		if ((ta_p->bootstrap_addr = psaddr) == 0)
3247c478bd9Sstevel@tonic-gate 			psaddr = uberdata_addr;
3257c478bd9Sstevel@tonic-gate 		else if (ps_pdread(ph_p, psaddr,
3267c478bd9Sstevel@tonic-gate 		    &psaddr, sizeof (psaddr)) != PS_OK)
3277c478bd9Sstevel@tonic-gate 			return (TD_DBERR);
328c3e74f84SToomas Soome 		if (psaddr == 0) {
329e33bf782SEdward Pilatowicz 			/* primary linkmap in the tgt is not initialized */
330c3e74f84SToomas Soome 			ta_p->bootstrap_addr = 0;
331e33bf782SEdward Pilatowicz 			psaddr = uberdata_addr;
332e33bf782SEdward Pilatowicz 		}
3337c478bd9Sstevel@tonic-gate 		ta_p->uberdata_addr = psaddr;
3347c478bd9Sstevel@tonic-gate 	} else {
3357c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
3367c478bd9Sstevel@tonic-gate 		caddr32_t psaddr;
3377c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, bootstrap_addr,
3387c478bd9Sstevel@tonic-gate 		    &psaddr, sizeof (psaddr)) != PS_OK)
3397c478bd9Sstevel@tonic-gate 			return (TD_DBERR);
340c3e74f84SToomas Soome 		if ((ta_p->bootstrap_addr = (psaddr_t)psaddr) == 0)
3417c478bd9Sstevel@tonic-gate 			psaddr = (caddr32_t)uberdata_addr;
3427c478bd9Sstevel@tonic-gate 		else if (ps_pdread(ph_p, (psaddr_t)psaddr,
3437c478bd9Sstevel@tonic-gate 		    &psaddr, sizeof (psaddr)) != PS_OK)
3447c478bd9Sstevel@tonic-gate 			return (TD_DBERR);
345c3e74f84SToomas Soome 		if (psaddr == 0) {
346e33bf782SEdward Pilatowicz 			/* primary linkmap in the tgt is not initialized */
347c3e74f84SToomas Soome 			ta_p->bootstrap_addr = 0;
348e33bf782SEdward Pilatowicz 			psaddr = (caddr32_t)uberdata_addr;
349e33bf782SEdward Pilatowicz 		}
3507c478bd9Sstevel@tonic-gate 		ta_p->uberdata_addr = (psaddr_t)psaddr;
3517c478bd9Sstevel@tonic-gate #else
3527c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
3537c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
3547c478bd9Sstevel@tonic-gate 	}
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	if ((return_val = td_read_uberdata(ta_p)) != TD_OK)
3577c478bd9Sstevel@tonic-gate 		return (return_val);
358c3e74f84SToomas Soome 	if (ta_p->bootstrap_addr == 0)
3597c478bd9Sstevel@tonic-gate 		ta_p->initialized = 0;
3607c478bd9Sstevel@tonic-gate 	return (TD_OK);
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate #pragma weak ps_kill
3647c478bd9Sstevel@tonic-gate #pragma weak ps_lrolltoaddr
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate /*
3677c478bd9Sstevel@tonic-gate  * Allocate a new agent process handle ("thread agent").
3687c478bd9Sstevel@tonic-gate  */
3697c478bd9Sstevel@tonic-gate #pragma weak td_ta_new = __td_ta_new
3707c478bd9Sstevel@tonic-gate td_err_e
__td_ta_new(struct ps_prochandle * ph_p,td_thragent_t ** ta_pp)3717c478bd9Sstevel@tonic-gate __td_ta_new(struct ps_prochandle *ph_p, td_thragent_t **ta_pp)
3727c478bd9Sstevel@tonic-gate {
3737c478bd9Sstevel@tonic-gate 	td_thragent_t *ta_p;
3747c478bd9Sstevel@tonic-gate 	int model;
3757c478bd9Sstevel@tonic-gate 	td_err_e return_val = TD_OK;
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	if (ph_p == NULL)
3787c478bd9Sstevel@tonic-gate 		return (TD_BADPH);
3797c478bd9Sstevel@tonic-gate 	if (ta_pp == NULL)
3807c478bd9Sstevel@tonic-gate 		return (TD_ERR);
3817c478bd9Sstevel@tonic-gate 	*ta_pp = NULL;
3827c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK)
3837c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
3847c478bd9Sstevel@tonic-gate 	/*
3857c478bd9Sstevel@tonic-gate 	 * ps_pdmodel might not be defined if this is an older client.
3867c478bd9Sstevel@tonic-gate 	 * Make it a weak symbol and test if it exists before calling.
3877c478bd9Sstevel@tonic-gate 	 */
3887c478bd9Sstevel@tonic-gate #pragma weak ps_pdmodel
3897c478bd9Sstevel@tonic-gate 	if (ps_pdmodel == NULL) {
3907c478bd9Sstevel@tonic-gate 		model = PR_MODEL_NATIVE;
3917c478bd9Sstevel@tonic-gate 	} else if (ps_pdmodel(ph_p, &model) != PS_OK) {
3927c478bd9Sstevel@tonic-gate 		(void) ps_pcontinue(ph_p);
3937c478bd9Sstevel@tonic-gate 		return (TD_ERR);
3947c478bd9Sstevel@tonic-gate 	}
3957c478bd9Sstevel@tonic-gate 	if ((ta_p = malloc(sizeof (*ta_p))) == NULL) {
3967c478bd9Sstevel@tonic-gate 		(void) ps_pcontinue(ph_p);
3977c478bd9Sstevel@tonic-gate 		return (TD_MALLOC);
3987c478bd9Sstevel@tonic-gate 	}
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	/*
4017c478bd9Sstevel@tonic-gate 	 * Initialize the agent process handle.
4027c478bd9Sstevel@tonic-gate 	 * Pick up the symbol value we need from the target process.
4037c478bd9Sstevel@tonic-gate 	 */
4047c478bd9Sstevel@tonic-gate 	(void) memset(ta_p, 0, sizeof (*ta_p));
4057c478bd9Sstevel@tonic-gate 	ta_p->ph_p = ph_p;
4067c478bd9Sstevel@tonic-gate 	(void) rwlock_init(&ta_p->rwlock, USYNC_THREAD, NULL);
4077c478bd9Sstevel@tonic-gate 	ta_p->model = model;
4087c478bd9Sstevel@tonic-gate 	return_val = td_read_bootstrap_data(ta_p);
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	/*
4117c478bd9Sstevel@tonic-gate 	 * Because the old libthread_db enabled lock tracking by default,
4127c478bd9Sstevel@tonic-gate 	 * we must also do it.  However, we do it only if the application
4137c478bd9Sstevel@tonic-gate 	 * provides the ps_kill() and ps_lrolltoaddr() interfaces.
4147c478bd9Sstevel@tonic-gate 	 * (dbx provides the ps_kill() and ps_lrolltoaddr() interfaces.)
4157c478bd9Sstevel@tonic-gate 	 */
4167c478bd9Sstevel@tonic-gate 	if (return_val == TD_OK && ps_kill != NULL && ps_lrolltoaddr != NULL) {
4177c478bd9Sstevel@tonic-gate 		register_sync_t oldenable;
4187c478bd9Sstevel@tonic-gate 		register_sync_t enable = REGISTER_SYNC_ENABLE;
4197c478bd9Sstevel@tonic-gate 		psaddr_t psaddr = ta_p->tdb_register_sync_addr;
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, psaddr,
4227c478bd9Sstevel@tonic-gate 		    &oldenable, sizeof (oldenable)) != PS_OK)
4237c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
4247c478bd9Sstevel@tonic-gate 		else if (oldenable != REGISTER_SYNC_OFF ||
4257c478bd9Sstevel@tonic-gate 		    ps_pdwrite(ph_p, psaddr,
4267c478bd9Sstevel@tonic-gate 		    &enable, sizeof (enable)) != PS_OK) {
4277c478bd9Sstevel@tonic-gate 			/*
4287c478bd9Sstevel@tonic-gate 			 * Lock tracking was already enabled or we
4297c478bd9Sstevel@tonic-gate 			 * failed to enable it, probably because we
4307c478bd9Sstevel@tonic-gate 			 * are examining a core file.  In either case
4317c478bd9Sstevel@tonic-gate 			 * set the sync_tracking flag non-zero to
4327c478bd9Sstevel@tonic-gate 			 * indicate that we should not attempt to
4337c478bd9Sstevel@tonic-gate 			 * disable lock tracking when we delete the
4347c478bd9Sstevel@tonic-gate 			 * agent process handle in td_ta_delete().
4357c478bd9Sstevel@tonic-gate 			 */
4367c478bd9Sstevel@tonic-gate 			ta_p->sync_tracking = 1;
4377c478bd9Sstevel@tonic-gate 		}
4387c478bd9Sstevel@tonic-gate 	}
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	if (return_val == TD_OK)
4417c478bd9Sstevel@tonic-gate 		*ta_pp = ta_p;
4427c478bd9Sstevel@tonic-gate 	else
4437c478bd9Sstevel@tonic-gate 		free(ta_p);
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
4467c478bd9Sstevel@tonic-gate 	return (return_val);
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate /*
4507c478bd9Sstevel@tonic-gate  * Utility function to grab the readers lock and return the prochandle,
4517c478bd9Sstevel@tonic-gate  * given an agent process handle.  Performs standard error checking.
4527c478bd9Sstevel@tonic-gate  * Returns non-NULL with the lock held, or NULL with the lock not held.
4537c478bd9Sstevel@tonic-gate  */
4547c478bd9Sstevel@tonic-gate static struct ps_prochandle *
ph_lock_ta(td_thragent_t * ta_p,td_err_e * err)4557c478bd9Sstevel@tonic-gate ph_lock_ta(td_thragent_t *ta_p, td_err_e *err)
4567c478bd9Sstevel@tonic-gate {
4577c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p = NULL;
4587c478bd9Sstevel@tonic-gate 	td_err_e error;
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	if (ta_p == NULL || ta_p->initialized == -1) {
4617c478bd9Sstevel@tonic-gate 		*err = TD_BADTA;
4627c478bd9Sstevel@tonic-gate 	} else if (rw_rdlock(&ta_p->rwlock) != 0) {	/* can't happen? */
4637c478bd9Sstevel@tonic-gate 		*err = TD_BADTA;
4647c478bd9Sstevel@tonic-gate 	} else if ((ph_p = ta_p->ph_p) == NULL) {
4657c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&ta_p->rwlock);
4667c478bd9Sstevel@tonic-gate 		*err = TD_BADPH;
4677c478bd9Sstevel@tonic-gate 	} else if (ta_p->initialized != 2 &&
4687c478bd9Sstevel@tonic-gate 	    (error = td_read_bootstrap_data(ta_p)) != TD_OK) {
4697c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&ta_p->rwlock);
4707c478bd9Sstevel@tonic-gate 		ph_p = NULL;
4717c478bd9Sstevel@tonic-gate 		*err = error;
4727c478bd9Sstevel@tonic-gate 	} else {
4737c478bd9Sstevel@tonic-gate 		*err = TD_OK;
4747c478bd9Sstevel@tonic-gate 	}
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 	return (ph_p);
4777c478bd9Sstevel@tonic-gate }
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate /*
4807c478bd9Sstevel@tonic-gate  * Utility function to grab the readers lock and return the prochandle,
4817c478bd9Sstevel@tonic-gate  * given an agent thread handle.  Performs standard error checking.
4827c478bd9Sstevel@tonic-gate  * Returns non-NULL with the lock held, or NULL with the lock not held.
4837c478bd9Sstevel@tonic-gate  */
4847c478bd9Sstevel@tonic-gate static struct ps_prochandle *
ph_lock_th(const td_thrhandle_t * th_p,td_err_e * err)4857c478bd9Sstevel@tonic-gate ph_lock_th(const td_thrhandle_t *th_p, td_err_e *err)
4867c478bd9Sstevel@tonic-gate {
487c3e74f84SToomas Soome 	if (th_p == NULL || th_p->th_unique == 0) {
4887c478bd9Sstevel@tonic-gate 		*err = TD_BADTH;
4897c478bd9Sstevel@tonic-gate 		return (NULL);
4907c478bd9Sstevel@tonic-gate 	}
4917c478bd9Sstevel@tonic-gate 	return (ph_lock_ta(th_p->th_ta_p, err));
4927c478bd9Sstevel@tonic-gate }
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate /*
4957c478bd9Sstevel@tonic-gate  * Utility function to grab the readers lock and return the prochandle,
4967c478bd9Sstevel@tonic-gate  * given a synchronization object handle.  Performs standard error checking.
4977c478bd9Sstevel@tonic-gate  * Returns non-NULL with the lock held, or NULL with the lock not held.
4987c478bd9Sstevel@tonic-gate  */
4997c478bd9Sstevel@tonic-gate static struct ps_prochandle *
ph_lock_sh(const td_synchandle_t * sh_p,td_err_e * err)5007c478bd9Sstevel@tonic-gate ph_lock_sh(const td_synchandle_t *sh_p, td_err_e *err)
5017c478bd9Sstevel@tonic-gate {
502c3e74f84SToomas Soome 	if (sh_p == NULL || sh_p->sh_unique == 0) {
5037c478bd9Sstevel@tonic-gate 		*err = TD_BADSH;
5047c478bd9Sstevel@tonic-gate 		return (NULL);
5057c478bd9Sstevel@tonic-gate 	}
5067c478bd9Sstevel@tonic-gate 	return (ph_lock_ta(sh_p->sh_ta_p, err));
5077c478bd9Sstevel@tonic-gate }
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate /*
5107c478bd9Sstevel@tonic-gate  * Unlock the agent process handle obtained from ph_lock_*().
5117c478bd9Sstevel@tonic-gate  */
5127c478bd9Sstevel@tonic-gate static void
ph_unlock(td_thragent_t * ta_p)5137c478bd9Sstevel@tonic-gate ph_unlock(td_thragent_t *ta_p)
5147c478bd9Sstevel@tonic-gate {
5157c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&ta_p->rwlock);
5167c478bd9Sstevel@tonic-gate }
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate /*
5197c478bd9Sstevel@tonic-gate  * De-allocate an agent process handle,
5207c478bd9Sstevel@tonic-gate  * releasing all related resources.
5217c478bd9Sstevel@tonic-gate  *
5227c478bd9Sstevel@tonic-gate  * XXX -- This is hopelessly broken ---
5237c478bd9Sstevel@tonic-gate  * Storage for thread agent is not deallocated.  The prochandle
5247c478bd9Sstevel@tonic-gate  * in the thread agent is set to NULL so that future uses of
5257c478bd9Sstevel@tonic-gate  * the thread agent can be detected and an error value returned.
5267c478bd9Sstevel@tonic-gate  * All functions in the external user interface that make
5277c478bd9Sstevel@tonic-gate  * use of the thread agent are expected
5287c478bd9Sstevel@tonic-gate  * to check for a NULL prochandle in the thread agent.
5297c478bd9Sstevel@tonic-gate  * All such functions are also expected to obtain a
5307c478bd9Sstevel@tonic-gate  * reader lock on the thread agent while it is using it.
5317c478bd9Sstevel@tonic-gate  */
5327c478bd9Sstevel@tonic-gate #pragma weak td_ta_delete = __td_ta_delete
5337c478bd9Sstevel@tonic-gate td_err_e
__td_ta_delete(td_thragent_t * ta_p)5347c478bd9Sstevel@tonic-gate __td_ta_delete(td_thragent_t *ta_p)
5357c478bd9Sstevel@tonic-gate {
5367c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 	/*
5397c478bd9Sstevel@tonic-gate 	 * This is the only place we grab the writer lock.
5407c478bd9Sstevel@tonic-gate 	 * We are going to NULL out the prochandle.
5417c478bd9Sstevel@tonic-gate 	 */
5427c478bd9Sstevel@tonic-gate 	if (ta_p == NULL || rw_wrlock(&ta_p->rwlock) != 0)
5437c478bd9Sstevel@tonic-gate 		return (TD_BADTA);
5447c478bd9Sstevel@tonic-gate 	if ((ph_p = ta_p->ph_p) == NULL) {
5457c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&ta_p->rwlock);
5467c478bd9Sstevel@tonic-gate 		return (TD_BADPH);
5477c478bd9Sstevel@tonic-gate 	}
5487c478bd9Sstevel@tonic-gate 	/*
5497c478bd9Sstevel@tonic-gate 	 * If synch. tracking was disabled when td_ta_new() was called and
5507c478bd9Sstevel@tonic-gate 	 * if td_ta_sync_tracking_enable() was never called, then disable
5517c478bd9Sstevel@tonic-gate 	 * synch. tracking (it was enabled by default in td_ta_new()).
5527c478bd9Sstevel@tonic-gate 	 */
5537c478bd9Sstevel@tonic-gate 	if (ta_p->sync_tracking == 0 &&
5547c478bd9Sstevel@tonic-gate 	    ps_kill != NULL && ps_lrolltoaddr != NULL) {
5557c478bd9Sstevel@tonic-gate 		register_sync_t enable = REGISTER_SYNC_DISABLE;
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 		(void) ps_pdwrite(ph_p, ta_p->tdb_register_sync_addr,
5587c478bd9Sstevel@tonic-gate 		    &enable, sizeof (enable));
5597c478bd9Sstevel@tonic-gate 	}
5607c478bd9Sstevel@tonic-gate 	ta_p->ph_p = NULL;
5617c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&ta_p->rwlock);
5627c478bd9Sstevel@tonic-gate 	return (TD_OK);
5637c478bd9Sstevel@tonic-gate }
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate /*
5667c478bd9Sstevel@tonic-gate  * Map an agent process handle to a client prochandle.
5677c478bd9Sstevel@tonic-gate  * Currently unused by dbx.
5687c478bd9Sstevel@tonic-gate  */
5697c478bd9Sstevel@tonic-gate #pragma weak td_ta_get_ph = __td_ta_get_ph
5707c478bd9Sstevel@tonic-gate td_err_e
__td_ta_get_ph(td_thragent_t * ta_p,struct ps_prochandle ** ph_pp)5717c478bd9Sstevel@tonic-gate __td_ta_get_ph(td_thragent_t *ta_p, struct ps_prochandle **ph_pp)
5727c478bd9Sstevel@tonic-gate {
5737c478bd9Sstevel@tonic-gate 	td_err_e return_val;
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 	if (ph_pp != NULL)	/* protect stupid callers */
5767c478bd9Sstevel@tonic-gate 		*ph_pp = NULL;
5777c478bd9Sstevel@tonic-gate 	if (ph_pp == NULL)
5787c478bd9Sstevel@tonic-gate 		return (TD_ERR);
5797c478bd9Sstevel@tonic-gate 	if ((*ph_pp = ph_lock_ta(ta_p, &return_val)) == NULL)
5807c478bd9Sstevel@tonic-gate 		return (return_val);
5817c478bd9Sstevel@tonic-gate 	ph_unlock(ta_p);
5827c478bd9Sstevel@tonic-gate 	return (TD_OK);
5837c478bd9Sstevel@tonic-gate }
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate /*
5867c478bd9Sstevel@tonic-gate  * Set the process's suggested concurrency level.
5877c478bd9Sstevel@tonic-gate  * This is a no-op in a one-level model.
5887c478bd9Sstevel@tonic-gate  * Currently unused by dbx.
5897c478bd9Sstevel@tonic-gate  */
5907c478bd9Sstevel@tonic-gate #pragma weak td_ta_setconcurrency = __td_ta_setconcurrency
5917c478bd9Sstevel@tonic-gate /* ARGSUSED1 */
5927c478bd9Sstevel@tonic-gate td_err_e
__td_ta_setconcurrency(const td_thragent_t * ta_p,int level)5937c478bd9Sstevel@tonic-gate __td_ta_setconcurrency(const td_thragent_t *ta_p, int level)
5947c478bd9Sstevel@tonic-gate {
5957c478bd9Sstevel@tonic-gate 	if (ta_p == NULL)
5967c478bd9Sstevel@tonic-gate 		return (TD_BADTA);
5977c478bd9Sstevel@tonic-gate 	if (ta_p->ph_p == NULL)
5987c478bd9Sstevel@tonic-gate 		return (TD_BADPH);
5997c478bd9Sstevel@tonic-gate 	return (TD_OK);
6007c478bd9Sstevel@tonic-gate }
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate /*
6037c478bd9Sstevel@tonic-gate  * Get the number of threads in the process.
6047c478bd9Sstevel@tonic-gate  */
6057c478bd9Sstevel@tonic-gate #pragma weak td_ta_get_nthreads = __td_ta_get_nthreads
6067c478bd9Sstevel@tonic-gate td_err_e
__td_ta_get_nthreads(td_thragent_t * ta_p,int * nthread_p)6077c478bd9Sstevel@tonic-gate __td_ta_get_nthreads(td_thragent_t *ta_p, int *nthread_p)
6087c478bd9Sstevel@tonic-gate {
6097c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
6107c478bd9Sstevel@tonic-gate 	td_err_e return_val;
6117c478bd9Sstevel@tonic-gate 	int nthreads;
6127c478bd9Sstevel@tonic-gate 	int nzombies;
6137c478bd9Sstevel@tonic-gate 	psaddr_t nthreads_addr;
6147c478bd9Sstevel@tonic-gate 	psaddr_t nzombies_addr;
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 	if (ta_p->model == PR_MODEL_NATIVE) {
6177c478bd9Sstevel@tonic-gate 		nthreads_addr = ta_p->uberdata_addr +
618d4204c85Sraf 		    offsetof(uberdata_t, nthreads);
6197c478bd9Sstevel@tonic-gate 		nzombies_addr = ta_p->uberdata_addr +
620d4204c85Sraf 		    offsetof(uberdata_t, nzombies);
6217c478bd9Sstevel@tonic-gate 	} else {
6227c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
6237c478bd9Sstevel@tonic-gate 		nthreads_addr = ta_p->uberdata_addr +
624d4204c85Sraf 		    offsetof(uberdata32_t, nthreads);
6257c478bd9Sstevel@tonic-gate 		nzombies_addr = ta_p->uberdata_addr +
626d4204c85Sraf 		    offsetof(uberdata32_t, nzombies);
6277c478bd9Sstevel@tonic-gate #else
6287c478bd9Sstevel@tonic-gate 		nthreads_addr = 0;
6297c478bd9Sstevel@tonic-gate 		nzombies_addr = 0;
6307c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
6317c478bd9Sstevel@tonic-gate 	}
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 	if (nthread_p == NULL)
6347c478bd9Sstevel@tonic-gate 		return (TD_ERR);
6357c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL)
6367c478bd9Sstevel@tonic-gate 		return (return_val);
6377c478bd9Sstevel@tonic-gate 	if (ps_pdread(ph_p, nthreads_addr, &nthreads, sizeof (int)) != PS_OK)
6387c478bd9Sstevel@tonic-gate 		return_val = TD_DBERR;
6397c478bd9Sstevel@tonic-gate 	if (ps_pdread(ph_p, nzombies_addr, &nzombies, sizeof (int)) != PS_OK)
6407c478bd9Sstevel@tonic-gate 		return_val = TD_DBERR;
6417c478bd9Sstevel@tonic-gate 	ph_unlock(ta_p);
6427c478bd9Sstevel@tonic-gate 	if (return_val == TD_OK)
6437c478bd9Sstevel@tonic-gate 		*nthread_p = nthreads + nzombies;
6447c478bd9Sstevel@tonic-gate 	return (return_val);
6457c478bd9Sstevel@tonic-gate }
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate typedef struct {
6487c478bd9Sstevel@tonic-gate 	thread_t	tid;
6497c478bd9Sstevel@tonic-gate 	int		found;
6507c478bd9Sstevel@tonic-gate 	td_thrhandle_t	th;
6517c478bd9Sstevel@tonic-gate } td_mapper_param_t;
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate /*
6547c478bd9Sstevel@tonic-gate  * Check the value in data against the thread id.
6557c478bd9Sstevel@tonic-gate  * If it matches, return 1 to terminate iterations.
6567c478bd9Sstevel@tonic-gate  * This function is used by td_ta_map_id2thr() to map a tid to a thread handle.
6577c478bd9Sstevel@tonic-gate  */
6587c478bd9Sstevel@tonic-gate static int
td_mapper_id2thr(td_thrhandle_t * th_p,td_mapper_param_t * data)6597c478bd9Sstevel@tonic-gate td_mapper_id2thr(td_thrhandle_t *th_p, td_mapper_param_t *data)
6607c478bd9Sstevel@tonic-gate {
6617c478bd9Sstevel@tonic-gate 	td_thrinfo_t ti;
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	if (__td_thr_get_info(th_p, &ti) == TD_OK &&
6647c478bd9Sstevel@tonic-gate 	    data->tid == ti.ti_tid) {
6657c478bd9Sstevel@tonic-gate 		data->found = 1;
6667c478bd9Sstevel@tonic-gate 		data->th = *th_p;
6677c478bd9Sstevel@tonic-gate 		return (1);
6687c478bd9Sstevel@tonic-gate 	}
6697c478bd9Sstevel@tonic-gate 	return (0);
6707c478bd9Sstevel@tonic-gate }
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate /*
6737c478bd9Sstevel@tonic-gate  * Given a thread identifier, return the corresponding thread handle.
6747c478bd9Sstevel@tonic-gate  */
6757c478bd9Sstevel@tonic-gate #pragma weak td_ta_map_id2thr = __td_ta_map_id2thr
6767c478bd9Sstevel@tonic-gate td_err_e
__td_ta_map_id2thr(td_thragent_t * ta_p,thread_t tid,td_thrhandle_t * th_p)6777c478bd9Sstevel@tonic-gate __td_ta_map_id2thr(td_thragent_t *ta_p, thread_t tid,
678c3e74f84SToomas Soome     td_thrhandle_t *th_p)
6797c478bd9Sstevel@tonic-gate {
6807c478bd9Sstevel@tonic-gate 	td_err_e		return_val;
6817c478bd9Sstevel@tonic-gate 	td_mapper_param_t	data;
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate 	if (th_p != NULL &&	/* optimize for a single thread */
6847c478bd9Sstevel@tonic-gate 	    ta_p != NULL &&
6857c478bd9Sstevel@tonic-gate 	    ta_p->initialized == 1 &&
6867c478bd9Sstevel@tonic-gate 	    (td_read_hash_size(ta_p) == 1 ||
6877c478bd9Sstevel@tonic-gate 	    td_read_uberdata(ta_p) == TD_OK) &&
6887c478bd9Sstevel@tonic-gate 	    ta_p->initialized == 1 &&
6897c478bd9Sstevel@tonic-gate 	    ta_p->single_lwpid == tid) {
6907c478bd9Sstevel@tonic-gate 		th_p->th_ta_p = ta_p;
6917c478bd9Sstevel@tonic-gate 		if ((th_p->th_unique = ta_p->single_ulwp_addr) == 0)
6927c478bd9Sstevel@tonic-gate 			return (TD_NOTHR);
6937c478bd9Sstevel@tonic-gate 		return (TD_OK);
6947c478bd9Sstevel@tonic-gate 	}
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 	/*
6977c478bd9Sstevel@tonic-gate 	 * LOCKING EXCEPTION - Locking is not required here because
6987c478bd9Sstevel@tonic-gate 	 * the locking and checking will be done in __td_ta_thr_iter.
6997c478bd9Sstevel@tonic-gate 	 */
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 	if (ta_p == NULL)
7027c478bd9Sstevel@tonic-gate 		return (TD_BADTA);
7037c478bd9Sstevel@tonic-gate 	if (th_p == NULL)
7047c478bd9Sstevel@tonic-gate 		return (TD_BADTH);
7057c478bd9Sstevel@tonic-gate 	if (tid == 0)
7067c478bd9Sstevel@tonic-gate 		return (TD_NOTHR);
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 	data.tid = tid;
7097c478bd9Sstevel@tonic-gate 	data.found = 0;
7107c478bd9Sstevel@tonic-gate 	return_val = __td_ta_thr_iter(ta_p,
711d4204c85Sraf 	    (td_thr_iter_f *)td_mapper_id2thr, (void *)&data,
712d4204c85Sraf 	    TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
713d4204c85Sraf 	    TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
7147c478bd9Sstevel@tonic-gate 	if (return_val == TD_OK) {
7157c478bd9Sstevel@tonic-gate 		if (data.found == 0)
7167c478bd9Sstevel@tonic-gate 			return_val = TD_NOTHR;
7177c478bd9Sstevel@tonic-gate 		else
7187c478bd9Sstevel@tonic-gate 			*th_p = data.th;
7197c478bd9Sstevel@tonic-gate 	}
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate 	return (return_val);
7227c478bd9Sstevel@tonic-gate }
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate /*
7257c478bd9Sstevel@tonic-gate  * Map the address of a synchronization object to a sync. object handle.
7267c478bd9Sstevel@tonic-gate  */
7277c478bd9Sstevel@tonic-gate #pragma weak td_ta_map_addr2sync = __td_ta_map_addr2sync
7287c478bd9Sstevel@tonic-gate td_err_e
__td_ta_map_addr2sync(td_thragent_t * ta_p,psaddr_t addr,td_synchandle_t * sh_p)7297c478bd9Sstevel@tonic-gate __td_ta_map_addr2sync(td_thragent_t *ta_p, psaddr_t addr, td_synchandle_t *sh_p)
7307c478bd9Sstevel@tonic-gate {
7317c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
7327c478bd9Sstevel@tonic-gate 	td_err_e return_val;
7337c478bd9Sstevel@tonic-gate 	uint16_t sync_magic;
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate 	if (sh_p == NULL)
7367c478bd9Sstevel@tonic-gate 		return (TD_BADSH);
737c3e74f84SToomas Soome 	if (addr == 0)
7387c478bd9Sstevel@tonic-gate 		return (TD_ERR);
7397c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL)
7407c478bd9Sstevel@tonic-gate 		return (return_val);
7417c478bd9Sstevel@tonic-gate 	/*
7427c478bd9Sstevel@tonic-gate 	 * Check the magic number of the sync. object to make sure it's valid.
7437c478bd9Sstevel@tonic-gate 	 * The magic number is at the same offset for all sync. objects.
7447c478bd9Sstevel@tonic-gate 	 */
7457c478bd9Sstevel@tonic-gate 	if (ps_pdread(ph_p, (psaddr_t)&((mutex_t *)addr)->mutex_magic,
7467c478bd9Sstevel@tonic-gate 	    &sync_magic, sizeof (sync_magic)) != PS_OK) {
7477c478bd9Sstevel@tonic-gate 		ph_unlock(ta_p);
7487c478bd9Sstevel@tonic-gate 		return (TD_BADSH);
7497c478bd9Sstevel@tonic-gate 	}
7507c478bd9Sstevel@tonic-gate 	ph_unlock(ta_p);
7517c478bd9Sstevel@tonic-gate 	if (sync_magic != MUTEX_MAGIC && sync_magic != COND_MAGIC &&
7527c478bd9Sstevel@tonic-gate 	    sync_magic != SEMA_MAGIC && sync_magic != RWL_MAGIC)
7537c478bd9Sstevel@tonic-gate 		return (TD_BADSH);
7547c478bd9Sstevel@tonic-gate 	/*
7557c478bd9Sstevel@tonic-gate 	 * Just fill in the appropriate fields of the sync. handle.
7567c478bd9Sstevel@tonic-gate 	 */
7577c478bd9Sstevel@tonic-gate 	sh_p->sh_ta_p = (td_thragent_t *)ta_p;
7587c478bd9Sstevel@tonic-gate 	sh_p->sh_unique = addr;
7597c478bd9Sstevel@tonic-gate 	return (TD_OK);
7607c478bd9Sstevel@tonic-gate }
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate /*
7637c478bd9Sstevel@tonic-gate  * Iterate over the set of global TSD keys.
7647c478bd9Sstevel@tonic-gate  * The call back function is called with three arguments,
7657c478bd9Sstevel@tonic-gate  * a key, a pointer to the destructor function, and the cbdata pointer.
7667c478bd9Sstevel@tonic-gate  * Currently unused by dbx.
7677c478bd9Sstevel@tonic-gate  */
7687c478bd9Sstevel@tonic-gate #pragma weak td_ta_tsd_iter = __td_ta_tsd_iter
7697c478bd9Sstevel@tonic-gate td_err_e
__td_ta_tsd_iter(td_thragent_t * ta_p,td_key_iter_f * cb,void * cbdata_p)7707c478bd9Sstevel@tonic-gate __td_ta_tsd_iter(td_thragent_t *ta_p, td_key_iter_f *cb, void *cbdata_p)
7717c478bd9Sstevel@tonic-gate {
7727c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
7737c478bd9Sstevel@tonic-gate 	td_err_e	return_val;
7747c478bd9Sstevel@tonic-gate 	int		key;
7757c478bd9Sstevel@tonic-gate 	int		numkeys;
7767c478bd9Sstevel@tonic-gate 	psaddr_t	dest_addr;
7777c478bd9Sstevel@tonic-gate 	psaddr_t	*destructors = NULL;
7787c478bd9Sstevel@tonic-gate 	PFrV		destructor;
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate 	if (cb == NULL)
7817c478bd9Sstevel@tonic-gate 		return (TD_ERR);
7827c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL)
7837c478bd9Sstevel@tonic-gate 		return (return_val);
7847c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
7857c478bd9Sstevel@tonic-gate 		ph_unlock(ta_p);
7867c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
7877c478bd9Sstevel@tonic-gate 	}
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate 	if (ta_p->model == PR_MODEL_NATIVE) {
7907c478bd9Sstevel@tonic-gate 		tsd_metadata_t tsdm;
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p,
7937c478bd9Sstevel@tonic-gate 		    ta_p->uberdata_addr + offsetof(uberdata_t, tsd_metadata),
7947c478bd9Sstevel@tonic-gate 		    &tsdm, sizeof (tsdm)) != PS_OK)
7957c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
7967c478bd9Sstevel@tonic-gate 		else {
7977c478bd9Sstevel@tonic-gate 			numkeys = tsdm.tsdm_nused;
7987c478bd9Sstevel@tonic-gate 			dest_addr = (psaddr_t)tsdm.tsdm_destro;
7997c478bd9Sstevel@tonic-gate 			if (numkeys > 0)
8007c478bd9Sstevel@tonic-gate 				destructors =
8017c478bd9Sstevel@tonic-gate 				    malloc(numkeys * sizeof (psaddr_t));
8027c478bd9Sstevel@tonic-gate 		}
8037c478bd9Sstevel@tonic-gate 	} else {
8047c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
8057c478bd9Sstevel@tonic-gate 		tsd_metadata32_t tsdm;
8067c478bd9Sstevel@tonic-gate 
8077c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p,
8087c478bd9Sstevel@tonic-gate 		    ta_p->uberdata_addr + offsetof(uberdata32_t, tsd_metadata),
8097c478bd9Sstevel@tonic-gate 		    &tsdm, sizeof (tsdm)) != PS_OK)
8107c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
8117c478bd9Sstevel@tonic-gate 		else {
8127c478bd9Sstevel@tonic-gate 			numkeys = tsdm.tsdm_nused;
8137c478bd9Sstevel@tonic-gate 			dest_addr = (psaddr_t)tsdm.tsdm_destro;
8147c478bd9Sstevel@tonic-gate 			if (numkeys > 0)
8157c478bd9Sstevel@tonic-gate 				destructors =
8167c478bd9Sstevel@tonic-gate 				    malloc(numkeys * sizeof (caddr32_t));
8177c478bd9Sstevel@tonic-gate 		}
8187c478bd9Sstevel@tonic-gate #else
8197c478bd9Sstevel@tonic-gate 		return_val = TD_DBERR;
8207c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
8217c478bd9Sstevel@tonic-gate 	}
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate 	if (return_val != TD_OK || numkeys <= 0) {
8247c478bd9Sstevel@tonic-gate 		(void) ps_pcontinue(ph_p);
8257c478bd9Sstevel@tonic-gate 		ph_unlock(ta_p);
8267c478bd9Sstevel@tonic-gate 		return (return_val);
8277c478bd9Sstevel@tonic-gate 	}
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate 	if (destructors == NULL)
8307c478bd9Sstevel@tonic-gate 		return_val = TD_MALLOC;
8317c478bd9Sstevel@tonic-gate 	else if (ta_p->model == PR_MODEL_NATIVE) {
8327c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, dest_addr,
8337c478bd9Sstevel@tonic-gate 		    destructors, numkeys * sizeof (psaddr_t)) != PS_OK)
8347c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
8357c478bd9Sstevel@tonic-gate 		else {
8367c478bd9Sstevel@tonic-gate 			for (key = 1; key < numkeys; key++) {
8377c478bd9Sstevel@tonic-gate 				destructor = (PFrV)destructors[key];
8387c478bd9Sstevel@tonic-gate 				if (destructor != TSD_UNALLOCATED &&
8397c478bd9Sstevel@tonic-gate 				    (*cb)(key, destructor, cbdata_p))
8407c478bd9Sstevel@tonic-gate 					break;
8417c478bd9Sstevel@tonic-gate 			}
8427c478bd9Sstevel@tonic-gate 		}
8437c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
8447c478bd9Sstevel@tonic-gate 	} else {
8457c478bd9Sstevel@tonic-gate 		caddr32_t *destructors32 = (caddr32_t *)destructors;
8467c478bd9Sstevel@tonic-gate 		caddr32_t destruct32;
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, dest_addr,
8497c478bd9Sstevel@tonic-gate 		    destructors32, numkeys * sizeof (caddr32_t)) != PS_OK)
8507c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
8517c478bd9Sstevel@tonic-gate 		else {
8527c478bd9Sstevel@tonic-gate 			for (key = 1; key < numkeys; key++) {
8537c478bd9Sstevel@tonic-gate 				destruct32 = destructors32[key];
854b30a53d0SRichard Lowe 				if ((destruct32 !=
855b30a53d0SRichard Lowe 				    (caddr32_t)(uintptr_t)TSD_UNALLOCATED) &&
8567c478bd9Sstevel@tonic-gate 				    (*cb)(key, (PFrV)(uintptr_t)destruct32,
8577c478bd9Sstevel@tonic-gate 				    cbdata_p))
8587c478bd9Sstevel@tonic-gate 					break;
8597c478bd9Sstevel@tonic-gate 			}
8607c478bd9Sstevel@tonic-gate 		}
8617c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
8627c478bd9Sstevel@tonic-gate 	}
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate 	if (destructors)
8657c478bd9Sstevel@tonic-gate 		free(destructors);
8667c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
8677c478bd9Sstevel@tonic-gate 	ph_unlock(ta_p);
8687c478bd9Sstevel@tonic-gate 	return (return_val);
8697c478bd9Sstevel@tonic-gate }
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate int
sigequalset(const sigset_t * s1,const sigset_t * s2)8727c478bd9Sstevel@tonic-gate sigequalset(const sigset_t *s1, const sigset_t *s2)
8737c478bd9Sstevel@tonic-gate {
874d4204c85Sraf 	return (
875d4204c85Sraf 	    s1->__sigbits[0] == s2->__sigbits[0] &&
876d4204c85Sraf 	    s1->__sigbits[1] == s2->__sigbits[1] &&
877d4204c85Sraf 	    s1->__sigbits[2] == s2->__sigbits[2] &&
878d4204c85Sraf 	    s1->__sigbits[3] == s2->__sigbits[3]);
8797c478bd9Sstevel@tonic-gate }
8807c478bd9Sstevel@tonic-gate 
8817c478bd9Sstevel@tonic-gate /*
8827c478bd9Sstevel@tonic-gate  * Description:
8837c478bd9Sstevel@tonic-gate  *   Iterate over all threads. For each thread call
8847c478bd9Sstevel@tonic-gate  * the function pointed to by "cb" with a pointer
8857c478bd9Sstevel@tonic-gate  * to a thread handle, and a pointer to data which
8867c478bd9Sstevel@tonic-gate  * can be NULL. Only call td_thr_iter_f() on threads
8877c478bd9Sstevel@tonic-gate  * which match the properties of state, ti_pri,
8887c478bd9Sstevel@tonic-gate  * ti_sigmask_p, and ti_user_flags.  If cb returns
8897c478bd9Sstevel@tonic-gate  * a non-zero value, terminate iterations.
8907c478bd9Sstevel@tonic-gate  *
8917c478bd9Sstevel@tonic-gate  * Input:
8927c478bd9Sstevel@tonic-gate  *   *ta_p - thread agent
8937c478bd9Sstevel@tonic-gate  *   *cb - call back function defined by user.
8947c478bd9Sstevel@tonic-gate  * td_thr_iter_f() takes a thread handle and
8957c478bd9Sstevel@tonic-gate  * cbdata_p as a parameter.
8967c478bd9Sstevel@tonic-gate  *   cbdata_p - parameter for td_thr_iter_f().
8977c478bd9Sstevel@tonic-gate  *
8987c478bd9Sstevel@tonic-gate  *   state - state of threads of interest.  A value of
8997c478bd9Sstevel@tonic-gate  * TD_THR_ANY_STATE from enum td_thr_state_e
9007c478bd9Sstevel@tonic-gate  * does not restrict iterations by state.
9017c478bd9Sstevel@tonic-gate  *   ti_pri - lower bound of priorities of threads of
9027c478bd9Sstevel@tonic-gate  * interest.  A value of TD_THR_LOWEST_PRIORITY
9037c478bd9Sstevel@tonic-gate  * defined in thread_db.h does not restrict
9047c478bd9Sstevel@tonic-gate  * iterations by priority.  A thread with priority
9057c478bd9Sstevel@tonic-gate  * less than ti_pri will NOT be passed to the callback
9067c478bd9Sstevel@tonic-gate  * function.
9077c478bd9Sstevel@tonic-gate  *   ti_sigmask_p - signal mask of threads of interest.
9087c478bd9Sstevel@tonic-gate  * A value of TD_SIGNO_MASK defined in thread_db.h
9097c478bd9Sstevel@tonic-gate  * does not restrict iterations by signal mask.
9107c478bd9Sstevel@tonic-gate  *   ti_user_flags - user flags of threads of interest.  A
9117c478bd9Sstevel@tonic-gate  * value of TD_THR_ANY_USER_FLAGS defined in thread_db.h
9127c478bd9Sstevel@tonic-gate  * does not restrict iterations by user flags.
9137c478bd9Sstevel@tonic-gate  */
9147c478bd9Sstevel@tonic-gate #pragma weak td_ta_thr_iter = __td_ta_thr_iter
9157c478bd9Sstevel@tonic-gate td_err_e
__td_ta_thr_iter(td_thragent_t * ta_p,td_thr_iter_f * cb,void * cbdata_p,td_thr_state_e state,int ti_pri,sigset_t * ti_sigmask_p,unsigned ti_user_flags)9167c478bd9Sstevel@tonic-gate __td_ta_thr_iter(td_thragent_t *ta_p, td_thr_iter_f *cb,
917c3e74f84SToomas Soome     void *cbdata_p, td_thr_state_e state, int ti_pri,
918c3e74f84SToomas Soome     sigset_t *ti_sigmask_p, unsigned ti_user_flags)
9197c478bd9Sstevel@tonic-gate {
9207c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
9217c478bd9Sstevel@tonic-gate 	psaddr_t	first_lwp_addr;
9227c478bd9Sstevel@tonic-gate 	psaddr_t	first_zombie_addr;
9237c478bd9Sstevel@tonic-gate 	psaddr_t	curr_lwp_addr;
9247c478bd9Sstevel@tonic-gate 	psaddr_t	next_lwp_addr;
9257c478bd9Sstevel@tonic-gate 	td_thrhandle_t	th;
9267c478bd9Sstevel@tonic-gate 	ps_err_e	db_return;
9277c478bd9Sstevel@tonic-gate 	ps_err_e	db_return2;
9287c478bd9Sstevel@tonic-gate 	td_err_e	return_val;
9297c478bd9Sstevel@tonic-gate 
9307c478bd9Sstevel@tonic-gate 	if (cb == NULL)
9317c478bd9Sstevel@tonic-gate 		return (TD_ERR);
9327c478bd9Sstevel@tonic-gate 	/*
9337c478bd9Sstevel@tonic-gate 	 * If state is not within bound, short circuit.
9347c478bd9Sstevel@tonic-gate 	 */
9357c478bd9Sstevel@tonic-gate 	if (state < TD_THR_ANY_STATE || state > TD_THR_STOPPED_ASLEEP)
9367c478bd9Sstevel@tonic-gate 		return (TD_OK);
9377c478bd9Sstevel@tonic-gate 
9387c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL)
9397c478bd9Sstevel@tonic-gate 		return (return_val);
9407c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
9417c478bd9Sstevel@tonic-gate 		ph_unlock(ta_p);
9427c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
9437c478bd9Sstevel@tonic-gate 	}
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 	/*
9467c478bd9Sstevel@tonic-gate 	 * For each ulwp_t in the circular linked lists pointed
9477c478bd9Sstevel@tonic-gate 	 * to by "all_lwps" and "all_zombies":
9487c478bd9Sstevel@tonic-gate 	 * (1) Filter each thread.
9497c478bd9Sstevel@tonic-gate 	 * (2) Create the thread_object for each thread that passes.
9507c478bd9Sstevel@tonic-gate 	 * (3) Call the call back function on each thread.
9517c478bd9Sstevel@tonic-gate 	 */
9527c478bd9Sstevel@tonic-gate 
9537c478bd9Sstevel@tonic-gate 	if (ta_p->model == PR_MODEL_NATIVE) {
9547c478bd9Sstevel@tonic-gate 		db_return = ps_pdread(ph_p,
9557c478bd9Sstevel@tonic-gate 		    ta_p->uberdata_addr + offsetof(uberdata_t, all_lwps),
9567c478bd9Sstevel@tonic-gate 		    &first_lwp_addr, sizeof (first_lwp_addr));
9577c478bd9Sstevel@tonic-gate 		db_return2 = ps_pdread(ph_p,
9587c478bd9Sstevel@tonic-gate 		    ta_p->uberdata_addr + offsetof(uberdata_t, all_zombies),
9597c478bd9Sstevel@tonic-gate 		    &first_zombie_addr, sizeof (first_zombie_addr));
9607c478bd9Sstevel@tonic-gate 	} else {
9617c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
9627c478bd9Sstevel@tonic-gate 		caddr32_t addr32;
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate 		db_return = ps_pdread(ph_p,
9657c478bd9Sstevel@tonic-gate 		    ta_p->uberdata_addr + offsetof(uberdata32_t, all_lwps),
9667c478bd9Sstevel@tonic-gate 		    &addr32, sizeof (addr32));
9677c478bd9Sstevel@tonic-gate 		first_lwp_addr = addr32;
9687c478bd9Sstevel@tonic-gate 		db_return2 = ps_pdread(ph_p,
9697c478bd9Sstevel@tonic-gate 		    ta_p->uberdata_addr + offsetof(uberdata32_t, all_zombies),
9707c478bd9Sstevel@tonic-gate 		    &addr32, sizeof (addr32));
9717c478bd9Sstevel@tonic-gate 		first_zombie_addr = addr32;
9727c478bd9Sstevel@tonic-gate #else	/* _SYSCALL32 */
9737c478bd9Sstevel@tonic-gate 		db_return = PS_ERR;
9747c478bd9Sstevel@tonic-gate 		db_return2 = PS_ERR;
9757c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
9767c478bd9Sstevel@tonic-gate 	}
9777c478bd9Sstevel@tonic-gate 	if (db_return == PS_OK)
9787c478bd9Sstevel@tonic-gate 		db_return = db_return2;
9797c478bd9Sstevel@tonic-gate 
9807c478bd9Sstevel@tonic-gate 	/*
9817c478bd9Sstevel@tonic-gate 	 * If first_lwp_addr and first_zombie_addr are both NULL,
9827c478bd9Sstevel@tonic-gate 	 * libc must not yet be initialized or all threads have
9837c478bd9Sstevel@tonic-gate 	 * exited.  Return TD_NOTHR and all will be well.
9847c478bd9Sstevel@tonic-gate 	 */
9857c478bd9Sstevel@tonic-gate 	if (db_return == PS_OK &&
986c3e74f84SToomas Soome 	    first_lwp_addr == 0 && first_zombie_addr == 0) {
9877c478bd9Sstevel@tonic-gate 		(void) ps_pcontinue(ph_p);
9887c478bd9Sstevel@tonic-gate 		ph_unlock(ta_p);
9897c478bd9Sstevel@tonic-gate 		return (TD_NOTHR);
9907c478bd9Sstevel@tonic-gate 	}
9917c478bd9Sstevel@tonic-gate 	if (db_return != PS_OK) {
9927c478bd9Sstevel@tonic-gate 		(void) ps_pcontinue(ph_p);
9937c478bd9Sstevel@tonic-gate 		ph_unlock(ta_p);
9947c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
9957c478bd9Sstevel@tonic-gate 	}
9967c478bd9Sstevel@tonic-gate 
9977c478bd9Sstevel@tonic-gate 	/*
9987c478bd9Sstevel@tonic-gate 	 * Run down the lists of all living and dead lwps.
9997c478bd9Sstevel@tonic-gate 	 */
1000c3e74f84SToomas Soome 	if (first_lwp_addr == 0)
10017c478bd9Sstevel@tonic-gate 		first_lwp_addr = first_zombie_addr;
10027c478bd9Sstevel@tonic-gate 	curr_lwp_addr = first_lwp_addr;
10037c478bd9Sstevel@tonic-gate 	for (;;) {
10047c478bd9Sstevel@tonic-gate 		td_thr_state_e ts_state;
10057c478bd9Sstevel@tonic-gate 		int userpri;
10067c478bd9Sstevel@tonic-gate 		unsigned userflags;
10077c478bd9Sstevel@tonic-gate 		sigset_t mask;
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate 		/*
10107c478bd9Sstevel@tonic-gate 		 * Read the ulwp struct.
10117c478bd9Sstevel@tonic-gate 		 */
10127c478bd9Sstevel@tonic-gate 		if (ta_p->model == PR_MODEL_NATIVE) {
10137c478bd9Sstevel@tonic-gate 			ulwp_t ulwp;
10147c478bd9Sstevel@tonic-gate 
10157c478bd9Sstevel@tonic-gate 			if (ps_pdread(ph_p, curr_lwp_addr,
10167c478bd9Sstevel@tonic-gate 			    &ulwp, sizeof (ulwp)) != PS_OK &&
10177c478bd9Sstevel@tonic-gate 			    ((void) memset(&ulwp, 0, sizeof (ulwp)),
10187c478bd9Sstevel@tonic-gate 			    ps_pdread(ph_p, curr_lwp_addr,
10197c478bd9Sstevel@tonic-gate 			    &ulwp, REPLACEMENT_SIZE)) != PS_OK) {
10207c478bd9Sstevel@tonic-gate 				return_val = TD_DBERR;
10217c478bd9Sstevel@tonic-gate 				break;
10227c478bd9Sstevel@tonic-gate 			}
10237c478bd9Sstevel@tonic-gate 			next_lwp_addr = (psaddr_t)ulwp.ul_forw;
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate 			ts_state = ulwp.ul_dead? TD_THR_ZOMBIE :
1026d4204c85Sraf 			    ulwp.ul_stop? TD_THR_STOPPED :
1027d4204c85Sraf 			    ulwp.ul_wchan? TD_THR_SLEEP :
1028d4204c85Sraf 			    TD_THR_ACTIVE;
10297c478bd9Sstevel@tonic-gate 			userpri = ulwp.ul_pri;
10307c478bd9Sstevel@tonic-gate 			userflags = ulwp.ul_usropts;
10317c478bd9Sstevel@tonic-gate 			if (ulwp.ul_dead)
10327c478bd9Sstevel@tonic-gate 				(void) sigemptyset(&mask);
10337c478bd9Sstevel@tonic-gate 			else
10347c478bd9Sstevel@tonic-gate 				mask = *(sigset_t *)&ulwp.ul_sigmask;
10357c478bd9Sstevel@tonic-gate 		} else {
10367c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
10377c478bd9Sstevel@tonic-gate 			ulwp32_t ulwp;
10387c478bd9Sstevel@tonic-gate 
10397c478bd9Sstevel@tonic-gate 			if (ps_pdread(ph_p, curr_lwp_addr,
10407c478bd9Sstevel@tonic-gate 			    &ulwp, sizeof (ulwp)) != PS_OK &&
10417c478bd9Sstevel@tonic-gate 			    ((void) memset(&ulwp, 0, sizeof (ulwp)),
10427c478bd9Sstevel@tonic-gate 			    ps_pdread(ph_p, curr_lwp_addr,
10437c478bd9Sstevel@tonic-gate 			    &ulwp, REPLACEMENT_SIZE32)) != PS_OK) {
10447c478bd9Sstevel@tonic-gate 				return_val = TD_DBERR;
10457c478bd9Sstevel@tonic-gate 				break;
10467c478bd9Sstevel@tonic-gate 			}
10477c478bd9Sstevel@tonic-gate 			next_lwp_addr = (psaddr_t)ulwp.ul_forw;
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate 			ts_state = ulwp.ul_dead? TD_THR_ZOMBIE :
1050d4204c85Sraf 			    ulwp.ul_stop? TD_THR_STOPPED :
1051d4204c85Sraf 			    ulwp.ul_wchan? TD_THR_SLEEP :
1052d4204c85Sraf 			    TD_THR_ACTIVE;
10537c478bd9Sstevel@tonic-gate 			userpri = ulwp.ul_pri;
10547c478bd9Sstevel@tonic-gate 			userflags = ulwp.ul_usropts;
10557c478bd9Sstevel@tonic-gate 			if (ulwp.ul_dead)
10567c478bd9Sstevel@tonic-gate 				(void) sigemptyset(&mask);
10577c478bd9Sstevel@tonic-gate 			else
10587c478bd9Sstevel@tonic-gate 				mask = *(sigset_t *)&ulwp.ul_sigmask;
10597c478bd9Sstevel@tonic-gate #else	/* _SYSCALL32 */
10607c478bd9Sstevel@tonic-gate 			return_val = TD_ERR;
10617c478bd9Sstevel@tonic-gate 			break;
10627c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
10637c478bd9Sstevel@tonic-gate 		}
10647c478bd9Sstevel@tonic-gate 
10657c478bd9Sstevel@tonic-gate 		/*
10667c478bd9Sstevel@tonic-gate 		 * Filter on state, priority, sigmask, and user flags.
10677c478bd9Sstevel@tonic-gate 		 */
10687c478bd9Sstevel@tonic-gate 
10697c478bd9Sstevel@tonic-gate 		if ((state != ts_state) &&
10707c478bd9Sstevel@tonic-gate 		    (state != TD_THR_ANY_STATE))
10717c478bd9Sstevel@tonic-gate 			goto advance;
10727c478bd9Sstevel@tonic-gate 
10737c478bd9Sstevel@tonic-gate 		if (ti_pri > userpri)
10747c478bd9Sstevel@tonic-gate 			goto advance;
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 		if (ti_sigmask_p != TD_SIGNO_MASK &&
10777c478bd9Sstevel@tonic-gate 		    !sigequalset(ti_sigmask_p, &mask))
10787c478bd9Sstevel@tonic-gate 			goto advance;
10797c478bd9Sstevel@tonic-gate 
10807c478bd9Sstevel@tonic-gate 		if (ti_user_flags != userflags &&
10817c478bd9Sstevel@tonic-gate 		    ti_user_flags != (unsigned)TD_THR_ANY_USER_FLAGS)
10827c478bd9Sstevel@tonic-gate 			goto advance;
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate 		/*
10857c478bd9Sstevel@tonic-gate 		 * Call back - break if the return
10867c478bd9Sstevel@tonic-gate 		 * from the call back is non-zero.
10877c478bd9Sstevel@tonic-gate 		 */
10887c478bd9Sstevel@tonic-gate 		th.th_ta_p = (td_thragent_t *)ta_p;
10897c478bd9Sstevel@tonic-gate 		th.th_unique = curr_lwp_addr;
10907c478bd9Sstevel@tonic-gate 		if ((*cb)(&th, cbdata_p))
10917c478bd9Sstevel@tonic-gate 			break;
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate advance:
10947c478bd9Sstevel@tonic-gate 		if ((curr_lwp_addr = next_lwp_addr) == first_lwp_addr) {
10957c478bd9Sstevel@tonic-gate 			/*
10967c478bd9Sstevel@tonic-gate 			 * Switch to the zombie list, unless it is NULL
10977c478bd9Sstevel@tonic-gate 			 * or we have already been doing the zombie list,
10987c478bd9Sstevel@tonic-gate 			 * in which case terminate the loop.
10997c478bd9Sstevel@tonic-gate 			 */
1100c3e74f84SToomas Soome 			if (first_zombie_addr == 0 ||
11017c478bd9Sstevel@tonic-gate 			    first_lwp_addr == first_zombie_addr)
11027c478bd9Sstevel@tonic-gate 				break;
11037c478bd9Sstevel@tonic-gate 			curr_lwp_addr = first_lwp_addr = first_zombie_addr;
11047c478bd9Sstevel@tonic-gate 		}
11057c478bd9Sstevel@tonic-gate 	}
11067c478bd9Sstevel@tonic-gate 
11077c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
11087c478bd9Sstevel@tonic-gate 	ph_unlock(ta_p);
11097c478bd9Sstevel@tonic-gate 	return (return_val);
11107c478bd9Sstevel@tonic-gate }
11117c478bd9Sstevel@tonic-gate 
11127c478bd9Sstevel@tonic-gate /*
11137c478bd9Sstevel@tonic-gate  * Enable or disable process synchronization object tracking.
11147c478bd9Sstevel@tonic-gate  * Currently unused by dbx.
11157c478bd9Sstevel@tonic-gate  */
11167c478bd9Sstevel@tonic-gate #pragma weak td_ta_sync_tracking_enable = __td_ta_sync_tracking_enable
11177c478bd9Sstevel@tonic-gate td_err_e
__td_ta_sync_tracking_enable(td_thragent_t * ta_p,int onoff)11187c478bd9Sstevel@tonic-gate __td_ta_sync_tracking_enable(td_thragent_t *ta_p, int onoff)
11197c478bd9Sstevel@tonic-gate {
11207c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
11217c478bd9Sstevel@tonic-gate 	td_err_e return_val;
11227c478bd9Sstevel@tonic-gate 	register_sync_t enable;
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL)
11257c478bd9Sstevel@tonic-gate 		return (return_val);
11267c478bd9Sstevel@tonic-gate 	/*
11277c478bd9Sstevel@tonic-gate 	 * Values of tdb_register_sync in the victim process:
11287c478bd9Sstevel@tonic-gate 	 *	REGISTER_SYNC_ENABLE	enables registration of synch objects
11297c478bd9Sstevel@tonic-gate 	 *	REGISTER_SYNC_DISABLE	disables registration of synch objects
11307c478bd9Sstevel@tonic-gate 	 * These cause the table to be cleared and tdb_register_sync set to:
11317c478bd9Sstevel@tonic-gate 	 *	REGISTER_SYNC_ON	registration in effect
11327c478bd9Sstevel@tonic-gate 	 *	REGISTER_SYNC_OFF	registration not in effect
11337c478bd9Sstevel@tonic-gate 	 */
11347c478bd9Sstevel@tonic-gate 	enable = onoff? REGISTER_SYNC_ENABLE : REGISTER_SYNC_DISABLE;
11357c478bd9Sstevel@tonic-gate 	if (ps_pdwrite(ph_p, ta_p->tdb_register_sync_addr,
11367c478bd9Sstevel@tonic-gate 	    &enable, sizeof (enable)) != PS_OK)
11377c478bd9Sstevel@tonic-gate 		return_val = TD_DBERR;
11387c478bd9Sstevel@tonic-gate 	/*
11397c478bd9Sstevel@tonic-gate 	 * Remember that this interface was called (see td_ta_delete()).
11407c478bd9Sstevel@tonic-gate 	 */
11417c478bd9Sstevel@tonic-gate 	ta_p->sync_tracking = 1;
11427c478bd9Sstevel@tonic-gate 	ph_unlock(ta_p);
11437c478bd9Sstevel@tonic-gate 	return (return_val);
11447c478bd9Sstevel@tonic-gate }
11457c478bd9Sstevel@tonic-gate 
11467c478bd9Sstevel@tonic-gate /*
11477c478bd9Sstevel@tonic-gate  * Iterate over all known synchronization variables.
11487c478bd9Sstevel@tonic-gate  * It is very possible that the list generated is incomplete,
11497c478bd9Sstevel@tonic-gate  * because the iterator can only find synchronization variables
11507c478bd9Sstevel@tonic-gate  * that have been registered by the process since synchronization
11517c478bd9Sstevel@tonic-gate  * object registration was enabled.
11527c478bd9Sstevel@tonic-gate  * The call back function cb is called for each synchronization
11537c478bd9Sstevel@tonic-gate  * variable with two arguments: a pointer to the synchronization
11547c478bd9Sstevel@tonic-gate  * handle and the passed-in argument cbdata.
11557c478bd9Sstevel@tonic-gate  * If cb returns a non-zero value, iterations are terminated.
11567c478bd9Sstevel@tonic-gate  */
11577c478bd9Sstevel@tonic-gate #pragma weak td_ta_sync_iter = __td_ta_sync_iter
11587c478bd9Sstevel@tonic-gate td_err_e
__td_ta_sync_iter(td_thragent_t * ta_p,td_sync_iter_f * cb,void * cbdata)11597c478bd9Sstevel@tonic-gate __td_ta_sync_iter(td_thragent_t *ta_p, td_sync_iter_f *cb, void *cbdata)
11607c478bd9Sstevel@tonic-gate {
11617c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
11627c478bd9Sstevel@tonic-gate 	td_err_e	return_val;
11637c478bd9Sstevel@tonic-gate 	int		i;
11647c478bd9Sstevel@tonic-gate 	register_sync_t	enable;
11657c478bd9Sstevel@tonic-gate 	psaddr_t	next_desc;
11667c478bd9Sstevel@tonic-gate 	tdb_sync_stats_t sync_stats;
11677c478bd9Sstevel@tonic-gate 	td_synchandle_t	synchandle;
11687c478bd9Sstevel@tonic-gate 	psaddr_t	psaddr;
11697c478bd9Sstevel@tonic-gate 	void		*vaddr;
11707c478bd9Sstevel@tonic-gate 	uint64_t	*sync_addr_hash = NULL;
11717c478bd9Sstevel@tonic-gate 
11727c478bd9Sstevel@tonic-gate 	if (cb == NULL)
11737c478bd9Sstevel@tonic-gate 		return (TD_ERR);
11747c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL)
11757c478bd9Sstevel@tonic-gate 		return (return_val);
11767c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
11777c478bd9Sstevel@tonic-gate 		ph_unlock(ta_p);
11787c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
11797c478bd9Sstevel@tonic-gate 	}
11807c478bd9Sstevel@tonic-gate 	if (ps_pdread(ph_p, ta_p->tdb_register_sync_addr,
11817c478bd9Sstevel@tonic-gate 	    &enable, sizeof (enable)) != PS_OK) {
11827c478bd9Sstevel@tonic-gate 		return_val = TD_DBERR;
11837c478bd9Sstevel@tonic-gate 		goto out;
11847c478bd9Sstevel@tonic-gate 	}
11857c478bd9Sstevel@tonic-gate 	if (enable != REGISTER_SYNC_ON)
11867c478bd9Sstevel@tonic-gate 		goto out;
11877c478bd9Sstevel@tonic-gate 
11887c478bd9Sstevel@tonic-gate 	/*
11897c478bd9Sstevel@tonic-gate 	 * First read the hash table.
11907c478bd9Sstevel@tonic-gate 	 * The hash table is large; allocate with mmap().
11917c478bd9Sstevel@tonic-gate 	 */
11927c478bd9Sstevel@tonic-gate 	if ((vaddr = mmap(NULL, TDB_HASH_SIZE * sizeof (uint64_t),
11937c478bd9Sstevel@tonic-gate 	    PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, (off_t)0))
11947c478bd9Sstevel@tonic-gate 	    == MAP_FAILED) {
11957c478bd9Sstevel@tonic-gate 		return_val = TD_MALLOC;
11967c478bd9Sstevel@tonic-gate 		goto out;
11977c478bd9Sstevel@tonic-gate 	}
11987c478bd9Sstevel@tonic-gate 	sync_addr_hash = vaddr;
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate 	if (ta_p->model == PR_MODEL_NATIVE) {
12017c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, ta_p->uberdata_addr +
12027c478bd9Sstevel@tonic-gate 		    offsetof(uberdata_t, tdb.tdb_sync_addr_hash),
12037c478bd9Sstevel@tonic-gate 		    &psaddr, sizeof (&psaddr)) != PS_OK) {
12047c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
12057c478bd9Sstevel@tonic-gate 			goto out;
12067c478bd9Sstevel@tonic-gate 		}
12077c478bd9Sstevel@tonic-gate 	} else {
12087c478bd9Sstevel@tonic-gate #ifdef  _SYSCALL32
12097c478bd9Sstevel@tonic-gate 		caddr32_t addr;
12107c478bd9Sstevel@tonic-gate 
12117c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, ta_p->uberdata_addr +
12127c478bd9Sstevel@tonic-gate 		    offsetof(uberdata32_t, tdb.tdb_sync_addr_hash),
12137c478bd9Sstevel@tonic-gate 		    &addr, sizeof (addr)) != PS_OK) {
12147c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
12157c478bd9Sstevel@tonic-gate 			goto out;
12167c478bd9Sstevel@tonic-gate 		}
12177c478bd9Sstevel@tonic-gate 		psaddr = addr;
12187c478bd9Sstevel@tonic-gate #else
12197c478bd9Sstevel@tonic-gate 		return_val = TD_ERR;
12207c478bd9Sstevel@tonic-gate 		goto out;
12217c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32 */
12227c478bd9Sstevel@tonic-gate 	}
12237c478bd9Sstevel@tonic-gate 
1224c3e74f84SToomas Soome 	if (psaddr == 0)
12257c478bd9Sstevel@tonic-gate 		goto out;
12267c478bd9Sstevel@tonic-gate 	if (ps_pdread(ph_p, psaddr, sync_addr_hash,
12277c478bd9Sstevel@tonic-gate 	    TDB_HASH_SIZE * sizeof (uint64_t)) != PS_OK) {
12287c478bd9Sstevel@tonic-gate 		return_val = TD_DBERR;
12297c478bd9Sstevel@tonic-gate 		goto out;
12307c478bd9Sstevel@tonic-gate 	}
12317c478bd9Sstevel@tonic-gate 
12327c478bd9Sstevel@tonic-gate 	/*
12337c478bd9Sstevel@tonic-gate 	 * Now scan the hash table.
12347c478bd9Sstevel@tonic-gate 	 */
12357c478bd9Sstevel@tonic-gate 	for (i = 0; i < TDB_HASH_SIZE; i++) {
12367c478bd9Sstevel@tonic-gate 		for (next_desc = (psaddr_t)sync_addr_hash[i];
1237c3e74f84SToomas Soome 		    next_desc != 0;
12387c478bd9Sstevel@tonic-gate 		    next_desc = (psaddr_t)sync_stats.next) {
12397c478bd9Sstevel@tonic-gate 			if (ps_pdread(ph_p, next_desc,
12407c478bd9Sstevel@tonic-gate 			    &sync_stats, sizeof (sync_stats)) != PS_OK) {
12417c478bd9Sstevel@tonic-gate 				return_val = TD_DBERR;
12427c478bd9Sstevel@tonic-gate 				goto out;
12437c478bd9Sstevel@tonic-gate 			}
12447c478bd9Sstevel@tonic-gate 			if (sync_stats.un.type == TDB_NONE) {
12457c478bd9Sstevel@tonic-gate 				/* not registered since registration enabled */
12467c478bd9Sstevel@tonic-gate 				continue;
12477c478bd9Sstevel@tonic-gate 			}
12487c478bd9Sstevel@tonic-gate 			synchandle.sh_ta_p = ta_p;
12497c478bd9Sstevel@tonic-gate 			synchandle.sh_unique = (psaddr_t)sync_stats.sync_addr;
12507c478bd9Sstevel@tonic-gate 			if ((*cb)(&synchandle, cbdata) != 0)
12517c478bd9Sstevel@tonic-gate 				goto out;
12527c478bd9Sstevel@tonic-gate 		}
12537c478bd9Sstevel@tonic-gate 	}
12547c478bd9Sstevel@tonic-gate 
12557c478bd9Sstevel@tonic-gate out:
12567c478bd9Sstevel@tonic-gate 	if (sync_addr_hash != NULL)
12577c478bd9Sstevel@tonic-gate 		(void) munmap((void *)sync_addr_hash,
12587c478bd9Sstevel@tonic-gate 		    TDB_HASH_SIZE * sizeof (uint64_t));
12597c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
12607c478bd9Sstevel@tonic-gate 	ph_unlock(ta_p);
12617c478bd9Sstevel@tonic-gate 	return (return_val);
12627c478bd9Sstevel@tonic-gate }
12637c478bd9Sstevel@tonic-gate 
12647c478bd9Sstevel@tonic-gate /*
12657c478bd9Sstevel@tonic-gate  * Enable process statistics collection.
12667c478bd9Sstevel@tonic-gate  */
12677c478bd9Sstevel@tonic-gate #pragma weak td_ta_enable_stats = __td_ta_enable_stats
12687c478bd9Sstevel@tonic-gate /* ARGSUSED */
12697c478bd9Sstevel@tonic-gate td_err_e
__td_ta_enable_stats(const td_thragent_t * ta_p,int onoff)12707c478bd9Sstevel@tonic-gate __td_ta_enable_stats(const td_thragent_t *ta_p, int onoff)
12717c478bd9Sstevel@tonic-gate {
12727c478bd9Sstevel@tonic-gate 	return (TD_NOCAPAB);
12737c478bd9Sstevel@tonic-gate }
12747c478bd9Sstevel@tonic-gate 
12757c478bd9Sstevel@tonic-gate /*
12767c478bd9Sstevel@tonic-gate  * Reset process statistics.
12777c478bd9Sstevel@tonic-gate  */
12787c478bd9Sstevel@tonic-gate #pragma weak td_ta_reset_stats = __td_ta_reset_stats
12797c478bd9Sstevel@tonic-gate /* ARGSUSED */
12807c478bd9Sstevel@tonic-gate td_err_e
__td_ta_reset_stats(const td_thragent_t * ta_p)12817c478bd9Sstevel@tonic-gate __td_ta_reset_stats(const td_thragent_t *ta_p)
12827c478bd9Sstevel@tonic-gate {
12837c478bd9Sstevel@tonic-gate 	return (TD_NOCAPAB);
12847c478bd9Sstevel@tonic-gate }
12857c478bd9Sstevel@tonic-gate 
12867c478bd9Sstevel@tonic-gate /*
12877c478bd9Sstevel@tonic-gate  * Read process statistics.
12887c478bd9Sstevel@tonic-gate  */
12897c478bd9Sstevel@tonic-gate #pragma weak td_ta_get_stats = __td_ta_get_stats
12907c478bd9Sstevel@tonic-gate /* ARGSUSED */
12917c478bd9Sstevel@tonic-gate td_err_e
__td_ta_get_stats(const td_thragent_t * ta_p,td_ta_stats_t * tstats)12927c478bd9Sstevel@tonic-gate __td_ta_get_stats(const td_thragent_t *ta_p, td_ta_stats_t *tstats)
12937c478bd9Sstevel@tonic-gate {
12947c478bd9Sstevel@tonic-gate 	return (TD_NOCAPAB);
12957c478bd9Sstevel@tonic-gate }
12967c478bd9Sstevel@tonic-gate 
12977c478bd9Sstevel@tonic-gate /*
12987c478bd9Sstevel@tonic-gate  * Transfer information from lwp struct to thread information struct.
12997c478bd9Sstevel@tonic-gate  * XXX -- lots of this needs cleaning up.
13007c478bd9Sstevel@tonic-gate  */
13017c478bd9Sstevel@tonic-gate static void
td_thr2to(td_thragent_t * ta_p,psaddr_t ts_addr,ulwp_t * ulwp,td_thrinfo_t * ti_p)13027c478bd9Sstevel@tonic-gate td_thr2to(td_thragent_t *ta_p, psaddr_t ts_addr,
1303c3e74f84SToomas Soome     ulwp_t *ulwp, td_thrinfo_t *ti_p)
13047c478bd9Sstevel@tonic-gate {
13057c478bd9Sstevel@tonic-gate 	lwpid_t lwpid;
13067c478bd9Sstevel@tonic-gate 
13077c478bd9Sstevel@tonic-gate 	if ((lwpid = ulwp->ul_lwpid) == 0)
13087c478bd9Sstevel@tonic-gate 		lwpid = 1;
13097c478bd9Sstevel@tonic-gate 	(void) memset(ti_p, 0, sizeof (*ti_p));
13107c478bd9Sstevel@tonic-gate 	ti_p->ti_ta_p = ta_p;
13117c478bd9Sstevel@tonic-gate 	ti_p->ti_user_flags = ulwp->ul_usropts;
13127c478bd9Sstevel@tonic-gate 	ti_p->ti_tid = lwpid;
13137c478bd9Sstevel@tonic-gate 	ti_p->ti_exitval = ulwp->ul_rval;
13147c478bd9Sstevel@tonic-gate 	ti_p->ti_startfunc = (psaddr_t)ulwp->ul_startpc;
13157c478bd9Sstevel@tonic-gate 	if (!ulwp->ul_dead) {
13167c478bd9Sstevel@tonic-gate 		/*
13177c478bd9Sstevel@tonic-gate 		 * The bloody fools got this backwards!
13187c478bd9Sstevel@tonic-gate 		 */
13197c478bd9Sstevel@tonic-gate 		ti_p->ti_stkbase = (psaddr_t)ulwp->ul_stktop;
13207c478bd9Sstevel@tonic-gate 		ti_p->ti_stksize = ulwp->ul_stksiz;
13217c478bd9Sstevel@tonic-gate 	}
13227c478bd9Sstevel@tonic-gate 	ti_p->ti_ro_area = ts_addr;
13237c478bd9Sstevel@tonic-gate 	ti_p->ti_ro_size = ulwp->ul_replace?
1324d4204c85Sraf 	    REPLACEMENT_SIZE : sizeof (ulwp_t);
13257c478bd9Sstevel@tonic-gate 	ti_p->ti_state = ulwp->ul_dead? TD_THR_ZOMBIE :
1326d4204c85Sraf 	    ulwp->ul_stop? TD_THR_STOPPED :
1327d4204c85Sraf 	    ulwp->ul_wchan? TD_THR_SLEEP :
1328d4204c85Sraf 	    TD_THR_ACTIVE;
13297c478bd9Sstevel@tonic-gate 	ti_p->ti_db_suspended = 0;
13307c478bd9Sstevel@tonic-gate 	ti_p->ti_type = TD_THR_USER;
13317c478bd9Sstevel@tonic-gate 	ti_p->ti_sp = ulwp->ul_sp;
13327c478bd9Sstevel@tonic-gate 	ti_p->ti_flags = 0;
13337c478bd9Sstevel@tonic-gate 	ti_p->ti_pri = ulwp->ul_pri;
13347c478bd9Sstevel@tonic-gate 	ti_p->ti_lid = lwpid;
13357c478bd9Sstevel@tonic-gate 	if (!ulwp->ul_dead)
13367c478bd9Sstevel@tonic-gate 		ti_p->ti_sigmask = ulwp->ul_sigmask;
13377c478bd9Sstevel@tonic-gate 	ti_p->ti_traceme = 0;
13387c478bd9Sstevel@tonic-gate 	ti_p->ti_preemptflag = 0;
13397c478bd9Sstevel@tonic-gate 	ti_p->ti_pirecflag = 0;
13407c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&ti_p->ti_pending);
13417c478bd9Sstevel@tonic-gate 	ti_p->ti_events = ulwp->ul_td_evbuf.eventmask;
13427c478bd9Sstevel@tonic-gate }
13437c478bd9Sstevel@tonic-gate 
13447c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
13457c478bd9Sstevel@tonic-gate static void
td_thr2to32(td_thragent_t * ta_p,psaddr_t ts_addr,ulwp32_t * ulwp,td_thrinfo_t * ti_p)13467c478bd9Sstevel@tonic-gate td_thr2to32(td_thragent_t *ta_p, psaddr_t ts_addr,
1347c3e74f84SToomas Soome     ulwp32_t *ulwp, td_thrinfo_t *ti_p)
13487c478bd9Sstevel@tonic-gate {
13497c478bd9Sstevel@tonic-gate 	lwpid_t lwpid;
13507c478bd9Sstevel@tonic-gate 
13517c478bd9Sstevel@tonic-gate 	if ((lwpid = ulwp->ul_lwpid) == 0)
13527c478bd9Sstevel@tonic-gate 		lwpid = 1;
13537c478bd9Sstevel@tonic-gate 	(void) memset(ti_p, 0, sizeof (*ti_p));
13547c478bd9Sstevel@tonic-gate 	ti_p->ti_ta_p = ta_p;
13557c478bd9Sstevel@tonic-gate 	ti_p->ti_user_flags = ulwp->ul_usropts;
13567c478bd9Sstevel@tonic-gate 	ti_p->ti_tid = lwpid;
13577c478bd9Sstevel@tonic-gate 	ti_p->ti_exitval = (void *)(uintptr_t)ulwp->ul_rval;
13587c478bd9Sstevel@tonic-gate 	ti_p->ti_startfunc = (psaddr_t)ulwp->ul_startpc;
13597c478bd9Sstevel@tonic-gate 	if (!ulwp->ul_dead) {
13607c478bd9Sstevel@tonic-gate 		/*
13617c478bd9Sstevel@tonic-gate 		 * The bloody fools got this backwards!
13627c478bd9Sstevel@tonic-gate 		 */
13637c478bd9Sstevel@tonic-gate 		ti_p->ti_stkbase = (psaddr_t)ulwp->ul_stktop;
13647c478bd9Sstevel@tonic-gate 		ti_p->ti_stksize = ulwp->ul_stksiz;
13657c478bd9Sstevel@tonic-gate 	}
13667c478bd9Sstevel@tonic-gate 	ti_p->ti_ro_area = ts_addr;
13677c478bd9Sstevel@tonic-gate 	ti_p->ti_ro_size = ulwp->ul_replace?
1368d4204c85Sraf 	    REPLACEMENT_SIZE32 : sizeof (ulwp32_t);
13697c478bd9Sstevel@tonic-gate 	ti_p->ti_state = ulwp->ul_dead? TD_THR_ZOMBIE :
1370d4204c85Sraf 	    ulwp->ul_stop? TD_THR_STOPPED :
1371d4204c85Sraf 	    ulwp->ul_wchan? TD_THR_SLEEP :
1372d4204c85Sraf 	    TD_THR_ACTIVE;
13737c478bd9Sstevel@tonic-gate 	ti_p->ti_db_suspended = 0;
13747c478bd9Sstevel@tonic-gate 	ti_p->ti_type = TD_THR_USER;
13757c478bd9Sstevel@tonic-gate 	ti_p->ti_sp = (uint32_t)ulwp->ul_sp;
13767c478bd9Sstevel@tonic-gate 	ti_p->ti_flags = 0;
13777c478bd9Sstevel@tonic-gate 	ti_p->ti_pri = ulwp->ul_pri;
13787c478bd9Sstevel@tonic-gate 	ti_p->ti_lid = lwpid;
13797c478bd9Sstevel@tonic-gate 	if (!ulwp->ul_dead)
13807c478bd9Sstevel@tonic-gate 		ti_p->ti_sigmask = *(sigset_t *)&ulwp->ul_sigmask;
13817c478bd9Sstevel@tonic-gate 	ti_p->ti_traceme = 0;
13827c478bd9Sstevel@tonic-gate 	ti_p->ti_preemptflag = 0;
13837c478bd9Sstevel@tonic-gate 	ti_p->ti_pirecflag = 0;
13847c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&ti_p->ti_pending);
13857c478bd9Sstevel@tonic-gate 	ti_p->ti_events = ulwp->ul_td_evbuf.eventmask;
13867c478bd9Sstevel@tonic-gate }
13877c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
13887c478bd9Sstevel@tonic-gate 
13897c478bd9Sstevel@tonic-gate /*
13907c478bd9Sstevel@tonic-gate  * Get thread information.
13917c478bd9Sstevel@tonic-gate  */
13927c478bd9Sstevel@tonic-gate #pragma weak td_thr_get_info = __td_thr_get_info
13937c478bd9Sstevel@tonic-gate td_err_e
__td_thr_get_info(td_thrhandle_t * th_p,td_thrinfo_t * ti_p)13947c478bd9Sstevel@tonic-gate __td_thr_get_info(td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
13957c478bd9Sstevel@tonic-gate {
13967c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
13977c478bd9Sstevel@tonic-gate 	td_thragent_t	*ta_p;
13987c478bd9Sstevel@tonic-gate 	td_err_e	return_val;
13997c478bd9Sstevel@tonic-gate 	psaddr_t	psaddr;
14007c478bd9Sstevel@tonic-gate 
14017c478bd9Sstevel@tonic-gate 	if (ti_p == NULL)
14027c478bd9Sstevel@tonic-gate 		return (TD_ERR);
1403c3e74f84SToomas Soome 	(void) memset(ti_p, 0, sizeof (*ti_p));
14047c478bd9Sstevel@tonic-gate 
14057c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
14067c478bd9Sstevel@tonic-gate 		return (return_val);
14077c478bd9Sstevel@tonic-gate 	ta_p = th_p->th_ta_p;
14087c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
14097c478bd9Sstevel@tonic-gate 		ph_unlock(ta_p);
14107c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
14117c478bd9Sstevel@tonic-gate 	}
14127c478bd9Sstevel@tonic-gate 
14137c478bd9Sstevel@tonic-gate 	/*
14147c478bd9Sstevel@tonic-gate 	 * Read the ulwp struct from the process.
14157c478bd9Sstevel@tonic-gate 	 * Transfer the ulwp struct to the thread information struct.
14167c478bd9Sstevel@tonic-gate 	 */
14177c478bd9Sstevel@tonic-gate 	psaddr = th_p->th_unique;
14187c478bd9Sstevel@tonic-gate 	if (ta_p->model == PR_MODEL_NATIVE) {
14197c478bd9Sstevel@tonic-gate 		ulwp_t ulwp;
14207c478bd9Sstevel@tonic-gate 
14217c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, psaddr, &ulwp, sizeof (ulwp)) != PS_OK &&
14227c478bd9Sstevel@tonic-gate 		    ((void) memset(&ulwp, 0, sizeof (ulwp)),
14237c478bd9Sstevel@tonic-gate 		    ps_pdread(ph_p, psaddr, &ulwp, REPLACEMENT_SIZE)) != PS_OK)
14247c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
14257c478bd9Sstevel@tonic-gate 		else
14267c478bd9Sstevel@tonic-gate 			td_thr2to(ta_p, psaddr, &ulwp, ti_p);
14277c478bd9Sstevel@tonic-gate 	} else {
14287c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
14297c478bd9Sstevel@tonic-gate 		ulwp32_t ulwp;
14307c478bd9Sstevel@tonic-gate 
14317c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, psaddr, &ulwp, sizeof (ulwp)) != PS_OK &&
14327c478bd9Sstevel@tonic-gate 		    ((void) memset(&ulwp, 0, sizeof (ulwp)),
14337c478bd9Sstevel@tonic-gate 		    ps_pdread(ph_p, psaddr, &ulwp, REPLACEMENT_SIZE32)) !=
1434d4204c85Sraf 		    PS_OK)
14357c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
14367c478bd9Sstevel@tonic-gate 		else
14377c478bd9Sstevel@tonic-gate 			td_thr2to32(ta_p, psaddr, &ulwp, ti_p);
14387c478bd9Sstevel@tonic-gate #else
14397c478bd9Sstevel@tonic-gate 		return_val = TD_ERR;
14407c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
14417c478bd9Sstevel@tonic-gate 	}
14427c478bd9Sstevel@tonic-gate 
14437c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
14447c478bd9Sstevel@tonic-gate 	ph_unlock(ta_p);
14457c478bd9Sstevel@tonic-gate 	return (return_val);
14467c478bd9Sstevel@tonic-gate }
14477c478bd9Sstevel@tonic-gate 
14487c478bd9Sstevel@tonic-gate /*
14497c478bd9Sstevel@tonic-gate  * Given a process and an event number, return information about
14507c478bd9Sstevel@tonic-gate  * an address in the process or at which a breakpoint can be set
14517c478bd9Sstevel@tonic-gate  * to monitor the event.
14527c478bd9Sstevel@tonic-gate  */
14537c478bd9Sstevel@tonic-gate #pragma weak td_ta_event_addr = __td_ta_event_addr
14547c478bd9Sstevel@tonic-gate td_err_e
__td_ta_event_addr(td_thragent_t * ta_p,td_event_e event,td_notify_t * notify_p)14557c478bd9Sstevel@tonic-gate __td_ta_event_addr(td_thragent_t *ta_p, td_event_e event, td_notify_t *notify_p)
14567c478bd9Sstevel@tonic-gate {
14577c478bd9Sstevel@tonic-gate 	if (ta_p == NULL)
14587c478bd9Sstevel@tonic-gate 		return (TD_BADTA);
14597c478bd9Sstevel@tonic-gate 	if (event < TD_MIN_EVENT_NUM || event > TD_MAX_EVENT_NUM)
14607c478bd9Sstevel@tonic-gate 		return (TD_NOEVENT);
14617c478bd9Sstevel@tonic-gate 	if (notify_p == NULL)
14627c478bd9Sstevel@tonic-gate 		return (TD_ERR);
14637c478bd9Sstevel@tonic-gate 
14647c478bd9Sstevel@tonic-gate 	notify_p->type = NOTIFY_BPT;
14657c478bd9Sstevel@tonic-gate 	notify_p->u.bptaddr = ta_p->tdb_events[event - TD_MIN_EVENT_NUM];
14667c478bd9Sstevel@tonic-gate 
14677c478bd9Sstevel@tonic-gate 	return (TD_OK);
14687c478bd9Sstevel@tonic-gate }
14697c478bd9Sstevel@tonic-gate 
14707c478bd9Sstevel@tonic-gate /*
14717c478bd9Sstevel@tonic-gate  * Add the events in eventset 2 to eventset 1.
14727c478bd9Sstevel@tonic-gate  */
14737c478bd9Sstevel@tonic-gate static void
eventsetaddset(td_thr_events_t * event1_p,td_thr_events_t * event2_p)14747c478bd9Sstevel@tonic-gate eventsetaddset(td_thr_events_t *event1_p, td_thr_events_t *event2_p)
14757c478bd9Sstevel@tonic-gate {
14767c478bd9Sstevel@tonic-gate 	int	i;
14777c478bd9Sstevel@tonic-gate 
14787c478bd9Sstevel@tonic-gate 	for (i = 0; i < TD_EVENTSIZE; i++)
14797c478bd9Sstevel@tonic-gate 		event1_p->event_bits[i] |= event2_p->event_bits[i];
14807c478bd9Sstevel@tonic-gate }
14817c478bd9Sstevel@tonic-gate 
14827c478bd9Sstevel@tonic-gate /*
14837c478bd9Sstevel@tonic-gate  * Delete the events in eventset 2 from eventset 1.
14847c478bd9Sstevel@tonic-gate  */
14857c478bd9Sstevel@tonic-gate static void
eventsetdelset(td_thr_events_t * event1_p,td_thr_events_t * event2_p)14867c478bd9Sstevel@tonic-gate eventsetdelset(td_thr_events_t *event1_p, td_thr_events_t *event2_p)
14877c478bd9Sstevel@tonic-gate {
14887c478bd9Sstevel@tonic-gate 	int	i;
14897c478bd9Sstevel@tonic-gate 
14907c478bd9Sstevel@tonic-gate 	for (i = 0; i < TD_EVENTSIZE; i++)
14917c478bd9Sstevel@tonic-gate 		event1_p->event_bits[i] &= ~event2_p->event_bits[i];
14927c478bd9Sstevel@tonic-gate }
14937c478bd9Sstevel@tonic-gate 
14947c478bd9Sstevel@tonic-gate /*
14957c478bd9Sstevel@tonic-gate  * Either add or delete the given event set from a thread's event mask.
14967c478bd9Sstevel@tonic-gate  */
14977c478bd9Sstevel@tonic-gate static td_err_e
mod_eventset(td_thrhandle_t * th_p,td_thr_events_t * events,int onoff)14987c478bd9Sstevel@tonic-gate mod_eventset(td_thrhandle_t *th_p, td_thr_events_t *events, int onoff)
14997c478bd9Sstevel@tonic-gate {
15007c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
15017c478bd9Sstevel@tonic-gate 	td_err_e	return_val = TD_OK;
15027c478bd9Sstevel@tonic-gate 	char		enable;
15037c478bd9Sstevel@tonic-gate 	td_thr_events_t	evset;
15047c478bd9Sstevel@tonic-gate 	psaddr_t	psaddr_evset;
15057c478bd9Sstevel@tonic-gate 	psaddr_t	psaddr_enab;
15067c478bd9Sstevel@tonic-gate 
15077c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
15087c478bd9Sstevel@tonic-gate 		return (return_val);
15097c478bd9Sstevel@tonic-gate 	if (th_p->th_ta_p->model == PR_MODEL_NATIVE) {
15107c478bd9Sstevel@tonic-gate 		ulwp_t *ulwp = (ulwp_t *)th_p->th_unique;
15117c478bd9Sstevel@tonic-gate 		psaddr_evset = (psaddr_t)&ulwp->ul_td_evbuf.eventmask;
15127c478bd9Sstevel@tonic-gate 		psaddr_enab = (psaddr_t)&ulwp->ul_td_events_enable;
15137c478bd9Sstevel@tonic-gate 	} else {
15147c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
15157c478bd9Sstevel@tonic-gate 		ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique;
15167c478bd9Sstevel@tonic-gate 		psaddr_evset = (psaddr_t)&ulwp->ul_td_evbuf.eventmask;
15177c478bd9Sstevel@tonic-gate 		psaddr_enab = (psaddr_t)&ulwp->ul_td_events_enable;
15187c478bd9Sstevel@tonic-gate #else
15197c478bd9Sstevel@tonic-gate 		ph_unlock(th_p->th_ta_p);
15207c478bd9Sstevel@tonic-gate 		return (TD_ERR);
15217c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
15227c478bd9Sstevel@tonic-gate 	}
15237c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
15247c478bd9Sstevel@tonic-gate 		ph_unlock(th_p->th_ta_p);
15257c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
15267c478bd9Sstevel@tonic-gate 	}
15277c478bd9Sstevel@tonic-gate 
15287c478bd9Sstevel@tonic-gate 	if (ps_pdread(ph_p, psaddr_evset, &evset, sizeof (evset)) != PS_OK)
15297c478bd9Sstevel@tonic-gate 		return_val = TD_DBERR;
15307c478bd9Sstevel@tonic-gate 	else {
15317c478bd9Sstevel@tonic-gate 		if (onoff)
15327c478bd9Sstevel@tonic-gate 			eventsetaddset(&evset, events);
15337c478bd9Sstevel@tonic-gate 		else
15347c478bd9Sstevel@tonic-gate 			eventsetdelset(&evset, events);
15357c478bd9Sstevel@tonic-gate 		if (ps_pdwrite(ph_p, psaddr_evset, &evset, sizeof (evset))
15367c478bd9Sstevel@tonic-gate 		    != PS_OK)
15377c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
15387c478bd9Sstevel@tonic-gate 		else {
15397c478bd9Sstevel@tonic-gate 			enable = 0;
15407c478bd9Sstevel@tonic-gate 			if (td_eventismember(&evset, TD_EVENTS_ENABLE))
15417c478bd9Sstevel@tonic-gate 				enable = 1;
15427c478bd9Sstevel@tonic-gate 			if (ps_pdwrite(ph_p, psaddr_enab,
15437c478bd9Sstevel@tonic-gate 			    &enable, sizeof (enable)) != PS_OK)
15447c478bd9Sstevel@tonic-gate 				return_val = TD_DBERR;
15457c478bd9Sstevel@tonic-gate 		}
15467c478bd9Sstevel@tonic-gate 	}
15477c478bd9Sstevel@tonic-gate 
15487c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
15497c478bd9Sstevel@tonic-gate 	ph_unlock(th_p->th_ta_p);
15507c478bd9Sstevel@tonic-gate 	return (return_val);
15517c478bd9Sstevel@tonic-gate }
15527c478bd9Sstevel@tonic-gate 
15537c478bd9Sstevel@tonic-gate /*
15547c478bd9Sstevel@tonic-gate  * Enable or disable tracing for a given thread.  Tracing
15557c478bd9Sstevel@tonic-gate  * is filtered based on the event mask of each thread.  Tracing
15567c478bd9Sstevel@tonic-gate  * can be turned on/off for the thread without changing thread
15577c478bd9Sstevel@tonic-gate  * event mask.
15587c478bd9Sstevel@tonic-gate  * Currently unused by dbx.
15597c478bd9Sstevel@tonic-gate  */
15607c478bd9Sstevel@tonic-gate #pragma weak td_thr_event_enable = __td_thr_event_enable
15617c478bd9Sstevel@tonic-gate td_err_e
__td_thr_event_enable(td_thrhandle_t * th_p,int onoff)15627c478bd9Sstevel@tonic-gate __td_thr_event_enable(td_thrhandle_t *th_p, int onoff)
15637c478bd9Sstevel@tonic-gate {
15647c478bd9Sstevel@tonic-gate 	td_thr_events_t	evset;
15657c478bd9Sstevel@tonic-gate 
15667c478bd9Sstevel@tonic-gate 	td_event_emptyset(&evset);
15677c478bd9Sstevel@tonic-gate 	td_event_addset(&evset, TD_EVENTS_ENABLE);
15687c478bd9Sstevel@tonic-gate 	return (mod_eventset(th_p, &evset, onoff));
15697c478bd9Sstevel@tonic-gate }
15707c478bd9Sstevel@tonic-gate 
15717c478bd9Sstevel@tonic-gate /*
15727c478bd9Sstevel@tonic-gate  * Set event mask to enable event. event is turned on in
15737c478bd9Sstevel@tonic-gate  * event mask for thread.  If a thread encounters an event
15747c478bd9Sstevel@tonic-gate  * for which its event mask is on, notification will be sent
15757c478bd9Sstevel@tonic-gate  * to the debugger.
15767c478bd9Sstevel@tonic-gate  * Addresses for each event are provided to the
15777c478bd9Sstevel@tonic-gate  * debugger.  It is assumed that a breakpoint of some type will
15787c478bd9Sstevel@tonic-gate  * be placed at that address.  If the event mask for the thread
15797c478bd9Sstevel@tonic-gate  * is on, the instruction at the address will be executed.
15807c478bd9Sstevel@tonic-gate  * Otherwise, the instruction will be skipped.
15817c478bd9Sstevel@tonic-gate  */
15827c478bd9Sstevel@tonic-gate #pragma weak td_thr_set_event = __td_thr_set_event
15837c478bd9Sstevel@tonic-gate td_err_e
__td_thr_set_event(td_thrhandle_t * th_p,td_thr_events_t * events)15847c478bd9Sstevel@tonic-gate __td_thr_set_event(td_thrhandle_t *th_p, td_thr_events_t *events)
15857c478bd9Sstevel@tonic-gate {
15867c478bd9Sstevel@tonic-gate 	return (mod_eventset(th_p, events, 1));
15877c478bd9Sstevel@tonic-gate }
15887c478bd9Sstevel@tonic-gate 
15897c478bd9Sstevel@tonic-gate /*
15907c478bd9Sstevel@tonic-gate  * Enable or disable a set of events in the process-global event mask,
15917c478bd9Sstevel@tonic-gate  * depending on the value of onoff.
15927c478bd9Sstevel@tonic-gate  */
15937c478bd9Sstevel@tonic-gate static td_err_e
td_ta_mod_event(td_thragent_t * ta_p,td_thr_events_t * events,int onoff)15947c478bd9Sstevel@tonic-gate td_ta_mod_event(td_thragent_t *ta_p, td_thr_events_t *events, int onoff)
15957c478bd9Sstevel@tonic-gate {
15967c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
15977c478bd9Sstevel@tonic-gate 	td_thr_events_t targ_eventset;
15987c478bd9Sstevel@tonic-gate 	td_err_e	return_val;
15997c478bd9Sstevel@tonic-gate 
16007c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_ta(ta_p, &return_val)) == NULL)
16017c478bd9Sstevel@tonic-gate 		return (return_val);
16027c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
16037c478bd9Sstevel@tonic-gate 		ph_unlock(ta_p);
16047c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
16057c478bd9Sstevel@tonic-gate 	}
16067c478bd9Sstevel@tonic-gate 	if (ps_pdread(ph_p, ta_p->tdb_eventmask_addr,
16077c478bd9Sstevel@tonic-gate 	    &targ_eventset, sizeof (targ_eventset)) != PS_OK)
16087c478bd9Sstevel@tonic-gate 		return_val = TD_DBERR;
16097c478bd9Sstevel@tonic-gate 	else {
16107c478bd9Sstevel@tonic-gate 		if (onoff)
16117c478bd9Sstevel@tonic-gate 			eventsetaddset(&targ_eventset, events);
16127c478bd9Sstevel@tonic-gate 		else
16137c478bd9Sstevel@tonic-gate 			eventsetdelset(&targ_eventset, events);
16147c478bd9Sstevel@tonic-gate 		if (ps_pdwrite(ph_p, ta_p->tdb_eventmask_addr,
16157c478bd9Sstevel@tonic-gate 		    &targ_eventset, sizeof (targ_eventset)) != PS_OK)
16167c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
16177c478bd9Sstevel@tonic-gate 	}
16187c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
16197c478bd9Sstevel@tonic-gate 	ph_unlock(ta_p);
16207c478bd9Sstevel@tonic-gate 	return (return_val);
16217c478bd9Sstevel@tonic-gate }
16227c478bd9Sstevel@tonic-gate 
16237c478bd9Sstevel@tonic-gate /*
16247c478bd9Sstevel@tonic-gate  * Enable a set of events in the process-global event mask.
16257c478bd9Sstevel@tonic-gate  */
16267c478bd9Sstevel@tonic-gate #pragma weak td_ta_set_event = __td_ta_set_event
16277c478bd9Sstevel@tonic-gate td_err_e
__td_ta_set_event(td_thragent_t * ta_p,td_thr_events_t * events)16287c478bd9Sstevel@tonic-gate __td_ta_set_event(td_thragent_t *ta_p, td_thr_events_t *events)
16297c478bd9Sstevel@tonic-gate {
16307c478bd9Sstevel@tonic-gate 	return (td_ta_mod_event(ta_p, events, 1));
16317c478bd9Sstevel@tonic-gate }
16327c478bd9Sstevel@tonic-gate 
16337c478bd9Sstevel@tonic-gate /*
16347c478bd9Sstevel@tonic-gate  * Set event mask to disable the given event set; these events are cleared
16357c478bd9Sstevel@tonic-gate  * from the event mask of the thread.  Events that occur for a thread
16367c478bd9Sstevel@tonic-gate  * with the event masked off will not cause notification to be
16377c478bd9Sstevel@tonic-gate  * sent to the debugger (see td_thr_set_event for fuller description).
16387c478bd9Sstevel@tonic-gate  */
16397c478bd9Sstevel@tonic-gate #pragma weak td_thr_clear_event = __td_thr_clear_event
16407c478bd9Sstevel@tonic-gate td_err_e
__td_thr_clear_event(td_thrhandle_t * th_p,td_thr_events_t * events)16417c478bd9Sstevel@tonic-gate __td_thr_clear_event(td_thrhandle_t *th_p, td_thr_events_t *events)
16427c478bd9Sstevel@tonic-gate {
16437c478bd9Sstevel@tonic-gate 	return (mod_eventset(th_p, events, 0));
16447c478bd9Sstevel@tonic-gate }
16457c478bd9Sstevel@tonic-gate 
16467c478bd9Sstevel@tonic-gate /*
16477c478bd9Sstevel@tonic-gate  * Disable a set of events in the process-global event mask.
16487c478bd9Sstevel@tonic-gate  */
16497c478bd9Sstevel@tonic-gate #pragma weak td_ta_clear_event = __td_ta_clear_event
16507c478bd9Sstevel@tonic-gate td_err_e
__td_ta_clear_event(td_thragent_t * ta_p,td_thr_events_t * events)16517c478bd9Sstevel@tonic-gate __td_ta_clear_event(td_thragent_t *ta_p, td_thr_events_t *events)
16527c478bd9Sstevel@tonic-gate {
16537c478bd9Sstevel@tonic-gate 	return (td_ta_mod_event(ta_p, events, 0));
16547c478bd9Sstevel@tonic-gate }
16557c478bd9Sstevel@tonic-gate 
16567c478bd9Sstevel@tonic-gate /*
16577c478bd9Sstevel@tonic-gate  * This function returns the most recent event message, if any,
16587c478bd9Sstevel@tonic-gate  * associated with a thread.  Given a thread handle, return the message
16597c478bd9Sstevel@tonic-gate  * corresponding to the event encountered by the thread.  Only one
16607c478bd9Sstevel@tonic-gate  * message per thread is saved.  Messages from earlier events are lost
16617c478bd9Sstevel@tonic-gate  * when later events occur.
16627c478bd9Sstevel@tonic-gate  */
16637c478bd9Sstevel@tonic-gate #pragma weak td_thr_event_getmsg = __td_thr_event_getmsg
16647c478bd9Sstevel@tonic-gate td_err_e
__td_thr_event_getmsg(td_thrhandle_t * th_p,td_event_msg_t * msg)16657c478bd9Sstevel@tonic-gate __td_thr_event_getmsg(td_thrhandle_t *th_p, td_event_msg_t *msg)
16667c478bd9Sstevel@tonic-gate {
16677c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
16687c478bd9Sstevel@tonic-gate 	td_err_e	return_val = TD_OK;
16697c478bd9Sstevel@tonic-gate 	psaddr_t	psaddr;
16707c478bd9Sstevel@tonic-gate 
16717c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
16727c478bd9Sstevel@tonic-gate 		return (return_val);
16737c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
16747c478bd9Sstevel@tonic-gate 		ph_unlock(th_p->th_ta_p);
16757c478bd9Sstevel@tonic-gate 		return (TD_BADTA);
16767c478bd9Sstevel@tonic-gate 	}
16777c478bd9Sstevel@tonic-gate 	if (th_p->th_ta_p->model == PR_MODEL_NATIVE) {
16787c478bd9Sstevel@tonic-gate 		ulwp_t *ulwp = (ulwp_t *)th_p->th_unique;
16797c478bd9Sstevel@tonic-gate 		td_evbuf_t evbuf;
16807c478bd9Sstevel@tonic-gate 
16817c478bd9Sstevel@tonic-gate 		psaddr = (psaddr_t)&ulwp->ul_td_evbuf;
16827c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, psaddr, &evbuf, sizeof (evbuf)) != PS_OK) {
16837c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
16847c478bd9Sstevel@tonic-gate 		} else if (evbuf.eventnum == TD_EVENT_NONE) {
16857c478bd9Sstevel@tonic-gate 			return_val = TD_NOEVENT;
16867c478bd9Sstevel@tonic-gate 		} else {
16877c478bd9Sstevel@tonic-gate 			msg->event = evbuf.eventnum;
16887c478bd9Sstevel@tonic-gate 			msg->th_p = (td_thrhandle_t *)th_p;
16897c478bd9Sstevel@tonic-gate 			msg->msg.data = (uintptr_t)evbuf.eventdata;
16907c478bd9Sstevel@tonic-gate 			/* "Consume" the message */
16917c478bd9Sstevel@tonic-gate 			evbuf.eventnum = TD_EVENT_NONE;
16927c478bd9Sstevel@tonic-gate 			evbuf.eventdata = NULL;
16937c478bd9Sstevel@tonic-gate 			if (ps_pdwrite(ph_p, psaddr, &evbuf, sizeof (evbuf))
16947c478bd9Sstevel@tonic-gate 			    != PS_OK)
16957c478bd9Sstevel@tonic-gate 				return_val = TD_DBERR;
16967c478bd9Sstevel@tonic-gate 		}
16977c478bd9Sstevel@tonic-gate 	} else {
16987c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
16997c478bd9Sstevel@tonic-gate 		ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique;
17007c478bd9Sstevel@tonic-gate 		td_evbuf32_t evbuf;
17017c478bd9Sstevel@tonic-gate 
17027c478bd9Sstevel@tonic-gate 		psaddr = (psaddr_t)&ulwp->ul_td_evbuf;
17037c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, psaddr, &evbuf, sizeof (evbuf)) != PS_OK) {
17047c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
17057c478bd9Sstevel@tonic-gate 		} else if (evbuf.eventnum == TD_EVENT_NONE) {
17067c478bd9Sstevel@tonic-gate 			return_val = TD_NOEVENT;
17077c478bd9Sstevel@tonic-gate 		} else {
17087c478bd9Sstevel@tonic-gate 			msg->event = evbuf.eventnum;
17097c478bd9Sstevel@tonic-gate 			msg->th_p = (td_thrhandle_t *)th_p;
17107c478bd9Sstevel@tonic-gate 			msg->msg.data = (uintptr_t)evbuf.eventdata;
17117c478bd9Sstevel@tonic-gate 			/* "Consume" the message */
17127c478bd9Sstevel@tonic-gate 			evbuf.eventnum = TD_EVENT_NONE;
1713c3e74f84SToomas Soome 			evbuf.eventdata = 0;
17147c478bd9Sstevel@tonic-gate 			if (ps_pdwrite(ph_p, psaddr, &evbuf, sizeof (evbuf))
17157c478bd9Sstevel@tonic-gate 			    != PS_OK)
17167c478bd9Sstevel@tonic-gate 				return_val = TD_DBERR;
17177c478bd9Sstevel@tonic-gate 		}
17187c478bd9Sstevel@tonic-gate #else
17197c478bd9Sstevel@tonic-gate 		return_val = TD_ERR;
17207c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
17217c478bd9Sstevel@tonic-gate 	}
17227c478bd9Sstevel@tonic-gate 
17237c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
17247c478bd9Sstevel@tonic-gate 	ph_unlock(th_p->th_ta_p);
17257c478bd9Sstevel@tonic-gate 	return (return_val);
17267c478bd9Sstevel@tonic-gate }
17277c478bd9Sstevel@tonic-gate 
17287c478bd9Sstevel@tonic-gate /*
17297c478bd9Sstevel@tonic-gate  * The callback function td_ta_event_getmsg uses when looking for
17307c478bd9Sstevel@tonic-gate  * a thread with an event.  A thin wrapper around td_thr_event_getmsg.
17317c478bd9Sstevel@tonic-gate  */
17327c478bd9Sstevel@tonic-gate static int
event_msg_cb(const td_thrhandle_t * th_p,void * arg)17337c478bd9Sstevel@tonic-gate event_msg_cb(const td_thrhandle_t *th_p, void *arg)
17347c478bd9Sstevel@tonic-gate {
17357c478bd9Sstevel@tonic-gate 	static td_thrhandle_t th;
17367c478bd9Sstevel@tonic-gate 	td_event_msg_t *msg = arg;
17377c478bd9Sstevel@tonic-gate 
17387c478bd9Sstevel@tonic-gate 	if (__td_thr_event_getmsg((td_thrhandle_t *)th_p, msg) == TD_OK) {
17397c478bd9Sstevel@tonic-gate 		/*
17407c478bd9Sstevel@tonic-gate 		 * Got an event, stop iterating.
17417c478bd9Sstevel@tonic-gate 		 *
17427c478bd9Sstevel@tonic-gate 		 * Because of past mistakes in interface definition,
17437c478bd9Sstevel@tonic-gate 		 * we are forced to pass back a static local variable
17447c478bd9Sstevel@tonic-gate 		 * for the thread handle because th_p is a pointer
17457c478bd9Sstevel@tonic-gate 		 * to a local variable in __td_ta_thr_iter().
17467c478bd9Sstevel@tonic-gate 		 * Grr...
17477c478bd9Sstevel@tonic-gate 		 */
17487c478bd9Sstevel@tonic-gate 		th = *th_p;
17497c478bd9Sstevel@tonic-gate 		msg->th_p = &th;
17507c478bd9Sstevel@tonic-gate 		return (1);
17517c478bd9Sstevel@tonic-gate 	}
17527c478bd9Sstevel@tonic-gate 	return (0);
17537c478bd9Sstevel@tonic-gate }
17547c478bd9Sstevel@tonic-gate 
17557c478bd9Sstevel@tonic-gate /*
17567c478bd9Sstevel@tonic-gate  * This function is just like td_thr_event_getmsg, except that it is
17577c478bd9Sstevel@tonic-gate  * passed a process handle rather than a thread handle, and returns
17587c478bd9Sstevel@tonic-gate  * an event message for some thread in the process that has an event
17597c478bd9Sstevel@tonic-gate  * message pending.  If no thread has an event message pending, this
17607c478bd9Sstevel@tonic-gate  * routine returns TD_NOEVENT.  Thus, all pending event messages may
17617c478bd9Sstevel@tonic-gate  * be collected from a process by repeatedly calling this routine
17627c478bd9Sstevel@tonic-gate  * until it returns TD_NOEVENT.
17637c478bd9Sstevel@tonic-gate  */
17647c478bd9Sstevel@tonic-gate #pragma weak td_ta_event_getmsg = __td_ta_event_getmsg
17657c478bd9Sstevel@tonic-gate td_err_e
__td_ta_event_getmsg(td_thragent_t * ta_p,td_event_msg_t * msg)17667c478bd9Sstevel@tonic-gate __td_ta_event_getmsg(td_thragent_t *ta_p, td_event_msg_t *msg)
17677c478bd9Sstevel@tonic-gate {
17687c478bd9Sstevel@tonic-gate 	td_err_e return_val;
17697c478bd9Sstevel@tonic-gate 
17707c478bd9Sstevel@tonic-gate 	if (ta_p == NULL)
17717c478bd9Sstevel@tonic-gate 		return (TD_BADTA);
17727c478bd9Sstevel@tonic-gate 	if (ta_p->ph_p == NULL)
17737c478bd9Sstevel@tonic-gate 		return (TD_BADPH);
17747c478bd9Sstevel@tonic-gate 	if (msg == NULL)
17757c478bd9Sstevel@tonic-gate 		return (TD_ERR);
17767c478bd9Sstevel@tonic-gate 	msg->event = TD_EVENT_NONE;
17777c478bd9Sstevel@tonic-gate 	if ((return_val = __td_ta_thr_iter(ta_p, event_msg_cb, msg,
17787c478bd9Sstevel@tonic-gate 	    TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK,
17797c478bd9Sstevel@tonic-gate 	    TD_THR_ANY_USER_FLAGS)) != TD_OK)
17807c478bd9Sstevel@tonic-gate 		return (return_val);
17817c478bd9Sstevel@tonic-gate 	if (msg->event == TD_EVENT_NONE)
17827c478bd9Sstevel@tonic-gate 		return (TD_NOEVENT);
17837c478bd9Sstevel@tonic-gate 	return (TD_OK);
17847c478bd9Sstevel@tonic-gate }
17857c478bd9Sstevel@tonic-gate 
17867c478bd9Sstevel@tonic-gate static lwpid_t
thr_to_lwpid(const td_thrhandle_t * th_p)17877c478bd9Sstevel@tonic-gate thr_to_lwpid(const td_thrhandle_t *th_p)
17887c478bd9Sstevel@tonic-gate {
17897c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p = th_p->th_ta_p->ph_p;
17907c478bd9Sstevel@tonic-gate 	lwpid_t lwpid;
17917c478bd9Sstevel@tonic-gate 
17927c478bd9Sstevel@tonic-gate 	/*
17937c478bd9Sstevel@tonic-gate 	 * The caller holds the prochandle lock
17947c478bd9Sstevel@tonic-gate 	 * and has already verfied everything.
17957c478bd9Sstevel@tonic-gate 	 */
17967c478bd9Sstevel@tonic-gate 	if (th_p->th_ta_p->model == PR_MODEL_NATIVE) {
17977c478bd9Sstevel@tonic-gate 		ulwp_t *ulwp = (ulwp_t *)th_p->th_unique;
17987c478bd9Sstevel@tonic-gate 
17997c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_lwpid,
18007c478bd9Sstevel@tonic-gate 		    &lwpid, sizeof (lwpid)) != PS_OK)
18017c478bd9Sstevel@tonic-gate 			lwpid = 0;
18027c478bd9Sstevel@tonic-gate 		else if (lwpid == 0)
18037c478bd9Sstevel@tonic-gate 			lwpid = 1;
18047c478bd9Sstevel@tonic-gate 	} else {
18057c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
18067c478bd9Sstevel@tonic-gate 		ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique;
18077c478bd9Sstevel@tonic-gate 
18087c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_lwpid,
18097c478bd9Sstevel@tonic-gate 		    &lwpid, sizeof (lwpid)) != PS_OK)
18107c478bd9Sstevel@tonic-gate 			lwpid = 0;
18117c478bd9Sstevel@tonic-gate 		else if (lwpid == 0)
18127c478bd9Sstevel@tonic-gate 			lwpid = 1;
18137c478bd9Sstevel@tonic-gate #else
18147c478bd9Sstevel@tonic-gate 		lwpid = 0;
18157c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
18167c478bd9Sstevel@tonic-gate 	}
18177c478bd9Sstevel@tonic-gate 
18187c478bd9Sstevel@tonic-gate 	return (lwpid);
18197c478bd9Sstevel@tonic-gate }
18207c478bd9Sstevel@tonic-gate 
18217c478bd9Sstevel@tonic-gate /*
18227c478bd9Sstevel@tonic-gate  * Suspend a thread.
18237c478bd9Sstevel@tonic-gate  * XXX: What does this mean in a one-level model?
18247c478bd9Sstevel@tonic-gate  */
18257c478bd9Sstevel@tonic-gate #pragma weak td_thr_dbsuspend = __td_thr_dbsuspend
18267c478bd9Sstevel@tonic-gate td_err_e
__td_thr_dbsuspend(const td_thrhandle_t * th_p)18277c478bd9Sstevel@tonic-gate __td_thr_dbsuspend(const td_thrhandle_t *th_p)
18287c478bd9Sstevel@tonic-gate {
18297c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
18307c478bd9Sstevel@tonic-gate 	td_err_e return_val;
18317c478bd9Sstevel@tonic-gate 
18327c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
18337c478bd9Sstevel@tonic-gate 		return (return_val);
18347c478bd9Sstevel@tonic-gate 	if (ps_lstop(ph_p, thr_to_lwpid(th_p)) != PS_OK)
18357c478bd9Sstevel@tonic-gate 		return_val = TD_DBERR;
18367c478bd9Sstevel@tonic-gate 	ph_unlock(th_p->th_ta_p);
18377c478bd9Sstevel@tonic-gate 	return (return_val);
18387c478bd9Sstevel@tonic-gate }
18397c478bd9Sstevel@tonic-gate 
18407c478bd9Sstevel@tonic-gate /*
18417c478bd9Sstevel@tonic-gate  * Resume a suspended thread.
18427c478bd9Sstevel@tonic-gate  * XXX: What does this mean in a one-level model?
18437c478bd9Sstevel@tonic-gate  */
18447c478bd9Sstevel@tonic-gate #pragma weak td_thr_dbresume = __td_thr_dbresume
18457c478bd9Sstevel@tonic-gate td_err_e
__td_thr_dbresume(const td_thrhandle_t * th_p)18467c478bd9Sstevel@tonic-gate __td_thr_dbresume(const td_thrhandle_t *th_p)
18477c478bd9Sstevel@tonic-gate {
18487c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
18497c478bd9Sstevel@tonic-gate 	td_err_e return_val;
18507c478bd9Sstevel@tonic-gate 
18517c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
18527c478bd9Sstevel@tonic-gate 		return (return_val);
18537c478bd9Sstevel@tonic-gate 	if (ps_lcontinue(ph_p, thr_to_lwpid(th_p)) != PS_OK)
18547c478bd9Sstevel@tonic-gate 		return_val = TD_DBERR;
18557c478bd9Sstevel@tonic-gate 	ph_unlock(th_p->th_ta_p);
18567c478bd9Sstevel@tonic-gate 	return (return_val);
18577c478bd9Sstevel@tonic-gate }
18587c478bd9Sstevel@tonic-gate 
18597c478bd9Sstevel@tonic-gate /*
18607c478bd9Sstevel@tonic-gate  * Set a thread's signal mask.
18617c478bd9Sstevel@tonic-gate  * Currently unused by dbx.
18627c478bd9Sstevel@tonic-gate  */
18637c478bd9Sstevel@tonic-gate #pragma weak td_thr_sigsetmask = __td_thr_sigsetmask
18647c478bd9Sstevel@tonic-gate /* ARGSUSED */
18657c478bd9Sstevel@tonic-gate td_err_e
__td_thr_sigsetmask(const td_thrhandle_t * th_p,const sigset_t ti_sigmask)18667c478bd9Sstevel@tonic-gate __td_thr_sigsetmask(const td_thrhandle_t *th_p, const sigset_t ti_sigmask)
18677c478bd9Sstevel@tonic-gate {
18687c478bd9Sstevel@tonic-gate 	return (TD_NOCAPAB);
18697c478bd9Sstevel@tonic-gate }
18707c478bd9Sstevel@tonic-gate 
18717c478bd9Sstevel@tonic-gate /*
18727c478bd9Sstevel@tonic-gate  * Set a thread's "signals-pending" set.
18737c478bd9Sstevel@tonic-gate  * Currently unused by dbx.
18747c478bd9Sstevel@tonic-gate  */
18757c478bd9Sstevel@tonic-gate #pragma weak td_thr_setsigpending = __td_thr_setsigpending
18767c478bd9Sstevel@tonic-gate /* ARGSUSED */
18777c478bd9Sstevel@tonic-gate td_err_e
__td_thr_setsigpending(const td_thrhandle_t * th_p,uchar_t ti_pending_flag,const sigset_t ti_pending)18787c478bd9Sstevel@tonic-gate __td_thr_setsigpending(const td_thrhandle_t *th_p,
1879c3e74f84SToomas Soome     uchar_t ti_pending_flag, const sigset_t ti_pending)
18807c478bd9Sstevel@tonic-gate {
18817c478bd9Sstevel@tonic-gate 	return (TD_NOCAPAB);
18827c478bd9Sstevel@tonic-gate }
18837c478bd9Sstevel@tonic-gate 
18847c478bd9Sstevel@tonic-gate /*
18857c478bd9Sstevel@tonic-gate  * Get a thread's general register set.
18867c478bd9Sstevel@tonic-gate  */
18877c478bd9Sstevel@tonic-gate #pragma weak td_thr_getgregs = __td_thr_getgregs
18887c478bd9Sstevel@tonic-gate td_err_e
__td_thr_getgregs(td_thrhandle_t * th_p,prgregset_t regset)18897c478bd9Sstevel@tonic-gate __td_thr_getgregs(td_thrhandle_t *th_p, prgregset_t regset)
18907c478bd9Sstevel@tonic-gate {
18917c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
18927c478bd9Sstevel@tonic-gate 	td_err_e return_val;
18937c478bd9Sstevel@tonic-gate 
18947c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
18957c478bd9Sstevel@tonic-gate 		return (return_val);
18967c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
18977c478bd9Sstevel@tonic-gate 		ph_unlock(th_p->th_ta_p);
18987c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
18997c478bd9Sstevel@tonic-gate 	}
19007c478bd9Sstevel@tonic-gate 
19017c478bd9Sstevel@tonic-gate 	if (ps_lgetregs(ph_p, thr_to_lwpid(th_p), regset) != PS_OK)
19027c478bd9Sstevel@tonic-gate 		return_val = TD_DBERR;
19037c478bd9Sstevel@tonic-gate 
19047c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
19057c478bd9Sstevel@tonic-gate 	ph_unlock(th_p->th_ta_p);
19067c478bd9Sstevel@tonic-gate 	return (return_val);
19077c478bd9Sstevel@tonic-gate }
19087c478bd9Sstevel@tonic-gate 
19097c478bd9Sstevel@tonic-gate /*
19107c478bd9Sstevel@tonic-gate  * Set a thread's general register set.
19117c478bd9Sstevel@tonic-gate  */
19127c478bd9Sstevel@tonic-gate #pragma weak td_thr_setgregs = __td_thr_setgregs
19137c478bd9Sstevel@tonic-gate td_err_e
__td_thr_setgregs(td_thrhandle_t * th_p,const prgregset_t regset)19147c478bd9Sstevel@tonic-gate __td_thr_setgregs(td_thrhandle_t *th_p, const prgregset_t regset)
19157c478bd9Sstevel@tonic-gate {
19167c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
19177c478bd9Sstevel@tonic-gate 	td_err_e return_val;
19187c478bd9Sstevel@tonic-gate 
19197c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
19207c478bd9Sstevel@tonic-gate 		return (return_val);
19217c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
19227c478bd9Sstevel@tonic-gate 		ph_unlock(th_p->th_ta_p);
19237c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
19247c478bd9Sstevel@tonic-gate 	}
19257c478bd9Sstevel@tonic-gate 
19267c478bd9Sstevel@tonic-gate 	if (ps_lsetregs(ph_p, thr_to_lwpid(th_p), regset) != PS_OK)
19277c478bd9Sstevel@tonic-gate 		return_val = TD_DBERR;
19287c478bd9Sstevel@tonic-gate 
19297c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
19307c478bd9Sstevel@tonic-gate 	ph_unlock(th_p->th_ta_p);
19317c478bd9Sstevel@tonic-gate 	return (return_val);
19327c478bd9Sstevel@tonic-gate }
19337c478bd9Sstevel@tonic-gate 
19347c478bd9Sstevel@tonic-gate /*
19357c478bd9Sstevel@tonic-gate  * Get a thread's floating-point register set.
19367c478bd9Sstevel@tonic-gate  */
19377c478bd9Sstevel@tonic-gate #pragma weak td_thr_getfpregs = __td_thr_getfpregs
19387c478bd9Sstevel@tonic-gate td_err_e
__td_thr_getfpregs(td_thrhandle_t * th_p,prfpregset_t * fpregset)19397c478bd9Sstevel@tonic-gate __td_thr_getfpregs(td_thrhandle_t *th_p, prfpregset_t *fpregset)
19407c478bd9Sstevel@tonic-gate {
19417c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
19427c478bd9Sstevel@tonic-gate 	td_err_e return_val;
19437c478bd9Sstevel@tonic-gate 
19447c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
19457c478bd9Sstevel@tonic-gate 		return (return_val);
19467c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
19477c478bd9Sstevel@tonic-gate 		ph_unlock(th_p->th_ta_p);
19487c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
19497c478bd9Sstevel@tonic-gate 	}
19507c478bd9Sstevel@tonic-gate 
19517c478bd9Sstevel@tonic-gate 	if (ps_lgetfpregs(ph_p, thr_to_lwpid(th_p), fpregset) != PS_OK)
19527c478bd9Sstevel@tonic-gate 		return_val = TD_DBERR;
19537c478bd9Sstevel@tonic-gate 
19547c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
19557c478bd9Sstevel@tonic-gate 	ph_unlock(th_p->th_ta_p);
19567c478bd9Sstevel@tonic-gate 	return (return_val);
19577c478bd9Sstevel@tonic-gate }
19587c478bd9Sstevel@tonic-gate 
19597c478bd9Sstevel@tonic-gate /*
19607c478bd9Sstevel@tonic-gate  * Set a thread's floating-point register set.
19617c478bd9Sstevel@tonic-gate  */
19627c478bd9Sstevel@tonic-gate #pragma weak td_thr_setfpregs = __td_thr_setfpregs
19637c478bd9Sstevel@tonic-gate td_err_e
__td_thr_setfpregs(td_thrhandle_t * th_p,const prfpregset_t * fpregset)19647c478bd9Sstevel@tonic-gate __td_thr_setfpregs(td_thrhandle_t *th_p, const prfpregset_t *fpregset)
19657c478bd9Sstevel@tonic-gate {
19667c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
19677c478bd9Sstevel@tonic-gate 	td_err_e return_val;
19687c478bd9Sstevel@tonic-gate 
19697c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
19707c478bd9Sstevel@tonic-gate 		return (return_val);
19717c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
19727c478bd9Sstevel@tonic-gate 		ph_unlock(th_p->th_ta_p);
19737c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
19747c478bd9Sstevel@tonic-gate 	}
19757c478bd9Sstevel@tonic-gate 
19767c478bd9Sstevel@tonic-gate 	if (ps_lsetfpregs(ph_p, thr_to_lwpid(th_p), fpregset) != PS_OK)
19777c478bd9Sstevel@tonic-gate 		return_val = TD_DBERR;
19787c478bd9Sstevel@tonic-gate 
19797c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
19807c478bd9Sstevel@tonic-gate 	ph_unlock(th_p->th_ta_p);
19817c478bd9Sstevel@tonic-gate 	return (return_val);
19827c478bd9Sstevel@tonic-gate }
19837c478bd9Sstevel@tonic-gate 
19847c478bd9Sstevel@tonic-gate /*
19857c478bd9Sstevel@tonic-gate  * Get the size of the extra state register set for this architecture.
19867c478bd9Sstevel@tonic-gate  * Currently unused by dbx.
19877c478bd9Sstevel@tonic-gate  */
19887c478bd9Sstevel@tonic-gate #pragma weak td_thr_getxregsize = __td_thr_getxregsize
19897c478bd9Sstevel@tonic-gate /* ARGSUSED */
19907c478bd9Sstevel@tonic-gate td_err_e
__td_thr_getxregsize(td_thrhandle_t * th_p,int * xregsize)19917c478bd9Sstevel@tonic-gate __td_thr_getxregsize(td_thrhandle_t *th_p, int *xregsize)
19927c478bd9Sstevel@tonic-gate {
19937c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
19947c478bd9Sstevel@tonic-gate 	td_err_e return_val;
19957c478bd9Sstevel@tonic-gate 
19967c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
19977c478bd9Sstevel@tonic-gate 		return (return_val);
19987c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
19997c478bd9Sstevel@tonic-gate 		ph_unlock(th_p->th_ta_p);
20007c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
20017c478bd9Sstevel@tonic-gate 	}
20027c478bd9Sstevel@tonic-gate 
20037c478bd9Sstevel@tonic-gate 	if (ps_lgetxregsize(ph_p, thr_to_lwpid(th_p), xregsize) != PS_OK)
20047c478bd9Sstevel@tonic-gate 		return_val = TD_DBERR;
20057c478bd9Sstevel@tonic-gate 
2006*ed093b41SRobert Mustacchi 	if (*xregsize == 0)
2007*ed093b41SRobert Mustacchi 		return_val = TD_NOXREGS;
2008*ed093b41SRobert Mustacchi 
20097c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
20107c478bd9Sstevel@tonic-gate 	ph_unlock(th_p->th_ta_p);
20117c478bd9Sstevel@tonic-gate 	return (return_val);
20127c478bd9Sstevel@tonic-gate }
20137c478bd9Sstevel@tonic-gate 
20147c478bd9Sstevel@tonic-gate /*
20157c478bd9Sstevel@tonic-gate  * Get a thread's extra state register set.
20167c478bd9Sstevel@tonic-gate  */
20177c478bd9Sstevel@tonic-gate #pragma weak td_thr_getxregs = __td_thr_getxregs
20187c478bd9Sstevel@tonic-gate td_err_e
__td_thr_getxregs(td_thrhandle_t * th_p,void * xregset)20197c478bd9Sstevel@tonic-gate __td_thr_getxregs(td_thrhandle_t *th_p, void *xregset)
20207c478bd9Sstevel@tonic-gate {
20217c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
20227c478bd9Sstevel@tonic-gate 	td_err_e return_val;
2023*ed093b41SRobert Mustacchi 	ps_err_e ps_err;
20247c478bd9Sstevel@tonic-gate 
20257c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
20267c478bd9Sstevel@tonic-gate 		return (return_val);
20277c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
20287c478bd9Sstevel@tonic-gate 		ph_unlock(th_p->th_ta_p);
20297c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
20307c478bd9Sstevel@tonic-gate 	}
20317c478bd9Sstevel@tonic-gate 
2032*ed093b41SRobert Mustacchi 	ps_err = ps_lgetxregs(ph_p, thr_to_lwpid(th_p), (caddr_t)xregset);
2033*ed093b41SRobert Mustacchi 	if (ps_err == PS_NOXREGS)
2034*ed093b41SRobert Mustacchi 		return_val = TD_NOXREGS;
2035*ed093b41SRobert Mustacchi 	else if (ps_err != PS_OK)
20367c478bd9Sstevel@tonic-gate 		return_val = TD_DBERR;
20377c478bd9Sstevel@tonic-gate 
20387c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
20397c478bd9Sstevel@tonic-gate 	ph_unlock(th_p->th_ta_p);
20407c478bd9Sstevel@tonic-gate 	return (return_val);
20417c478bd9Sstevel@tonic-gate }
20427c478bd9Sstevel@tonic-gate 
20437c478bd9Sstevel@tonic-gate /*
20447c478bd9Sstevel@tonic-gate  * Set a thread's extra state register set.
20457c478bd9Sstevel@tonic-gate  */
20467c478bd9Sstevel@tonic-gate #pragma weak td_thr_setxregs = __td_thr_setxregs
20477c478bd9Sstevel@tonic-gate td_err_e
__td_thr_setxregs(td_thrhandle_t * th_p,const void * xregset)20487c478bd9Sstevel@tonic-gate __td_thr_setxregs(td_thrhandle_t *th_p, const void *xregset)
20497c478bd9Sstevel@tonic-gate {
20507c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
20517c478bd9Sstevel@tonic-gate 	td_err_e return_val;
20527c478bd9Sstevel@tonic-gate 
20537c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
20547c478bd9Sstevel@tonic-gate 		return (return_val);
20557c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
20567c478bd9Sstevel@tonic-gate 		ph_unlock(th_p->th_ta_p);
20577c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
20587c478bd9Sstevel@tonic-gate 	}
20597c478bd9Sstevel@tonic-gate 
20607c478bd9Sstevel@tonic-gate 	if (ps_lsetxregs(ph_p, thr_to_lwpid(th_p), (caddr_t)xregset) != PS_OK)
20617c478bd9Sstevel@tonic-gate 		return_val = TD_DBERR;
20627c478bd9Sstevel@tonic-gate 
20637c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
20647c478bd9Sstevel@tonic-gate 	ph_unlock(th_p->th_ta_p);
20657c478bd9Sstevel@tonic-gate 	return (return_val);
20667c478bd9Sstevel@tonic-gate }
20677c478bd9Sstevel@tonic-gate 
20687c478bd9Sstevel@tonic-gate struct searcher {
20697c478bd9Sstevel@tonic-gate 	psaddr_t	addr;
20707c478bd9Sstevel@tonic-gate 	int		status;
20717c478bd9Sstevel@tonic-gate };
20727c478bd9Sstevel@tonic-gate 
20737c478bd9Sstevel@tonic-gate /*
20747c478bd9Sstevel@tonic-gate  * Check the struct thread address in *th_p again first
20757c478bd9Sstevel@tonic-gate  * value in "data".  If value in data is found, set second value
20767c478bd9Sstevel@tonic-gate  * in "data" to 1 and return 1 to terminate iterations.
20777c478bd9Sstevel@tonic-gate  * This function is used by td_thr_validate() to verify that
20787c478bd9Sstevel@tonic-gate  * a thread handle is valid.
20797c478bd9Sstevel@tonic-gate  */
20807c478bd9Sstevel@tonic-gate static int
td_searcher(const td_thrhandle_t * th_p,void * data)20817c478bd9Sstevel@tonic-gate td_searcher(const td_thrhandle_t *th_p, void *data)
20827c478bd9Sstevel@tonic-gate {
20837c478bd9Sstevel@tonic-gate 	struct searcher *searcher_data = (struct searcher *)data;
20847c478bd9Sstevel@tonic-gate 
20857c478bd9Sstevel@tonic-gate 	if (searcher_data->addr == th_p->th_unique) {
20867c478bd9Sstevel@tonic-gate 		searcher_data->status = 1;
20877c478bd9Sstevel@tonic-gate 		return (1);
20887c478bd9Sstevel@tonic-gate 	}
20897c478bd9Sstevel@tonic-gate 	return (0);
20907c478bd9Sstevel@tonic-gate }
20917c478bd9Sstevel@tonic-gate 
20927c478bd9Sstevel@tonic-gate /*
20937c478bd9Sstevel@tonic-gate  * Validate the thread handle.  Check that
20947c478bd9Sstevel@tonic-gate  * a thread exists in the thread agent/process that
20957c478bd9Sstevel@tonic-gate  * corresponds to thread with handle *th_p.
20967c478bd9Sstevel@tonic-gate  * Currently unused by dbx.
20977c478bd9Sstevel@tonic-gate  */
20987c478bd9Sstevel@tonic-gate #pragma weak td_thr_validate = __td_thr_validate
20997c478bd9Sstevel@tonic-gate td_err_e
__td_thr_validate(const td_thrhandle_t * th_p)21007c478bd9Sstevel@tonic-gate __td_thr_validate(const td_thrhandle_t *th_p)
21017c478bd9Sstevel@tonic-gate {
21027c478bd9Sstevel@tonic-gate 	td_err_e return_val;
21037c478bd9Sstevel@tonic-gate 	struct searcher searcher_data = {0, 0};
21047c478bd9Sstevel@tonic-gate 
21057c478bd9Sstevel@tonic-gate 	if (th_p == NULL)
21067c478bd9Sstevel@tonic-gate 		return (TD_BADTH);
2107c3e74f84SToomas Soome 	if (th_p->th_unique == 0 || th_p->th_ta_p == NULL)
21087c478bd9Sstevel@tonic-gate 		return (TD_BADTH);
21097c478bd9Sstevel@tonic-gate 
21107c478bd9Sstevel@tonic-gate 	/*
21117c478bd9Sstevel@tonic-gate 	 * LOCKING EXCEPTION - Locking is not required
21127c478bd9Sstevel@tonic-gate 	 * here because no use of the thread agent is made (other
21137c478bd9Sstevel@tonic-gate 	 * than the sanity check) and checking of the thread
21147c478bd9Sstevel@tonic-gate 	 * agent will be done in __td_ta_thr_iter.
21157c478bd9Sstevel@tonic-gate 	 */
21167c478bd9Sstevel@tonic-gate 
21177c478bd9Sstevel@tonic-gate 	searcher_data.addr = th_p->th_unique;
21187c478bd9Sstevel@tonic-gate 	return_val = __td_ta_thr_iter(th_p->th_ta_p,
2119d4204c85Sraf 	    td_searcher, &searcher_data,
2120d4204c85Sraf 	    TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
2121d4204c85Sraf 	    TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
21227c478bd9Sstevel@tonic-gate 
21237c478bd9Sstevel@tonic-gate 	if (return_val == TD_OK && searcher_data.status == 0)
21247c478bd9Sstevel@tonic-gate 		return_val = TD_NOTHR;
21257c478bd9Sstevel@tonic-gate 
21267c478bd9Sstevel@tonic-gate 	return (return_val);
21277c478bd9Sstevel@tonic-gate }
21287c478bd9Sstevel@tonic-gate 
21297c478bd9Sstevel@tonic-gate /*
21307c478bd9Sstevel@tonic-gate  * Get a thread's private binding to a given thread specific
2131bbf21555SRichard Lowe  * data(TSD) key(see thr_getspecific(3C).  If the thread doesn't
21327c478bd9Sstevel@tonic-gate  * have a binding for a particular key, then NULL is returned.
21337c478bd9Sstevel@tonic-gate  */
21347c478bd9Sstevel@tonic-gate #pragma weak td_thr_tsd = __td_thr_tsd
21357c478bd9Sstevel@tonic-gate td_err_e
__td_thr_tsd(td_thrhandle_t * th_p,thread_key_t key,void ** data_pp)21367c478bd9Sstevel@tonic-gate __td_thr_tsd(td_thrhandle_t *th_p, thread_key_t key, void **data_pp)
21377c478bd9Sstevel@tonic-gate {
21387c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
21397c478bd9Sstevel@tonic-gate 	td_thragent_t	*ta_p;
21407c478bd9Sstevel@tonic-gate 	td_err_e	return_val;
21417c478bd9Sstevel@tonic-gate 	int		maxkey;
21427c478bd9Sstevel@tonic-gate 	int		nkey;
21437c478bd9Sstevel@tonic-gate 	psaddr_t	tsd_paddr;
21447c478bd9Sstevel@tonic-gate 
21457c478bd9Sstevel@tonic-gate 	if (data_pp == NULL)
21467c478bd9Sstevel@tonic-gate 		return (TD_ERR);
21477c478bd9Sstevel@tonic-gate 	*data_pp = NULL;
21487c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
21497c478bd9Sstevel@tonic-gate 		return (return_val);
21507c478bd9Sstevel@tonic-gate 	ta_p = th_p->th_ta_p;
21517c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
21527c478bd9Sstevel@tonic-gate 		ph_unlock(ta_p);
21537c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
21547c478bd9Sstevel@tonic-gate 	}
21557c478bd9Sstevel@tonic-gate 
21567c478bd9Sstevel@tonic-gate 	if (ta_p->model == PR_MODEL_NATIVE) {
21577c478bd9Sstevel@tonic-gate 		ulwp_t *ulwp = (ulwp_t *)th_p->th_unique;
21587c478bd9Sstevel@tonic-gate 		tsd_metadata_t tsdm;
21597c478bd9Sstevel@tonic-gate 		tsd_t stsd;
21607c478bd9Sstevel@tonic-gate 
21617c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p,
21627c478bd9Sstevel@tonic-gate 		    ta_p->uberdata_addr + offsetof(uberdata_t, tsd_metadata),
21637c478bd9Sstevel@tonic-gate 		    &tsdm, sizeof (tsdm)) != PS_OK)
21647c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
21657c478bd9Sstevel@tonic-gate 		else if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_stsd,
21667c478bd9Sstevel@tonic-gate 		    &tsd_paddr, sizeof (tsd_paddr)) != PS_OK)
21677c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
2168c3e74f84SToomas Soome 		else if (tsd_paddr != 0 &&
21697c478bd9Sstevel@tonic-gate 		    ps_pdread(ph_p, tsd_paddr, &stsd, sizeof (stsd)) != PS_OK)
21707c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
21717c478bd9Sstevel@tonic-gate 		else {
21727c478bd9Sstevel@tonic-gate 			maxkey = tsdm.tsdm_nused;
2173c3e74f84SToomas Soome 			nkey = tsd_paddr == 0 ? TSD_NFAST : stsd.tsd_nalloc;
21747c478bd9Sstevel@tonic-gate 
21757c478bd9Sstevel@tonic-gate 			if (key < TSD_NFAST)
21767c478bd9Sstevel@tonic-gate 				tsd_paddr = (psaddr_t)&ulwp->ul_ftsd[0];
21777c478bd9Sstevel@tonic-gate 		}
21787c478bd9Sstevel@tonic-gate 	} else {
21797c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
21807c478bd9Sstevel@tonic-gate 		ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique;
21817c478bd9Sstevel@tonic-gate 		tsd_metadata32_t tsdm;
21827c478bd9Sstevel@tonic-gate 		tsd32_t stsd;
21837c478bd9Sstevel@tonic-gate 		caddr32_t addr;
21847c478bd9Sstevel@tonic-gate 
21857c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p,
21867c478bd9Sstevel@tonic-gate 		    ta_p->uberdata_addr + offsetof(uberdata32_t, tsd_metadata),
21877c478bd9Sstevel@tonic-gate 		    &tsdm, sizeof (tsdm)) != PS_OK)
21887c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
21897c478bd9Sstevel@tonic-gate 		else if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_stsd,
21907c478bd9Sstevel@tonic-gate 		    &addr, sizeof (addr)) != PS_OK)
21917c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
2192c3e74f84SToomas Soome 		else if (addr != 0 &&
21937c478bd9Sstevel@tonic-gate 		    ps_pdread(ph_p, addr, &stsd, sizeof (stsd)) != PS_OK)
21947c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
21957c478bd9Sstevel@tonic-gate 		else {
21967c478bd9Sstevel@tonic-gate 			maxkey = tsdm.tsdm_nused;
2197c3e74f84SToomas Soome 			nkey = addr == 0 ? TSD_NFAST : stsd.tsd_nalloc;
21987c478bd9Sstevel@tonic-gate 
21997c478bd9Sstevel@tonic-gate 			if (key < TSD_NFAST) {
22007c478bd9Sstevel@tonic-gate 				tsd_paddr = (psaddr_t)&ulwp->ul_ftsd[0];
22017c478bd9Sstevel@tonic-gate 			} else {
22027c478bd9Sstevel@tonic-gate 				tsd_paddr = addr;
22037c478bd9Sstevel@tonic-gate 			}
22047c478bd9Sstevel@tonic-gate 		}
22057c478bd9Sstevel@tonic-gate #else
22067c478bd9Sstevel@tonic-gate 		return_val = TD_ERR;
22077c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
22087c478bd9Sstevel@tonic-gate 	}
22097c478bd9Sstevel@tonic-gate 
22107c478bd9Sstevel@tonic-gate 	if (return_val == TD_OK && (key < 1 || key >= maxkey))
22117c478bd9Sstevel@tonic-gate 		return_val = TD_NOTSD;
22127c478bd9Sstevel@tonic-gate 	if (return_val != TD_OK || key >= nkey) {
22137c478bd9Sstevel@tonic-gate 		/* NULL has already been stored in data_pp */
22147c478bd9Sstevel@tonic-gate 		(void) ps_pcontinue(ph_p);
22157c478bd9Sstevel@tonic-gate 		ph_unlock(ta_p);
22167c478bd9Sstevel@tonic-gate 		return (return_val);
22177c478bd9Sstevel@tonic-gate 	}
22187c478bd9Sstevel@tonic-gate 
22197c478bd9Sstevel@tonic-gate 	/*
22207c478bd9Sstevel@tonic-gate 	 * Read the value from the thread's tsd array.
22217c478bd9Sstevel@tonic-gate 	 */
22227c478bd9Sstevel@tonic-gate 	if (ta_p->model == PR_MODEL_NATIVE) {
22237c478bd9Sstevel@tonic-gate 		void *value;
22247c478bd9Sstevel@tonic-gate 
22257c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, tsd_paddr + key * sizeof (void *),
22267c478bd9Sstevel@tonic-gate 		    &value, sizeof (value)) != PS_OK)
22277c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
22287c478bd9Sstevel@tonic-gate 		else
22297c478bd9Sstevel@tonic-gate 			*data_pp = value;
22307c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
22317c478bd9Sstevel@tonic-gate 	} else {
22327c478bd9Sstevel@tonic-gate 		caddr32_t value32;
22337c478bd9Sstevel@tonic-gate 
22347c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, tsd_paddr + key * sizeof (caddr32_t),
22357c478bd9Sstevel@tonic-gate 		    &value32, sizeof (value32)) != PS_OK)
22367c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
22377c478bd9Sstevel@tonic-gate 		else
22387c478bd9Sstevel@tonic-gate 			*data_pp = (void *)(uintptr_t)value32;
22397c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
22407c478bd9Sstevel@tonic-gate 	}
22417c478bd9Sstevel@tonic-gate 
22427c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
22437c478bd9Sstevel@tonic-gate 	ph_unlock(ta_p);
22447c478bd9Sstevel@tonic-gate 	return (return_val);
22457c478bd9Sstevel@tonic-gate }
22467c478bd9Sstevel@tonic-gate 
22477c478bd9Sstevel@tonic-gate /*
22487c478bd9Sstevel@tonic-gate  * Get the base address of a thread's thread local storage (TLS) block
22497c478bd9Sstevel@tonic-gate  * for the module (executable or shared object) identified by 'moduleid'.
22507c478bd9Sstevel@tonic-gate  */
22517c478bd9Sstevel@tonic-gate #pragma weak td_thr_tlsbase = __td_thr_tlsbase
22527c478bd9Sstevel@tonic-gate td_err_e
__td_thr_tlsbase(td_thrhandle_t * th_p,ulong_t moduleid,psaddr_t * base)22537c478bd9Sstevel@tonic-gate __td_thr_tlsbase(td_thrhandle_t *th_p, ulong_t moduleid, psaddr_t *base)
22547c478bd9Sstevel@tonic-gate {
22557c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
22567c478bd9Sstevel@tonic-gate 	td_thragent_t	*ta_p;
22577c478bd9Sstevel@tonic-gate 	td_err_e	return_val;
22587c478bd9Sstevel@tonic-gate 
22597c478bd9Sstevel@tonic-gate 	if (base == NULL)
22607c478bd9Sstevel@tonic-gate 		return (TD_ERR);
2261c3e74f84SToomas Soome 	*base = 0;
22627c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_th(th_p, &return_val)) == NULL)
22637c478bd9Sstevel@tonic-gate 		return (return_val);
22647c478bd9Sstevel@tonic-gate 	ta_p = th_p->th_ta_p;
22657c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
22667c478bd9Sstevel@tonic-gate 		ph_unlock(ta_p);
22677c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
22687c478bd9Sstevel@tonic-gate 	}
22697c478bd9Sstevel@tonic-gate 
22707c478bd9Sstevel@tonic-gate 	if (ta_p->model == PR_MODEL_NATIVE) {
22717c478bd9Sstevel@tonic-gate 		ulwp_t *ulwp = (ulwp_t *)th_p->th_unique;
22727c478bd9Sstevel@tonic-gate 		tls_metadata_t tls_metadata;
22737c478bd9Sstevel@tonic-gate 		TLS_modinfo tlsmod;
22747c478bd9Sstevel@tonic-gate 		tls_t tls;
22757c478bd9Sstevel@tonic-gate 
22767c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p,
22777c478bd9Sstevel@tonic-gate 		    ta_p->uberdata_addr + offsetof(uberdata_t, tls_metadata),
22787c478bd9Sstevel@tonic-gate 		    &tls_metadata, sizeof (tls_metadata)) != PS_OK)
22797c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
22807c478bd9Sstevel@tonic-gate 		else if (moduleid >= tls_metadata.tls_modinfo.tls_size)
22817c478bd9Sstevel@tonic-gate 			return_val = TD_NOTLS;
22827c478bd9Sstevel@tonic-gate 		else if (ps_pdread(ph_p,
22837c478bd9Sstevel@tonic-gate 		    (psaddr_t)((TLS_modinfo *)
22847c478bd9Sstevel@tonic-gate 		    tls_metadata.tls_modinfo.tls_data + moduleid),
22857c478bd9Sstevel@tonic-gate 		    &tlsmod, sizeof (tlsmod)) != PS_OK)
22867c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
22877c478bd9Sstevel@tonic-gate 		else if (tlsmod.tm_memsz == 0)
22887c478bd9Sstevel@tonic-gate 			return_val = TD_NOTLS;
22897c478bd9Sstevel@tonic-gate 		else if (tlsmod.tm_flags & TM_FLG_STATICTLS)
22907c478bd9Sstevel@tonic-gate 			*base = (psaddr_t)ulwp - tlsmod.tm_stattlsoffset;
22917c478bd9Sstevel@tonic-gate 		else if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_tls,
22927c478bd9Sstevel@tonic-gate 		    &tls, sizeof (tls)) != PS_OK)
22937c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
22947c478bd9Sstevel@tonic-gate 		else if (moduleid >= tls.tls_size)
22957c478bd9Sstevel@tonic-gate 			return_val = TD_TLSDEFER;
22967c478bd9Sstevel@tonic-gate 		else if (ps_pdread(ph_p,
22977c478bd9Sstevel@tonic-gate 		    (psaddr_t)((tls_t *)tls.tls_data + moduleid),
22987c478bd9Sstevel@tonic-gate 		    &tls, sizeof (tls)) != PS_OK)
22997c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
23007c478bd9Sstevel@tonic-gate 		else if (tls.tls_size == 0)
23017c478bd9Sstevel@tonic-gate 			return_val = TD_TLSDEFER;
23027c478bd9Sstevel@tonic-gate 		else
23037c478bd9Sstevel@tonic-gate 			*base = (psaddr_t)tls.tls_data;
23047c478bd9Sstevel@tonic-gate 	} else {
23057c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
23067c478bd9Sstevel@tonic-gate 		ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique;
23077c478bd9Sstevel@tonic-gate 		tls_metadata32_t tls_metadata;
23087c478bd9Sstevel@tonic-gate 		TLS_modinfo32 tlsmod;
23097c478bd9Sstevel@tonic-gate 		tls32_t tls;
23107c478bd9Sstevel@tonic-gate 
23117c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p,
23127c478bd9Sstevel@tonic-gate 		    ta_p->uberdata_addr + offsetof(uberdata32_t, tls_metadata),
23137c478bd9Sstevel@tonic-gate 		    &tls_metadata, sizeof (tls_metadata)) != PS_OK)
23147c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
23157c478bd9Sstevel@tonic-gate 		else if (moduleid >= tls_metadata.tls_modinfo.tls_size)
23167c478bd9Sstevel@tonic-gate 			return_val = TD_NOTLS;
23177c478bd9Sstevel@tonic-gate 		else if (ps_pdread(ph_p,
23187c478bd9Sstevel@tonic-gate 		    (psaddr_t)((TLS_modinfo32 *)
23197c478bd9Sstevel@tonic-gate 		    (uintptr_t)tls_metadata.tls_modinfo.tls_data + moduleid),
23207c478bd9Sstevel@tonic-gate 		    &tlsmod, sizeof (tlsmod)) != PS_OK)
23217c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
23227c478bd9Sstevel@tonic-gate 		else if (tlsmod.tm_memsz == 0)
23237c478bd9Sstevel@tonic-gate 			return_val = TD_NOTLS;
23247c478bd9Sstevel@tonic-gate 		else if (tlsmod.tm_flags & TM_FLG_STATICTLS)
23257c478bd9Sstevel@tonic-gate 			*base = (psaddr_t)ulwp - tlsmod.tm_stattlsoffset;
23267c478bd9Sstevel@tonic-gate 		else if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_tls,
23277c478bd9Sstevel@tonic-gate 		    &tls, sizeof (tls)) != PS_OK)
23287c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
23297c478bd9Sstevel@tonic-gate 		else if (moduleid >= tls.tls_size)
23307c478bd9Sstevel@tonic-gate 			return_val = TD_TLSDEFER;
23317c478bd9Sstevel@tonic-gate 		else if (ps_pdread(ph_p,
23327c478bd9Sstevel@tonic-gate 		    (psaddr_t)((tls32_t *)(uintptr_t)tls.tls_data + moduleid),
23337c478bd9Sstevel@tonic-gate 		    &tls, sizeof (tls)) != PS_OK)
23347c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
23357c478bd9Sstevel@tonic-gate 		else if (tls.tls_size == 0)
23367c478bd9Sstevel@tonic-gate 			return_val = TD_TLSDEFER;
23377c478bd9Sstevel@tonic-gate 		else
23387c478bd9Sstevel@tonic-gate 			*base = (psaddr_t)tls.tls_data;
23397c478bd9Sstevel@tonic-gate #else
23407c478bd9Sstevel@tonic-gate 		return_val = TD_ERR;
23417c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
23427c478bd9Sstevel@tonic-gate 	}
23437c478bd9Sstevel@tonic-gate 
23447c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
23457c478bd9Sstevel@tonic-gate 	ph_unlock(ta_p);
23467c478bd9Sstevel@tonic-gate 	return (return_val);
23477c478bd9Sstevel@tonic-gate }
23487c478bd9Sstevel@tonic-gate 
23497c478bd9Sstevel@tonic-gate /*
23507c478bd9Sstevel@tonic-gate  * Change a thread's priority to the value specified by ti_pri.
23517c478bd9Sstevel@tonic-gate  * Currently unused by dbx.
23527c478bd9Sstevel@tonic-gate  */
23537c478bd9Sstevel@tonic-gate #pragma weak td_thr_setprio = __td_thr_setprio
2354d4204c85Sraf /* ARGSUSED */
23557c478bd9Sstevel@tonic-gate td_err_e
__td_thr_setprio(td_thrhandle_t * th_p,int ti_pri)23567c478bd9Sstevel@tonic-gate __td_thr_setprio(td_thrhandle_t *th_p, int ti_pri)
23577c478bd9Sstevel@tonic-gate {
2358d4204c85Sraf 	return (TD_NOCAPAB);
23597c478bd9Sstevel@tonic-gate }
23607c478bd9Sstevel@tonic-gate 
23617c478bd9Sstevel@tonic-gate /*
23627c478bd9Sstevel@tonic-gate  * This structure links td_thr_lockowner and the lowner_cb callback function.
23637c478bd9Sstevel@tonic-gate  */
23647c478bd9Sstevel@tonic-gate typedef struct {
23657c478bd9Sstevel@tonic-gate 	td_sync_iter_f	*owner_cb;
23667c478bd9Sstevel@tonic-gate 	void		*owner_cb_arg;
23677c478bd9Sstevel@tonic-gate 	td_thrhandle_t	*th_p;
23687c478bd9Sstevel@tonic-gate } lowner_cb_ctl_t;
23697c478bd9Sstevel@tonic-gate 
23707c478bd9Sstevel@tonic-gate static int
lowner_cb(const td_synchandle_t * sh_p,void * arg)23717c478bd9Sstevel@tonic-gate lowner_cb(const td_synchandle_t *sh_p, void *arg)
23727c478bd9Sstevel@tonic-gate {
23737c478bd9Sstevel@tonic-gate 	lowner_cb_ctl_t *ocb = arg;
23747c478bd9Sstevel@tonic-gate 	int trunc = 0;
23757c478bd9Sstevel@tonic-gate 	union {
23767c478bd9Sstevel@tonic-gate 		rwlock_t rwl;
23777c478bd9Sstevel@tonic-gate 		mutex_t mx;
23787c478bd9Sstevel@tonic-gate 	} rw_m;
23797c478bd9Sstevel@tonic-gate 
23807c478bd9Sstevel@tonic-gate 	if (ps_pdread(sh_p->sh_ta_p->ph_p, sh_p->sh_unique,
23817c478bd9Sstevel@tonic-gate 	    &rw_m, sizeof (rw_m)) != PS_OK) {
23827c478bd9Sstevel@tonic-gate 		trunc = 1;
23837c478bd9Sstevel@tonic-gate 		if (ps_pdread(sh_p->sh_ta_p->ph_p, sh_p->sh_unique,
23847c478bd9Sstevel@tonic-gate 		    &rw_m.mx, sizeof (rw_m.mx)) != PS_OK)
23857c478bd9Sstevel@tonic-gate 			return (0);
23867c478bd9Sstevel@tonic-gate 	}
23877c478bd9Sstevel@tonic-gate 	if (rw_m.mx.mutex_magic == MUTEX_MAGIC &&
23887c478bd9Sstevel@tonic-gate 	    rw_m.mx.mutex_owner == ocb->th_p->th_unique)
23897c478bd9Sstevel@tonic-gate 		return ((ocb->owner_cb)(sh_p, ocb->owner_cb_arg));
23907c478bd9Sstevel@tonic-gate 	if (!trunc && rw_m.rwl.magic == RWL_MAGIC) {
23917c478bd9Sstevel@tonic-gate 		mutex_t *rwlock = &rw_m.rwl.mutex;
23927c478bd9Sstevel@tonic-gate 		if (rwlock->mutex_owner == ocb->th_p->th_unique)
23937c478bd9Sstevel@tonic-gate 			return ((ocb->owner_cb)(sh_p, ocb->owner_cb_arg));
23947c478bd9Sstevel@tonic-gate 	}
23957c478bd9Sstevel@tonic-gate 	return (0);
23967c478bd9Sstevel@tonic-gate }
23977c478bd9Sstevel@tonic-gate 
23987c478bd9Sstevel@tonic-gate /*
23997c478bd9Sstevel@tonic-gate  * Iterate over the set of locks owned by a specified thread.
24007c478bd9Sstevel@tonic-gate  * If cb returns a non-zero value, terminate iterations.
24017c478bd9Sstevel@tonic-gate  */
24027c478bd9Sstevel@tonic-gate #pragma weak td_thr_lockowner = __td_thr_lockowner
24037c478bd9Sstevel@tonic-gate td_err_e
__td_thr_lockowner(const td_thrhandle_t * th_p,td_sync_iter_f * cb,void * cb_data)24047c478bd9Sstevel@tonic-gate __td_thr_lockowner(const td_thrhandle_t *th_p, td_sync_iter_f *cb,
2405c3e74f84SToomas Soome     void *cb_data)
24067c478bd9Sstevel@tonic-gate {
24077c478bd9Sstevel@tonic-gate 	td_thragent_t	*ta_p;
24087c478bd9Sstevel@tonic-gate 	td_err_e	return_val;
24097c478bd9Sstevel@tonic-gate 	lowner_cb_ctl_t	lcb;
24107c478bd9Sstevel@tonic-gate 
24117c478bd9Sstevel@tonic-gate 	/*
24127c478bd9Sstevel@tonic-gate 	 * Just sanity checks.
24137c478bd9Sstevel@tonic-gate 	 */
24147c478bd9Sstevel@tonic-gate 	if (ph_lock_th((td_thrhandle_t *)th_p, &return_val) == NULL)
24157c478bd9Sstevel@tonic-gate 		return (return_val);
24167c478bd9Sstevel@tonic-gate 	ta_p = th_p->th_ta_p;
24177c478bd9Sstevel@tonic-gate 	ph_unlock(ta_p);
24187c478bd9Sstevel@tonic-gate 
24197c478bd9Sstevel@tonic-gate 	lcb.owner_cb = cb;
24207c478bd9Sstevel@tonic-gate 	lcb.owner_cb_arg = cb_data;
24217c478bd9Sstevel@tonic-gate 	lcb.th_p = (td_thrhandle_t *)th_p;
24227c478bd9Sstevel@tonic-gate 	return (__td_ta_sync_iter(ta_p, lowner_cb, &lcb));
24237c478bd9Sstevel@tonic-gate }
24247c478bd9Sstevel@tonic-gate 
24257c478bd9Sstevel@tonic-gate /*
24267c478bd9Sstevel@tonic-gate  * If a thread is asleep on a synchronization variable,
24277c478bd9Sstevel@tonic-gate  * then get the synchronization handle.
24287c478bd9Sstevel@tonic-gate  */
24297c478bd9Sstevel@tonic-gate #pragma weak td_thr_sleepinfo = __td_thr_sleepinfo
24307c478bd9Sstevel@tonic-gate td_err_e
__td_thr_sleepinfo(const td_thrhandle_t * th_p,td_synchandle_t * sh_p)24317c478bd9Sstevel@tonic-gate __td_thr_sleepinfo(const td_thrhandle_t *th_p, td_synchandle_t *sh_p)
24327c478bd9Sstevel@tonic-gate {
24337c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
24347c478bd9Sstevel@tonic-gate 	td_err_e	return_val = TD_OK;
24357c478bd9Sstevel@tonic-gate 	uintptr_t	wchan;
24367c478bd9Sstevel@tonic-gate 
24377c478bd9Sstevel@tonic-gate 	if (sh_p == NULL)
24387c478bd9Sstevel@tonic-gate 		return (TD_ERR);
24397c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_th((td_thrhandle_t *)th_p, &return_val)) == NULL)
24407c478bd9Sstevel@tonic-gate 		return (return_val);
24417c478bd9Sstevel@tonic-gate 
24427c478bd9Sstevel@tonic-gate 	/*
24437c478bd9Sstevel@tonic-gate 	 * No need to stop the process for a simple read.
24447c478bd9Sstevel@tonic-gate 	 */
24457c478bd9Sstevel@tonic-gate 	if (th_p->th_ta_p->model == PR_MODEL_NATIVE) {
24467c478bd9Sstevel@tonic-gate 		ulwp_t *ulwp = (ulwp_t *)th_p->th_unique;
24477c478bd9Sstevel@tonic-gate 
24487c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_wchan,
24497c478bd9Sstevel@tonic-gate 		    &wchan, sizeof (wchan)) != PS_OK)
24507c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
24517c478bd9Sstevel@tonic-gate 	} else {
24527c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
24537c478bd9Sstevel@tonic-gate 		ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique;
24547c478bd9Sstevel@tonic-gate 		caddr32_t wchan32;
24557c478bd9Sstevel@tonic-gate 
24567c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_wchan,
24577c478bd9Sstevel@tonic-gate 		    &wchan32, sizeof (wchan32)) != PS_OK)
24587c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
24597c478bd9Sstevel@tonic-gate 		wchan = wchan32;
24607c478bd9Sstevel@tonic-gate #else
24617c478bd9Sstevel@tonic-gate 		return_val = TD_ERR;
24627c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
24637c478bd9Sstevel@tonic-gate 	}
24647c478bd9Sstevel@tonic-gate 
2465c3e74f84SToomas Soome 	if (return_val != TD_OK || wchan == 0) {
24667c478bd9Sstevel@tonic-gate 		sh_p->sh_ta_p = NULL;
2467c3e74f84SToomas Soome 		sh_p->sh_unique = 0;
24687c478bd9Sstevel@tonic-gate 		if (return_val == TD_OK)
24697c478bd9Sstevel@tonic-gate 			return_val = TD_ERR;
24707c478bd9Sstevel@tonic-gate 	} else {
24717c478bd9Sstevel@tonic-gate 		sh_p->sh_ta_p = th_p->th_ta_p;
24727c478bd9Sstevel@tonic-gate 		sh_p->sh_unique = (psaddr_t)wchan;
24737c478bd9Sstevel@tonic-gate 	}
24747c478bd9Sstevel@tonic-gate 
24757c478bd9Sstevel@tonic-gate 	ph_unlock(th_p->th_ta_p);
24767c478bd9Sstevel@tonic-gate 	return (return_val);
24777c478bd9Sstevel@tonic-gate }
24787c478bd9Sstevel@tonic-gate 
24797c478bd9Sstevel@tonic-gate /*
24807c478bd9Sstevel@tonic-gate  * Which thread is running on an lwp?
24817c478bd9Sstevel@tonic-gate  */
24827c478bd9Sstevel@tonic-gate #pragma weak td_ta_map_lwp2thr = __td_ta_map_lwp2thr
24837c478bd9Sstevel@tonic-gate td_err_e
__td_ta_map_lwp2thr(td_thragent_t * ta_p,lwpid_t lwpid,td_thrhandle_t * th_p)24847c478bd9Sstevel@tonic-gate __td_ta_map_lwp2thr(td_thragent_t *ta_p, lwpid_t lwpid,
2485c3e74f84SToomas Soome     td_thrhandle_t *th_p)
24867c478bd9Sstevel@tonic-gate {
24877c478bd9Sstevel@tonic-gate 	return (__td_ta_map_id2thr(ta_p, lwpid, th_p));
24887c478bd9Sstevel@tonic-gate }
24897c478bd9Sstevel@tonic-gate 
24907c478bd9Sstevel@tonic-gate /*
24917c478bd9Sstevel@tonic-gate  * Common code for td_sync_get_info() and td_sync_get_stats()
24927c478bd9Sstevel@tonic-gate  */
24937c478bd9Sstevel@tonic-gate static td_err_e
sync_get_info_common(const td_synchandle_t * sh_p,struct ps_prochandle * ph_p,td_syncinfo_t * si_p)24947c478bd9Sstevel@tonic-gate sync_get_info_common(const td_synchandle_t *sh_p, struct ps_prochandle *ph_p,
2495c3e74f84SToomas Soome     td_syncinfo_t *si_p)
24967c478bd9Sstevel@tonic-gate {
24977c478bd9Sstevel@tonic-gate 	int trunc = 0;
24987c478bd9Sstevel@tonic-gate 	td_so_un_t generic_so;
24997c478bd9Sstevel@tonic-gate 
25007c478bd9Sstevel@tonic-gate 	/*
25017c478bd9Sstevel@tonic-gate 	 * Determine the sync. object type; a little type fudgery here.
25027c478bd9Sstevel@tonic-gate 	 * First attempt to read the whole union.  If that fails, attempt
25037c478bd9Sstevel@tonic-gate 	 * to read just the condvar.  A condvar is the smallest sync. object.
25047c478bd9Sstevel@tonic-gate 	 */
25057c478bd9Sstevel@tonic-gate 	if (ps_pdread(ph_p, sh_p->sh_unique,
25067c478bd9Sstevel@tonic-gate 	    &generic_so, sizeof (generic_so)) != PS_OK) {
25077c478bd9Sstevel@tonic-gate 		trunc = 1;
25087c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, sh_p->sh_unique, &generic_so.condition,
25097c478bd9Sstevel@tonic-gate 		    sizeof (generic_so.condition)) != PS_OK)
25107c478bd9Sstevel@tonic-gate 			return (TD_DBERR);
25117c478bd9Sstevel@tonic-gate 	}
25127c478bd9Sstevel@tonic-gate 
25137c478bd9Sstevel@tonic-gate 	switch (generic_so.condition.cond_magic) {
25147c478bd9Sstevel@tonic-gate 	case MUTEX_MAGIC:
25157c478bd9Sstevel@tonic-gate 		if (trunc && ps_pdread(ph_p, sh_p->sh_unique,
25167c478bd9Sstevel@tonic-gate 		    &generic_so.lock, sizeof (generic_so.lock)) != PS_OK)
25177c478bd9Sstevel@tonic-gate 			return (TD_DBERR);
25187c478bd9Sstevel@tonic-gate 		si_p->si_type = TD_SYNC_MUTEX;
2519883492d5Sraf 		si_p->si_shared_type =
2520883492d5Sraf 		    (generic_so.lock.mutex_type & USYNC_PROCESS);
25217c478bd9Sstevel@tonic-gate 		(void) memcpy(si_p->si_flags, &generic_so.lock.mutex_flag,
25227c478bd9Sstevel@tonic-gate 		    sizeof (generic_so.lock.mutex_flag));
25237c478bd9Sstevel@tonic-gate 		si_p->si_state.mutex_locked =
25247c478bd9Sstevel@tonic-gate 		    (generic_so.lock.mutex_lockw != 0);
25257c478bd9Sstevel@tonic-gate 		si_p->si_size = sizeof (generic_so.lock);
25267c478bd9Sstevel@tonic-gate 		si_p->si_has_waiters = generic_so.lock.mutex_waiters;
25277c478bd9Sstevel@tonic-gate 		si_p->si_rcount = generic_so.lock.mutex_rcount;
25287c478bd9Sstevel@tonic-gate 		si_p->si_prioceiling = generic_so.lock.mutex_ceiling;
25297c478bd9Sstevel@tonic-gate 		if (si_p->si_state.mutex_locked) {
2530883492d5Sraf 			if (si_p->si_shared_type & USYNC_PROCESS)
25317c478bd9Sstevel@tonic-gate 				si_p->si_ownerpid =
2532d4204c85Sraf 				    generic_so.lock.mutex_ownerpid;
25337c478bd9Sstevel@tonic-gate 			si_p->si_owner.th_ta_p = sh_p->sh_ta_p;
25347c478bd9Sstevel@tonic-gate 			si_p->si_owner.th_unique = generic_so.lock.mutex_owner;
25357c478bd9Sstevel@tonic-gate 		}
25367c478bd9Sstevel@tonic-gate 		break;
25377c478bd9Sstevel@tonic-gate 	case COND_MAGIC:
25387c478bd9Sstevel@tonic-gate 		si_p->si_type = TD_SYNC_COND;
2539883492d5Sraf 		si_p->si_shared_type =
2540883492d5Sraf 		    (generic_so.condition.cond_type & USYNC_PROCESS);
25417c478bd9Sstevel@tonic-gate 		(void) memcpy(si_p->si_flags, generic_so.condition.flags.flag,
25427c478bd9Sstevel@tonic-gate 		    sizeof (generic_so.condition.flags.flag));
25437c478bd9Sstevel@tonic-gate 		si_p->si_size = sizeof (generic_so.condition);
25447c478bd9Sstevel@tonic-gate 		si_p->si_has_waiters =
2545d4204c85Sraf 		    (generic_so.condition.cond_waiters_user |
2546d4204c85Sraf 		    generic_so.condition.cond_waiters_kernel)? 1 : 0;
25477c478bd9Sstevel@tonic-gate 		break;
25487c478bd9Sstevel@tonic-gate 	case SEMA_MAGIC:
25497c478bd9Sstevel@tonic-gate 		if (trunc && ps_pdread(ph_p, sh_p->sh_unique,
25507c478bd9Sstevel@tonic-gate 		    &generic_so.semaphore, sizeof (generic_so.semaphore))
25517c478bd9Sstevel@tonic-gate 		    != PS_OK)
25527c478bd9Sstevel@tonic-gate 			return (TD_DBERR);
25537c478bd9Sstevel@tonic-gate 		si_p->si_type = TD_SYNC_SEMA;
2554883492d5Sraf 		si_p->si_shared_type =
2555883492d5Sraf 		    (generic_so.semaphore.type & USYNC_PROCESS);
25567c478bd9Sstevel@tonic-gate 		si_p->si_state.sem_count = generic_so.semaphore.count;
25577c478bd9Sstevel@tonic-gate 		si_p->si_size = sizeof (generic_so.semaphore);
25587c478bd9Sstevel@tonic-gate 		si_p->si_has_waiters =
25597c478bd9Sstevel@tonic-gate 		    ((lwp_sema_t *)&generic_so.semaphore)->flags[7];
25607c478bd9Sstevel@tonic-gate 		/* this is useless but the old interface provided it */
25617c478bd9Sstevel@tonic-gate 		si_p->si_data = (psaddr_t)generic_so.semaphore.count;
25627c478bd9Sstevel@tonic-gate 		break;
25637c478bd9Sstevel@tonic-gate 	case RWL_MAGIC:
2564d4204c85Sraf 	{
256541efec22Sraf 		uint32_t rwstate;
256641efec22Sraf 
25677c478bd9Sstevel@tonic-gate 		if (trunc && ps_pdread(ph_p, sh_p->sh_unique,
25687c478bd9Sstevel@tonic-gate 		    &generic_so.rwlock, sizeof (generic_so.rwlock)) != PS_OK)
25697c478bd9Sstevel@tonic-gate 			return (TD_DBERR);
25707c478bd9Sstevel@tonic-gate 		si_p->si_type = TD_SYNC_RWLOCK;
2571883492d5Sraf 		si_p->si_shared_type =
2572883492d5Sraf 		    (generic_so.rwlock.rwlock_type & USYNC_PROCESS);
25737c478bd9Sstevel@tonic-gate 		si_p->si_size = sizeof (generic_so.rwlock);
257441efec22Sraf 
257541efec22Sraf 		rwstate = (uint32_t)generic_so.rwlock.rwlock_readers;
257641efec22Sraf 		if (rwstate & URW_WRITE_LOCKED) {
257741efec22Sraf 			si_p->si_state.nreaders = -1;
257841efec22Sraf 			si_p->si_is_wlock = 1;
257941efec22Sraf 			si_p->si_owner.th_ta_p = sh_p->sh_ta_p;
258041efec22Sraf 			si_p->si_owner.th_unique =
2581d4204c85Sraf 			    generic_so.rwlock.rwlock_owner;
258241efec22Sraf 			if (si_p->si_shared_type & USYNC_PROCESS)
258341efec22Sraf 				si_p->si_ownerpid =
2584d4204c85Sraf 				    generic_so.rwlock.rwlock_ownerpid;
25857c478bd9Sstevel@tonic-gate 		} else {
258641efec22Sraf 			si_p->si_state.nreaders = (rwstate & URW_READERS_MASK);
25877c478bd9Sstevel@tonic-gate 		}
258841efec22Sraf 		si_p->si_has_waiters = ((rwstate & URW_HAS_WAITERS) != 0);
258941efec22Sraf 
25907c478bd9Sstevel@tonic-gate 		/* this is useless but the old interface provided it */
25917c478bd9Sstevel@tonic-gate 		si_p->si_data = (psaddr_t)generic_so.rwlock.readers;
25927c478bd9Sstevel@tonic-gate 		break;
2593d4204c85Sraf 	}
25947c478bd9Sstevel@tonic-gate 	default:
25957c478bd9Sstevel@tonic-gate 		return (TD_BADSH);
25967c478bd9Sstevel@tonic-gate 	}
25977c478bd9Sstevel@tonic-gate 
25987c478bd9Sstevel@tonic-gate 	si_p->si_ta_p = sh_p->sh_ta_p;
25997c478bd9Sstevel@tonic-gate 	si_p->si_sv_addr = sh_p->sh_unique;
26007c478bd9Sstevel@tonic-gate 	return (TD_OK);
26017c478bd9Sstevel@tonic-gate }
26027c478bd9Sstevel@tonic-gate 
26037c478bd9Sstevel@tonic-gate /*
26047c478bd9Sstevel@tonic-gate  * Given a synchronization handle, fill in the
26057c478bd9Sstevel@tonic-gate  * information for the synchronization variable into *si_p.
26067c478bd9Sstevel@tonic-gate  */
26077c478bd9Sstevel@tonic-gate #pragma weak td_sync_get_info = __td_sync_get_info
26087c478bd9Sstevel@tonic-gate td_err_e
__td_sync_get_info(const td_synchandle_t * sh_p,td_syncinfo_t * si_p)26097c478bd9Sstevel@tonic-gate __td_sync_get_info(const td_synchandle_t *sh_p, td_syncinfo_t *si_p)
26107c478bd9Sstevel@tonic-gate {
26117c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
26127c478bd9Sstevel@tonic-gate 	td_err_e return_val;
26137c478bd9Sstevel@tonic-gate 
26147c478bd9Sstevel@tonic-gate 	if (si_p == NULL)
26157c478bd9Sstevel@tonic-gate 		return (TD_ERR);
26167c478bd9Sstevel@tonic-gate 	(void) memset(si_p, 0, sizeof (*si_p));
26177c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_sh(sh_p, &return_val)) == NULL)
26187c478bd9Sstevel@tonic-gate 		return (return_val);
26197c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
26207c478bd9Sstevel@tonic-gate 		ph_unlock(sh_p->sh_ta_p);
26217c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
26227c478bd9Sstevel@tonic-gate 	}
26237c478bd9Sstevel@tonic-gate 
26247c478bd9Sstevel@tonic-gate 	return_val = sync_get_info_common(sh_p, ph_p, si_p);
26257c478bd9Sstevel@tonic-gate 
26267c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
26277c478bd9Sstevel@tonic-gate 	ph_unlock(sh_p->sh_ta_p);
26287c478bd9Sstevel@tonic-gate 	return (return_val);
26297c478bd9Sstevel@tonic-gate }
26307c478bd9Sstevel@tonic-gate 
26317c478bd9Sstevel@tonic-gate static uint_t
tdb_addr_hash64(uint64_t addr)26327c478bd9Sstevel@tonic-gate tdb_addr_hash64(uint64_t addr)
26337c478bd9Sstevel@tonic-gate {
26347c478bd9Sstevel@tonic-gate 	uint64_t value60 = (addr >> 4);
26357c478bd9Sstevel@tonic-gate 	uint32_t value30 = (value60 >> 30) ^ (value60 & 0x3fffffff);
26367c478bd9Sstevel@tonic-gate 	return ((value30 >> 15) ^ (value30 & 0x7fff));
26377c478bd9Sstevel@tonic-gate }
26387c478bd9Sstevel@tonic-gate 
26397c478bd9Sstevel@tonic-gate static uint_t
tdb_addr_hash32(uint64_t addr)26407c478bd9Sstevel@tonic-gate tdb_addr_hash32(uint64_t addr)
26417c478bd9Sstevel@tonic-gate {
26427c478bd9Sstevel@tonic-gate 	uint32_t value30 = (addr >> 2);		/* 30 bits */
26437c478bd9Sstevel@tonic-gate 	return ((value30 >> 15) ^ (value30 & 0x7fff));
26447c478bd9Sstevel@tonic-gate }
26457c478bd9Sstevel@tonic-gate 
26467c478bd9Sstevel@tonic-gate static td_err_e
read_sync_stats(td_thragent_t * ta_p,psaddr_t hash_table,psaddr_t sync_obj_addr,tdb_sync_stats_t * sync_stats)26477c478bd9Sstevel@tonic-gate read_sync_stats(td_thragent_t *ta_p, psaddr_t hash_table,
2648c3e74f84SToomas Soome     psaddr_t sync_obj_addr, tdb_sync_stats_t *sync_stats)
26497c478bd9Sstevel@tonic-gate {
26507c478bd9Sstevel@tonic-gate 	psaddr_t next_desc;
26517c478bd9Sstevel@tonic-gate 	uint64_t first;
26527c478bd9Sstevel@tonic-gate 	uint_t ix;
26537c478bd9Sstevel@tonic-gate 
26547c478bd9Sstevel@tonic-gate 	/*
26557c478bd9Sstevel@tonic-gate 	 * Compute the hash table index from the synch object's address.
26567c478bd9Sstevel@tonic-gate 	 */
26577c478bd9Sstevel@tonic-gate 	if (ta_p->model == PR_MODEL_LP64)
26587c478bd9Sstevel@tonic-gate 		ix = tdb_addr_hash64(sync_obj_addr);
26597c478bd9Sstevel@tonic-gate 	else
26607c478bd9Sstevel@tonic-gate 		ix = tdb_addr_hash32(sync_obj_addr);
26617c478bd9Sstevel@tonic-gate 
26627c478bd9Sstevel@tonic-gate 	/*
26637c478bd9Sstevel@tonic-gate 	 * Get the address of the first element in the linked list.
26647c478bd9Sstevel@tonic-gate 	 */
26657c478bd9Sstevel@tonic-gate 	if (ps_pdread(ta_p->ph_p, hash_table + ix * sizeof (uint64_t),
26667c478bd9Sstevel@tonic-gate 	    &first, sizeof (first)) != PS_OK)
26677c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
26687c478bd9Sstevel@tonic-gate 
26697c478bd9Sstevel@tonic-gate 	/*
26707c478bd9Sstevel@tonic-gate 	 * Search the linked list for an entry for the synch object..
26717c478bd9Sstevel@tonic-gate 	 */
2672c3e74f84SToomas Soome 	for (next_desc = (psaddr_t)first; next_desc != 0;
26737c478bd9Sstevel@tonic-gate 	    next_desc = (psaddr_t)sync_stats->next) {
26747c478bd9Sstevel@tonic-gate 		if (ps_pdread(ta_p->ph_p, next_desc,
26757c478bd9Sstevel@tonic-gate 		    sync_stats, sizeof (*sync_stats)) != PS_OK)
26767c478bd9Sstevel@tonic-gate 			return (TD_DBERR);
26777c478bd9Sstevel@tonic-gate 		if (sync_stats->sync_addr == sync_obj_addr)
26787c478bd9Sstevel@tonic-gate 			return (TD_OK);
26797c478bd9Sstevel@tonic-gate 	}
26807c478bd9Sstevel@tonic-gate 
26817c478bd9Sstevel@tonic-gate 	(void) memset(sync_stats, 0, sizeof (*sync_stats));
26827c478bd9Sstevel@tonic-gate 	return (TD_OK);
26837c478bd9Sstevel@tonic-gate }
26847c478bd9Sstevel@tonic-gate 
26857c478bd9Sstevel@tonic-gate /*
26867c478bd9Sstevel@tonic-gate  * Given a synchronization handle, fill in the
26877c478bd9Sstevel@tonic-gate  * statistics for the synchronization variable into *ss_p.
26887c478bd9Sstevel@tonic-gate  */
26897c478bd9Sstevel@tonic-gate #pragma weak td_sync_get_stats = __td_sync_get_stats
26907c478bd9Sstevel@tonic-gate td_err_e
__td_sync_get_stats(const td_synchandle_t * sh_p,td_syncstats_t * ss_p)26917c478bd9Sstevel@tonic-gate __td_sync_get_stats(const td_synchandle_t *sh_p, td_syncstats_t *ss_p)
26927c478bd9Sstevel@tonic-gate {
26937c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
26947c478bd9Sstevel@tonic-gate 	td_thragent_t *ta_p;
26957c478bd9Sstevel@tonic-gate 	td_err_e return_val;
26967c478bd9Sstevel@tonic-gate 	register_sync_t enable;
26977c478bd9Sstevel@tonic-gate 	psaddr_t hashaddr;
26987c478bd9Sstevel@tonic-gate 	tdb_sync_stats_t sync_stats;
26997c478bd9Sstevel@tonic-gate 	size_t ix;
27007c478bd9Sstevel@tonic-gate 
27017c478bd9Sstevel@tonic-gate 	if (ss_p == NULL)
27027c478bd9Sstevel@tonic-gate 		return (TD_ERR);
27037c478bd9Sstevel@tonic-gate 	(void) memset(ss_p, 0, sizeof (*ss_p));
27047c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_sh(sh_p, &return_val)) == NULL)
27057c478bd9Sstevel@tonic-gate 		return (return_val);
27067c478bd9Sstevel@tonic-gate 	ta_p = sh_p->sh_ta_p;
27077c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
27087c478bd9Sstevel@tonic-gate 		ph_unlock(ta_p);
27097c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
27107c478bd9Sstevel@tonic-gate 	}
27117c478bd9Sstevel@tonic-gate 
27127c478bd9Sstevel@tonic-gate 	if ((return_val = sync_get_info_common(sh_p, ph_p, &ss_p->ss_info))
27137c478bd9Sstevel@tonic-gate 	    != TD_OK) {
27147c478bd9Sstevel@tonic-gate 		if (return_val != TD_BADSH)
27157c478bd9Sstevel@tonic-gate 			goto out;
27167c478bd9Sstevel@tonic-gate 		/* we can correct TD_BADSH */
27177c478bd9Sstevel@tonic-gate 		(void) memset(&ss_p->ss_info, 0, sizeof (ss_p->ss_info));
27187c478bd9Sstevel@tonic-gate 		ss_p->ss_info.si_ta_p = sh_p->sh_ta_p;
27197c478bd9Sstevel@tonic-gate 		ss_p->ss_info.si_sv_addr = sh_p->sh_unique;
27207c478bd9Sstevel@tonic-gate 		/* we correct si_type and si_size below */
27217c478bd9Sstevel@tonic-gate 		return_val = TD_OK;
27227c478bd9Sstevel@tonic-gate 	}
27237c478bd9Sstevel@tonic-gate 	if (ps_pdread(ph_p, ta_p->tdb_register_sync_addr,
27247c478bd9Sstevel@tonic-gate 	    &enable, sizeof (enable)) != PS_OK) {
27257c478bd9Sstevel@tonic-gate 		return_val = TD_DBERR;
27267c478bd9Sstevel@tonic-gate 		goto out;
27277c478bd9Sstevel@tonic-gate 	}
27287c478bd9Sstevel@tonic-gate 	if (enable != REGISTER_SYNC_ON)
27297c478bd9Sstevel@tonic-gate 		goto out;
27307c478bd9Sstevel@tonic-gate 
27317c478bd9Sstevel@tonic-gate 	/*
27327c478bd9Sstevel@tonic-gate 	 * Get the address of the hash table in the target process.
27337c478bd9Sstevel@tonic-gate 	 */
27347c478bd9Sstevel@tonic-gate 	if (ta_p->model == PR_MODEL_NATIVE) {
27357c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, ta_p->uberdata_addr +
27367c478bd9Sstevel@tonic-gate 		    offsetof(uberdata_t, tdb.tdb_sync_addr_hash),
27377c478bd9Sstevel@tonic-gate 		    &hashaddr, sizeof (&hashaddr)) != PS_OK) {
27387c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
27397c478bd9Sstevel@tonic-gate 			goto out;
27407c478bd9Sstevel@tonic-gate 		}
27417c478bd9Sstevel@tonic-gate 	} else {
27427c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
27437c478bd9Sstevel@tonic-gate 		caddr32_t addr;
27447c478bd9Sstevel@tonic-gate 
27457c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, ta_p->uberdata_addr +
27467c478bd9Sstevel@tonic-gate 		    offsetof(uberdata32_t, tdb.tdb_sync_addr_hash),
27477c478bd9Sstevel@tonic-gate 		    &addr, sizeof (addr)) != PS_OK) {
27487c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
27497c478bd9Sstevel@tonic-gate 			goto out;
27507c478bd9Sstevel@tonic-gate 		}
27517c478bd9Sstevel@tonic-gate 		hashaddr = addr;
27527c478bd9Sstevel@tonic-gate #else
27537c478bd9Sstevel@tonic-gate 		return_val = TD_ERR;
27547c478bd9Sstevel@tonic-gate 		goto out;
27557c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
27567c478bd9Sstevel@tonic-gate 	}
27577c478bd9Sstevel@tonic-gate 
27587c478bd9Sstevel@tonic-gate 	if (hashaddr == 0)
27597c478bd9Sstevel@tonic-gate 		return_val = TD_BADSH;
27607c478bd9Sstevel@tonic-gate 	else
27617c478bd9Sstevel@tonic-gate 		return_val = read_sync_stats(ta_p, hashaddr,
2762d4204c85Sraf 		    sh_p->sh_unique, &sync_stats);
27637c478bd9Sstevel@tonic-gate 	if (return_val != TD_OK)
27647c478bd9Sstevel@tonic-gate 		goto out;
27657c478bd9Sstevel@tonic-gate 
27667c478bd9Sstevel@tonic-gate 	/*
27677c478bd9Sstevel@tonic-gate 	 * We have the hash table entry.  Transfer the data to
27687c478bd9Sstevel@tonic-gate 	 * the td_syncstats_t structure provided by the caller.
27697c478bd9Sstevel@tonic-gate 	 */
27707c478bd9Sstevel@tonic-gate 	switch (sync_stats.un.type) {
27717c478bd9Sstevel@tonic-gate 	case TDB_MUTEX:
2772d4204c85Sraf 	{
27737c478bd9Sstevel@tonic-gate 		td_mutex_stats_t *msp = &ss_p->ss_un.mutex;
27747c478bd9Sstevel@tonic-gate 
27757c478bd9Sstevel@tonic-gate 		ss_p->ss_info.si_type = TD_SYNC_MUTEX;
27767c478bd9Sstevel@tonic-gate 		ss_p->ss_info.si_size = sizeof (mutex_t);
27777c478bd9Sstevel@tonic-gate 		msp->mutex_lock =
2778d4204c85Sraf 		    sync_stats.un.mutex.mutex_lock;
27797c478bd9Sstevel@tonic-gate 		msp->mutex_sleep =
2780d4204c85Sraf 		    sync_stats.un.mutex.mutex_sleep;
27817c478bd9Sstevel@tonic-gate 		msp->mutex_sleep_time =
2782d4204c85Sraf 		    sync_stats.un.mutex.mutex_sleep_time;
27837c478bd9Sstevel@tonic-gate 		msp->mutex_hold_time =
2784d4204c85Sraf 		    sync_stats.un.mutex.mutex_hold_time;
27857c478bd9Sstevel@tonic-gate 		msp->mutex_try =
2786d4204c85Sraf 		    sync_stats.un.mutex.mutex_try;
27877c478bd9Sstevel@tonic-gate 		msp->mutex_try_fail =
2788d4204c85Sraf 		    sync_stats.un.mutex.mutex_try_fail;
27897c478bd9Sstevel@tonic-gate 		if (sync_stats.sync_addr >= ta_p->hash_table_addr &&
27907c478bd9Sstevel@tonic-gate 		    (ix = sync_stats.sync_addr - ta_p->hash_table_addr)
27917c478bd9Sstevel@tonic-gate 		    < ta_p->hash_size * sizeof (thr_hash_table_t))
27927c478bd9Sstevel@tonic-gate 			msp->mutex_internal =
2793d4204c85Sraf 			    ix / sizeof (thr_hash_table_t) + 1;
27947c478bd9Sstevel@tonic-gate 		break;
2795d4204c85Sraf 	}
27967c478bd9Sstevel@tonic-gate 	case TDB_COND:
2797d4204c85Sraf 	{
27987c478bd9Sstevel@tonic-gate 		td_cond_stats_t *csp = &ss_p->ss_un.cond;
27997c478bd9Sstevel@tonic-gate 
28007c478bd9Sstevel@tonic-gate 		ss_p->ss_info.si_type = TD_SYNC_COND;
28017c478bd9Sstevel@tonic-gate 		ss_p->ss_info.si_size = sizeof (cond_t);
28027c478bd9Sstevel@tonic-gate 		csp->cond_wait =
2803d4204c85Sraf 		    sync_stats.un.cond.cond_wait;
28047c478bd9Sstevel@tonic-gate 		csp->cond_timedwait =
2805d4204c85Sraf 		    sync_stats.un.cond.cond_timedwait;
28067c478bd9Sstevel@tonic-gate 		csp->cond_wait_sleep_time =
2807d4204c85Sraf 		    sync_stats.un.cond.cond_wait_sleep_time;
28087c478bd9Sstevel@tonic-gate 		csp->cond_timedwait_sleep_time =
2809d4204c85Sraf 		    sync_stats.un.cond.cond_timedwait_sleep_time;
28107c478bd9Sstevel@tonic-gate 		csp->cond_timedwait_timeout =
2811d4204c85Sraf 		    sync_stats.un.cond.cond_timedwait_timeout;
28127c478bd9Sstevel@tonic-gate 		csp->cond_signal =
2813d4204c85Sraf 		    sync_stats.un.cond.cond_signal;
28147c478bd9Sstevel@tonic-gate 		csp->cond_broadcast =
2815d4204c85Sraf 		    sync_stats.un.cond.cond_broadcast;
28167c478bd9Sstevel@tonic-gate 		if (sync_stats.sync_addr >= ta_p->hash_table_addr &&
28177c478bd9Sstevel@tonic-gate 		    (ix = sync_stats.sync_addr - ta_p->hash_table_addr)
28187c478bd9Sstevel@tonic-gate 		    < ta_p->hash_size * sizeof (thr_hash_table_t))
28197c478bd9Sstevel@tonic-gate 			csp->cond_internal =
2820d4204c85Sraf 			    ix / sizeof (thr_hash_table_t) + 1;
28217c478bd9Sstevel@tonic-gate 		break;
2822d4204c85Sraf 	}
28237c478bd9Sstevel@tonic-gate 	case TDB_RWLOCK:
2824d4204c85Sraf 	{
28257c478bd9Sstevel@tonic-gate 		td_rwlock_stats_t *rwsp = &ss_p->ss_un.rwlock;
28267c478bd9Sstevel@tonic-gate 
28277c478bd9Sstevel@tonic-gate 		ss_p->ss_info.si_type = TD_SYNC_RWLOCK;
28287c478bd9Sstevel@tonic-gate 		ss_p->ss_info.si_size = sizeof (rwlock_t);
28297c478bd9Sstevel@tonic-gate 		rwsp->rw_rdlock =
2830d4204c85Sraf 		    sync_stats.un.rwlock.rw_rdlock;
28317c478bd9Sstevel@tonic-gate 		rwsp->rw_rdlock_try =
2832d4204c85Sraf 		    sync_stats.un.rwlock.rw_rdlock_try;
28337c478bd9Sstevel@tonic-gate 		rwsp->rw_rdlock_try_fail =
2834d4204c85Sraf 		    sync_stats.un.rwlock.rw_rdlock_try_fail;
28357c478bd9Sstevel@tonic-gate 		rwsp->rw_wrlock =
2836d4204c85Sraf 		    sync_stats.un.rwlock.rw_wrlock;
28377c478bd9Sstevel@tonic-gate 		rwsp->rw_wrlock_hold_time =
2838d4204c85Sraf 		    sync_stats.un.rwlock.rw_wrlock_hold_time;
28397c478bd9Sstevel@tonic-gate 		rwsp->rw_wrlock_try =
2840d4204c85Sraf 		    sync_stats.un.rwlock.rw_wrlock_try;
28417c478bd9Sstevel@tonic-gate 		rwsp->rw_wrlock_try_fail =
2842d4204c85Sraf 		    sync_stats.un.rwlock.rw_wrlock_try_fail;
28437c478bd9Sstevel@tonic-gate 		break;
2844d4204c85Sraf 	}
28457c478bd9Sstevel@tonic-gate 	case TDB_SEMA:
2846d4204c85Sraf 	{
28477c478bd9Sstevel@tonic-gate 		td_sema_stats_t *ssp = &ss_p->ss_un.sema;
28487c478bd9Sstevel@tonic-gate 
28497c478bd9Sstevel@tonic-gate 		ss_p->ss_info.si_type = TD_SYNC_SEMA;
28507c478bd9Sstevel@tonic-gate 		ss_p->ss_info.si_size = sizeof (sema_t);
28517c478bd9Sstevel@tonic-gate 		ssp->sema_wait =
2852d4204c85Sraf 		    sync_stats.un.sema.sema_wait;
28537c478bd9Sstevel@tonic-gate 		ssp->sema_wait_sleep =
2854d4204c85Sraf 		    sync_stats.un.sema.sema_wait_sleep;
28557c478bd9Sstevel@tonic-gate 		ssp->sema_wait_sleep_time =
2856d4204c85Sraf 		    sync_stats.un.sema.sema_wait_sleep_time;
28577c478bd9Sstevel@tonic-gate 		ssp->sema_trywait =
2858d4204c85Sraf 		    sync_stats.un.sema.sema_trywait;
28597c478bd9Sstevel@tonic-gate 		ssp->sema_trywait_fail =
2860d4204c85Sraf 		    sync_stats.un.sema.sema_trywait_fail;
28617c478bd9Sstevel@tonic-gate 		ssp->sema_post =
2862d4204c85Sraf 		    sync_stats.un.sema.sema_post;
28637c478bd9Sstevel@tonic-gate 		ssp->sema_max_count =
2864d4204c85Sraf 		    sync_stats.un.sema.sema_max_count;
28657c478bd9Sstevel@tonic-gate 		ssp->sema_min_count =
2866d4204c85Sraf 		    sync_stats.un.sema.sema_min_count;
28677c478bd9Sstevel@tonic-gate 		break;
2868d4204c85Sraf 	}
28697c478bd9Sstevel@tonic-gate 	default:
28707c478bd9Sstevel@tonic-gate 		return_val = TD_BADSH;
28717c478bd9Sstevel@tonic-gate 		break;
28727c478bd9Sstevel@tonic-gate 	}
28737c478bd9Sstevel@tonic-gate 
28747c478bd9Sstevel@tonic-gate out:
28757c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
28767c478bd9Sstevel@tonic-gate 	ph_unlock(ta_p);
28777c478bd9Sstevel@tonic-gate 	return (return_val);
28787c478bd9Sstevel@tonic-gate }
28797c478bd9Sstevel@tonic-gate 
28807c478bd9Sstevel@tonic-gate /*
28817c478bd9Sstevel@tonic-gate  * Change the state of a synchronization variable.
28827c478bd9Sstevel@tonic-gate  *	1) mutex lock state set to value
28837c478bd9Sstevel@tonic-gate  *	2) semaphore's count set to value
288441efec22Sraf  *	3) writer's lock set by value < 0
288541efec22Sraf  *	4) reader's lock number of readers set to value >= 0
28867c478bd9Sstevel@tonic-gate  * Currently unused by dbx.
28877c478bd9Sstevel@tonic-gate  */
28887c478bd9Sstevel@tonic-gate #pragma weak td_sync_setstate = __td_sync_setstate
28897c478bd9Sstevel@tonic-gate td_err_e
__td_sync_setstate(const td_synchandle_t * sh_p,int value)2890fb79d529SToomas Soome __td_sync_setstate(const td_synchandle_t *sh_p, int value)
28917c478bd9Sstevel@tonic-gate {
28927c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
28937c478bd9Sstevel@tonic-gate 	int		trunc = 0;
28947c478bd9Sstevel@tonic-gate 	td_err_e	return_val;
28957c478bd9Sstevel@tonic-gate 	td_so_un_t	generic_so;
289641efec22Sraf 	uint32_t	*rwstate;
28977c478bd9Sstevel@tonic-gate 
28987c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_sh(sh_p, &return_val)) == NULL)
28997c478bd9Sstevel@tonic-gate 		return (return_val);
29007c478bd9Sstevel@tonic-gate 	if (ps_pstop(ph_p) != PS_OK) {
29017c478bd9Sstevel@tonic-gate 		ph_unlock(sh_p->sh_ta_p);
29027c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
29037c478bd9Sstevel@tonic-gate 	}
29047c478bd9Sstevel@tonic-gate 
29057c478bd9Sstevel@tonic-gate 	/*
29067c478bd9Sstevel@tonic-gate 	 * Read the synch. variable information.
29077c478bd9Sstevel@tonic-gate 	 * First attempt to read the whole union and if that fails
29087c478bd9Sstevel@tonic-gate 	 * fall back to reading only the smallest member, the condvar.
29097c478bd9Sstevel@tonic-gate 	 */
29107c478bd9Sstevel@tonic-gate 	if (ps_pdread(ph_p, sh_p->sh_unique, &generic_so,
29117c478bd9Sstevel@tonic-gate 	    sizeof (generic_so)) != PS_OK) {
29127c478bd9Sstevel@tonic-gate 		trunc = 1;
29137c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, sh_p->sh_unique, &generic_so.condition,
29147c478bd9Sstevel@tonic-gate 		    sizeof (generic_so.condition)) != PS_OK) {
29157c478bd9Sstevel@tonic-gate 			(void) ps_pcontinue(ph_p);
29167c478bd9Sstevel@tonic-gate 			ph_unlock(sh_p->sh_ta_p);
29177c478bd9Sstevel@tonic-gate 			return (TD_DBERR);
29187c478bd9Sstevel@tonic-gate 		}
29197c478bd9Sstevel@tonic-gate 	}
29207c478bd9Sstevel@tonic-gate 
29217c478bd9Sstevel@tonic-gate 	/*
29227c478bd9Sstevel@tonic-gate 	 * Set the new value in the sync. variable, read the synch. variable
29237c478bd9Sstevel@tonic-gate 	 * information. from the process, reset its value and write it back.
29247c478bd9Sstevel@tonic-gate 	 */
29257c478bd9Sstevel@tonic-gate 	switch (generic_so.condition.mutex_magic) {
29267c478bd9Sstevel@tonic-gate 	case MUTEX_MAGIC:
29277c478bd9Sstevel@tonic-gate 		if (trunc && ps_pdread(ph_p, sh_p->sh_unique,
29287c478bd9Sstevel@tonic-gate 		    &generic_so.lock, sizeof (generic_so.lock)) != PS_OK) {
29297c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
29307c478bd9Sstevel@tonic-gate 			break;
29317c478bd9Sstevel@tonic-gate 		}
29327c478bd9Sstevel@tonic-gate 		generic_so.lock.mutex_lockw = (uint8_t)value;
29337c478bd9Sstevel@tonic-gate 		if (ps_pdwrite(ph_p, sh_p->sh_unique, &generic_so.lock,
29347c478bd9Sstevel@tonic-gate 		    sizeof (generic_so.lock)) != PS_OK)
29357c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
29367c478bd9Sstevel@tonic-gate 		break;
29377c478bd9Sstevel@tonic-gate 	case SEMA_MAGIC:
29387c478bd9Sstevel@tonic-gate 		if (trunc && ps_pdread(ph_p, sh_p->sh_unique,
29397c478bd9Sstevel@tonic-gate 		    &generic_so.semaphore, sizeof (generic_so.semaphore))
29407c478bd9Sstevel@tonic-gate 		    != PS_OK) {
29417c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
29427c478bd9Sstevel@tonic-gate 			break;
29437c478bd9Sstevel@tonic-gate 		}
29447c478bd9Sstevel@tonic-gate 		generic_so.semaphore.count = value;
29457c478bd9Sstevel@tonic-gate 		if (ps_pdwrite(ph_p, sh_p->sh_unique, &generic_so.semaphore,
29467c478bd9Sstevel@tonic-gate 		    sizeof (generic_so.semaphore)) != PS_OK)
29477c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
29487c478bd9Sstevel@tonic-gate 		break;
29497c478bd9Sstevel@tonic-gate 	case COND_MAGIC:
29507c478bd9Sstevel@tonic-gate 		/* Operation not supported on a condition variable */
29517c478bd9Sstevel@tonic-gate 		return_val = TD_ERR;
29527c478bd9Sstevel@tonic-gate 		break;
29537c478bd9Sstevel@tonic-gate 	case RWL_MAGIC:
29547c478bd9Sstevel@tonic-gate 		if (trunc && ps_pdread(ph_p, sh_p->sh_unique,
29557c478bd9Sstevel@tonic-gate 		    &generic_so.rwlock, sizeof (generic_so.rwlock)) != PS_OK) {
29567c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
29577c478bd9Sstevel@tonic-gate 			break;
29587c478bd9Sstevel@tonic-gate 		}
295941efec22Sraf 		rwstate = (uint32_t *)&generic_so.rwlock.readers;
296041efec22Sraf 		*rwstate &= URW_HAS_WAITERS;
296141efec22Sraf 		if (value < 0)
296241efec22Sraf 			*rwstate |= URW_WRITE_LOCKED;
296341efec22Sraf 		else
296441efec22Sraf 			*rwstate |= (value & URW_READERS_MASK);
29657c478bd9Sstevel@tonic-gate 		if (ps_pdwrite(ph_p, sh_p->sh_unique, &generic_so.rwlock,
29667c478bd9Sstevel@tonic-gate 		    sizeof (generic_so.rwlock)) != PS_OK)
29677c478bd9Sstevel@tonic-gate 			return_val = TD_DBERR;
29687c478bd9Sstevel@tonic-gate 		break;
29697c478bd9Sstevel@tonic-gate 	default:
29707c478bd9Sstevel@tonic-gate 		/* Bad sync. object type */
29717c478bd9Sstevel@tonic-gate 		return_val = TD_BADSH;
29727c478bd9Sstevel@tonic-gate 		break;
29737c478bd9Sstevel@tonic-gate 	}
29747c478bd9Sstevel@tonic-gate 
29757c478bd9Sstevel@tonic-gate 	(void) ps_pcontinue(ph_p);
29767c478bd9Sstevel@tonic-gate 	ph_unlock(sh_p->sh_ta_p);
29777c478bd9Sstevel@tonic-gate 	return (return_val);
29787c478bd9Sstevel@tonic-gate }
29797c478bd9Sstevel@tonic-gate 
29807c478bd9Sstevel@tonic-gate typedef struct {
29817c478bd9Sstevel@tonic-gate 	td_thr_iter_f	*waiter_cb;
29827c478bd9Sstevel@tonic-gate 	psaddr_t	sync_obj_addr;
29837c478bd9Sstevel@tonic-gate 	uint16_t	sync_magic;
29847c478bd9Sstevel@tonic-gate 	void		*waiter_cb_arg;
29857c478bd9Sstevel@tonic-gate 	td_err_e	errcode;
29867c478bd9Sstevel@tonic-gate } waiter_cb_ctl_t;
29877c478bd9Sstevel@tonic-gate 
29887c478bd9Sstevel@tonic-gate static int
waiters_cb(const td_thrhandle_t * th_p,void * arg)29897c478bd9Sstevel@tonic-gate waiters_cb(const td_thrhandle_t *th_p, void *arg)
29907c478bd9Sstevel@tonic-gate {
29917c478bd9Sstevel@tonic-gate 	td_thragent_t	*ta_p = th_p->th_ta_p;
29927c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p = ta_p->ph_p;
29937c478bd9Sstevel@tonic-gate 	waiter_cb_ctl_t	*wcb = arg;
29947c478bd9Sstevel@tonic-gate 	caddr_t		wchan;
29957c478bd9Sstevel@tonic-gate 
29967c478bd9Sstevel@tonic-gate 	if (ta_p->model == PR_MODEL_NATIVE) {
29977c478bd9Sstevel@tonic-gate 		ulwp_t *ulwp = (ulwp_t *)th_p->th_unique;
29987c478bd9Sstevel@tonic-gate 
29997c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_wchan,
30007c478bd9Sstevel@tonic-gate 		    &wchan, sizeof (wchan)) != PS_OK) {
30017c478bd9Sstevel@tonic-gate 			wcb->errcode = TD_DBERR;
30027c478bd9Sstevel@tonic-gate 			return (1);
30037c478bd9Sstevel@tonic-gate 		}
30047c478bd9Sstevel@tonic-gate 	} else {
30057c478bd9Sstevel@tonic-gate #if defined(_LP64) && defined(_SYSCALL32)
30067c478bd9Sstevel@tonic-gate 		ulwp32_t *ulwp = (ulwp32_t *)th_p->th_unique;
30077c478bd9Sstevel@tonic-gate 		caddr32_t wchan32;
30087c478bd9Sstevel@tonic-gate 
30097c478bd9Sstevel@tonic-gate 		if (ps_pdread(ph_p, (psaddr_t)&ulwp->ul_wchan,
30107c478bd9Sstevel@tonic-gate 		    &wchan32, sizeof (wchan32)) != PS_OK) {
30117c478bd9Sstevel@tonic-gate 			wcb->errcode = TD_DBERR;
30127c478bd9Sstevel@tonic-gate 			return (1);
30137c478bd9Sstevel@tonic-gate 		}
30147c478bd9Sstevel@tonic-gate 		wchan = (caddr_t)(uintptr_t)wchan32;
30157c478bd9Sstevel@tonic-gate #else
30167c478bd9Sstevel@tonic-gate 		wcb->errcode = TD_ERR;
30177c478bd9Sstevel@tonic-gate 		return (1);
30187c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
30197c478bd9Sstevel@tonic-gate 	}
30207c478bd9Sstevel@tonic-gate 
30217c478bd9Sstevel@tonic-gate 	if (wchan == NULL)
30227c478bd9Sstevel@tonic-gate 		return (0);
30237c478bd9Sstevel@tonic-gate 
30247c478bd9Sstevel@tonic-gate 	if (wchan == (caddr_t)wcb->sync_obj_addr)
30257c478bd9Sstevel@tonic-gate 		return ((*wcb->waiter_cb)(th_p, wcb->waiter_cb_arg));
30267c478bd9Sstevel@tonic-gate 
30277c478bd9Sstevel@tonic-gate 	return (0);
30287c478bd9Sstevel@tonic-gate }
30297c478bd9Sstevel@tonic-gate 
30307c478bd9Sstevel@tonic-gate /*
30317c478bd9Sstevel@tonic-gate  * For a given synchronization variable, iterate over the
30327c478bd9Sstevel@tonic-gate  * set of waiting threads.  The call back function is passed
30337c478bd9Sstevel@tonic-gate  * two parameters, a pointer to a thread handle and a pointer
30347c478bd9Sstevel@tonic-gate  * to extra call back data.
30357c478bd9Sstevel@tonic-gate  */
30367c478bd9Sstevel@tonic-gate #pragma weak td_sync_waiters = __td_sync_waiters
30377c478bd9Sstevel@tonic-gate td_err_e
__td_sync_waiters(const td_synchandle_t * sh_p,td_thr_iter_f * cb,void * cb_data)30387c478bd9Sstevel@tonic-gate __td_sync_waiters(const td_synchandle_t *sh_p, td_thr_iter_f *cb, void *cb_data)
30397c478bd9Sstevel@tonic-gate {
30407c478bd9Sstevel@tonic-gate 	struct ps_prochandle *ph_p;
30417c478bd9Sstevel@tonic-gate 	waiter_cb_ctl_t	wcb;
30427c478bd9Sstevel@tonic-gate 	td_err_e	return_val;
30437c478bd9Sstevel@tonic-gate 
30447c478bd9Sstevel@tonic-gate 	if ((ph_p = ph_lock_sh(sh_p, &return_val)) == NULL)
30457c478bd9Sstevel@tonic-gate 		return (return_val);
30467c478bd9Sstevel@tonic-gate 	if (ps_pdread(ph_p,
30477c478bd9Sstevel@tonic-gate 	    (psaddr_t)&((mutex_t *)sh_p->sh_unique)->mutex_magic,
30487c478bd9Sstevel@tonic-gate 	    (caddr_t)&wcb.sync_magic, sizeof (wcb.sync_magic)) != PS_OK) {
30497c478bd9Sstevel@tonic-gate 		ph_unlock(sh_p->sh_ta_p);
30507c478bd9Sstevel@tonic-gate 		return (TD_DBERR);
30517c478bd9Sstevel@tonic-gate 	}
30527c478bd9Sstevel@tonic-gate 	ph_unlock(sh_p->sh_ta_p);
30537c478bd9Sstevel@tonic-gate 
30547c478bd9Sstevel@tonic-gate 	switch (wcb.sync_magic) {
30557c478bd9Sstevel@tonic-gate 	case MUTEX_MAGIC:
30567c478bd9Sstevel@tonic-gate 	case COND_MAGIC:
30577c478bd9Sstevel@tonic-gate 	case SEMA_MAGIC:
30587c478bd9Sstevel@tonic-gate 	case RWL_MAGIC:
30597c478bd9Sstevel@tonic-gate 		break;
30607c478bd9Sstevel@tonic-gate 	default:
30617c478bd9Sstevel@tonic-gate 		return (TD_BADSH);
30627c478bd9Sstevel@tonic-gate 	}
30637c478bd9Sstevel@tonic-gate 
30647c478bd9Sstevel@tonic-gate 	wcb.waiter_cb = cb;
30657c478bd9Sstevel@tonic-gate 	wcb.sync_obj_addr = sh_p->sh_unique;
30667c478bd9Sstevel@tonic-gate 	wcb.waiter_cb_arg = cb_data;
30677c478bd9Sstevel@tonic-gate 	wcb.errcode = TD_OK;
30687c478bd9Sstevel@tonic-gate 	return_val = __td_ta_thr_iter(sh_p->sh_ta_p, waiters_cb, &wcb,
3069d4204c85Sraf 	    TD_THR_SLEEP, TD_THR_LOWEST_PRIORITY,
3070d4204c85Sraf 	    TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
30717c478bd9Sstevel@tonic-gate 
30727c478bd9Sstevel@tonic-gate 	if (return_val != TD_OK)
30737c478bd9Sstevel@tonic-gate 		return (return_val);
30747c478bd9Sstevel@tonic-gate 
30757c478bd9Sstevel@tonic-gate 	return (wcb.errcode);
30767c478bd9Sstevel@tonic-gate }
3077