1*00b67f09SDavid van Moolenbroek /* $NetBSD: rwlock.h,v 1.5 2014/12/10 04:38:00 christos Exp $ */ 2*00b67f09SDavid van Moolenbroek 3*00b67f09SDavid van Moolenbroek /* 4*00b67f09SDavid van Moolenbroek * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") 5*00b67f09SDavid van Moolenbroek * Copyright (C) 1998-2001, 2003 Internet Software Consortium. 6*00b67f09SDavid van Moolenbroek * 7*00b67f09SDavid van Moolenbroek * Permission to use, copy, modify, and/or distribute this software for any 8*00b67f09SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above 9*00b67f09SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies. 10*00b67f09SDavid van Moolenbroek * 11*00b67f09SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12*00b67f09SDavid van Moolenbroek * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13*00b67f09SDavid van Moolenbroek * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14*00b67f09SDavid van Moolenbroek * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15*00b67f09SDavid van Moolenbroek * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16*00b67f09SDavid van Moolenbroek * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17*00b67f09SDavid van Moolenbroek * PERFORMANCE OF THIS SOFTWARE. 18*00b67f09SDavid van Moolenbroek */ 19*00b67f09SDavid van Moolenbroek 20*00b67f09SDavid van Moolenbroek /* Id: rwlock.h,v 1.28 2007/06/19 23:47:18 tbox Exp */ 21*00b67f09SDavid van Moolenbroek 22*00b67f09SDavid van Moolenbroek #ifndef ISC_RWLOCK_H 23*00b67f09SDavid van Moolenbroek #define ISC_RWLOCK_H 1 24*00b67f09SDavid van Moolenbroek 25*00b67f09SDavid van Moolenbroek /*! \file isc/rwlock.h */ 26*00b67f09SDavid van Moolenbroek 27*00b67f09SDavid van Moolenbroek #include <isc/condition.h> 28*00b67f09SDavid van Moolenbroek #include <isc/lang.h> 29*00b67f09SDavid van Moolenbroek #include <isc/platform.h> 30*00b67f09SDavid van Moolenbroek #include <isc/types.h> 31*00b67f09SDavid van Moolenbroek 32*00b67f09SDavid van Moolenbroek ISC_LANG_BEGINDECLS 33*00b67f09SDavid van Moolenbroek 34*00b67f09SDavid van Moolenbroek typedef enum { 35*00b67f09SDavid van Moolenbroek isc_rwlocktype_none = 0, 36*00b67f09SDavid van Moolenbroek isc_rwlocktype_read, 37*00b67f09SDavid van Moolenbroek isc_rwlocktype_write 38*00b67f09SDavid van Moolenbroek } isc_rwlocktype_t; 39*00b67f09SDavid van Moolenbroek 40*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS 41*00b67f09SDavid van Moolenbroek #ifndef ISC_PLATFORM_USE_NATIVE_RWLOCKS 42*00b67f09SDavid van Moolenbroek #if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG) 43*00b67f09SDavid van Moolenbroek #define ISC_RWLOCK_USEATOMIC 1 44*00b67f09SDavid van Moolenbroek #endif 45*00b67f09SDavid van Moolenbroek 46*00b67f09SDavid van Moolenbroek struct isc_rwlock { 47*00b67f09SDavid van Moolenbroek /* Unlocked. */ 48*00b67f09SDavid van Moolenbroek unsigned int magic; 49*00b67f09SDavid van Moolenbroek isc_mutex_t lock; 50*00b67f09SDavid van Moolenbroek 51*00b67f09SDavid van Moolenbroek #if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG) 52*00b67f09SDavid van Moolenbroek /* 53*00b67f09SDavid van Moolenbroek * When some atomic instructions with hardware assistance are 54*00b67f09SDavid van Moolenbroek * available, rwlock will use those so that concurrent readers do not 55*00b67f09SDavid van Moolenbroek * interfere with each other through mutex as long as no writers 56*00b67f09SDavid van Moolenbroek * appear, massively reducing the lock overhead in the typical case. 57*00b67f09SDavid van Moolenbroek * 58*00b67f09SDavid van Moolenbroek * The basic algorithm of this approach is the "simple 59*00b67f09SDavid van Moolenbroek * writer-preference lock" shown in the following URL: 60*00b67f09SDavid van Moolenbroek * http://www.cs.rochester.edu/u/scott/synchronization/pseudocode/rw.html 61*00b67f09SDavid van Moolenbroek * but our implementation does not rely on the spin lock unlike the 62*00b67f09SDavid van Moolenbroek * original algorithm to be more portable as a user space application. 63*00b67f09SDavid van Moolenbroek */ 64*00b67f09SDavid van Moolenbroek 65*00b67f09SDavid van Moolenbroek /* Read or modified atomically. */ 66*00b67f09SDavid van Moolenbroek isc_int32_t write_requests; 67*00b67f09SDavid van Moolenbroek isc_int32_t write_completions; 68*00b67f09SDavid van Moolenbroek isc_int32_t cnt_and_flag; 69*00b67f09SDavid van Moolenbroek 70*00b67f09SDavid van Moolenbroek /* Locked by lock. */ 71*00b67f09SDavid van Moolenbroek isc_condition_t readable; 72*00b67f09SDavid van Moolenbroek isc_condition_t writeable; 73*00b67f09SDavid van Moolenbroek unsigned int readers_waiting; 74*00b67f09SDavid van Moolenbroek 75*00b67f09SDavid van Moolenbroek /* Locked by rwlock itself. */ 76*00b67f09SDavid van Moolenbroek unsigned int write_granted; 77*00b67f09SDavid van Moolenbroek 78*00b67f09SDavid van Moolenbroek /* Unlocked. */ 79*00b67f09SDavid van Moolenbroek unsigned int write_quota; 80*00b67f09SDavid van Moolenbroek 81*00b67f09SDavid van Moolenbroek #else /* ISC_PLATFORM_HAVEXADD && ISC_PLATFORM_HAVECMPXCHG */ 82*00b67f09SDavid van Moolenbroek 83*00b67f09SDavid van Moolenbroek /*%< Locked by lock. */ 84*00b67f09SDavid van Moolenbroek isc_condition_t readable; 85*00b67f09SDavid van Moolenbroek isc_condition_t writeable; 86*00b67f09SDavid van Moolenbroek isc_rwlocktype_t type; 87*00b67f09SDavid van Moolenbroek 88*00b67f09SDavid van Moolenbroek /*% The number of threads that have the lock. */ 89*00b67f09SDavid van Moolenbroek unsigned int active; 90*00b67f09SDavid van Moolenbroek 91*00b67f09SDavid van Moolenbroek /*% 92*00b67f09SDavid van Moolenbroek * The number of lock grants made since the lock was last switched 93*00b67f09SDavid van Moolenbroek * from reading to writing or vice versa; used in determining 94*00b67f09SDavid van Moolenbroek * when the quota is reached and it is time to switch. 95*00b67f09SDavid van Moolenbroek */ 96*00b67f09SDavid van Moolenbroek unsigned int granted; 97*00b67f09SDavid van Moolenbroek 98*00b67f09SDavid van Moolenbroek unsigned int readers_waiting; 99*00b67f09SDavid van Moolenbroek unsigned int writers_waiting; 100*00b67f09SDavid van Moolenbroek unsigned int read_quota; 101*00b67f09SDavid van Moolenbroek unsigned int write_quota; 102*00b67f09SDavid van Moolenbroek isc_rwlocktype_t original; 103*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_HAVEXADD && ISC_PLATFORM_HAVECMPXCHG */ 104*00b67f09SDavid van Moolenbroek }; 105*00b67f09SDavid van Moolenbroek #endif /* !ISC_PLATFORM_USE_NATIVE_RWLOCKS */ 106*00b67f09SDavid van Moolenbroek #else /* ISC_PLATFORM_USETHREADS */ 107*00b67f09SDavid van Moolenbroek struct isc_rwlock { 108*00b67f09SDavid van Moolenbroek unsigned int magic; 109*00b67f09SDavid van Moolenbroek isc_rwlocktype_t type; 110*00b67f09SDavid van Moolenbroek unsigned int active; 111*00b67f09SDavid van Moolenbroek }; 112*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */ 113*00b67f09SDavid van Moolenbroek 114*00b67f09SDavid van Moolenbroek 115*00b67f09SDavid van Moolenbroek isc_result_t 116*00b67f09SDavid van Moolenbroek isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota, 117*00b67f09SDavid van Moolenbroek unsigned int write_quota); 118*00b67f09SDavid van Moolenbroek 119*00b67f09SDavid van Moolenbroek isc_result_t 120*00b67f09SDavid van Moolenbroek isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type); 121*00b67f09SDavid van Moolenbroek 122*00b67f09SDavid van Moolenbroek isc_result_t 123*00b67f09SDavid van Moolenbroek isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type); 124*00b67f09SDavid van Moolenbroek 125*00b67f09SDavid van Moolenbroek isc_result_t 126*00b67f09SDavid van Moolenbroek isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type); 127*00b67f09SDavid van Moolenbroek 128*00b67f09SDavid van Moolenbroek isc_result_t 129*00b67f09SDavid van Moolenbroek isc_rwlock_tryupgrade(isc_rwlock_t *rwl); 130*00b67f09SDavid van Moolenbroek 131*00b67f09SDavid van Moolenbroek void 132*00b67f09SDavid van Moolenbroek isc_rwlock_downgrade(isc_rwlock_t *rwl); 133*00b67f09SDavid van Moolenbroek 134*00b67f09SDavid van Moolenbroek void 135*00b67f09SDavid van Moolenbroek isc_rwlock_destroy(isc_rwlock_t *rwl); 136*00b67f09SDavid van Moolenbroek 137*00b67f09SDavid van Moolenbroek ISC_LANG_ENDDECLS 138*00b67f09SDavid van Moolenbroek 139*00b67f09SDavid van Moolenbroek #endif /* ISC_RWLOCK_H */ 140