git: 1b89d40fbf77 - main - Revert "vm: use atomic fetchadd in vm_page_sunbusy"

From: Mateusz Guzik <mjg_at_FreeBSD.org>
Date: Wed, 17 Aug 2022 16:25:06 UTC
The branch main has been updated by mjg:

URL: https://cgit.FreeBSD.org/src/commit/?id=1b89d40fbf7788c75a7612b22b1dba1612e45c9a

commit 1b89d40fbf7788c75a7612b22b1dba1612e45c9a
Author:     Mateusz Guzik <mjg@FreeBSD.org>
AuthorDate: 2022-08-17 16:24:14 +0000
Commit:     Mateusz Guzik <mjg@FreeBSD.org>
CommitDate: 2022-08-17 16:24:14 +0000

    Revert "vm: use atomic fetchadd in vm_page_sunbusy"
    
    This reverts commit f6ffed44a8eb5d1ab89a18e60fb056aab2105be7.
    
    fetchadd will fail the waiters flag, which can cause other
    code to wait when it should not with nothing clear it
    
    Revert until I sort this out.
    
    Reported by:    markj
---
 sys/vm/vm_page.c | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index defcebb286ae..e7500e9d3e71 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -973,13 +973,27 @@ vm_page_sunbusy(vm_page_t m)
 {
 	u_int x;
 
-	atomic_thread_fence_rel();
-	x = atomic_fetchadd_int(&m->busy_lock, -VPB_ONE_SHARER);
-	KASSERT(x != VPB_FREED, ("page %p is freed", m));
-	KASSERT(x != VPB_UNBUSIED && (x & VPB_BIT_SHARED) != 0,
-	    ("page %p not sbusied", m));
-	if (x == (VPB_SHARERS_WORD(1) | VPB_BIT_WAITERS))
+	vm_page_assert_sbusied(m);
+
+	x = vm_page_busy_fetch(m);
+	for (;;) {
+		KASSERT(x != VPB_FREED,
+		    ("vm_page_sunbusy: Unlocking freed page."));
+		if (VPB_SHARERS(x) > 1) {
+			if (atomic_fcmpset_int(&m->busy_lock, &x,
+			    x - VPB_ONE_SHARER))
+				break;
+			continue;
+		}
+		KASSERT((x & ~VPB_BIT_WAITERS) == VPB_SHARERS_WORD(1),
+		    ("vm_page_sunbusy: invalid lock state"));
+		if (!atomic_fcmpset_rel_int(&m->busy_lock, &x, VPB_UNBUSIED))
+			continue;
+		if ((x & VPB_BIT_WAITERS) == 0)
+			break;
 		wakeup(m);
+		break;
+	}
 }
 
 /*