1135446Strhodes/* 2193149Sdougb * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") 3135446Strhodes * Copyright (C) 1998-2001, 2003 Internet Software Consortium. 4135446Strhodes * 5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any 6135446Strhodes * purpose with or without fee is hereby granted, provided that the above 7135446Strhodes * copyright notice and this permission notice appear in all copies. 8135446Strhodes * 9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11135446Strhodes * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15135446Strhodes * PERFORMANCE OF THIS SOFTWARE. 16135446Strhodes */ 17135446Strhodes 18234010Sdougb/* $Id: rwlock.h,v 1.28 2007/06/19 23:47:18 tbox Exp $ */ 19135446Strhodes 20135446Strhodes#ifndef ISC_RWLOCK_H 21135446Strhodes#define ISC_RWLOCK_H 1 22135446Strhodes 23193149Sdougb/*! \file isc/rwlock.h */ 24170222Sdougb 25135446Strhodes#include <isc/condition.h> 26135446Strhodes#include <isc/lang.h> 27135446Strhodes#include <isc/platform.h> 28135446Strhodes#include <isc/types.h> 29135446Strhodes 30135446StrhodesISC_LANG_BEGINDECLS 31135446Strhodes 32135446Strhodestypedef enum { 33135446Strhodes isc_rwlocktype_none = 0, 34135446Strhodes isc_rwlocktype_read, 35135446Strhodes isc_rwlocktype_write 36135446Strhodes} isc_rwlocktype_t; 37135446Strhodes 38135446Strhodes#ifdef ISC_PLATFORM_USETHREADS 39170222Sdougb#if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG) 40170222Sdougb#define ISC_RWLOCK_USEATOMIC 1 41170222Sdougb#endif 42170222Sdougb 43135446Strhodesstruct isc_rwlock { 44135446Strhodes /* Unlocked. */ 45135446Strhodes unsigned int magic; 46135446Strhodes isc_mutex_t lock; 47170222Sdougb 48170222Sdougb#if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG) 49170222Sdougb /* 50170222Sdougb * When some atomic instructions with hardware assistance are 51170222Sdougb * available, rwlock will use those so that concurrent readers do not 52170222Sdougb * interfere with each other through mutex as long as no writers 53170222Sdougb * appear, massively reducing the lock overhead in the typical case. 54170222Sdougb * 55170222Sdougb * The basic algorithm of this approach is the "simple 56170222Sdougb * writer-preference lock" shown in the following URL: 57170222Sdougb * http://www.cs.rochester.edu/u/scott/synchronization/pseudocode/rw.html 58170222Sdougb * but our implementation does not rely on the spin lock unlike the 59170222Sdougb * original algorithm to be more portable as a user space application. 60170222Sdougb */ 61170222Sdougb 62170222Sdougb /* Read or modified atomically. */ 63170222Sdougb isc_int32_t write_requests; 64170222Sdougb isc_int32_t write_completions; 65170222Sdougb isc_int32_t cnt_and_flag; 66170222Sdougb 67135446Strhodes /* Locked by lock. */ 68135446Strhodes isc_condition_t readable; 69135446Strhodes isc_condition_t writeable; 70170222Sdougb unsigned int readers_waiting; 71170222Sdougb 72170222Sdougb /* Locked by rwlock itself. */ 73170222Sdougb unsigned int write_granted; 74170222Sdougb 75170222Sdougb /* Unlocked. */ 76170222Sdougb unsigned int write_quota; 77170222Sdougb 78170222Sdougb#else /* ISC_PLATFORM_HAVEXADD && ISC_PLATFORM_HAVECMPXCHG */ 79170222Sdougb 80170222Sdougb /*%< Locked by lock. */ 81170222Sdougb isc_condition_t readable; 82170222Sdougb isc_condition_t writeable; 83135446Strhodes isc_rwlocktype_t type; 84135446Strhodes 85170222Sdougb /*% The number of threads that have the lock. */ 86135446Strhodes unsigned int active; 87135446Strhodes 88170222Sdougb /*% 89135446Strhodes * The number of lock grants made since the lock was last switched 90135446Strhodes * from reading to writing or vice versa; used in determining 91135446Strhodes * when the quota is reached and it is time to switch. 92135446Strhodes */ 93135446Strhodes unsigned int granted; 94135446Strhodes 95135446Strhodes unsigned int readers_waiting; 96135446Strhodes unsigned int writers_waiting; 97135446Strhodes unsigned int read_quota; 98135446Strhodes unsigned int write_quota; 99135446Strhodes isc_rwlocktype_t original; 100170222Sdougb#endif /* ISC_PLATFORM_HAVEXADD && ISC_PLATFORM_HAVECMPXCHG */ 101135446Strhodes}; 102135446Strhodes#else /* ISC_PLATFORM_USETHREADS */ 103135446Strhodesstruct isc_rwlock { 104135446Strhodes unsigned int magic; 105135446Strhodes isc_rwlocktype_t type; 106135446Strhodes unsigned int active; 107135446Strhodes}; 108135446Strhodes#endif /* ISC_PLATFORM_USETHREADS */ 109135446Strhodes 110135446Strhodes 111135446Strhodesisc_result_t 112135446Strhodesisc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota, 113135446Strhodes unsigned int write_quota); 114135446Strhodes 115135446Strhodesisc_result_t 116135446Strhodesisc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type); 117135446Strhodes 118135446Strhodesisc_result_t 119135446Strhodesisc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type); 120135446Strhodes 121135446Strhodesisc_result_t 122135446Strhodesisc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type); 123135446Strhodes 124135446Strhodesisc_result_t 125135446Strhodesisc_rwlock_tryupgrade(isc_rwlock_t *rwl); 126135446Strhodes 127135446Strhodesvoid 128135446Strhodesisc_rwlock_downgrade(isc_rwlock_t *rwl); 129135446Strhodes 130135446Strhodesvoid 131135446Strhodesisc_rwlock_destroy(isc_rwlock_t *rwl); 132135446Strhodes 133135446StrhodesISC_LANG_ENDDECLS 134135446Strhodes 135135446Strhodes#endif /* ISC_RWLOCK_H */ 136