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