* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbtdb.c,v 1.186 2003/02/27 00:19:03 marka Exp $ */
+/* $Id: rbtdb.c,v 1.187 2003/04/17 01:56:34 marka Exp $ */
/*
* Principal Author: Bob Halley
* we only do a trylock.
*/
if (lock == isc_rwlocktype_read)
- RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
-
- result = isc_rwlock_trylock(&rbtdb->tree_lock,
- isc_rwlocktype_write);
+ result = isc_rwlock_tryupgrade(&rbtdb->tree_lock);
+ else
+ result = isc_rwlock_trylock(&rbtdb->tree_lock,
+ isc_rwlocktype_write);
RUNTIME_CHECK(result == ISC_R_SUCCESS ||
result == ISC_R_LOCKBUSY);
/*
* Relock a read lock, or unlock the write lock if no lock was held.
*/
- if (lock != isc_rwlocktype_write)
+ if (lock == isc_rwlocktype_none)
if (write_locked)
RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
if (lock == isc_rwlocktype_read)
- RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+ if (write_locked)
+ isc_rwlock_downgrade(&rbtdb->tree_lock);
}
static inline void
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rwlock.h,v 1.18 2001/03/08 00:55:15 tale Exp $ */
+/* $Id: rwlock.h,v 1.19 2003/04/17 01:56:35 marka Exp $ */
#ifndef ISC_RWLOCK_H
#define ISC_RWLOCK_H 1
isc_result_t
isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
+isc_result_t
+isc_rwlock_tryupgrade(isc_rwlock_t *rwl);
+
+void
+isc_rwlock_downgrade(isc_rwlock_t *rwl);
+
void
isc_rwlock_destroy(isc_rwlock_t *rwl);
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rwlock.c,v 1.33 2001/04/17 14:36:45 tale Exp $ */
+/* $Id: rwlock.c,v 1.34 2003/04/17 01:56:34 marka Exp $ */
#include <config.h>
return (doit(rwl, type, ISC_TRUE));
}
+isc_result_t
+isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(VALID_RWLOCK(rwl));
+ LOCK(&rwl->lock);
+ REQUIRE(rwl->type == isc_rwlocktype_read);
+ REQUIRE(rwl->active != 0);
+
+ /* If we are the only reader then succeed. */
+ if (rwl->active == 1)
+ rwl->type = isc_rwlocktype_write;
+ else
+ result = ISC_R_LOCKBUSY;
+
+ UNLOCK(&rwl->lock);
+ return (result);
+}
+
+void
+isc_rwlock_downgrade(isc_rwlock_t *rwl) {
+
+ REQUIRE(VALID_RWLOCK(rwl));
+ LOCK(&rwl->lock);
+ REQUIRE(rwl->type == isc_rwlocktype_write);
+ REQUIRE(rwl->active == 1);
+
+ rwl->type = isc_rwlocktype_read;
+ /*
+ * Wake up waiting readers if there are no waiting writers.
+ */
+ if ((rwl->writers_waiting == 0 || rwl->granted < rwl->read_quota) &&
+ rwl->readers_waiting > 0)
+ BROADCAST(&rwl->readable);
+
+ UNLOCK(&rwl->lock);
+}
+
isc_result_t
isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
return (isc_rwlock_lock(rwl, type));
}
+isc_result_t
+isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(VALID_RWLOCK(rwl));
+ REQUIRE(rwl->type == isc_rwlocktype_read);
+ REQUIRE(rwl->active != 0);
+
+ /* If we are the only reader then succeed. */
+ if (rwl->active == 1)
+ rwl->type = isc_rwlocktype_write;
+ else
+ result = ISC_R_LOCKBUSY;
+ return (result);
+}
+
+void
+isc_rwlock_downgrade(isc_rwlock_t *rwl) {
+
+ REQUIRE(VALID_RWLOCK(rwl));
+ REQUIRE(rwl->type == isc_rwlocktype_write);
+ REQUIRE(rwl->active == 1);
+
+ rwl->type = isc_rwlocktype_read;
+}
+
isc_result_t
isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
REQUIRE(VALID_RWLOCK(rwl));