Home | History | Annotate | Download | only in libnisdb
      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