mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-02 15:45:25 +00:00
Implement isc_rwlock_downgrade using pthreads and single atomic_bool
This commit is contained in:
@@ -36,6 +36,7 @@ typedef enum {
|
|||||||
|
|
||||||
struct isc_rwlock {
|
struct isc_rwlock {
|
||||||
pthread_rwlock_t rwlock;
|
pthread_rwlock_t rwlock;
|
||||||
|
atomic_bool downgrade;
|
||||||
};
|
};
|
||||||
|
|
||||||
#else /* HAVE_PTHREAD_RWLOCK_RDLOCK */
|
#else /* HAVE_PTHREAD_RWLOCK_RDLOCK */
|
||||||
|
@@ -39,15 +39,32 @@ isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
|
|||||||
UNUSED(read_quota);
|
UNUSED(read_quota);
|
||||||
UNUSED(write_quota);
|
UNUSED(write_quota);
|
||||||
REQUIRE(pthread_rwlock_init(&rwl->rwlock, NULL) == 0);
|
REQUIRE(pthread_rwlock_init(&rwl->rwlock, NULL) == 0);
|
||||||
|
atomic_init(&rwl->downgrade, false);
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case isc_rwlocktype_read: REQUIRE(pthread_rwlock_rdlock(&rwl->rwlock) == 0); break;
|
case isc_rwlocktype_read:
|
||||||
case isc_rwlocktype_write: REQUIRE(pthread_rwlock_wrlock(&rwl->rwlock) == 0); break;
|
REQUIRE(pthread_rwlock_rdlock(&rwl->rwlock) == 0);
|
||||||
default: INSIST(0);
|
break;
|
||||||
|
case isc_rwlocktype_write:
|
||||||
|
while (true) {
|
||||||
|
REQUIRE(pthread_rwlock_wrlock(&rwl->rwlock) == 0);
|
||||||
|
/* Unlock if in middle of downgrade operation */
|
||||||
|
if (atomic_load_release(&rwl->downgrade)) {
|
||||||
|
REQUIRE(pthread_rwlock_unlock(&rwl->rwlock)
|
||||||
|
== 0);
|
||||||
|
while (atomic_load(&rwl->downgrade));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
INSIST(0);
|
||||||
|
ISC_UNREACHABLE();
|
||||||
}
|
}
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
@@ -61,6 +78,10 @@ isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
|
|||||||
break;
|
break;
|
||||||
case isc_rwlocktype_write:
|
case isc_rwlocktype_write:
|
||||||
ret = pthread_rwlock_trywrlock(&rwl->rwlock);
|
ret = pthread_rwlock_trywrlock(&rwl->rwlock);
|
||||||
|
if ((ret == 0) && atomic_load(&rwl->downgrade)) {
|
||||||
|
isc_rwlock_unlock(rwl, type);
|
||||||
|
return (ISC_R_LOCKBUSY);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default: INSIST(0);
|
default: INSIST(0);
|
||||||
}
|
}
|
||||||
@@ -88,8 +109,10 @@ isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
isc_rwlock_downgrade(isc_rwlock_t *rwl) {
|
isc_rwlock_downgrade(isc_rwlock_t *rwl) {
|
||||||
|
atomic_store_acquire(&rwl->downgrade, true);
|
||||||
isc_rwlock_unlock(rwl, isc_rwlocktype_write);
|
isc_rwlock_unlock(rwl, isc_rwlocktype_write);
|
||||||
isc_rwlock_lock(rwl, isc_rwlocktype_read);
|
isc_rwlock_lock(rwl, isc_rwlocktype_read);
|
||||||
|
atomic_store_acquire(&rwl->downgrade, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Reference in New Issue
Block a user