summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2016-06-23 08:28:13 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2016-06-23 08:28:13 +0000
commit35e8002c58e8930086a98aebb48d071a484c9dc9 (patch)
tree8d76ccde67aa54eb33b14d358e79494f64529a82
parent505cd5d13b48ec3b068d70411da1c472af9f7e41 (diff)
Notes
-rw-r--r--sys/vm/vm_page.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index 5fa1f80671cd..2c89cd949c5b 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -760,17 +760,36 @@ vm_page_trysbusy(vm_page_t m)
}
static void
+vm_page_xunbusy_locked(vm_page_t m)
+{
+
+ vm_page_assert_xbusied(m);
+ vm_page_assert_locked(m);
+
+ atomic_store_rel_int(&m->busy_lock, VPB_UNBUSIED);
+ /* There is a waiter, do wakeup() instead of vm_page_flash(). */
+ wakeup(m);
+}
+
+static void
vm_page_xunbusy_maybelocked(vm_page_t m)
{
bool lockacq;
vm_page_assert_xbusied(m);
+ /*
+ * Fast path for unbusy. If it succeeds, we know that there
+ * are no waiters, so we do not need a wakeup.
+ */
+ if (atomic_cmpset_rel_int(&m->busy_lock, VPB_SINGLE_EXCLUSIVER,
+ VPB_UNBUSIED))
+ return;
+
lockacq = !mtx_owned(vm_page_lockptr(m));
if (lockacq)
vm_page_lock(m);
- vm_page_flash(m);
- atomic_store_rel_int(&m->busy_lock, VPB_UNBUSIED);
+ vm_page_xunbusy_locked(m);
if (lockacq)
vm_page_unlock(m);
}
@@ -788,8 +807,7 @@ vm_page_xunbusy_hard(vm_page_t m)
vm_page_assert_xbusied(m);
vm_page_lock(m);
- atomic_store_rel_int(&m->busy_lock, VPB_UNBUSIED);
- wakeup(m);
+ vm_page_xunbusy_locked(m);
vm_page_unlock(m);
}