2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-02 07:35:26 +00:00

Implement isc_rwlock_downgrade using pthreads and single atomic_bool

This commit is contained in:
Ondřej Surý
2018-11-22 11:42:12 +01:00
parent 64fbffbbaa
commit 4501f646ee
2 changed files with 27 additions and 3 deletions

View File

@@ -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 */

View File

@@ -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