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