10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53864Sraf * Common Development and Distribution License (the "License").
63864Sraf * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
213864Sraf
220Sstevel@tonic-gate /*
236515Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
280Sstevel@tonic-gate
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate * This file contains most of the functionality
310Sstevel@tonic-gate * required to support the threads portion of libc_db.
320Sstevel@tonic-gate */
330Sstevel@tonic-gate
340Sstevel@tonic-gate #include "lint.h"
350Sstevel@tonic-gate #include "thr_uberdata.h"
360Sstevel@tonic-gate
370Sstevel@tonic-gate static void
tdb_event_ready(void)380Sstevel@tonic-gate tdb_event_ready(void) {}
390Sstevel@tonic-gate
400Sstevel@tonic-gate static void
tdb_event_sleep(void)410Sstevel@tonic-gate tdb_event_sleep(void) {}
420Sstevel@tonic-gate
430Sstevel@tonic-gate static void
tdb_event_switchto(void)440Sstevel@tonic-gate tdb_event_switchto(void) {}
450Sstevel@tonic-gate
460Sstevel@tonic-gate static void
tdb_event_switchfrom(void)470Sstevel@tonic-gate tdb_event_switchfrom(void) {}
480Sstevel@tonic-gate
490Sstevel@tonic-gate static void
tdb_event_lock_try(void)500Sstevel@tonic-gate tdb_event_lock_try(void) {}
510Sstevel@tonic-gate
520Sstevel@tonic-gate static void
tdb_event_catchsig(void)530Sstevel@tonic-gate tdb_event_catchsig(void) {}
540Sstevel@tonic-gate
550Sstevel@tonic-gate static void
tdb_event_idle(void)560Sstevel@tonic-gate tdb_event_idle(void) {}
570Sstevel@tonic-gate
580Sstevel@tonic-gate static void
tdb_event_create(void)590Sstevel@tonic-gate tdb_event_create(void) {}
600Sstevel@tonic-gate
610Sstevel@tonic-gate static void
tdb_event_death(void)620Sstevel@tonic-gate tdb_event_death(void) {}
630Sstevel@tonic-gate
640Sstevel@tonic-gate static void
tdb_event_preempt(void)650Sstevel@tonic-gate tdb_event_preempt(void) {}
660Sstevel@tonic-gate
670Sstevel@tonic-gate static void
tdb_event_pri_inherit(void)680Sstevel@tonic-gate tdb_event_pri_inherit(void) {}
690Sstevel@tonic-gate
700Sstevel@tonic-gate static void
tdb_event_reap(void)710Sstevel@tonic-gate tdb_event_reap(void) {}
720Sstevel@tonic-gate
730Sstevel@tonic-gate static void
tdb_event_concurrency(void)740Sstevel@tonic-gate tdb_event_concurrency(void) {}
750Sstevel@tonic-gate
760Sstevel@tonic-gate static void
tdb_event_timeout(void)770Sstevel@tonic-gate tdb_event_timeout(void) {}
780Sstevel@tonic-gate
790Sstevel@tonic-gate /*
800Sstevel@tonic-gate * uberflags.uf_tdb_register_sync is set to REGISTER_SYNC_ENABLE by a debugger
810Sstevel@tonic-gate * to empty the table and then enable synchronization object registration.
820Sstevel@tonic-gate *
830Sstevel@tonic-gate * uberflags.uf_tdb_register_sync is set to REGISTER_SYNC_DISABLE by a debugger
840Sstevel@tonic-gate * to empty the table and then disable synchronization object registration.
850Sstevel@tonic-gate */
860Sstevel@tonic-gate
870Sstevel@tonic-gate const tdb_ev_func_t tdb_events[TD_MAX_EVENT_NUM - TD_MIN_EVENT_NUM + 1] = {
880Sstevel@tonic-gate tdb_event_ready,
890Sstevel@tonic-gate tdb_event_sleep,
900Sstevel@tonic-gate tdb_event_switchto,
910Sstevel@tonic-gate tdb_event_switchfrom,
920Sstevel@tonic-gate tdb_event_lock_try,
930Sstevel@tonic-gate tdb_event_catchsig,
940Sstevel@tonic-gate tdb_event_idle,
950Sstevel@tonic-gate tdb_event_create,
960Sstevel@tonic-gate tdb_event_death,
970Sstevel@tonic-gate tdb_event_preempt,
980Sstevel@tonic-gate tdb_event_pri_inherit,
990Sstevel@tonic-gate tdb_event_reap,
1000Sstevel@tonic-gate tdb_event_concurrency,
1010Sstevel@tonic-gate tdb_event_timeout
1020Sstevel@tonic-gate };
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate #if TDB_HASH_SHIFT != 15
1050Sstevel@tonic-gate #error "this is all broken because TDB_HASH_SHIFT is not 15"
1060Sstevel@tonic-gate #endif
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate static uint_t
tdb_addr_hash(void * addr)1090Sstevel@tonic-gate tdb_addr_hash(void *addr)
1100Sstevel@tonic-gate {
1110Sstevel@tonic-gate /*
1120Sstevel@tonic-gate * This knows for a fact that the hash table has
1130Sstevel@tonic-gate * 32K entries; that is, that TDB_HASH_SHIFT is 15.
1140Sstevel@tonic-gate */
1150Sstevel@tonic-gate #ifdef _LP64
1160Sstevel@tonic-gate uint64_t value60 = ((uintptr_t)addr >> 4); /* 60 bits */
1170Sstevel@tonic-gate uint32_t value30 = (value60 >> 30) ^ (value60 & 0x3fffffff);
1180Sstevel@tonic-gate #else
1190Sstevel@tonic-gate uint32_t value30 = ((uintptr_t)addr >> 2); /* 30 bits */
1200Sstevel@tonic-gate #endif
1210Sstevel@tonic-gate return ((value30 >> 15) ^ (value30 & 0x7fff));
1220Sstevel@tonic-gate }
1230Sstevel@tonic-gate
1240Sstevel@tonic-gate static tdb_sync_stats_t *
alloc_sync_addr(void * addr)1250Sstevel@tonic-gate alloc_sync_addr(void *addr)
1260Sstevel@tonic-gate {
1270Sstevel@tonic-gate uberdata_t *udp = curthread->ul_uberdata;
1280Sstevel@tonic-gate tdb_t *tdbp = &udp->tdb;
1290Sstevel@tonic-gate tdb_sync_stats_t *sap;
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate ASSERT(MUTEX_OWNED(&udp->tdb_hash_lock, curthread));
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate if ((sap = tdbp->tdb_sync_addr_free) == NULL) {
1340Sstevel@tonic-gate void *vaddr;
1350Sstevel@tonic-gate int i;
1360Sstevel@tonic-gate
1370Sstevel@tonic-gate /*
1380Sstevel@tonic-gate * Don't keep trying after mmap() has already failed.
1390Sstevel@tonic-gate */
1400Sstevel@tonic-gate if (tdbp->tdb_hash_alloc_failed)
1410Sstevel@tonic-gate return (NULL);
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate /* double the allocation each time */
1440Sstevel@tonic-gate tdbp->tdb_sync_alloc *= 2;
1456515Sraf if ((vaddr = mmap(NULL,
1460Sstevel@tonic-gate tdbp->tdb_sync_alloc * sizeof (tdb_sync_stats_t),
1470Sstevel@tonic-gate PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON,
1480Sstevel@tonic-gate -1, (off_t)0)) == MAP_FAILED) {
1490Sstevel@tonic-gate tdbp->tdb_hash_alloc_failed = 1;
1500Sstevel@tonic-gate return (NULL);
1510Sstevel@tonic-gate }
1520Sstevel@tonic-gate sap = tdbp->tdb_sync_addr_free = vaddr;
1530Sstevel@tonic-gate for (i = 1; i < tdbp->tdb_sync_alloc; sap++, i++)
1540Sstevel@tonic-gate sap->next = (uintptr_t)(sap + 1);
1550Sstevel@tonic-gate sap->next = (uintptr_t)0;
1560Sstevel@tonic-gate tdbp->tdb_sync_addr_last = sap;
1570Sstevel@tonic-gate
1580Sstevel@tonic-gate sap = tdbp->tdb_sync_addr_free;
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate tdbp->tdb_sync_addr_free = (tdb_sync_stats_t *)(uintptr_t)sap->next;
1620Sstevel@tonic-gate sap->next = (uintptr_t)0;
1630Sstevel@tonic-gate sap->sync_addr = (uintptr_t)addr;
1646515Sraf (void) memset(&sap->un, 0, sizeof (sap->un));
1650Sstevel@tonic-gate return (sap);
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate static void
initialize_sync_hash()1690Sstevel@tonic-gate initialize_sync_hash()
1700Sstevel@tonic-gate {
1710Sstevel@tonic-gate uberdata_t *udp = curthread->ul_uberdata;
1720Sstevel@tonic-gate tdb_t *tdbp = &udp->tdb;
1730Sstevel@tonic-gate uint64_t *addr_hash;
1740Sstevel@tonic-gate tdb_sync_stats_t *sap;
1750Sstevel@tonic-gate void *vaddr;
1760Sstevel@tonic-gate int i;
1770Sstevel@tonic-gate
1780Sstevel@tonic-gate if (tdbp->tdb_hash_alloc_failed)
1790Sstevel@tonic-gate return;
1800Sstevel@tonic-gate lmutex_lock(&udp->tdb_hash_lock);
1810Sstevel@tonic-gate if (udp->uberflags.uf_tdb_register_sync == REGISTER_SYNC_DISABLE) {
1820Sstevel@tonic-gate /*
1830Sstevel@tonic-gate * There is no point allocating the hash table
1840Sstevel@tonic-gate * if we are disabling registration.
1850Sstevel@tonic-gate */
1860Sstevel@tonic-gate udp->uberflags.uf_tdb_register_sync = REGISTER_SYNC_OFF;
1870Sstevel@tonic-gate lmutex_unlock(&udp->tdb_hash_lock);
1880Sstevel@tonic-gate return;
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate if (tdbp->tdb_sync_addr_hash != NULL || tdbp->tdb_hash_alloc_failed) {
1910Sstevel@tonic-gate lmutex_unlock(&udp->tdb_hash_lock);
1920Sstevel@tonic-gate return;
1930Sstevel@tonic-gate }
1940Sstevel@tonic-gate /* start with a free list of 2k elements */
1950Sstevel@tonic-gate tdbp->tdb_sync_alloc = 2*1024;
1966515Sraf if ((vaddr = mmap(NULL, TDB_HASH_SIZE * sizeof (uint64_t) +
1970Sstevel@tonic-gate tdbp->tdb_sync_alloc * sizeof (tdb_sync_stats_t),
1980Sstevel@tonic-gate PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON,
1990Sstevel@tonic-gate -1, (off_t)0)) == MAP_FAILED) {
2000Sstevel@tonic-gate tdbp->tdb_hash_alloc_failed = 1;
2010Sstevel@tonic-gate return;
2020Sstevel@tonic-gate }
2030Sstevel@tonic-gate addr_hash = vaddr;
2040Sstevel@tonic-gate
2050Sstevel@tonic-gate /* initialize the free list */
2060Sstevel@tonic-gate tdbp->tdb_sync_addr_free = sap =
2076515Sraf (tdb_sync_stats_t *)&addr_hash[TDB_HASH_SIZE];
2080Sstevel@tonic-gate for (i = 1; i < tdbp->tdb_sync_alloc; sap++, i++)
2090Sstevel@tonic-gate sap->next = (uintptr_t)(sap + 1);
2100Sstevel@tonic-gate sap->next = (uintptr_t)0;
2110Sstevel@tonic-gate tdbp->tdb_sync_addr_last = sap;
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate /* insert &udp->tdb_hash_lock itself into the new (empty) table */
2140Sstevel@tonic-gate udp->tdb_hash_lock_stats.next = (uintptr_t)0;
2150Sstevel@tonic-gate udp->tdb_hash_lock_stats.sync_addr = (uintptr_t)&udp->tdb_hash_lock;
2160Sstevel@tonic-gate addr_hash[tdb_addr_hash(&udp->tdb_hash_lock)] =
2176515Sraf (uintptr_t)&udp->tdb_hash_lock_stats;
2180Sstevel@tonic-gate
2193864Sraf tdbp->tdb_register_count = 1;
2200Sstevel@tonic-gate /* assign to tdb_sync_addr_hash only after fully initialized */
221*6812Sraf membar_producer();
2220Sstevel@tonic-gate tdbp->tdb_sync_addr_hash = addr_hash;
2230Sstevel@tonic-gate lmutex_unlock(&udp->tdb_hash_lock);
2240Sstevel@tonic-gate }
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate tdb_sync_stats_t *
tdb_sync_obj_register(void * addr,int * new)2270Sstevel@tonic-gate tdb_sync_obj_register(void *addr, int *new)
2280Sstevel@tonic-gate {
2290Sstevel@tonic-gate ulwp_t *self = curthread;
2300Sstevel@tonic-gate uberdata_t *udp = self->ul_uberdata;
2310Sstevel@tonic-gate tdb_t *tdbp = &udp->tdb;
2320Sstevel@tonic-gate uint64_t *sapp;
2330Sstevel@tonic-gate tdb_sync_stats_t *sap = NULL;
2340Sstevel@tonic-gate int locked = 0;
2350Sstevel@tonic-gate int i;
2360Sstevel@tonic-gate
2370Sstevel@tonic-gate /*
2380Sstevel@tonic-gate * Don't start statistics collection until
2390Sstevel@tonic-gate * we have initialized the primary link map.
2400Sstevel@tonic-gate */
2410Sstevel@tonic-gate if (!self->ul_primarymap)
2420Sstevel@tonic-gate return (NULL);
2430Sstevel@tonic-gate
2440Sstevel@tonic-gate if (new)
2450Sstevel@tonic-gate *new = 0;
2460Sstevel@tonic-gate /*
2470Sstevel@tonic-gate * To avoid recursion problems, we must do two things:
2480Sstevel@tonic-gate * 1. Make a special case for tdb_hash_lock (we use it internally).
2490Sstevel@tonic-gate * 2. Deal with the dynamic linker's lock interface:
2500Sstevel@tonic-gate * When calling any external function, we may invoke the
2510Sstevel@tonic-gate * dynamic linker. It grabs a lock, which calls back here.
2520Sstevel@tonic-gate * This only happens on the first call to the external
2530Sstevel@tonic-gate * function, so we can just return NULL if we are called
2540Sstevel@tonic-gate * recursively (and miss the first count).
2550Sstevel@tonic-gate */
2560Sstevel@tonic-gate if (addr == (void *)&udp->tdb_hash_lock)
2570Sstevel@tonic-gate return (&udp->tdb_hash_lock_stats);
2580Sstevel@tonic-gate if (self->ul_sync_obj_reg) /* recursive call */
2590Sstevel@tonic-gate return (NULL);
2600Sstevel@tonic-gate self->ul_sync_obj_reg = 1;
2610Sstevel@tonic-gate
2620Sstevel@tonic-gate /*
2630Sstevel@tonic-gate * On the first time through, initialize the hash table and free list.
2640Sstevel@tonic-gate */
2650Sstevel@tonic-gate if (tdbp->tdb_sync_addr_hash == NULL) {
2660Sstevel@tonic-gate initialize_sync_hash();
2670Sstevel@tonic-gate if (tdbp->tdb_sync_addr_hash == NULL) { /* utter failure */
2680Sstevel@tonic-gate udp->uberflags.uf_tdb_register_sync = REGISTER_SYNC_OFF;
2690Sstevel@tonic-gate goto out;
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate }
272*6812Sraf membar_consumer();
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate sapp = &tdbp->tdb_sync_addr_hash[tdb_addr_hash(addr)];
2750Sstevel@tonic-gate if (udp->uberflags.uf_tdb_register_sync == REGISTER_SYNC_ON) {
2760Sstevel@tonic-gate /*
2770Sstevel@tonic-gate * Look up an address in the synchronization object hash table.
2780Sstevel@tonic-gate * No lock is required since it can only deliver a false
2790Sstevel@tonic-gate * negative, in which case we fall into the locked case below.
2800Sstevel@tonic-gate */
2810Sstevel@tonic-gate for (sap = (tdb_sync_stats_t *)(uintptr_t)*sapp; sap != NULL;
2820Sstevel@tonic-gate sap = (tdb_sync_stats_t *)(uintptr_t)sap->next) {
2830Sstevel@tonic-gate if (sap->sync_addr == (uintptr_t)addr)
2840Sstevel@tonic-gate goto out;
2850Sstevel@tonic-gate }
2860Sstevel@tonic-gate }
2870Sstevel@tonic-gate
2880Sstevel@tonic-gate /*
2890Sstevel@tonic-gate * The search with no lock held failed or a special action is required.
2900Sstevel@tonic-gate * Grab tdb_hash_lock to do special actions and/or get a precise result.
2910Sstevel@tonic-gate */
2920Sstevel@tonic-gate lmutex_lock(&udp->tdb_hash_lock);
2930Sstevel@tonic-gate locked = 1;
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate switch (udp->uberflags.uf_tdb_register_sync) {
2960Sstevel@tonic-gate case REGISTER_SYNC_ON:
2970Sstevel@tonic-gate break;
2980Sstevel@tonic-gate case REGISTER_SYNC_OFF:
2990Sstevel@tonic-gate goto out;
3000Sstevel@tonic-gate default:
3010Sstevel@tonic-gate /*
3020Sstevel@tonic-gate * For all debugger actions, first zero out the
3030Sstevel@tonic-gate * statistics block of every element in the hash table.
3040Sstevel@tonic-gate */
3050Sstevel@tonic-gate for (i = 0; i < TDB_HASH_SIZE; i++)
3060Sstevel@tonic-gate for (sap = (tdb_sync_stats_t *)
3070Sstevel@tonic-gate (uintptr_t)tdbp->tdb_sync_addr_hash[i];
3080Sstevel@tonic-gate sap != NULL;
3090Sstevel@tonic-gate sap = (tdb_sync_stats_t *)(uintptr_t)sap->next)
3106515Sraf (void) memset(&sap->un, 0, sizeof (sap->un));
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate switch (udp->uberflags.uf_tdb_register_sync) {
3130Sstevel@tonic-gate case REGISTER_SYNC_ENABLE:
3140Sstevel@tonic-gate udp->uberflags.uf_tdb_register_sync = REGISTER_SYNC_ON;
3150Sstevel@tonic-gate break;
3160Sstevel@tonic-gate case REGISTER_SYNC_DISABLE:
3170Sstevel@tonic-gate default:
3180Sstevel@tonic-gate udp->uberflags.uf_tdb_register_sync = REGISTER_SYNC_OFF;
3190Sstevel@tonic-gate goto out;
3200Sstevel@tonic-gate }
3210Sstevel@tonic-gate break;
3220Sstevel@tonic-gate }
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate /*
3250Sstevel@tonic-gate * Perform the search while holding tdb_hash_lock.
3260Sstevel@tonic-gate * Keep track of the insertion point.
3270Sstevel@tonic-gate */
3280Sstevel@tonic-gate while ((sap = (tdb_sync_stats_t *)(uintptr_t)*sapp) != NULL) {
3290Sstevel@tonic-gate if (sap->sync_addr == (uintptr_t)addr)
3300Sstevel@tonic-gate break;
3310Sstevel@tonic-gate sapp = &sap->next;
3320Sstevel@tonic-gate }
3330Sstevel@tonic-gate
3340Sstevel@tonic-gate /*
3350Sstevel@tonic-gate * Insert a new element if necessary.
3360Sstevel@tonic-gate */
3370Sstevel@tonic-gate if (sap == NULL && (sap = alloc_sync_addr(addr)) != NULL) {
3380Sstevel@tonic-gate *sapp = (uintptr_t)sap;
3390Sstevel@tonic-gate tdbp->tdb_register_count++;
3400Sstevel@tonic-gate if (new)
3410Sstevel@tonic-gate *new = 1;
3420Sstevel@tonic-gate }
3430Sstevel@tonic-gate
3440Sstevel@tonic-gate out:
3450Sstevel@tonic-gate if (locked)
3460Sstevel@tonic-gate lmutex_unlock(&udp->tdb_hash_lock);
3470Sstevel@tonic-gate self->ul_sync_obj_reg = 0;
3480Sstevel@tonic-gate return (sap);
3490Sstevel@tonic-gate }
3500Sstevel@tonic-gate
3510Sstevel@tonic-gate void
tdb_sync_obj_deregister(void * addr)3520Sstevel@tonic-gate tdb_sync_obj_deregister(void *addr)
3530Sstevel@tonic-gate {
3540Sstevel@tonic-gate uberdata_t *udp = curthread->ul_uberdata;
3550Sstevel@tonic-gate tdb_t *tdbp = &udp->tdb;
3560Sstevel@tonic-gate uint64_t *sapp;
3570Sstevel@tonic-gate tdb_sync_stats_t *sap;
3580Sstevel@tonic-gate uint_t hash;
3590Sstevel@tonic-gate
3600Sstevel@tonic-gate /*
3610Sstevel@tonic-gate * tdb_hash_lock is never destroyed.
3620Sstevel@tonic-gate */
3630Sstevel@tonic-gate ASSERT(addr != &udp->tdb_hash_lock);
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate /*
3660Sstevel@tonic-gate * Avoid acquiring tdb_hash_lock if lock statistics gathering has
3670Sstevel@tonic-gate * never been initiated or there is nothing in the hash bucket.
3680Sstevel@tonic-gate * (Once the hash table is allocated, it is never deallocated.)
3690Sstevel@tonic-gate */
3700Sstevel@tonic-gate if (tdbp->tdb_sync_addr_hash == NULL ||
3710Sstevel@tonic-gate tdbp->tdb_sync_addr_hash[hash = tdb_addr_hash(addr)] == NULL)
3720Sstevel@tonic-gate return;
3730Sstevel@tonic-gate
3740Sstevel@tonic-gate lmutex_lock(&udp->tdb_hash_lock);
3750Sstevel@tonic-gate sapp = &tdbp->tdb_sync_addr_hash[hash];
3760Sstevel@tonic-gate while ((sap = (tdb_sync_stats_t *)(uintptr_t)*sapp) != NULL) {
3770Sstevel@tonic-gate if (sap->sync_addr == (uintptr_t)addr) {
3780Sstevel@tonic-gate /* remove it from the hash table */
3790Sstevel@tonic-gate *sapp = sap->next;
3800Sstevel@tonic-gate tdbp->tdb_register_count--;
3810Sstevel@tonic-gate /* clear it */
3820Sstevel@tonic-gate sap->next = (uintptr_t)0;
3830Sstevel@tonic-gate sap->sync_addr = (uintptr_t)0;
3840Sstevel@tonic-gate /* insert it on the tail of the free list */
3850Sstevel@tonic-gate if (tdbp->tdb_sync_addr_free == NULL) {
3860Sstevel@tonic-gate tdbp->tdb_sync_addr_free = sap;
3870Sstevel@tonic-gate tdbp->tdb_sync_addr_last = sap;
3880Sstevel@tonic-gate } else {
3890Sstevel@tonic-gate tdbp->tdb_sync_addr_last->next = (uintptr_t)sap;
3900Sstevel@tonic-gate tdbp->tdb_sync_addr_last = sap;
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate break;
3930Sstevel@tonic-gate }
3940Sstevel@tonic-gate sapp = &sap->next;
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate lmutex_unlock(&udp->tdb_hash_lock);
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate /*
4000Sstevel@tonic-gate * Return a mutex statistics block for the given mutex.
4010Sstevel@tonic-gate */
4020Sstevel@tonic-gate tdb_mutex_stats_t *
tdb_mutex_stats(mutex_t * mp)4030Sstevel@tonic-gate tdb_mutex_stats(mutex_t *mp)
4040Sstevel@tonic-gate {
4050Sstevel@tonic-gate tdb_sync_stats_t *tssp;
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate /* avoid stealing the cache line unnecessarily */
4080Sstevel@tonic-gate if (mp->mutex_magic != MUTEX_MAGIC)
4090Sstevel@tonic-gate mp->mutex_magic = MUTEX_MAGIC;
4100Sstevel@tonic-gate if ((tssp = tdb_sync_obj_register(mp, NULL)) == NULL)
4110Sstevel@tonic-gate return (NULL);
4120Sstevel@tonic-gate tssp->un.type = TDB_MUTEX;
4130Sstevel@tonic-gate return (&tssp->un.mutex);
4140Sstevel@tonic-gate }
4150Sstevel@tonic-gate
4160Sstevel@tonic-gate /*
4170Sstevel@tonic-gate * Return a condvar statistics block for the given condvar.
4180Sstevel@tonic-gate */
4190Sstevel@tonic-gate tdb_cond_stats_t *
tdb_cond_stats(cond_t * cvp)4200Sstevel@tonic-gate tdb_cond_stats(cond_t *cvp)
4210Sstevel@tonic-gate {
4220Sstevel@tonic-gate tdb_sync_stats_t *tssp;
4230Sstevel@tonic-gate
4240Sstevel@tonic-gate /* avoid stealing the cache line unnecessarily */
4250Sstevel@tonic-gate if (cvp->cond_magic != COND_MAGIC)
4260Sstevel@tonic-gate cvp->cond_magic = COND_MAGIC;
4270Sstevel@tonic-gate if ((tssp = tdb_sync_obj_register(cvp, NULL)) == NULL)
4280Sstevel@tonic-gate return (NULL);
4290Sstevel@tonic-gate tssp->un.type = TDB_COND;
4300Sstevel@tonic-gate return (&tssp->un.cond);
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate /*
4340Sstevel@tonic-gate * Return an rwlock statistics block for the given rwlock.
4350Sstevel@tonic-gate */
4360Sstevel@tonic-gate tdb_rwlock_stats_t *
tdb_rwlock_stats(rwlock_t * rwlp)4370Sstevel@tonic-gate tdb_rwlock_stats(rwlock_t *rwlp)
4380Sstevel@tonic-gate {
4390Sstevel@tonic-gate tdb_sync_stats_t *tssp;
4400Sstevel@tonic-gate
4410Sstevel@tonic-gate /* avoid stealing the cache line unnecessarily */
4420Sstevel@tonic-gate if (rwlp->magic != RWL_MAGIC)
4430Sstevel@tonic-gate rwlp->magic = RWL_MAGIC;
4440Sstevel@tonic-gate if ((tssp = tdb_sync_obj_register(rwlp, NULL)) == NULL)
4450Sstevel@tonic-gate return (NULL);
4460Sstevel@tonic-gate tssp->un.type = TDB_RWLOCK;
4470Sstevel@tonic-gate return (&tssp->un.rwlock);
4480Sstevel@tonic-gate }
4490Sstevel@tonic-gate
4500Sstevel@tonic-gate /*
4510Sstevel@tonic-gate * Return a semaphore statistics block for the given semaphore.
4520Sstevel@tonic-gate */
4530Sstevel@tonic-gate tdb_sema_stats_t *
tdb_sema_stats(sema_t * sp)4540Sstevel@tonic-gate tdb_sema_stats(sema_t *sp)
4550Sstevel@tonic-gate {
4560Sstevel@tonic-gate tdb_sync_stats_t *tssp;
4570Sstevel@tonic-gate int new;
4580Sstevel@tonic-gate
4590Sstevel@tonic-gate /* avoid stealing the cache line unnecessarily */
4600Sstevel@tonic-gate if (sp->magic != SEMA_MAGIC)
4610Sstevel@tonic-gate sp->magic = SEMA_MAGIC;
4620Sstevel@tonic-gate if ((tssp = tdb_sync_obj_register(sp, &new)) == NULL)
4630Sstevel@tonic-gate return (NULL);
4640Sstevel@tonic-gate tssp->un.type = TDB_SEMA;
4650Sstevel@tonic-gate if (new) {
4660Sstevel@tonic-gate tssp->un.sema.sema_max_count = sp->count;
4670Sstevel@tonic-gate tssp->un.sema.sema_min_count = sp->count;
4680Sstevel@tonic-gate }
4690Sstevel@tonic-gate return (&tssp->un.sema);
4700Sstevel@tonic-gate }
471