1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
/*
* 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.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#ifndef _NISDB_RW_H
#define _NISDB_RW_H
#include <pthread.h>
#include <thread.h>
#include <synch.h>
#include <stdlib.h>
#include <malloc.h>
#include <sys/errno.h>
#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 */
|