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