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 #ifndef _NISDB_RW_H 28 #define _NISDB_RW_H 29 30 #include <pthread.h> 31 #include <thread.h> 32 #include <synch.h> 33 #include <stdlib.h> 34 #include <malloc.h> 35 #include <sys/errno.h> 36 37 #ifdef __cplusplus 38 extern "C" { 39 #endif 40 41 #define INV_PTHREAD_ID 0 42 43 /* 44 * DEFAULTNISDBRWLOCK_RW is the default initializer that does _not_ 45 * force read lock requests to write locks, while DEFAULTNISDBRWLOCK_W 46 * does force all locks to be exclusive. 47 * 48 * Locks should be initialized DEFAULTNISDBRWLOCK_W until it's been 49 * determined that non-exclusive locking can be safely used; see 50 * comments in __nisdb_rwinit() in nisdb_rw.c. 51 */ 52 #define DEFAULTNISDBRWLOCK_RW {DEFAULTMUTEX, DEFAULTCV, 0, 0, \ 53 0, {INV_PTHREAD_ID, 0, 0, 0}, \ 54 0, 0, {INV_PTHREAD_ID, 0, 0, 0}} 55 56 #define DEFAULTNISDBRWLOCK_W {DEFAULTMUTEX, DEFAULTCV, 0, 1, \ 57 0, {INV_PTHREAD_ID, 0, 0, 0}, \ 58 0, 0, {INV_PTHREAD_ID, 0, 0, 0}} 59 60 #define DEFAULTNISDBRWLOCK DEFAULTNISDBRWLOCK_W 61 62 /* 63 * The value used for the 'force_write' field initialization in 64 * __nisdb_rwinit(). Should be one unless it's been determined that 65 * read locks can safely be used in for _all_ locks initialized 66 * by __nisdb_rwinit(). 67 */ 68 #define NISDB_FORCE_WRITE 1 69 70 #ifdef NISDB_MT_DEBUG 71 72 #define DECLMUTEXLOCK(var) pthread_mutex_t var ## _pmutex = \ 73 PTHREAD_MUTEX_INITIALIZER; \ 74 pthread_t var ## _owner = INV_PTHREAD_ID 75 #define USEMUTEXLOCK(var) extern pthread_mutex_t var ## _pmutex; \ 76 extern pthread_t var ## _owner 77 #define STRUCTMUTEXLOCK(var) pthread_mutex_t var ## _pmutex; \ 78 pthread_t var ## _owner 79 #define INITMUTEX(var) (void) pthread_mutex_init(&var ## _pmutex, 0) 80 #define MUTEXLOCK(var, msg) if (var ## _owner != pthread_self()) { \ 81 pthread_mutex_lock(&var ## _pmutex); \ 82 var ## _owner = pthread_self(); \ 83 } else \ 84 abort(); 85 #define MUTEXUNLOCK(var, msg) if (var ## _owner == pthread_self()) { \ 86 var ## _owner = INV_PTHREAD_ID; \ 87 pthread_mutex_unlock(&var ## _pmutex);\ 88 } else \ 89 abort(); 90 #define ASSERTMUTEXHELD(var) if (var ## _owner != pthread_self()) \ 91 abort(); 92 93 #define DECLRWLOCK(var) __nisdb_rwlock_t var ## _rwlock = \ 94 DEFAULTNISDBRWLOCK 95 #define USERWLOCK(var) extern __nisdb_rwlock_t var ## _rwlock 96 #define STRUCTRWLOCK(var) __nisdb_rwlock_t var ## _rwlock 97 #define INITRW(var) (void) __nisdb_rwinit(&var ## _rwlock) 98 #define READLOCKOK(var) (void) __nisdb_rw_readlock_ok(&var ## _rwlock) 99 #define RLOCK(var) __nisdb_rlock(&var ## _rwlock) 100 #define WLOCK(var) __nisdb_wlock(&var ## _rwlock) 101 #define TRYWLOCK(var) __nisdb_wlock_trylock(&var ## _rwlock, 1) 102 #define RULOCK(var) __nisdb_rulock(&var ## _rwlock) 103 #define WULOCK(var) __nisdb_wulock(&var ## _rwlock) 104 #define DESTROYRW(var) __nisdb_destroy_lock(&var ## _rwlock) 105 #define ASSERTWHELD(var) if (__nisdb_assert_wheld(&var ## _rwlock) \ 106 != 0) \ 107 abort(); 108 #define ASSERTRHELD(var) if (__nisdb_assert_rheld(&var ## _rwlock) \ 109 != 0) \ 110 abort(); 111 112 #else /* NISDB_MT_DEBUG */ 113 114 #define DECLMUTEXLOCK(var) pthread_mutex_t var ## _pmutex = \ 115 PTHREAD_MUTEX_INITIALIZER 116 #define USEMUTEXLOCK(var) extern pthread_mutex_t var ## _pmutex 117 #define STRUCTMUTEXLOCK(var) pthread_mutex_t var ## _pmutex 118 #define INITMUTEX(var) (void) pthread_mutex_init(&var ## _pmutex, 0) 119 #define MUTEXLOCK(var, msg) pthread_mutex_lock(&var ## _pmutex) 120 #define MUTEXUNLOCK(var, msg) pthread_mutex_unlock(&var ## _pmutex) 121 122 #define DECLRWLOCK(var) __nisdb_rwlock_t var ## _rwlock = \ 123 DEFAULTNISDBRWLOCK 124 #define USERWLOCK(var) extern __nisdb_rwlock_t var ## _rwlock 125 #define STRUCTRWLOCK(var) __nisdb_rwlock_t var ## _rwlock 126 #define INITRW(var) (void) __nisdb_rwinit(&var ## _rwlock) 127 #define READLOCKOK(var) (void) __nisdb_rw_readlock_ok(&var ## _rwlock) 128 #define RLOCK(var) __nisdb_rlock(&var ## _rwlock) 129 #define WLOCK(var) __nisdb_wlock(&var ## _rwlock) 130 #define TRYWLOCK(var) __nisdb_wlock_trylock(&var ## _rwlock, 1) 131 #define RULOCK(var) __nisdb_rulock(&var ## _rwlock) 132 #define WULOCK(var) __nisdb_wulock(&var ## _rwlock) 133 #define DESTROYRW(var) __nisdb_destroy_lock(&var ## _rwlock) 134 #define ASSERTMUTEXHELD(var) 135 #define ASSERTWHELD(var) 136 #define ASSERTRHELD(var) 137 138 #endif /* NISDB_MT_DEBUG */ 139 140 /* Nesting-safe RW locking */ 141 typedef struct __nisdb_rwlock { 142 pthread_t id; /* Which thread */ 143 uint32_t count; /* Lock depth for thread */ 144 uint32_t wait; /* Blocked on mutex */ 145 struct __nisdb_rwlock *next; /* Next reader record */ 146 } __nisdb_rl_t; 147 148 typedef struct { 149 mutex_t mutex; /* Exclusive access to structure */ 150 cond_t cv; /* CV for signaling */ 151 uint32_t destroyed; /* Set if lock has been destroyed */ 152 uint32_t force_write; /* Set if read locks forced to write */ 153 uint32_t writer_count; /* Number of writer threads [0, 1] */ 154 __nisdb_rl_t writer; /* Writer record */ 155 uint32_t reader_count; /* # of reader threads [0, N] */ 156 uint32_t reader_blocked; /* # of readers blocked on mutex */ 157 __nisdb_rl_t reader; /* List of reader records */ 158 } __nisdb_rwlock_t; 159 160 extern int __nisdb_rwinit(__nisdb_rwlock_t *); 161 extern int __nisdb_rw_readlock_ok(__nisdb_rwlock_t *rw); 162 extern int __nisdb_rw_force_writelock(__nisdb_rwlock_t *rw); 163 extern int __nisdb_wlock(__nisdb_rwlock_t *); 164 extern int __nisdb_wlock_trylock(__nisdb_rwlock_t *, int); 165 extern int __nisdb_rlock(__nisdb_rwlock_t *); 166 extern int __nisdb_wulock(__nisdb_rwlock_t *); 167 extern int __nisdb_rulock(__nisdb_rwlock_t *); 168 extern int __nisdb_assert_wheld(__nisdb_rwlock_t *); 169 extern int __nisdb_assert_rheld(__nisdb_rwlock_t *); 170 extern int __nisdb_destroy_lock(__nisdb_rwlock_t *); 171 extern void __nisdb_lock_report(__nisdb_rwlock_t *rw); 172 173 #ifdef __cplusplus 174 } 175 #endif 176 177 #endif /* _NISDB_RW_H */ 178