/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2001 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _NISDB_RW_H #define _NISDB_RW_H #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #define INV_PTHREAD_ID 0 /* * DEFAULTNISDBRWLOCK_RW is the default initializer that does _not_ * force read lock requests to write locks, while DEFAULTNISDBRWLOCK_W * does force all locks to be exclusive. * * Locks should be initialized DEFAULTNISDBRWLOCK_W until it's been * determined that non-exclusive locking can be safely used; see * comments in __nisdb_rwinit() in nisdb_rw.c. */ #define DEFAULTNISDBRWLOCK_RW {DEFAULTMUTEX, DEFAULTCV, 0, 0, \ 0, {INV_PTHREAD_ID, 0, 0, 0}, \ 0, 0, {INV_PTHREAD_ID, 0, 0, 0}} #define DEFAULTNISDBRWLOCK_W {DEFAULTMUTEX, DEFAULTCV, 0, 1, \ 0, {INV_PTHREAD_ID, 0, 0, 0}, \ 0, 0, {INV_PTHREAD_ID, 0, 0, 0}} #define DEFAULTNISDBRWLOCK DEFAULTNISDBRWLOCK_W /* * The value used for the 'force_write' field initialization in * __nisdb_rwinit(). Should be one unless it's been determined that * read locks can safely be used in for _all_ locks initialized * by __nisdb_rwinit(). */ #define NISDB_FORCE_WRITE 1 #ifdef NISDB_MT_DEBUG #define DECLMUTEXLOCK(var) pthread_mutex_t var ## _pmutex = \ PTHREAD_MUTEX_INITIALIZER; \ pthread_t var ## _owner = INV_PTHREAD_ID #define USEMUTEXLOCK(var) extern pthread_mutex_t var ## _pmutex; \ extern pthread_t var ## _owner #define STRUCTMUTEXLOCK(var) pthread_mutex_t var ## _pmutex; \ pthread_t var ## _owner #define INITMUTEX(var) (void) pthread_mutex_init(&var ## _pmutex, 0) #define MUTEXLOCK(var, msg) if (var ## _owner != pthread_self()) { \ pthread_mutex_lock(&var ## _pmutex); \ var ## _owner = pthread_self(); \ } else \ abort(); #define MUTEXUNLOCK(var, msg) if (var ## _owner == pthread_self()) { \ var ## _owner = INV_PTHREAD_ID; \ pthread_mutex_unlock(&var ## _pmutex);\ } else \ abort(); #define ASSERTMUTEXHELD(var) if (var ## _owner != pthread_self()) \ abort(); #define DECLRWLOCK(var) __nisdb_rwlock_t var ## _rwlock = \ DEFAULTNISDBRWLOCK #define USERWLOCK(var) extern __nisdb_rwlock_t var ## _rwlock #define STRUCTRWLOCK(var) __nisdb_rwlock_t var ## _rwlock #define INITRW(var) (void) __nisdb_rwinit(&var ## _rwlock) #define READLOCKOK(var) (void) __nisdb_rw_readlock_ok(&var ## _rwlock) #define RLOCK(var) __nisdb_rlock(&var ## _rwlock) #define WLOCK(var) __nisdb_wlock(&var ## _rwlock) #define TRYWLOCK(var) __nisdb_wlock_trylock(&var ## _rwlock, 1) #define RULOCK(var) __nisdb_rulock(&var ## _rwlock) #define WULOCK(var) __nisdb_wulock(&var ## _rwlock) #define DESTROYRW(var) __nisdb_destroy_lock(&var ## _rwlock) #define ASSERTWHELD(var) if (__nisdb_assert_wheld(&var ## _rwlock) \ != 0) \ abort(); #define ASSERTRHELD(var) if (__nisdb_assert_rheld(&var ## _rwlock) \ != 0) \ abort(); #else /* NISDB_MT_DEBUG */ #define DECLMUTEXLOCK(var) pthread_mutex_t var ## _pmutex = \ PTHREAD_MUTEX_INITIALIZER #define USEMUTEXLOCK(var) extern pthread_mutex_t var ## _pmutex #define STRUCTMUTEXLOCK(var) pthread_mutex_t var ## _pmutex #define INITMUTEX(var) (void) pthread_mutex_init(&var ## _pmutex, 0) #define MUTEXLOCK(var, msg) pthread_mutex_lock(&var ## _pmutex) #define MUTEXUNLOCK(var, msg) pthread_mutex_unlock(&var ## _pmutex) #define DECLRWLOCK(var) __nisdb_rwlock_t var ## _rwlock = \ DEFAULTNISDBRWLOCK #define USERWLOCK(var) extern __nisdb_rwlock_t var ## _rwlock #define STRUCTRWLOCK(var) __nisdb_rwlock_t var ## _rwlock #define INITRW(var) (void) __nisdb_rwinit(&var ## _rwlock) #define READLOCKOK(var) (void) __nisdb_rw_readlock_ok(&var ## _rwlock) #define RLOCK(var) __nisdb_rlock(&var ## _rwlock) #define WLOCK(var) __nisdb_wlock(&var ## _rwlock) #define TRYWLOCK(var) __nisdb_wlock_trylock(&var ## _rwlock, 1) #define RULOCK(var) __nisdb_rulock(&var ## _rwlock) #define WULOCK(var) __nisdb_wulock(&var ## _rwlock) #define DESTROYRW(var) __nisdb_destroy_lock(&var ## _rwlock) #define ASSERTMUTEXHELD(var) #define ASSERTWHELD(var) #define ASSERTRHELD(var) #endif /* NISDB_MT_DEBUG */ /* Nesting-safe RW locking */ typedef struct __nisdb_rwlock { pthread_t id; /* Which thread */ uint32_t count; /* Lock depth for thread */ uint32_t wait; /* Blocked on mutex */ struct __nisdb_rwlock *next; /* Next reader record */ } __nisdb_rl_t; typedef struct { mutex_t mutex; /* Exclusive access to structure */ cond_t cv; /* CV for signaling */ uint32_t destroyed; /* Set if lock has been destroyed */ uint32_t force_write; /* Set if read locks forced to write */ uint32_t writer_count; /* Number of writer threads [0, 1] */ __nisdb_rl_t writer; /* Writer record */ uint32_t reader_count; /* # of reader threads [0, N] */ uint32_t reader_blocked; /* # of readers blocked on mutex */ __nisdb_rl_t reader; /* List of reader records */ } __nisdb_rwlock_t; extern int __nisdb_rwinit(__nisdb_rwlock_t *); extern int __nisdb_rw_readlock_ok(__nisdb_rwlock_t *rw); extern int __nisdb_rw_force_writelock(__nisdb_rwlock_t *rw); extern int __nisdb_wlock(__nisdb_rwlock_t *); extern int __nisdb_wlock_trylock(__nisdb_rwlock_t *, int); extern int __nisdb_rlock(__nisdb_rwlock_t *); extern int __nisdb_wulock(__nisdb_rwlock_t *); extern int __nisdb_rulock(__nisdb_rwlock_t *); extern int __nisdb_assert_wheld(__nisdb_rwlock_t *); extern int __nisdb_assert_rheld(__nisdb_rwlock_t *); extern int __nisdb_destroy_lock(__nisdb_rwlock_t *); extern void __nisdb_lock_report(__nisdb_rwlock_t *rw); #ifdef __cplusplus } #endif #endif /* _NISDB_RW_H */