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