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 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23*a87701e9SGary Mills * Copyright 2015 Gary Mills 247c478bd9Sstevel@tonic-gate * Copyright (c) 2001 by Sun Microsystems, Inc. 257c478bd9Sstevel@tonic-gate * All rights reserved. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <stdio.h> 297c478bd9Sstevel@tonic-gate #include <rpc/types.h> 307c478bd9Sstevel@tonic-gate #include <rpc/xdr.h> 317c478bd9Sstevel@tonic-gate #include "db_dictionary_c.h" 327c478bd9Sstevel@tonic-gate #include "nisdb_rw.h" 337c478bd9Sstevel@tonic-gate #include "nisdb_ldap.h" 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate /* 367c478bd9Sstevel@tonic-gate * Nesting-safe RW locking functions. Return 0 when successful, an 377c478bd9Sstevel@tonic-gate * error number from the E-series when not. 387c478bd9Sstevel@tonic-gate */ 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate int 417c478bd9Sstevel@tonic-gate __nisdb_rwinit(__nisdb_rwlock_t *rw) { 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate int ret; 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate if (rw == 0) { 467c478bd9Sstevel@tonic-gate #ifdef NISDB_MT_DEBUG 477c478bd9Sstevel@tonic-gate abort(); 487c478bd9Sstevel@tonic-gate #endif /* NISDB_MT_DEBUG */ 497c478bd9Sstevel@tonic-gate return (EFAULT); 507c478bd9Sstevel@tonic-gate } 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate if ((ret = mutex_init(&rw->mutex, USYNC_THREAD, 0)) != 0) 537c478bd9Sstevel@tonic-gate return (ret); 547c478bd9Sstevel@tonic-gate if ((ret = cond_init(&rw->cv, USYNC_THREAD, 0)) != 0) 557c478bd9Sstevel@tonic-gate return (ret); 567c478bd9Sstevel@tonic-gate rw->destroyed = 0; 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate /* 597c478bd9Sstevel@tonic-gate * If we allow read-to-write lock migration, there's a potential 607c478bd9Sstevel@tonic-gate * race condition if two or more threads want to upgrade at the 617c478bd9Sstevel@tonic-gate * same time. The simple and safe (but crude and possibly costly) 627c478bd9Sstevel@tonic-gate * method to fix this is to always use exclusive locks, and so 637c478bd9Sstevel@tonic-gate * that has to be the default. 647c478bd9Sstevel@tonic-gate * 657c478bd9Sstevel@tonic-gate * There are two conditions under which it is safe to set 667c478bd9Sstevel@tonic-gate * 'force_write' to zero for a certain lock structure: 677c478bd9Sstevel@tonic-gate * 687c478bd9Sstevel@tonic-gate * (1) The lock will never be subject to migration, or 697c478bd9Sstevel@tonic-gate * 707c478bd9Sstevel@tonic-gate * (2) It's OK if the data protected by the lock has changed 717c478bd9Sstevel@tonic-gate * (a) Every time the lock (read or write) has been 727c478bd9Sstevel@tonic-gate * acquired (even if the lock already was held by 737c478bd9Sstevel@tonic-gate * the thread), and 747c478bd9Sstevel@tonic-gate * (b) After every call to a function that might have 757c478bd9Sstevel@tonic-gate * acquired the lock. 767c478bd9Sstevel@tonic-gate */ 777c478bd9Sstevel@tonic-gate rw->force_write = NISDB_FORCE_WRITE; 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate rw->writer_count = rw->reader_count = rw->reader_blocked = 0; 807c478bd9Sstevel@tonic-gate rw->writer.id = rw->reader.id = INV_PTHREAD_ID; 817c478bd9Sstevel@tonic-gate rw->writer.count = rw->reader.count = 0; 827c478bd9Sstevel@tonic-gate rw->writer.next = rw->reader.next = 0; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate return (0); 857c478bd9Sstevel@tonic-gate } 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate static __nisdb_rl_t * 897c478bd9Sstevel@tonic-gate find_reader(pthread_t id, __nisdb_rwlock_t *rw) { 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate __nisdb_rl_t *rr; 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate for (rr = &rw->reader; rr != 0; rr = rr->next) { 947c478bd9Sstevel@tonic-gate if (rr->id == INV_PTHREAD_ID) { 957c478bd9Sstevel@tonic-gate rr = 0; 967c478bd9Sstevel@tonic-gate break; 977c478bd9Sstevel@tonic-gate } 987c478bd9Sstevel@tonic-gate if (rr->id == id) 997c478bd9Sstevel@tonic-gate break; 1007c478bd9Sstevel@tonic-gate } 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate return (rr); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate int 1077c478bd9Sstevel@tonic-gate __nisdb_rw_readlock_ok(__nisdb_rwlock_t *rw) { 1087c478bd9Sstevel@tonic-gate int ret; 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate if (rw == 0) 1117c478bd9Sstevel@tonic-gate return (EFAULT); 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate if (rw->destroyed != 0) 1147c478bd9Sstevel@tonic-gate return (ESHUTDOWN); 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate if ((ret = mutex_lock(&rw->mutex)) != 0) 1177c478bd9Sstevel@tonic-gate return (ret); 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate /* 1207c478bd9Sstevel@tonic-gate * Only allow changing 'force_write' when it's really safe; i.e., 1217c478bd9Sstevel@tonic-gate * the lock hasn't been destroyed, and there are no readers. 1227c478bd9Sstevel@tonic-gate */ 1237c478bd9Sstevel@tonic-gate if (rw->destroyed == 0 && rw->reader_count == 0) { 1247c478bd9Sstevel@tonic-gate rw->force_write = 0; 1257c478bd9Sstevel@tonic-gate ret = 0; 1267c478bd9Sstevel@tonic-gate } else { 1277c478bd9Sstevel@tonic-gate ret = EBUSY; 1287c478bd9Sstevel@tonic-gate } 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate return (ret); 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate int 1377c478bd9Sstevel@tonic-gate __nisdb_rw_force_writelock(__nisdb_rwlock_t *rw) { 1387c478bd9Sstevel@tonic-gate int ret; 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate if (rw == 0 || rw->destroyed != 0) 1417c478bd9Sstevel@tonic-gate return (ESHUTDOWN); 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate if ((ret = mutex_lock(&rw->mutex)) != 0) 1447c478bd9Sstevel@tonic-gate return (ret); 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate /* 1477c478bd9Sstevel@tonic-gate * Only allow changing 'force_write' when it's really safe; i.e., 1487c478bd9Sstevel@tonic-gate * the lock hasn't been destroyed, and there are no readers. 1497c478bd9Sstevel@tonic-gate */ 1507c478bd9Sstevel@tonic-gate if (rw->destroyed == 0 && rw->reader_count == 0) { 1517c478bd9Sstevel@tonic-gate rw->force_write = 1; 1527c478bd9Sstevel@tonic-gate ret = 0; 1537c478bd9Sstevel@tonic-gate } else { 1547c478bd9Sstevel@tonic-gate ret = EBUSY; 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate return (ret); 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate int 1647c478bd9Sstevel@tonic-gate __nisdb_wlock_trylock(__nisdb_rwlock_t *rw, int trylock) { 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate int ret; 1677c478bd9Sstevel@tonic-gate pthread_t myself = pthread_self(); 1687c478bd9Sstevel@tonic-gate int all_readers_blocked = 0; 1697c478bd9Sstevel@tonic-gate __nisdb_rl_t *rr = 0; 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate if (rw == 0) { 1727c478bd9Sstevel@tonic-gate #ifdef NISDB_MT_DEBUG 1737c478bd9Sstevel@tonic-gate /* This shouldn't happen */ 1747c478bd9Sstevel@tonic-gate abort(); 1757c478bd9Sstevel@tonic-gate #endif /* NISDB_MT_DEBUG */ 1767c478bd9Sstevel@tonic-gate return (EFAULT); 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate if (rw->destroyed != 0) 1807c478bd9Sstevel@tonic-gate return (ESHUTDOWN); 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate if ((ret = mutex_lock(&rw->mutex)) != 0) 1837c478bd9Sstevel@tonic-gate return (ret); 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate if (rw->destroyed != 0) { 1867c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 1877c478bd9Sstevel@tonic-gate return (ESHUTDOWN); 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate /* Simplest (and probably most common) case: no readers or writers */ 1917c478bd9Sstevel@tonic-gate if (rw->reader_count == 0 && rw->writer_count == 0) { 1927c478bd9Sstevel@tonic-gate rw->writer_count = 1; 1937c478bd9Sstevel@tonic-gate rw->writer.id = myself; 1947c478bd9Sstevel@tonic-gate rw->writer.count = 1; 1957c478bd9Sstevel@tonic-gate return (mutex_unlock(&rw->mutex)); 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate /* 1997c478bd9Sstevel@tonic-gate * Need to know if we're holding a read lock already, and if 2007c478bd9Sstevel@tonic-gate * all other readers are blocked waiting for the mutex. 2017c478bd9Sstevel@tonic-gate */ 2027c478bd9Sstevel@tonic-gate if (rw->reader_count > 0) { 2037c478bd9Sstevel@tonic-gate if ((rr = find_reader(myself, rw)) != 0) { 204*a87701e9SGary Mills if (rr->count) { 2057c478bd9Sstevel@tonic-gate /* 2067c478bd9Sstevel@tonic-gate * We're already holding a read lock, so 2077c478bd9Sstevel@tonic-gate * if the number of readers equals the number 2087c478bd9Sstevel@tonic-gate * of blocked readers plus one, all other 2097c478bd9Sstevel@tonic-gate * readers are blocked. 2107c478bd9Sstevel@tonic-gate */ 2117c478bd9Sstevel@tonic-gate if (rw->reader_count == 2127c478bd9Sstevel@tonic-gate (rw->reader_blocked + 1)) 2137c478bd9Sstevel@tonic-gate all_readers_blocked = 1; 214*a87701e9SGary Mills } else { 2157c478bd9Sstevel@tonic-gate /* 2167c478bd9Sstevel@tonic-gate * We're not holding a read lock, so the 2177c478bd9Sstevel@tonic-gate * number of readers should equal the number 2187c478bd9Sstevel@tonic-gate * of blocked readers if all readers are 2197c478bd9Sstevel@tonic-gate * blocked. 2207c478bd9Sstevel@tonic-gate */ 2217c478bd9Sstevel@tonic-gate if (rw->reader_count == rw->reader_blocked) 2227c478bd9Sstevel@tonic-gate all_readers_blocked = 1; 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate } 225*a87701e9SGary Mills } 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate /* Wait for reader(s) or writer to finish */ 2287c478bd9Sstevel@tonic-gate while (1) { 2297c478bd9Sstevel@tonic-gate /* 2307c478bd9Sstevel@tonic-gate * We can stop looping if one of the following holds: 2317c478bd9Sstevel@tonic-gate * - No readers, no writers 2327c478bd9Sstevel@tonic-gate * - No writers (or writer is myself), and one of: 2337c478bd9Sstevel@tonic-gate * - No readers 2347c478bd9Sstevel@tonic-gate * - One reader, and it's us 2357c478bd9Sstevel@tonic-gate * - N readers, but all blocked on the mutex 2367c478bd9Sstevel@tonic-gate */ 2377c478bd9Sstevel@tonic-gate if ( 2387c478bd9Sstevel@tonic-gate (rw->writer_count == 0 && rw->reader_count == 0) || 239*a87701e9SGary Mills (((rw->writer_count == 0 || rw->writer.id == myself) && 240*a87701e9SGary Mills (rw->reader_count == 0)) || 2417c478bd9Sstevel@tonic-gate (rw->reader_count == 1 && 2427c478bd9Sstevel@tonic-gate rw->reader.id == myself))) { 2437c478bd9Sstevel@tonic-gate break; 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate /* 2467c478bd9Sstevel@tonic-gate * Provided that all readers are blocked on the mutex 2477c478bd9Sstevel@tonic-gate * we break a potential dead-lock by acquiring the 2487c478bd9Sstevel@tonic-gate * write lock. 2497c478bd9Sstevel@tonic-gate */ 2507c478bd9Sstevel@tonic-gate if (all_readers_blocked) { 2517c478bd9Sstevel@tonic-gate if (rw->writer_count == 0 || rw->writer.id == myself) { 2527c478bd9Sstevel@tonic-gate break; 2537c478bd9Sstevel@tonic-gate } 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate /* 2577c478bd9Sstevel@tonic-gate * If 'trylock' is set, tell the caller that we'd have to 2587c478bd9Sstevel@tonic-gate * block to obtain the lock. 2597c478bd9Sstevel@tonic-gate */ 2607c478bd9Sstevel@tonic-gate if (trylock) { 2617c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 2627c478bd9Sstevel@tonic-gate return (EBUSY); 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate /* If we're also a reader, indicate that we're blocking */ 2667c478bd9Sstevel@tonic-gate if (rr != 0) { 2677c478bd9Sstevel@tonic-gate rr->wait = 1; 2687c478bd9Sstevel@tonic-gate rw->reader_blocked++; 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate if ((ret = cond_wait(&rw->cv, &rw->mutex)) != 0) { 2717c478bd9Sstevel@tonic-gate if (rr != 0) { 2727c478bd9Sstevel@tonic-gate rr->wait = 0; 2737c478bd9Sstevel@tonic-gate if (rw->reader_blocked > 0) 2747c478bd9Sstevel@tonic-gate rw->reader_blocked--; 2757c478bd9Sstevel@tonic-gate #ifdef NISDB_MT_DEBUG 2767c478bd9Sstevel@tonic-gate else 2777c478bd9Sstevel@tonic-gate abort(); 2787c478bd9Sstevel@tonic-gate #endif /* NISDB_MT_DEBUG */ 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 2817c478bd9Sstevel@tonic-gate return (ret); 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate if (rr != 0) { 2847c478bd9Sstevel@tonic-gate rr->wait = 0; 2857c478bd9Sstevel@tonic-gate if (rw->reader_blocked > 0) 2867c478bd9Sstevel@tonic-gate rw->reader_blocked--; 2877c478bd9Sstevel@tonic-gate #ifdef NISDB_MT_DEBUG 2887c478bd9Sstevel@tonic-gate else 2897c478bd9Sstevel@tonic-gate abort(); 2907c478bd9Sstevel@tonic-gate #endif /* NISDB_MT_DEBUG */ 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate /* OK to grab the write lock */ 2957c478bd9Sstevel@tonic-gate rw->writer.id = myself; 2967c478bd9Sstevel@tonic-gate /* Increment lock depth */ 2977c478bd9Sstevel@tonic-gate rw->writer.count++; 2987c478bd9Sstevel@tonic-gate /* Set number of writers (doesn't increase with lock depth) */ 2997c478bd9Sstevel@tonic-gate if (rw->writer_count == 0) 3007c478bd9Sstevel@tonic-gate rw->writer_count = 1; 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate return (mutex_unlock(&rw->mutex)); 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate int 3067c478bd9Sstevel@tonic-gate __nisdb_wlock(__nisdb_rwlock_t *rw) { 3077c478bd9Sstevel@tonic-gate return (__nisdb_wlock_trylock(rw, 0)); 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate static __nisdb_rl_t * 3127c478bd9Sstevel@tonic-gate increment_reader(pthread_t id, __nisdb_rwlock_t *rw) { 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate __nisdb_rl_t *rr; 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate for (rr = &rw->reader; rr != 0; rr = rr->next) { 3177c478bd9Sstevel@tonic-gate if (rr->id == id || rr->id == INV_PTHREAD_ID) 3187c478bd9Sstevel@tonic-gate break; 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate if (rw->reader_count == 0 && rr == &rw->reader) { 3217c478bd9Sstevel@tonic-gate /* No previous reader */ 3227c478bd9Sstevel@tonic-gate rr->id = id; 3237c478bd9Sstevel@tonic-gate rw->reader_count = 1; 3247c478bd9Sstevel@tonic-gate } else if (rr == 0) { 3257c478bd9Sstevel@tonic-gate if ((rr = malloc(sizeof (__nisdb_rl_t))) == 0) 3267c478bd9Sstevel@tonic-gate return (0); 3277c478bd9Sstevel@tonic-gate rr->id = id; 3287c478bd9Sstevel@tonic-gate rr->count = 0; 3297c478bd9Sstevel@tonic-gate /* 3307c478bd9Sstevel@tonic-gate * For insertion simplicity, make it the second item 3317c478bd9Sstevel@tonic-gate * on the list. 3327c478bd9Sstevel@tonic-gate */ 3337c478bd9Sstevel@tonic-gate rr->next = rw->reader.next; 3347c478bd9Sstevel@tonic-gate rw->reader.next = rr; 3357c478bd9Sstevel@tonic-gate rw->reader_count++; 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate rr->count++; 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate return (rr); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate int 3447c478bd9Sstevel@tonic-gate __nisdb_rlock(__nisdb_rwlock_t *rw) { 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate int ret; 3477c478bd9Sstevel@tonic-gate pthread_t myself = pthread_self(); 3487c478bd9Sstevel@tonic-gate __nisdb_rl_t *rr; 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate if (rw == 0) { 3517c478bd9Sstevel@tonic-gate #ifdef NISDB_MT_DEBUG 3527c478bd9Sstevel@tonic-gate /* This shouldn't happen */ 3537c478bd9Sstevel@tonic-gate abort(); 3547c478bd9Sstevel@tonic-gate #endif /* NISDB_MT_DEBUG */ 3557c478bd9Sstevel@tonic-gate return (EFAULT); 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate if (rw->destroyed != 0) 3597c478bd9Sstevel@tonic-gate return (ESHUTDOWN); 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate if (rw->force_write) 3627c478bd9Sstevel@tonic-gate return (__nisdb_wlock(rw)); 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate if ((ret = mutex_lock(&rw->mutex)) != 0) 3657c478bd9Sstevel@tonic-gate return (ret); 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate if (rw->destroyed != 0) { 3687c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 3697c478bd9Sstevel@tonic-gate return (ESHUTDOWN); 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate rr = find_reader(myself, rw); 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate /* Wait for writer to complete; writer == myself also OK */ 3757c478bd9Sstevel@tonic-gate while (rw->writer_count > 0 && rw->writer.id != myself) { 3767c478bd9Sstevel@tonic-gate if (rr != 0) { 3777c478bd9Sstevel@tonic-gate rr->wait = 1; 3787c478bd9Sstevel@tonic-gate rw->reader_blocked++; 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate if ((ret = cond_wait(&rw->cv, &rw->mutex)) != 0) { 3817c478bd9Sstevel@tonic-gate if (rr != 0) { 3827c478bd9Sstevel@tonic-gate rr->wait = 0; 3837c478bd9Sstevel@tonic-gate if (rw->reader_blocked > 0) 3847c478bd9Sstevel@tonic-gate rw->reader_blocked--; 3857c478bd9Sstevel@tonic-gate #ifdef NISDB_MT_DEBUG 3867c478bd9Sstevel@tonic-gate else 3877c478bd9Sstevel@tonic-gate abort(); 3887c478bd9Sstevel@tonic-gate #endif /* NISDB_MT_DEBUG */ 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 3917c478bd9Sstevel@tonic-gate return (ret); 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate if (rr != 0) { 3947c478bd9Sstevel@tonic-gate rr->wait = 0; 3957c478bd9Sstevel@tonic-gate if (rw->reader_blocked > 0) 3967c478bd9Sstevel@tonic-gate rw->reader_blocked--; 3977c478bd9Sstevel@tonic-gate #ifdef NISDB_MT_DEBUG 3987c478bd9Sstevel@tonic-gate else 3997c478bd9Sstevel@tonic-gate abort(); 4007c478bd9Sstevel@tonic-gate #endif /* NISDB_MT_DEBUG */ 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate } 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate rr = increment_reader(myself, rw); 4057c478bd9Sstevel@tonic-gate ret = mutex_unlock(&rw->mutex); 4067c478bd9Sstevel@tonic-gate return ((rr == 0) ? ENOMEM : ret); 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate int 4117c478bd9Sstevel@tonic-gate __nisdb_wulock(__nisdb_rwlock_t *rw) { 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate int ret; 4147c478bd9Sstevel@tonic-gate pthread_t myself = pthread_self(); 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate if (rw == 0) { 4177c478bd9Sstevel@tonic-gate #ifdef NISDB_MT_DEBUG 4187c478bd9Sstevel@tonic-gate /* This shouldn't happen */ 4197c478bd9Sstevel@tonic-gate abort(); 4207c478bd9Sstevel@tonic-gate #endif /* NISDB_MT_DEBUG */ 4217c478bd9Sstevel@tonic-gate return (EFAULT); 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate if (rw->destroyed != 0) 4257c478bd9Sstevel@tonic-gate return (ESHUTDOWN); 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate if ((ret = mutex_lock(&rw->mutex)) != 0) 4287c478bd9Sstevel@tonic-gate return (ret); 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate if (rw->destroyed != 0) { 4317c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 4327c478bd9Sstevel@tonic-gate return (ESHUTDOWN); 4337c478bd9Sstevel@tonic-gate } 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate /* Sanity check */ 4367c478bd9Sstevel@tonic-gate if (rw->writer_count == 0 || 4377c478bd9Sstevel@tonic-gate rw->writer.id != myself || rw->writer.count == 0) { 4387c478bd9Sstevel@tonic-gate #ifdef NISDB_MT_DEBUG 4397c478bd9Sstevel@tonic-gate abort(); 4407c478bd9Sstevel@tonic-gate #endif /* NISDB_MT_DEBUG */ 4417c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 4427c478bd9Sstevel@tonic-gate return (ENOLCK); 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate rw->writer.count--; 4467c478bd9Sstevel@tonic-gate if (rw->writer.count == 0) { 4477c478bd9Sstevel@tonic-gate rw->writer.id = INV_PTHREAD_ID; 4487c478bd9Sstevel@tonic-gate rw->writer_count = 0; 4497c478bd9Sstevel@tonic-gate if ((ret = cond_broadcast(&rw->cv)) != 0) { 4507c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 4517c478bd9Sstevel@tonic-gate return (ret); 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate return (mutex_unlock(&rw->mutex)); 4567c478bd9Sstevel@tonic-gate } 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate int 4607c478bd9Sstevel@tonic-gate __nisdb_rulock(__nisdb_rwlock_t *rw) { 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate int ret; 4637c478bd9Sstevel@tonic-gate pthread_t myself = pthread_self(); 4647c478bd9Sstevel@tonic-gate __nisdb_rl_t *rr, *prev; 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate if (rw == 0) { 4677c478bd9Sstevel@tonic-gate #ifdef NISDB_MT_DEBUG 4687c478bd9Sstevel@tonic-gate abort(); 4697c478bd9Sstevel@tonic-gate #endif /* NISDB_MT_DEBUG */ 4707c478bd9Sstevel@tonic-gate return (EFAULT); 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate if (rw->destroyed != 0) 4747c478bd9Sstevel@tonic-gate return (ESHUTDOWN); 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate if (rw->force_write) 4777c478bd9Sstevel@tonic-gate return (__nisdb_wulock(rw)); 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate if ((ret = mutex_lock(&rw->mutex)) != 0) 4807c478bd9Sstevel@tonic-gate return (ret); 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate if (rw->destroyed != 0) { 4837c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 4847c478bd9Sstevel@tonic-gate return (ESHUTDOWN); 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate /* Sanity check */ 4887c478bd9Sstevel@tonic-gate if (rw->reader_count == 0 || 4897c478bd9Sstevel@tonic-gate (rw->writer_count > 0 && rw->writer.id != myself)) { 4907c478bd9Sstevel@tonic-gate #ifdef NISDB_MT_DEBUG 4917c478bd9Sstevel@tonic-gate abort(); 4927c478bd9Sstevel@tonic-gate #endif /* NISDB_MT_DEBUG */ 4937c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 4947c478bd9Sstevel@tonic-gate return (ENOLCK); 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate /* Find the reader record */ 4987c478bd9Sstevel@tonic-gate for (rr = &rw->reader, prev = 0; rr != 0; prev = rr, rr = rr->next) { 4997c478bd9Sstevel@tonic-gate if (rr->id == myself) 5007c478bd9Sstevel@tonic-gate break; 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate if (rr == 0 || rr->count == 0) { 5047c478bd9Sstevel@tonic-gate #ifdef NISDB_MT_DEBUG 5057c478bd9Sstevel@tonic-gate abort(); 5067c478bd9Sstevel@tonic-gate #endif /* NISDB_MT_DEBUG */ 5077c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 5087c478bd9Sstevel@tonic-gate return (ENOLCK); 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate rr->count--; 5127c478bd9Sstevel@tonic-gate if (rr->count == 0) { 5137c478bd9Sstevel@tonic-gate if (rr != &rw->reader) { 5147c478bd9Sstevel@tonic-gate /* Remove item from list and free it */ 5157c478bd9Sstevel@tonic-gate prev->next = rr->next; 5167c478bd9Sstevel@tonic-gate free(rr); 5177c478bd9Sstevel@tonic-gate } else { 5187c478bd9Sstevel@tonic-gate /* 5197c478bd9Sstevel@tonic-gate * First record: copy second to first, and free second 5207c478bd9Sstevel@tonic-gate * record. 5217c478bd9Sstevel@tonic-gate */ 5227c478bd9Sstevel@tonic-gate if (rr->next != 0) { 5237c478bd9Sstevel@tonic-gate rr = rr->next; 5247c478bd9Sstevel@tonic-gate rw->reader.id = rr->id; 5257c478bd9Sstevel@tonic-gate rw->reader.count = rr->count; 5267c478bd9Sstevel@tonic-gate rw->reader.next = rr->next; 5277c478bd9Sstevel@tonic-gate free(rr); 5287c478bd9Sstevel@tonic-gate } else { 5297c478bd9Sstevel@tonic-gate /* Decomission the first record */ 5307c478bd9Sstevel@tonic-gate rr->id = INV_PTHREAD_ID; 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate rw->reader_count--; 5347c478bd9Sstevel@tonic-gate } 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate /* If there are no readers, wake up any waiting writer */ 5377c478bd9Sstevel@tonic-gate if (rw->reader_count == 0) { 5387c478bd9Sstevel@tonic-gate if ((ret = cond_broadcast(&rw->cv)) != 0) { 5397c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 5407c478bd9Sstevel@tonic-gate return (ret); 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate return (mutex_unlock(&rw->mutex)); 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate /* Return zero if write lock held by this thread, non-zero otherwise */ 5497c478bd9Sstevel@tonic-gate int 5507c478bd9Sstevel@tonic-gate __nisdb_assert_wheld(__nisdb_rwlock_t *rw) { 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate int ret; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate if (rw == 0) { 5567c478bd9Sstevel@tonic-gate #ifdef NISDB_MT_DEBUG 5577c478bd9Sstevel@tonic-gate abort(); 5587c478bd9Sstevel@tonic-gate #endif /* NISDB_MT_DEBUG */ 5597c478bd9Sstevel@tonic-gate return (EFAULT); 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate if (rw->destroyed != 0) 5637c478bd9Sstevel@tonic-gate return (ESHUTDOWN); 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate if ((ret = mutex_lock(&rw->mutex)) != 0) 5667c478bd9Sstevel@tonic-gate return (ret); 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate if (rw->destroyed != 0) { 5697c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 5707c478bd9Sstevel@tonic-gate return (ESHUTDOWN); 5717c478bd9Sstevel@tonic-gate } 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate if (rw->writer_count == 0 || rw->writer.id != pthread_self()) { 5747c478bd9Sstevel@tonic-gate ret = mutex_unlock(&rw->mutex); 5757c478bd9Sstevel@tonic-gate return ((ret == 0) ? -1 : ret); 5767c478bd9Sstevel@tonic-gate } 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate /* 5797c478bd9Sstevel@tonic-gate * We're holding the lock, so we should return zero. Since 5807c478bd9Sstevel@tonic-gate * that's what mutex_unlock() does if it succeeds, we just 5817c478bd9Sstevel@tonic-gate * return the value of mutex_unlock(). 5827c478bd9Sstevel@tonic-gate */ 5837c478bd9Sstevel@tonic-gate return (mutex_unlock(&rw->mutex)); 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate /* Return zero if read lock held by this thread, non-zero otherwise */ 5887c478bd9Sstevel@tonic-gate int 5897c478bd9Sstevel@tonic-gate __nisdb_assert_rheld(__nisdb_rwlock_t *rw) { 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate int ret; 5927c478bd9Sstevel@tonic-gate pthread_t myself = pthread_self(); 5937c478bd9Sstevel@tonic-gate __nisdb_rl_t *rr; 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate if (rw == 0) { 5977c478bd9Sstevel@tonic-gate #ifdef NISDB_MT_DEBUG 5987c478bd9Sstevel@tonic-gate abort(); 5997c478bd9Sstevel@tonic-gate #endif /* NISDB_MT_DEBUG */ 6007c478bd9Sstevel@tonic-gate return (EFAULT); 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate if (rw->destroyed != 0) 6047c478bd9Sstevel@tonic-gate return (ESHUTDOWN); 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate if (rw->force_write) 6077c478bd9Sstevel@tonic-gate return (__nisdb_assert_wheld(rw)); 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate if ((ret = mutex_lock(&rw->mutex)) != 0) 6107c478bd9Sstevel@tonic-gate return (ret); 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate if (rw->destroyed != 0) { 6137c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 6147c478bd9Sstevel@tonic-gate return (ESHUTDOWN); 6157c478bd9Sstevel@tonic-gate } 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate /* Write lock also OK */ 6187c478bd9Sstevel@tonic-gate if (rw->writer_count > 0 && rw->writer.id == myself) { 6197c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 6207c478bd9Sstevel@tonic-gate return (0); 6217c478bd9Sstevel@tonic-gate } 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate if (rw->reader_count == 0) { 6247c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 6257c478bd9Sstevel@tonic-gate return (EBUSY); 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate rr = &rw->reader; 6297c478bd9Sstevel@tonic-gate do { 6307c478bd9Sstevel@tonic-gate if (rr->id == myself) { 6317c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 6327c478bd9Sstevel@tonic-gate return (0); 6337c478bd9Sstevel@tonic-gate } 6347c478bd9Sstevel@tonic-gate rr = rr->next; 6357c478bd9Sstevel@tonic-gate } while (rr != 0); 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate ret = mutex_unlock(&rw->mutex); 6387c478bd9Sstevel@tonic-gate return ((ret == 0) ? EBUSY : ret); 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate int 6437c478bd9Sstevel@tonic-gate __nisdb_destroy_lock(__nisdb_rwlock_t *rw) { 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate int ret; 6467c478bd9Sstevel@tonic-gate pthread_t myself = pthread_self(); 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate if (rw == 0) { 6507c478bd9Sstevel@tonic-gate #ifdef NISDB_MT_DEBUG 6517c478bd9Sstevel@tonic-gate abort(); 6527c478bd9Sstevel@tonic-gate #endif /* NISDB_MT_DEBUG */ 6537c478bd9Sstevel@tonic-gate return (EFAULT); 6547c478bd9Sstevel@tonic-gate } 6557c478bd9Sstevel@tonic-gate 6567c478bd9Sstevel@tonic-gate if (rw->destroyed != 0) 6577c478bd9Sstevel@tonic-gate return (ESHUTDOWN); 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate if ((ret = mutex_lock(&rw->mutex)) != 0) 6607c478bd9Sstevel@tonic-gate return (ret); 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate if (rw->destroyed != 0) { 6637c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 6647c478bd9Sstevel@tonic-gate return (ESHUTDOWN); 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate /* 6687c478bd9Sstevel@tonic-gate * Only proceed if if there are neither readers nor writers 6697c478bd9Sstevel@tonic-gate * other than this thread. Also, no nested locks may be in 6707c478bd9Sstevel@tonic-gate * effect. 6717c478bd9Sstevel@tonic-gate */ 672*a87701e9SGary Mills if (((rw->writer_count > 0 && 673*a87701e9SGary Mills (rw->writer.id != myself || rw->writer.count != 1)) || 6747c478bd9Sstevel@tonic-gate (rw->reader_count > 0 && 6757c478bd9Sstevel@tonic-gate !(rw->reader_count == 1 && rw->reader.id == myself && 6767c478bd9Sstevel@tonic-gate rw->reader.count == 1))) || 6777c478bd9Sstevel@tonic-gate (rw->writer_count > 0 && rw->reader_count > 0)) { 6787c478bd9Sstevel@tonic-gate #ifdef NISDB_MT_DEBUG 6797c478bd9Sstevel@tonic-gate abort(); 6807c478bd9Sstevel@tonic-gate #endif /* NISDB_MT_DEBUG */ 6817c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rw->mutex); 6827c478bd9Sstevel@tonic-gate return (ENOLCK); 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate /* 6867c478bd9Sstevel@tonic-gate * Mark lock destroyed, so that any thread waiting on the mutex 6877c478bd9Sstevel@tonic-gate * will know what's what. Of course, this is a bit iffy, since 6887c478bd9Sstevel@tonic-gate * we're probably being called from a destructor, and the structure 6897c478bd9Sstevel@tonic-gate * where we live will soon cease to exist (i.e., be freed and 6907c478bd9Sstevel@tonic-gate * perhaps re-used). Still, we can only do our best, and give 6917c478bd9Sstevel@tonic-gate * those other threads the best chance possible. 6927c478bd9Sstevel@tonic-gate */ 6937c478bd9Sstevel@tonic-gate rw->destroyed++; 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate return (mutex_unlock(&rw->mutex)); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate void 6997c478bd9Sstevel@tonic-gate __nisdb_lock_report(__nisdb_rwlock_t *rw) { 7007c478bd9Sstevel@tonic-gate char *myself = "__nisdb_lock_report"; 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate if (rw == 0) { 7037c478bd9Sstevel@tonic-gate printf("%s: NULL argument\n", myself); 7047c478bd9Sstevel@tonic-gate return; 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate 7077c478bd9Sstevel@tonic-gate if (rw->destroyed) 7087c478bd9Sstevel@tonic-gate printf("0x%x: DESTROYED\n", rw); 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate printf("0x%x: Read locking %s\n", 7117c478bd9Sstevel@tonic-gate rw, rw->force_write ? "disallowed" : "allowed"); 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate if (rw->writer_count == 0) 7147c478bd9Sstevel@tonic-gate printf("0x%x: No writer\n", rw); 7157c478bd9Sstevel@tonic-gate else if (rw->writer_count == 1) { 7167c478bd9Sstevel@tonic-gate printf("0x%x: Write locked by %d, depth = %d\n", 7177c478bd9Sstevel@tonic-gate rw, rw->writer.id, rw->writer.count); 7187c478bd9Sstevel@tonic-gate if (rw->writer.wait) 7197c478bd9Sstevel@tonic-gate printf("0x%x:\tWriter blocked\n", rw); 7207c478bd9Sstevel@tonic-gate } else 7217c478bd9Sstevel@tonic-gate printf("0x%x: Invalid writer count = %d\n", 7227c478bd9Sstevel@tonic-gate rw, rw->writer_count); 7237c478bd9Sstevel@tonic-gate 7247c478bd9Sstevel@tonic-gate if (rw->reader_count == 0) 7257c478bd9Sstevel@tonic-gate printf("0x%x: No readers\n", rw); 7267c478bd9Sstevel@tonic-gate else { 7277c478bd9Sstevel@tonic-gate __nisdb_rl_t *r; 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate printf("0x%x: %d readers, %d blocked\n", 7307c478bd9Sstevel@tonic-gate rw, rw->reader_count, rw->reader_blocked); 7317c478bd9Sstevel@tonic-gate for (r = &rw->reader; r != 0; r = r->next) { 7327c478bd9Sstevel@tonic-gate printf("0x%x:\tthread %d, depth = %d%s\n", 7337c478bd9Sstevel@tonic-gate rw, r->id, r->count, 7347c478bd9Sstevel@tonic-gate (r->wait ? " (blocked)" : "")); 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate } 7377c478bd9Sstevel@tonic-gate } 738