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