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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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