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