diff --git a/CHANGES b/CHANGES index 8e49dce8e5..77314c1c6b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +1492. [cleanup] Preserve rwlock quota context when upgrading / + downgrading. [RT #5599] + 1491. [bug] dns_master_dump*() would produce extraneous $ORIGIN lines. [RT #6206] diff --git a/lib/isc/include/isc/rwlock.h b/lib/isc/include/isc/rwlock.h index d84d4db210..252bcc3707 100644 --- a/lib/isc/include/isc/rwlock.h +++ b/lib/isc/include/isc/rwlock.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rwlock.h,v 1.19 2003/04/17 01:56:35 marka Exp $ */ +/* $Id: rwlock.h,v 1.20 2003/07/21 01:14:18 marka Exp $ */ #ifndef ISC_RWLOCK_H #define ISC_RWLOCK_H 1 @@ -57,6 +57,7 @@ struct isc_rwlock { unsigned int writers_waiting; unsigned int read_quota; unsigned int write_quota; + isc_rwlocktype_t original; }; #else /* ISC_PLATFORM_USETHREADS */ struct isc_rwlock { diff --git a/lib/isc/rwlock.c b/lib/isc/rwlock.c index 25172dcdd3..73c4ae6a72 100644 --- a/lib/isc/rwlock.c +++ b/lib/isc/rwlock.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rwlock.c,v 1.34 2003/04/17 01:56:34 marka Exp $ */ +/* $Id: rwlock.c,v 1.35 2003/07/21 01:14:18 marka Exp $ */ #include @@ -82,6 +82,7 @@ isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota, rwl->magic = 0; rwl->type = isc_rwlocktype_read; + rwl->original = isc_rwlocktype_none; rwl->active = 0; rwl->granted = 0; rwl->readers_waiting = 0; @@ -215,9 +216,11 @@ isc_rwlock_tryupgrade(isc_rwlock_t *rwl) { REQUIRE(rwl->active != 0); /* If we are the only reader then succeed. */ - if (rwl->active == 1) + if (rwl->active == 1) { + rwl->original = (rwl->original == isc_rwlocktype_none) ? + isc_rwlocktype_read : isc_rwlocktype_none; rwl->type = isc_rwlocktype_write; - else + } else result = ISC_R_LOCKBUSY; UNLOCK(&rwl->lock); @@ -233,10 +236,14 @@ isc_rwlock_downgrade(isc_rwlock_t *rwl) { REQUIRE(rwl->active == 1); rwl->type = isc_rwlocktype_read; + rwl->original = (rwl->original == isc_rwlocktype_none) ? + isc_rwlocktype_write : isc_rwlocktype_none; /* - * Wake up waiting readers if there are no waiting writers. + * Resume processing any read request that were blocked when + * we upgraded. */ - if ((rwl->writers_waiting == 0 || rwl->granted < rwl->read_quota) && + if (rwl->original == isc_rwlocktype_none && + (rwl->writers_waiting == 0 || rwl->granted < rwl->read_quota) && rwl->readers_waiting > 0) BROADCAST(&rwl->readable); @@ -260,6 +267,10 @@ isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { INSIST(rwl->active > 0); rwl->active--; if (rwl->active == 0) { + if (rwl->original != isc_rwlocktype_none) { + rwl->type = rwl->original; + rwl->original = isc_rwlocktype_none; + } if (rwl->type == isc_rwlocktype_read) { rwl->granted = 0; if (rwl->writers_waiting > 0) { @@ -287,6 +298,7 @@ isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { } } } + INSIST(rwl->original == isc_rwlock_none); #ifdef ISC_RWLOCK_TRACE print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,