1 /*
2 * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2010 Mellanox Technologies LTD. All rights reserved.
4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5 *
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
11 *
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
14 * conditions are met:
15 *
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer.
19 *
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 * SOFTWARE.
33 *
34 */
35
36 /*
37 * Abstract:
38 * This file contains the passive lock, which synchronizes passive threads.
39 * The passive lock allows multiple readers to access a resource
40 * simultaneously, exclusive from a single thread allowed writing.
41 * Several writer threads are allowed - but only one can write at a given time
42 */
43
44 #ifndef _CL_PASSIVE_LOCK_H_
45 #define _CL_PASSIVE_LOCK_H_
46 #include <complib/cl_types.h>
47 #include <pthread.h>
48
49 #ifdef __cplusplus
50 # define BEGIN_C_DECLS extern "C" {
51 # define END_C_DECLS }
52 #else /* !__cplusplus */
53 # define BEGIN_C_DECLS
54 # define END_C_DECLS
55 #endif /* __cplusplus */
56
57 BEGIN_C_DECLS
58 /****h* Component Library/Passive Lock
59 * NAME
60 * Passive Lock
61 *
62 * DESCRIPTION
63 * The Passive Lock provides synchronization between multiple threads that
64 * are sharing the lock with a single thread holding the lock exclusively.
65 *
66 * Passive lock works exclusively between threads and cannot be used in
67 * situations where the caller cannot be put into a waiting state.
68 *
69 * The passive lock functions operate a cl_plock_t structure which should
70 * be treated as opaque and should be manipulated only through the provided
71 * functions.
72 *
73 * SEE ALSO
74 * Structures:
75 * cl_plock_t
76 *
77 * Initialization:
78 * cl_plock_construct, cl_plock_init, cl_plock_destroy
79 *
80 * Manipulation
81 * cl_plock_acquire, cl_plock_excl_acquire, cl_plock_release
82 *********/
83 /****s* Component Library: Passive Lock/cl_plock_t
84 * NAME
85 * cl_plock_t
86 *
87 * DESCRIPTION
88 * Passive Lock structure.
89 *
90 * The cl_plock_t structure should be treated as opaque and should
91 * be manipulated only through the provided functions.
92 *
93 * SYNOPSIS
94 */
95 typedef struct _cl_plock {
96 pthread_rwlock_t lock;
97 cl_state_t state;
98 } cl_plock_t;
99 /*
100 * FIELDS
101 * lock
102 * Pthread RWLOCK object
103 *
104 * state
105 * Records the current state of the lock, such as initialized,
106 * destroying, etc.
107 *
108 * SEE ALSO
109 * Passive Lock
110 *********/
111
112 /****f* Component Library: Passive Lock/cl_plock_construct
113 * NAME
114 * cl_plock_construct
115 *
116 * DESCRIPTION
117 * The cl_plock_construct function initializes the state of a
118 * passive lock.
119 *
120 * SYNOPSIS
121 */
cl_plock_construct(IN cl_plock_t * const p_lock)122 static inline void cl_plock_construct(IN cl_plock_t * const p_lock)
123 {
124 CL_ASSERT(p_lock);
125
126 p_lock->state = CL_UNINITIALIZED;
127 }
128
129 /*
130 * PARAMETERS
131 * p_lock
132 * [in] Pointer to a cl_plock_t structure whose state to initialize.
133 *
134 * RETURN VALUE
135 * This function does not return a value.
136 *
137 * NOTES
138 * Allows calling cl_plock_destroy without first calling cl_plock_init.
139 *
140 * Calling cl_plock_construct is a prerequisite to calling any other
141 * passive lock function except cl_plock_init.
142 *
143 * SEE ALSO
144 * Passive Lock, cl_plock_init, cl_plock_destroy
145 *********/
146
147 /****f* Component Library: Passive Lock/cl_plock_destroy
148 * NAME
149 * cl_plock_destroy
150 *
151 * DESCRIPTION
152 * The cl_plock_destroy function performs any necessary cleanup
153 * of a passive lock.
154 *
155 * SYNOPSIS
156 */
cl_plock_destroy(IN cl_plock_t * const p_lock)157 static inline void cl_plock_destroy(IN cl_plock_t * const p_lock)
158 {
159 CL_ASSERT(p_lock);
160 p_lock->state = CL_DESTROYING;
161 pthread_rwlock_destroy(&p_lock->lock);
162 p_lock->state = CL_DESTROYED;
163 }
164
165 /*
166 * PARAMETERS
167 * p_lock
168 * [in] Pointer to a cl_plock_t structure whose state to initialize.
169 *
170 * RETURN VALUE
171 * This function does not return a value.
172 *
173 * NOTES
174 * cl_plock_destroy performs any necessary cleanup of the specified
175 * passive lock.
176 *
177 * This function must only be called if cl_plock_construct or
178 * cl_plock_init has been called. The passive lock must not be held
179 * when calling this function.
180 *
181 * SEE ALSO
182 * Passive Lock, cl_plock_construct, cl_plock_init
183 *********/
184
185 /****f* Component Library: Passive Lock/cl_plock_init
186 * NAME
187 * cl_plock_init
188 *
189 * DESCRIPTION
190 * The cl_plock_init function initializes a passive lock.
191 *
192 * SYNOPSIS
193 */
cl_plock_init(IN cl_plock_t * const p_lock)194 static inline cl_status_t cl_plock_init(IN cl_plock_t * const p_lock)
195 {
196 cl_status_t status;
197
198 CL_ASSERT(p_lock);
199 status = pthread_rwlock_init(&p_lock->lock, NULL);
200 if (status)
201 return CL_ERROR;
202 p_lock->state = CL_INITIALIZED;
203 return (CL_SUCCESS);
204 }
205
206 /*
207 * PARAMETERS
208 * p_lock
209 * [in] Pointer to a cl_plock_t structure to initialize.
210 *
211 * RETURN VALUES
212 * CL_SUCCESS if the passive lock was initialized successfully.
213 *
214 * CL_ERROR otherwise.
215 *
216 * NOTES
217 * Allows calling cl_plock_acquire, cl_plock_release,
218 * cl_plock_excl_acquire
219 *
220 * SEE ALSO
221 * Passive Lock, cl_plock_construct, cl_plock_destroy,
222 * cl_plock_excl_acquire, cl_plock_acquire, cl_plock_release
223 *********/
224
225 /****f* Component Library: Passive Lock/cl_plock_acquire
226 * NAME
227 * cl_plock_acquire
228 *
229 * DESCRIPTION
230 * The cl_plock_acquire function acquires a passive lock for
231 * shared access.
232 *
233 * SYNOPSIS
234 */
cl_plock_acquire(IN cl_plock_t * const p_lock)235 static inline void cl_plock_acquire(IN cl_plock_t * const p_lock)
236 {
237 cl_status_t __attribute__((unused)) status;
238 CL_ASSERT(p_lock);
239 CL_ASSERT(p_lock->state == CL_INITIALIZED);
240
241 status = pthread_rwlock_rdlock(&p_lock->lock);
242 CL_ASSERT(status == 0);
243 }
244
245 /*
246 * PARAMETERS
247 * p_lock
248 * [in] Pointer to a cl_plock_t structure to acquire.
249 *
250 * RETURN VALUE
251 * This function does not return a value.
252 *
253 * SEE ALSO
254 * Passive Lock, cl_plock_release, cl_plock_excl_acquire
255 *********/
256
257 /****f* Component Library: Passive Lock/cl_plock_excl_acquire
258 * NAME
259 * cl_plock_excl_acquire
260 *
261 * DESCRIPTION
262 * The cl_plock_excl_acquire function acquires exclusive access
263 * to a passive lock.
264 *
265 * SYNOPSIS
266 */
cl_plock_excl_acquire(IN cl_plock_t * const p_lock)267 static inline void cl_plock_excl_acquire(IN cl_plock_t * const p_lock)
268 {
269 cl_status_t __attribute__((unused)) status;
270
271 CL_ASSERT(p_lock);
272 CL_ASSERT(p_lock->state == CL_INITIALIZED);
273
274 status = pthread_rwlock_wrlock(&p_lock->lock);
275 CL_ASSERT(status == 0);
276 }
277
278 /*
279 * PARAMETERS
280 * p_lock
281 * [in] Pointer to a cl_plock_t structure to acquire exclusively.
282 *
283 * RETURN VALUE
284 * This function does not return a value.
285 *
286 * SEE ALSO
287 * Passive Lock, cl_plock_release, cl_plock_acquire
288 *********/
289
290 /****f* Component Library: Passive Lock/cl_plock_release
291 * NAME
292 * cl_plock_release
293 *
294 * DESCRIPTION
295 * The cl_plock_release function releases a passive lock from
296 * shared or exclusive access.
297 *
298 * SYNOPSIS
299 */
cl_plock_release(IN cl_plock_t * const p_lock)300 static inline void cl_plock_release(IN cl_plock_t * const p_lock)
301 {
302 cl_status_t __attribute__((unused)) status;
303 CL_ASSERT(p_lock);
304 CL_ASSERT(p_lock->state == CL_INITIALIZED);
305
306 status = pthread_rwlock_unlock(&p_lock->lock);
307 CL_ASSERT(status == 0);
308 }
309
310 /*
311 * PARAMETERS
312 * p_lock
313 * [in] Pointer to a cl_plock_t structure to release.
314 *
315 * RETURN VALUE
316 * This function does not return a value.
317 *
318 * SEE ALSO
319 * Passive Lock, cl_plock_acquire, cl_plock_excl_acquire
320 *********/
321
322 END_C_DECLS
323 #endif /* _CL_PASSIVE_LOCK_H_ */
324