1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 2001 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #ifndef _NISDB_RW_H 30 #define _NISDB_RW_H 31 32 #include <pthread.h> 33 #include <thread.h> 34 #include <synch.h> 35 #include <stdlib.h> 36 #include <malloc.h> 37 #include <sys/errno.h> 38 39 #ifdef __cplusplus 40 extern "C" { 41 #endif 42 43 #define INV_PTHREAD_ID 0 44 45 /* 46 * DEFAULTNISDBRWLOCK_RW is the default initializer that does _not_ 47 * force read lock requests to write locks, while DEFAULTNISDBRWLOCK_W 48 * does force all locks to be exclusive. 49 * 50 * Locks should be initialized DEFAULTNISDBRWLOCK_W until it's been 51 * determined that non-exclusive locking can be safely used; see 52 * comments in __nisdb_rwinit() in nisdb_rw.c. 53 */ 54 #define DEFAULTNISDBRWLOCK_RW {DEFAULTMUTEX, DEFAULTCV, 0, 0, \ 55 0, {INV_PTHREAD_ID, 0, 0, 0}, \ 56 0, 0, {INV_PTHREAD_ID, 0, 0, 0}} 57 58 #define DEFAULTNISDBRWLOCK_W {DEFAULTMUTEX, DEFAULTCV, 0, 1, \ 59 0, {INV_PTHREAD_ID, 0, 0, 0}, \ 60 0, 0, {INV_PTHREAD_ID, 0, 0, 0}} 61 62 #define DEFAULTNISDBRWLOCK DEFAULTNISDBRWLOCK_W 63 64 /* 65 * The value used for the 'force_write' field initialization in 66 * __nisdb_rwinit(). Should be one unless it's been determined that 67 * read locks can safely be used in for _all_ locks initialized 68 * by __nisdb_rwinit(). 69 */ 70 #define NISDB_FORCE_WRITE 1 71 72 #ifdef NISDB_MT_DEBUG 73 74 #define DECLMUTEXLOCK(var) pthread_mutex_t var ## _pmutex = \ 75 PTHREAD_MUTEX_INITIALIZER; \ 76 pthread_t var ## _owner = INV_PTHREAD_ID 77 #define USEMUTEXLOCK(var) extern pthread_mutex_t var ## _pmutex; \ 78 extern pthread_t var ## _owner 79 #define STRUCTMUTEXLOCK(var) pthread_mutex_t var ## _pmutex; \ 80 pthread_t var ## _owner 81 #define INITMUTEX(var) (void) pthread_mutex_init(&var ## _pmutex, 0) 82 #define MUTEXLOCK(var, msg) if (var ## _owner != pthread_self()) { \ 83 pthread_mutex_lock(&var ## _pmutex); \ 84 var ## _owner = pthread_self(); \ 85 } else \ 86 abort(); 87 #define MUTEXUNLOCK(var, msg) if (var ## _owner == pthread_self()) { \ 88 var ## _owner = INV_PTHREAD_ID; \ 89 pthread_mutex_unlock(&var ## _pmutex);\ 90 } else \ 91 abort(); 92 #define ASSERTMUTEXHELD(var) if (var ## _owner != pthread_self()) \ 93 abort(); 94 95 #define DECLRWLOCK(var) __nisdb_rwlock_t var ## _rwlock = \ 96 DEFAULTNISDBRWLOCK 97 #define USERWLOCK(var) extern __nisdb_rwlock_t var ## _rwlock 98 #define STRUCTRWLOCK(var) __nisdb_rwlock_t var ## _rwlock 99 #define INITRW(var) (void) __nisdb_rwinit(&var ## _rwlock) 100 #define READLOCKOK(var) (void) __nisdb_rw_readlock_ok(&var ## _rwlock) 101 #define RLOCK(var) __nisdb_rlock(&var ## _rwlock) 102 #define WLOCK(var) __nisdb_wlock(&var ## _rwlock) 103 #define TRYWLOCK(var) __nisdb_wlock_trylock(&var ## _rwlock, 1) 104 #define RULOCK(var) __nisdb_rulock(&var ## _rwlock) 105 #define WULOCK(var) __nisdb_wulock(&var ## _rwlock) 106 #define DESTROYRW(var) __nisdb_destroy_lock(&var ## _rwlock) 107 #define ASSERTWHELD(var) if (__nisdb_assert_wheld(&var ## _rwlock) \ 108 != 0) \ 109 abort(); 110 #define ASSERTRHELD(var) if (__nisdb_assert_rheld(&var ## _rwlock) \ 111 != 0) \ 112 abort(); 113 114 #else /* NISDB_MT_DEBUG */ 115 116 #define DECLMUTEXLOCK(var) pthread_mutex_t var ## _pmutex = \ 117 PTHREAD_MUTEX_INITIALIZER 118 #define USEMUTEXLOCK(var) extern pthread_mutex_t var ## _pmutex 119 #define STRUCTMUTEXLOCK(var) pthread_mutex_t var ## _pmutex 120 #define INITMUTEX(var) (void) pthread_mutex_init(&var ## _pmutex, 0) 121 #define MUTEXLOCK(var, msg) pthread_mutex_lock(&var ## _pmutex) 122 #define MUTEXUNLOCK(var, msg) pthread_mutex_unlock(&var ## _pmutex) 123 124 #define DECLRWLOCK(var) __nisdb_rwlock_t var ## _rwlock = \ 125 DEFAULTNISDBRWLOCK 126 #define USERWLOCK(var) extern __nisdb_rwlock_t var ## _rwlock 127 #define STRUCTRWLOCK(var) __nisdb_rwlock_t var ## _rwlock 128 #define INITRW(var) (void) __nisdb_rwinit(&var ## _rwlock) 129 #define READLOCKOK(var) (void) __nisdb_rw_readlock_ok(&var ## _rwlock) 130 #define RLOCK(var) __nisdb_rlock(&var ## _rwlock) 131 #define WLOCK(var) __nisdb_wlock(&var ## _rwlock) 132 #define TRYWLOCK(var) __nisdb_wlock_trylock(&var ## _rwlock, 1) 133 #define RULOCK(var) __nisdb_rulock(&var ## _rwlock) 134 #define WULOCK(var) __nisdb_wulock(&var ## _rwlock) 135 #define DESTROYRW(var) __nisdb_destroy_lock(&var ## _rwlock) 136 #define ASSERTMUTEXHELD(var) 137 #define ASSERTWHELD(var) 138 #define ASSERTRHELD(var) 139 140 #endif /* NISDB_MT_DEBUG */ 141 142 /* Nesting-safe RW locking */ 143 typedef struct __nisdb_rwlock { 144 pthread_t id; /* Which thread */ 145 uint32_t count; /* Lock depth for thread */ 146 uint32_t wait; /* Blocked on mutex */ 147 struct __nisdb_rwlock *next; /* Next reader record */ 148 } __nisdb_rl_t; 149 150 typedef struct { 151 mutex_t mutex; /* Exclusive access to structure */ 152 cond_t cv; /* CV for signaling */ 153 uint32_t destroyed; /* Set if lock has been destroyed */ 154 uint32_t force_write; /* Set if read locks forced to write */ 155 uint32_t writer_count; /* Number of writer threads [0, 1] */ 156 __nisdb_rl_t writer; /* Writer record */ 157 uint32_t reader_count; /* # of reader threads [0, N] */ 158 uint32_t reader_blocked; /* # of readers blocked on mutex */ 159 __nisdb_rl_t reader; /* List of reader records */ 160 } __nisdb_rwlock_t; 161 162 extern int __nisdb_rwinit(__nisdb_rwlock_t *); 163 extern int __nisdb_rw_readlock_ok(__nisdb_rwlock_t *rw); 164 extern int __nisdb_rw_force_writelock(__nisdb_rwlock_t *rw); 165 extern int __nisdb_wlock(__nisdb_rwlock_t *); 166 extern int __nisdb_wlock_trylock(__nisdb_rwlock_t *, int); 167 extern int __nisdb_rlock(__nisdb_rwlock_t *); 168 extern int __nisdb_wulock(__nisdb_rwlock_t *); 169 extern int __nisdb_rulock(__nisdb_rwlock_t *); 170 extern int __nisdb_assert_wheld(__nisdb_rwlock_t *); 171 extern int __nisdb_assert_rheld(__nisdb_rwlock_t *); 172 extern int __nisdb_destroy_lock(__nisdb_rwlock_t *); 173 extern void __nisdb_lock_report(__nisdb_rwlock_t *rw); 174 175 #ifdef __cplusplus 176 } 177 #endif 178 179 #endif /* _NISDB_RW_H */ 180