1219820Sjeff/*
2219820Sjeff * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
3219820Sjeff * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4219820Sjeff * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5219820Sjeff *
6219820Sjeff * This software is available to you under a choice of one of two
7219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
8219820Sjeff * General Public License (GPL) Version 2, available from the file
9219820Sjeff * COPYING in the main directory of this source tree, or the
10219820Sjeff * OpenIB.org BSD license below:
11219820Sjeff *
12219820Sjeff *     Redistribution and use in source and binary forms, with or
13219820Sjeff *     without modification, are permitted provided that the following
14219820Sjeff *     conditions are met:
15219820Sjeff *
16219820Sjeff *      - Redistributions of source code must retain the above
17219820Sjeff *        copyright notice, this list of conditions and the following
18219820Sjeff *        disclaimer.
19219820Sjeff *
20219820Sjeff *      - Redistributions in binary form must reproduce the above
21219820Sjeff *        copyright notice, this list of conditions and the following
22219820Sjeff *        disclaimer in the documentation and/or other materials
23219820Sjeff *        provided with the distribution.
24219820Sjeff *
25219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32219820Sjeff * SOFTWARE.
33219820Sjeff *
34219820Sjeff */
35219820Sjeff
36219820Sjeff/*
37219820Sjeff * Abstract:
38219820Sjeff *	This file contains the passive lock, which synchronizes passive threads.
39219820Sjeff *	The passive lock allows multiple readers to access a resource
40219820Sjeff *	simultaneously, exclusive from a single thread allowed writing.
41219820Sjeff * Several writer threads are allowed - but only one can write at a given time
42219820Sjeff */
43219820Sjeff
44219820Sjeff#ifndef _CL_PASSIVE_LOCK_H_
45219820Sjeff#define _CL_PASSIVE_LOCK_H_
46219820Sjeff#include <complib/cl_types.h>
47219820Sjeff#include <pthread.h>
48219820Sjeff
49219820Sjeff#ifdef __cplusplus
50219820Sjeff#  define BEGIN_C_DECLS extern "C" {
51219820Sjeff#  define END_C_DECLS   }
52219820Sjeff#else				/* !__cplusplus */
53219820Sjeff#  define BEGIN_C_DECLS
54219820Sjeff#  define END_C_DECLS
55219820Sjeff#endif				/* __cplusplus */
56219820Sjeff
57219820SjeffBEGIN_C_DECLS
58219820Sjeff/****h* Component Library/Passive Lock
59219820Sjeff* NAME
60219820Sjeff*	Passive Lock
61219820Sjeff*
62219820Sjeff* DESCRIPTION
63219820Sjeff*	The Passive Lock provides synchronization between multiple threads that
64219820Sjeff*	are sharing the lock with a single thread holding the lock exclusively.
65219820Sjeff*
66219820Sjeff*	Passive lock works exclusively between threads and cannot be used in
67219820Sjeff*	situations where the caller cannot be put into a waiting state.
68219820Sjeff*
69219820Sjeff*	The passive lock functions operate a cl_plock_t structure which should
70219820Sjeff*	be treated as opaque and should be manipulated only through the provided
71219820Sjeff*	functions.
72219820Sjeff*
73219820Sjeff* SEE ALSO
74219820Sjeff*	Structures:
75219820Sjeff*		cl_plock_t
76219820Sjeff*
77219820Sjeff*	Initialization:
78219820Sjeff*		cl_plock_construct, cl_plock_init, cl_plock_destroy
79219820Sjeff*
80219820Sjeff*	Manipulation
81219820Sjeff*		cl_plock_acquire, cl_plock_excl_acquire, cl_plock_release
82219820Sjeff*********/
83219820Sjeff/****s* Component Library: Passive Lock/cl_plock_t
84219820Sjeff* NAME
85219820Sjeff*	cl_plock_t
86219820Sjeff*
87219820Sjeff* DESCRIPTION
88219820Sjeff*	Passive Lock structure.
89219820Sjeff*
90219820Sjeff*	The cl_plock_t structure should be treated as opaque and should
91219820Sjeff*	be manipulated only through the provided functions.
92219820Sjeff*
93219820Sjeff* SYNOPSIS
94219820Sjeff*/
95219820Sjefftypedef struct _cl_plock {
96219820Sjeff	pthread_rwlock_t lock;
97219820Sjeff	cl_state_t state;
98219820Sjeff} cl_plock_t;
99219820Sjeff/*
100219820Sjeff* FIELDS
101219820Sjeff*	lock
102219820Sjeff*		Pthread RWLOCK object
103219820Sjeff*
104219820Sjeff*	state
105219820Sjeff*		Records the current state of the lock, such as initialized,
106219820Sjeff*		destroying, etc.
107219820Sjeff*
108219820Sjeff* SEE ALSO
109219820Sjeff*	Passive Lock
110219820Sjeff*********/
111219820Sjeff
112219820Sjeff/****f* Component Library: Passive Lock/cl_plock_construct
113219820Sjeff* NAME
114219820Sjeff*	cl_plock_construct
115219820Sjeff*
116219820Sjeff* DESCRIPTION
117219820Sjeff*	The cl_plock_construct function initializes the state of a
118219820Sjeff*	passive lock.
119219820Sjeff*
120219820Sjeff* SYNOPSIS
121219820Sjeff*/
122219820Sjeffstatic inline void cl_plock_construct(IN cl_plock_t * const p_lock)
123219820Sjeff{
124219820Sjeff	CL_ASSERT(p_lock);
125219820Sjeff
126219820Sjeff	p_lock->state = CL_UNINITIALIZED;
127219820Sjeff}
128219820Sjeff
129219820Sjeff/*
130219820Sjeff* PARAMETERS
131219820Sjeff*	p_lock
132219820Sjeff*		[in] Pointer to a cl_plock_t structure whose state to initialize.
133219820Sjeff*
134219820Sjeff* RETURN VALUE
135219820Sjeff*	This function does not return a value.
136219820Sjeff*
137219820Sjeff* NOTES
138219820Sjeff*	Allows calling cl_plock_destroy without first calling cl_plock_init.
139219820Sjeff*
140219820Sjeff*	Calling cl_plock_construct is a prerequisite to calling any other
141219820Sjeff*	passive lock function except cl_plock_init.
142219820Sjeff*
143219820Sjeff* SEE ALSO
144219820Sjeff*	Passive Lock, cl_plock_init, cl_plock_destroy
145219820Sjeff*********/
146219820Sjeff
147219820Sjeff/****f* Component Library: Passive Lock/cl_plock_destroy
148219820Sjeff* NAME
149219820Sjeff*	cl_plock_destroy
150219820Sjeff*
151219820Sjeff* DESCRIPTION
152219820Sjeff*	The cl_plock_destroy function performs any necessary cleanup
153219820Sjeff*	of a passive lock.
154219820Sjeff*
155219820Sjeff* SYNOPSIS
156219820Sjeff*/
157219820Sjeffstatic inline void cl_plock_destroy(IN cl_plock_t * const p_lock)
158219820Sjeff{
159219820Sjeff	CL_ASSERT(p_lock);
160219820Sjeff	p_lock->state = CL_DESTROYING;
161219820Sjeff	pthread_rwlock_destroy(&p_lock->lock);
162219820Sjeff	p_lock->state = CL_DESTROYED;
163219820Sjeff}
164219820Sjeff
165219820Sjeff/*
166219820Sjeff* PARAMETERS
167219820Sjeff*	p_lock
168219820Sjeff*		[in] Pointer to a cl_plock_t structure whose state to initialize.
169219820Sjeff*
170219820Sjeff* RETURN VALUE
171219820Sjeff*	This function does not return a value.
172219820Sjeff*
173219820Sjeff* NOTES
174219820Sjeff*	cl_plock_destroy performs any necessary cleanup of the specified
175219820Sjeff*	passive lock.
176219820Sjeff*
177219820Sjeff*	This function must only be called if cl_plock_construct or
178219820Sjeff*	cl_plock_init has been called. The passive lock must not be held
179219820Sjeff*	when calling this function.
180219820Sjeff*
181219820Sjeff* SEE ALSO
182219820Sjeff*	Passive Lock, cl_plock_construct, cl_plock_init
183219820Sjeff*********/
184219820Sjeff
185219820Sjeff/****f* Component Library: Passive Lock/cl_plock_init
186219820Sjeff* NAME
187219820Sjeff*	cl_plock_init
188219820Sjeff*
189219820Sjeff* DESCRIPTION
190219820Sjeff*	The cl_plock_init function initializes a passive lock.
191219820Sjeff*
192219820Sjeff* SYNOPSIS
193219820Sjeff*/
194219820Sjeffstatic inline cl_status_t cl_plock_init(IN cl_plock_t * const p_lock)
195219820Sjeff{
196219820Sjeff	cl_status_t status;
197219820Sjeff
198219820Sjeff	CL_ASSERT(p_lock);
199219820Sjeff	status = (cl_status_t) pthread_rwlock_init(&p_lock->lock, NULL);
200219820Sjeff	if (status)
201219820Sjeff		return CL_ERROR;
202219820Sjeff	p_lock->state = CL_INITIALIZED;
203219820Sjeff	return (CL_SUCCESS);
204219820Sjeff}
205219820Sjeff
206219820Sjeff/*
207219820Sjeff* PARAMETERS
208219820Sjeff*	p_lock
209219820Sjeff*		[in] Pointer to a cl_plock_t structure to initialize.
210219820Sjeff*
211219820Sjeff* RETURN VALUES
212219820Sjeff*	CL_SUCCESS if the passive lock was initialized successfully.
213219820Sjeff*
214219820Sjeff*	CL_ERROR otherwise.
215219820Sjeff*
216219820Sjeff* NOTES
217219820Sjeff*	Allows calling cl_plock_acquire, cl_plock_release,
218219820Sjeff*	cl_plock_excl_acquire
219219820Sjeff*
220219820Sjeff* SEE ALSO
221219820Sjeff*	Passive Lock, cl_plock_construct, cl_plock_destroy,
222219820Sjeff*	cl_plock_excl_acquire, cl_plock_acquire, cl_plock_release
223219820Sjeff*********/
224219820Sjeff
225219820Sjeff/****f* Component Library: Passive Lock/cl_plock_acquire
226219820Sjeff* NAME
227219820Sjeff*	cl_plock_acquire
228219820Sjeff*
229219820Sjeff* DESCRIPTION
230219820Sjeff*	The cl_plock_acquire function acquires a passive lock for
231219820Sjeff*	shared access.
232219820Sjeff*
233219820Sjeff* SYNOPSIS
234219820Sjeff*/
235219820Sjeffstatic inline void cl_plock_acquire(IN cl_plock_t * const p_lock)
236219820Sjeff{
237219820Sjeff	cl_status_t status;
238219820Sjeff	CL_ASSERT(p_lock);
239219820Sjeff	CL_ASSERT(p_lock->state == CL_INITIALIZED);
240219820Sjeff
241219820Sjeff	status = (cl_status_t) pthread_rwlock_rdlock(&p_lock->lock);
242219820Sjeff	CL_ASSERT(status == 0);
243219820Sjeff}
244219820Sjeff
245219820Sjeff/*
246219820Sjeff* PARAMETERS
247219820Sjeff*	p_lock
248219820Sjeff*		[in] Pointer to a cl_plock_t structure to acquire.
249219820Sjeff*
250219820Sjeff* RETURN VALUE
251219820Sjeff*	This function does not return a value.
252219820Sjeff*
253219820Sjeff* SEE ALSO
254219820Sjeff*	Passive Lock, cl_plock_release, cl_plock_excl_acquire
255219820Sjeff*********/
256219820Sjeff
257219820Sjeff/****f* Component Library: Passive Lock/cl_plock_excl_acquire
258219820Sjeff* NAME
259219820Sjeff*	cl_plock_excl_acquire
260219820Sjeff*
261219820Sjeff* DESCRIPTION
262219820Sjeff*	The cl_plock_excl_acquire function acquires exclusive access
263219820Sjeff*	to a passive lock.
264219820Sjeff*
265219820Sjeff* SYNOPSIS
266219820Sjeff*/
267219820Sjeffstatic inline void cl_plock_excl_acquire(IN cl_plock_t * const p_lock)
268219820Sjeff{
269219820Sjeff	cl_status_t status;
270219820Sjeff
271219820Sjeff	CL_ASSERT(p_lock);
272219820Sjeff	CL_ASSERT(p_lock->state == CL_INITIALIZED);
273219820Sjeff
274219820Sjeff	status = (cl_status_t) pthread_rwlock_wrlock(&p_lock->lock);
275219820Sjeff	CL_ASSERT(status == 0);
276219820Sjeff}
277219820Sjeff
278219820Sjeff/*
279219820Sjeff* PARAMETERS
280219820Sjeff*	p_lock
281219820Sjeff*		[in] Pointer to a cl_plock_t structure to acquire exclusively.
282219820Sjeff*
283219820Sjeff* RETURN VALUE
284219820Sjeff*	This function does not return a value.
285219820Sjeff*
286219820Sjeff* SEE ALSO
287219820Sjeff*	Passive Lock, cl_plock_release, cl_plock_acquire
288219820Sjeff*********/
289219820Sjeff
290219820Sjeff/****f* Component Library: Passive Lock/cl_plock_release
291219820Sjeff* NAME
292219820Sjeff*	cl_plock_release
293219820Sjeff*
294219820Sjeff* DESCRIPTION
295219820Sjeff*	The cl_plock_release function releases a passive lock from
296219820Sjeff*	shared or exclusive access.
297219820Sjeff*
298219820Sjeff* SYNOPSIS
299219820Sjeff*/
300219820Sjeffstatic inline void cl_plock_release(IN cl_plock_t * const p_lock)
301219820Sjeff{
302219820Sjeff	cl_status_t status;
303219820Sjeff	CL_ASSERT(p_lock);
304219820Sjeff	CL_ASSERT(p_lock->state == CL_INITIALIZED);
305219820Sjeff
306219820Sjeff	status = (cl_status_t) pthread_rwlock_unlock(&p_lock->lock);
307219820Sjeff	CL_ASSERT(status == 0);
308219820Sjeff}
309219820Sjeff
310219820Sjeff/*
311219820Sjeff* PARAMETERS
312219820Sjeff*	p_lock
313219820Sjeff*		[in] Pointer to a cl_plock_t structure to release.
314219820Sjeff*
315219820Sjeff* RETURN VALUE
316219820Sjeff*	This function does not return a value.
317219820Sjeff*
318219820Sjeff* SEE ALSO
319219820Sjeff*	Passive Lock, cl_plock_acquire, cl_plock_excl_acquire
320219820Sjeff*********/
321219820Sjeff
322219820SjeffEND_C_DECLS
323219820Sjeff#endif				/* _CL_PASSIVE_LOCK_H_ */
324