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