Blame SOURCES/bind-9.11.13-rwlock.patch

10d019
From bc9a36bad14b014340244bfc35a20df6809a5568 Mon Sep 17 00:00:00 2001
10d019
From: Miroslav Lichvar <mlichvar@redhat.com>
10d019
Date: Thu, 27 Feb 2020 15:35:31 +0100
10d019
Subject: [PATCH] Fix rwlock to be thread-safe
10d019
MIME-Version: 1.0
10d019
Content-Type: text/plain; charset=UTF-8
10d019
Content-Transfer-Encoding: 8bit
10d019
10d019
This is a backport of the following commits
10d019
10d019
commit 4cf275ba8aa1caf47ed763b51c37fa561005cb8d
10d019
Author: Ondřej Surý <ondrej@isc.org>
10d019
Date:   Wed Feb 12 09:17:55 2020 +0100
10d019
10d019
    Replace non-loop usage of atomic_compare_exchange_weak with strong variant
10d019
10d019
commit b43f5e023885dac9f1ffdace54720150768a333b
10d019
Author: Ondřej Surý <ondrej@isc.org>
10d019
Date:   Sat Feb 1 10:48:20 2020 +0100
10d019
10d019
    Convert all atomic operations in isc_rwlock to release-acquire memory ordering
10d019
10d019
commit 49462cf9747261cbc39d5fa4c691b64ac5472af4
10d019
Author: Ondřej Surý <ondrej@sury.org>
10d019
Date:   Tue May 14 00:19:11 2019 +0700
10d019
10d019
    Make isc_rwlock.c thread-safe
10d019
10d019
commit 9d5df99a9d9d13c9487969b6fa3818a8b83b4ee2
10d019
Author: Ondřej Surý <ondrej@sury.org>
10d019
Date:   Thu Aug 23 15:30:06 2018 +0200
10d019
10d019
    Directly use return value of atomic_compare_exchange_strong_explicit insteaf of comparing expected value
10d019
10d019
commit b5709e5531d9d45f9fc3db129c11ad474477d7b6
10d019
Author: Ondřej Surý <ondrej@sury.org>
10d019
Date:   Fri Aug 17 19:21:12 2018 +0200
10d019
10d019
    Explicitly load atomic values in lib/isc/rwlock.c
10d019
---
10d019
 lib/isc/rwlock.c | 275 ++++++++++++++++++-----------------------------
10d019
 1 file changed, 107 insertions(+), 168 deletions(-)
10d019
10d019
diff --git a/lib/isc/rwlock.c b/lib/isc/rwlock.c
10d019
index 9533c0f828..5591eff719 100644
10d019
--- a/lib/isc/rwlock.c
10d019
+++ b/lib/isc/rwlock.c
10d019
@@ -46,6 +46,26 @@
10d019
 #if defined(ISC_RWLOCK_USEATOMIC)
10d019
 static isc_result_t
10d019
 isc__rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
10d019
+
10d019
+#ifndef ISC_RWLOCK_USESTDATOMIC
10d019
+#error non-stdatomic support removed
10d019
+#endif
10d019
+
10d019
+#define atomic_load_acquire(o)						\
10d019
+	atomic_load_explicit((o), memory_order_acquire)
10d019
+#define atomic_store_release(o, v)					\
10d019
+	atomic_store_explicit((o), (v), memory_order_release)
10d019
+#define atomic_fetch_add_release(o, v)					\
10d019
+	atomic_fetch_add_explicit((o), (v), memory_order_release)
10d019
+#define atomic_fetch_sub_release(o, v)					\
10d019
+	atomic_fetch_sub_explicit((o), (v), memory_order_release)
10d019
+#define atomic_compare_exchange_weak_acq_rel(o, e, d)			\
10d019
+	atomic_compare_exchange_weak_explicit((o), (e), (d),		\
10d019
+					      memory_order_acq_rel,	\
10d019
+					      memory_order_acquire)
10d019
+#define atomic_compare_exchange_strong_acq_rel(o, e, d)			\
10d019
+	atomic_compare_exchange_strong_explicit(			\
10d019
+		(o), (e), (d), memory_order_acq_rel, memory_order_acquire)
10d019
 #endif
10d019
 
10d019
 #ifdef ISC_RWLOCK_TRACE
10d019
@@ -108,13 +128,13 @@ isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
10d019
 	 */
10d019
 	rwl->magic = 0;
10d019
 
10d019
-	rwl->spins = 0;
10d019
 #if defined(ISC_RWLOCK_USEATOMIC)
10d019
-	rwl->write_requests = 0;
10d019
-	rwl->write_completions = 0;
10d019
-	rwl->cnt_and_flag = 0;
10d019
+	atomic_init(&rwl->spins, 0);
10d019
+	atomic_init(&rwl->write_requests, 0);
10d019
+	atomic_init(&rwl->write_completions, 0);
10d019
+	atomic_init(&rwl->cnt_and_flag, 0);
10d019
 	rwl->readers_waiting = 0;
10d019
-	rwl->write_granted = 0;
10d019
+	atomic_init(&rwl->write_granted, 0);
10d019
 	if (read_quota != 0) {
10d019
 		UNEXPECTED_ERROR(__FILE__, __LINE__,
10d019
 				 "read quota is not supported");
10d019
@@ -123,6 +143,7 @@ isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
10d019
 		write_quota = RWLOCK_DEFAULT_WRITE_QUOTA;
10d019
 	rwl->write_quota = write_quota;
10d019
 #else
10d019
+	rwl->spins = 0;
10d019
 	rwl->type = isc_rwlocktype_read;
10d019
 	rwl->original = isc_rwlocktype_none;
10d019
 	rwl->active = 0;
10d019
@@ -178,16 +199,9 @@ void
10d019
 isc_rwlock_destroy(isc_rwlock_t *rwl) {
10d019
 	REQUIRE(VALID_RWLOCK(rwl));
10d019
 
10d019
-#if defined(ISC_RWLOCK_USEATOMIC)
10d019
-	REQUIRE(rwl->write_requests == rwl->write_completions &&
10d019
-		rwl->cnt_and_flag == 0 && rwl->readers_waiting == 0);
10d019
-#else
10d019
-	LOCK(&rwl->lock);
10d019
-	REQUIRE(rwl->active == 0 &&
10d019
-		rwl->readers_waiting == 0 &&
10d019
-		rwl->writers_waiting == 0);
10d019
-	UNLOCK(&rwl->lock);
10d019
-#endif
10d019
+	REQUIRE(atomic_load_acquire(&rwl->write_requests) ==
10d019
+		atomic_load_acquire(&rwl->write_completions) &&
10d019
+		atomic_load_acquire(&rwl->cnt_and_flag) == 0 && rwl->readers_waiting == 0);
10d019
 
10d019
 	rwl->magic = 0;
10d019
 	(void)isc_condition_destroy(&rwl->readable);
10d019
@@ -274,10 +288,13 @@ isc__rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
10d019
 #endif
10d019
 
10d019
 	if (type == isc_rwlocktype_read) {
10d019
-		if (rwl->write_requests != rwl->write_completions) {
10d019
+		if (atomic_load_acquire(&rwl->write_requests) !=
10d019
+		    atomic_load_acquire(&rwl->write_completions))
10d019
+		{
10d019
 			/* there is a waiting or active writer */
10d019
 			LOCK(&rwl->lock);
10d019
-			if (rwl->write_requests != rwl->write_completions) {
10d019
+			if (atomic_load_acquire(&rwl->write_requests) !=
10d019
+			    atomic_load_acquire(&rwl->write_completions)) {
10d019
 				rwl->readers_waiting++;
10d019
 				WAIT(&rwl->readable, &rwl->lock);
10d019
 				rwl->readers_waiting--;
10d019
@@ -285,23 +302,24 @@ isc__rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
10d019
 			UNLOCK(&rwl->lock);
10d019
 		}
10d019
 
10d019
-#if defined(ISC_RWLOCK_USESTDATOMIC)
10d019
-		cntflag = atomic_fetch_add_explicit(&rwl->cnt_and_flag,
10d019
-						    READER_INCR,
10d019
-						    memory_order_relaxed);
10d019
-#else
10d019
-		cntflag = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR);
10d019
-#endif
10d019
+		cntflag = atomic_fetch_add_release(&rwl->cnt_and_flag,
10d019
+						   READER_INCR);
10d019
 		POST(cntflag);
10d019
 		while (1) {
10d019
-			if ((rwl->cnt_and_flag & WRITER_ACTIVE) == 0)
10d019
+			if ((atomic_load_acquire(&rwl->cnt_and_flag)
10d019
+			     & WRITER_ACTIVE) == 0)
10d019
+			{
10d019
 				break;
10d019
+			}
10d019
 
10d019
 			/* A writer is still working */
10d019
 			LOCK(&rwl->lock);
10d019
 			rwl->readers_waiting++;
10d019
-			if ((rwl->cnt_and_flag & WRITER_ACTIVE) != 0)
10d019
+			if ((atomic_load_acquire(&rwl->cnt_and_flag)
10d019
+			     & WRITER_ACTIVE) != 0)
10d019
+			{
10d019
 				WAIT(&rwl->readable, &rwl->lock);
10d019
+			}
10d019
 			rwl->readers_waiting--;
10d019
 			UNLOCK(&rwl->lock);
10d019
 
10d019
@@ -336,20 +354,19 @@ isc__rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
10d019
 		 * quota, reset the condition (race among readers doesn't
10d019
 		 * matter).
10d019
 		 */
10d019
-		rwl->write_granted = 0;
10d019
+		atomic_store_release(&rwl->write_granted, 0);
10d019
 	} else {
10d019
 		int32_t prev_writer;
10d019
 
10d019
 		/* enter the waiting queue, and wait for our turn */
10d019
-#if defined(ISC_RWLOCK_USESTDATOMIC)
10d019
-		prev_writer = atomic_fetch_add_explicit(&rwl->write_requests, 1,
10d019
-							memory_order_relaxed);
10d019
-#else
10d019
-		prev_writer = isc_atomic_xadd(&rwl->write_requests, 1);
10d019
-#endif
10d019
-		while (rwl->write_completions != prev_writer) {
10d019
+		prev_writer = atomic_fetch_add_release(&rwl->write_requests, 1);
10d019
+		while (atomic_load_acquire(&rwl->write_completions)
10d019
+		       != prev_writer)
10d019
+		{
10d019
 			LOCK(&rwl->lock);
10d019
-			if (rwl->write_completions != prev_writer) {
10d019
+			if (atomic_load_acquire(&rwl->write_completions)
10d019
+			    != prev_writer)
10d019
+			{
10d019
 				WAIT(&rwl->writeable, &rwl->lock);
10d019
 				UNLOCK(&rwl->lock);
10d019
 				continue;
10d019
@@ -359,29 +376,24 @@ isc__rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
10d019
 		}
10d019
 
10d019
 		while (1) {
10d019
-#if defined(ISC_RWLOCK_USESTDATOMIC)
10d019
 			int_fast32_t cntflag2 = 0;
10d019
-			atomic_compare_exchange_strong_explicit
10d019
-				(&rwl->cnt_and_flag, &cntflag2, WRITER_ACTIVE,
10d019
-				 memory_order_relaxed, memory_order_relaxed);
10d019
-#else
10d019
-			int32_t cntflag2;
10d019
-			cntflag2 = isc_atomic_cmpxchg(&rwl->cnt_and_flag, 0,
10d019
-						      WRITER_ACTIVE);
10d019
-#endif
10d019
-
10d019
-			if (cntflag2 == 0)
10d019
+			if (atomic_compare_exchange_weak_acq_rel(
10d019
+				    &rwl->cnt_and_flag, &cntflag2, WRITER_ACTIVE))
10d019
+			{
10d019
 				break;
10d019
+			}
10d019
 
10d019
 			/* Another active reader or writer is working. */
10d019
 			LOCK(&rwl->lock);
10d019
-			if (rwl->cnt_and_flag != 0)
10d019
+			if (atomic_load_acquire(&rwl->cnt_and_flag) != 0) {
10d019
 				WAIT(&rwl->writeable, &rwl->lock);
10d019
+			}
10d019
 			UNLOCK(&rwl->lock);
10d019
 		}
10d019
 
10d019
-		INSIST((rwl->cnt_and_flag & WRITER_ACTIVE) != 0);
10d019
-		rwl->write_granted++;
10d019
+		INSIST((atomic_load_acquire(&rwl->cnt_and_flag)
10d019
+			& WRITER_ACTIVE));
10d019
+		atomic_fetch_add_release(&rwl->write_granted, 1);
10d019
 	}
10d019
 
10d019
 #ifdef ISC_RWLOCK_TRACE
10d019
@@ -395,12 +407,10 @@ isc__rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
10d019
 isc_result_t
10d019
 isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
10d019
 	int32_t cnt = 0;
10d019
-	int32_t max_cnt = rwl->spins * 2 + 10;
10d019
+	int32_t spins = atomic_load_acquire(&rwl->spins) * 2 + 10;
10d019
+	int32_t max_cnt = ISC_MAX(spins, RWLOCK_MAX_ADAPTIVE_COUNT);
10d019
 	isc_result_t result = ISC_R_SUCCESS;
10d019
 
10d019
-	if (max_cnt > RWLOCK_MAX_ADAPTIVE_COUNT)
10d019
-		max_cnt = RWLOCK_MAX_ADAPTIVE_COUNT;
10d019
-
10d019
 	do {
10d019
 		if (cnt++ >= max_cnt) {
10d019
 			result = isc__rwlock_lock(rwl, type);
10d019
@@ -411,7 +421,7 @@ isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
10d019
 #endif
10d019
 	} while (isc_rwlock_trylock(rwl, type) != ISC_R_SUCCESS);
10d019
 
10d019
-	rwl->spins += (cnt - rwl->spins) / 8;
10d019
+	atomic_fetch_add_release(&rwl->spins, (cnt - spins) / 8);
10d019
 
10d019
 	return (result);
10d019
 }
10d019
@@ -429,36 +439,28 @@ isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
10d019
 
10d019
 	if (type == isc_rwlocktype_read) {
10d019
 		/* If a writer is waiting or working, we fail. */
10d019
-		if (rwl->write_requests != rwl->write_completions)
10d019
+		if (atomic_load_acquire(&rwl->write_requests) !=
10d019
+		    atomic_load_acquire(&rwl->write_completions))
10d019
 			return (ISC_R_LOCKBUSY);
10d019
 
10d019
 		/* Otherwise, be ready for reading. */
10d019
-#if defined(ISC_RWLOCK_USESTDATOMIC)
10d019
-		cntflag = atomic_fetch_add_explicit(&rwl->cnt_and_flag,
10d019
-						    READER_INCR,
10d019
-						    memory_order_relaxed);
10d019
-#else
10d019
-		cntflag = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR);
10d019
-#endif
10d019
+		cntflag = atomic_fetch_add_release(&rwl->cnt_and_flag,
10d019
+						   READER_INCR);
10d019
 		if ((cntflag & WRITER_ACTIVE) != 0) {
10d019
 			/*
10d019
 			 * A writer is working.  We lose, and cancel the read
10d019
 			 * request.
10d019
 			 */
10d019
-#if defined(ISC_RWLOCK_USESTDATOMIC)
10d019
-			cntflag = atomic_fetch_sub_explicit
10d019
-				(&rwl->cnt_and_flag, READER_INCR,
10d019
-				 memory_order_relaxed);
10d019
-#else
10d019
-			cntflag = isc_atomic_xadd(&rwl->cnt_and_flag,
10d019
-						  -READER_INCR);
10d019
-#endif
10d019
+			cntflag = atomic_fetch_sub_release(
10d019
+				&rwl->cnt_and_flag, READER_INCR);
10d019
 			/*
10d019
 			 * If no other readers are waiting and we've suspended
10d019
 			 * new writers in this short period, wake them up.
10d019
 			 */
10d019
 			if (cntflag == READER_INCR &&
10d019
-			    rwl->write_completions != rwl->write_requests) {
10d019
+			    atomic_load_acquire(&rwl->write_completions) !=
10d019
+			    atomic_load_acquire(&rwl->write_requests))
10d019
+			{
10d019
 				LOCK(&rwl->lock);
10d019
 				BROADCAST(&rwl->writeable);
10d019
 				UNLOCK(&rwl->lock);
10d019
@@ -468,31 +470,19 @@ isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
10d019
 		}
10d019
 	} else {
10d019
 		/* Try locking without entering the waiting queue. */
10d019
-#if defined(ISC_RWLOCK_USESTDATOMIC)
10d019
 		int_fast32_t zero = 0;
10d019
-		if (!atomic_compare_exchange_strong_explicit
10d019
-		    (&rwl->cnt_and_flag, &zero, WRITER_ACTIVE,
10d019
-		     memory_order_relaxed, memory_order_relaxed))
10d019
+		if (!atomic_compare_exchange_strong_acq_rel(
10d019
+		    &rwl->cnt_and_flag, &zero, WRITER_ACTIVE))
10d019
+		{
10d019
 			return (ISC_R_LOCKBUSY);
10d019
-#else
10d019
-		cntflag = isc_atomic_cmpxchg(&rwl->cnt_and_flag, 0,
10d019
-					     WRITER_ACTIVE);
10d019
-		if (cntflag != 0)
10d019
-			return (ISC_R_LOCKBUSY);
10d019
-#endif
10d019
+		}
10d019
 
10d019
 		/*
10d019
 		 * XXXJT: jump into the queue, possibly breaking the writer
10d019
 		 * order.
10d019
 		 */
10d019
-#if defined(ISC_RWLOCK_USESTDATOMIC)
10d019
-		atomic_fetch_sub_explicit(&rwl->write_completions, 1,
10d019
-					  memory_order_relaxed);
10d019
-#else
10d019
-		(void)isc_atomic_xadd(&rwl->write_completions, -1);
10d019
-#endif
10d019
-
10d019
-		rwl->write_granted++;
10d019
+		atomic_fetch_sub_release(&rwl->write_completions, 1);
10d019
+		atomic_fetch_add_release(&rwl->write_granted, 1);
10d019
 	}
10d019
 
10d019
 #ifdef ISC_RWLOCK_TRACE
10d019
@@ -507,14 +497,12 @@ isc_result_t
10d019
 isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
10d019
 	REQUIRE(VALID_RWLOCK(rwl));
10d019
 
10d019
-#if defined(ISC_RWLOCK_USESTDATOMIC)
10d019
 	{
10d019
 		int_fast32_t reader_incr = READER_INCR;
10d019
 
10d019
 		/* Try to acquire write access. */
10d019
-		atomic_compare_exchange_strong_explicit
10d019
-			(&rwl->cnt_and_flag, &reader_incr, WRITER_ACTIVE,
10d019
-			 memory_order_relaxed, memory_order_relaxed);
10d019
+		atomic_compare_exchange_strong_acq_rel(
10d019
+			&rwl->cnt_and_flag, &reader_incr, WRITER_ACTIVE);
10d019
 		/*
10d019
 		 * There must have been no writer, and there must have
10d019
 		 * been at least one reader.
10d019
@@ -527,36 +515,11 @@ isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
10d019
 			 * We are the only reader and have been upgraded.
10d019
 			 * Now jump into the head of the writer waiting queue.
10d019
 			 */
10d019
-			atomic_fetch_sub_explicit(&rwl->write_completions, 1,
10d019
-						  memory_order_relaxed);
10d019
+			atomic_fetch_sub_release(&rwl->write_completions, 1);
10d019
 		} else
10d019
 			return (ISC_R_LOCKBUSY);
10d019
 
10d019
 	}
10d019
-#else
10d019
-	{
10d019
-		int32_t prevcnt;
10d019
-
10d019
-		/* Try to acquire write access. */
10d019
-		prevcnt = isc_atomic_cmpxchg(&rwl->cnt_and_flag,
10d019
-					     READER_INCR, WRITER_ACTIVE);
10d019
-		/*
10d019
-		 * There must have been no writer, and there must have
10d019
-		 * been at least one reader.
10d019
-		 */
10d019
-		INSIST((prevcnt & WRITER_ACTIVE) == 0 &&
10d019
-		       (prevcnt & ~WRITER_ACTIVE) != 0);
10d019
-
10d019
-		if (prevcnt == READER_INCR) {
10d019
-			/*
10d019
-			 * We are the only reader and have been upgraded.
10d019
-			 * Now jump into the head of the writer waiting queue.
10d019
-			 */
10d019
-			(void)isc_atomic_xadd(&rwl->write_completions, -1);
10d019
-		} else
10d019
-			return (ISC_R_LOCKBUSY);
10d019
-	}
10d019
-#endif
10d019
 
10d019
 	return (ISC_R_SUCCESS);
10d019
 }
10d019
@@ -567,33 +530,15 @@ isc_rwlock_downgrade(isc_rwlock_t *rwl) {
10d019
 
10d019
 	REQUIRE(VALID_RWLOCK(rwl));
10d019
 
10d019
-#if defined(ISC_RWLOCK_USESTDATOMIC)
10d019
-	{
10d019
-		/* Become an active reader. */
10d019
-		prev_readers = atomic_fetch_add_explicit(&rwl->cnt_and_flag,
10d019
-							 READER_INCR,
10d019
-							 memory_order_relaxed);
10d019
-		/* We must have been a writer. */
10d019
-		INSIST((prev_readers & WRITER_ACTIVE) != 0);
10d019
-
10d019
-		/* Complete write */
10d019
-		atomic_fetch_sub_explicit(&rwl->cnt_and_flag, WRITER_ACTIVE,
10d019
-					  memory_order_relaxed);
10d019
-		atomic_fetch_add_explicit(&rwl->write_completions, 1,
10d019
-					  memory_order_relaxed);
10d019
-	}
10d019
-#else
10d019
-	{
10d019
-		/* Become an active reader. */
10d019
-		prev_readers = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR);
10d019
-		/* We must have been a writer. */
10d019
-		INSIST((prev_readers & WRITER_ACTIVE) != 0);
10d019
-
10d019
-		/* Complete write */
10d019
-		(void)isc_atomic_xadd(&rwl->cnt_and_flag, -WRITER_ACTIVE);
10d019
-		(void)isc_atomic_xadd(&rwl->write_completions, 1);
10d019
-	}
10d019
-#endif
10d019
+	/* Become an active reader. */
10d019
+	prev_readers = atomic_fetch_add_release(&rwl->cnt_and_flag,
10d019
+						READER_INCR);
10d019
+	/* We must have been a writer. */
10d019
+	INSIST((prev_readers & WRITER_ACTIVE) != 0);
10d019
+
10d019
+	/* Complete write */
10d019
+	atomic_fetch_sub_release(&rwl->cnt_and_flag, WRITER_ACTIVE);
10d019
+	atomic_fetch_add_release(&rwl->write_completions, 1);
10d019
 
10d019
 	/* Resume other readers */
10d019
 	LOCK(&rwl->lock);
10d019
@@ -614,20 +559,16 @@ isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
10d019
 #endif
10d019
 
10d019
 	if (type == isc_rwlocktype_read) {
10d019
-#if defined(ISC_RWLOCK_USESTDATOMIC)
10d019
-		prev_cnt = atomic_fetch_sub_explicit(&rwl->cnt_and_flag,
10d019
-						     READER_INCR,
10d019
-						     memory_order_relaxed);
10d019
-#else
10d019
-		prev_cnt = isc_atomic_xadd(&rwl->cnt_and_flag, -READER_INCR);
10d019
-#endif
10d019
+		prev_cnt = atomic_fetch_sub_release(&rwl->cnt_and_flag,
10d019
+						    READER_INCR);
10d019
 		/*
10d019
 		 * If we're the last reader and any writers are waiting, wake
10d019
 		 * them up.  We need to wake up all of them to ensure the
10d019
 		 * FIFO order.
10d019
 		 */
10d019
 		if (prev_cnt == READER_INCR &&
10d019
-		    rwl->write_completions != rwl->write_requests) {
10d019
+		    atomic_load_acquire(&rwl->write_completions) !=
10d019
+		    atomic_load_acquire(&rwl->write_requests)) {
10d019
 			LOCK(&rwl->lock);
10d019
 			BROADCAST(&rwl->writeable);
10d019
 			UNLOCK(&rwl->lock);
10d019
@@ -639,19 +580,16 @@ isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
10d019
 		 * Reset the flag, and (implicitly) tell other writers
10d019
 		 * we are done.
10d019
 		 */
10d019
-#if defined(ISC_RWLOCK_USESTDATOMIC)
10d019
-		atomic_fetch_sub_explicit(&rwl->cnt_and_flag, WRITER_ACTIVE,
10d019
-					  memory_order_relaxed);
10d019
-		atomic_fetch_add_explicit(&rwl->write_completions, 1,
10d019
-					  memory_order_relaxed);
10d019
-#else
10d019
-		(void)isc_atomic_xadd(&rwl->cnt_and_flag, -WRITER_ACTIVE);
10d019
-		(void)isc_atomic_xadd(&rwl->write_completions, 1);
10d019
-#endif
10d019
-
10d019
-		if (rwl->write_granted >= rwl->write_quota ||
10d019
-		    rwl->write_requests == rwl->write_completions ||
10d019
-		    (rwl->cnt_and_flag & ~WRITER_ACTIVE) != 0) {
10d019
+		atomic_fetch_sub_release(&rwl->cnt_and_flag, WRITER_ACTIVE);
10d019
+		atomic_fetch_add_release(&rwl->write_completions, 1);
10d019
+
10d019
+		if ((atomic_load_acquire(&rwl->write_granted) >=
10d019
+		     rwl->write_quota) ||
10d019
+		    (atomic_load_acquire(&rwl->write_requests) ==
10d019
+		    atomic_load_acquire(&rwl->write_completions)) ||
10d019
+		    (atomic_load_acquire(&rwl->cnt_and_flag)
10d019
+		     & ~WRITER_ACTIVE))
10d019
+		{
10d019
 			/*
10d019
 			 * We have passed the write quota, no writer is
10d019
 			 * waiting, or some readers are almost ready, pending
10d019
@@ -668,7 +606,8 @@ isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
10d019
 			UNLOCK(&rwl->lock);
10d019
 		}
10d019
 
10d019
-		if (rwl->write_requests != rwl->write_completions &&
10d019
+		if ((atomic_load_acquire(&rwl->write_requests) !=
10d019
+		     atomic_load_acquire(&rwl->write_completions)) &&
10d019
 		    wakeup_writers) {
10d019
 			LOCK(&rwl->lock);
10d019
 			BROADCAST(&rwl->writeable);
10d019
-- 
10d019
2.21.0
10d019