Source-Changes archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

CVS commit: src/sys/kern



Module Name:    src
Committed By:   riastradh
Date:           Sun Dec  1 20:56:40 UTC 2019

Modified Files:
        src/sys/kern: subr_xcall.c

Log Message:
Restore xcall(9) fast path using atomic_load/store_*.

While here, fix a bug that was formerly in xcall(9): a missing
acquire operation in the xc_wait fast path so that all memory
operations in the xcall on remote CPUs will happen before any memory
operations on the issuing CPU after xc_wait returns.

All stores of xc->xc_donep are done with atomic_store_release so that
we can safely use atomic_load_acquire to read it outside the lock.
However, this fast path only works on platforms with cheap 64-bit
atomic load/store, so conditionalize it on __HAVE_ATOMIC64_LOADSTORE.
(Under the lock, no need for atomic loads since nobody else will be
issuing stores.)

For review, here's the relevant diff from the old version of the fast
path, from before it was removed and some other things changed in the
file:

diff --git a/sys/kern/subr_xcall.c b/sys/kern/subr_xcall.c
index 45a877aa90e0..b6bfb6455291 100644
--- a/sys/kern/subr_xcall.c
+++ b/sys/kern/subr_xcall.c
@@ -84,6 +84,7 @@ __KERNEL_RCSID(0, "$NetBSD: subr_xcall.c,v 1.27 2019/10/06 15:11:17 uwe Exp $");
 #include <sys/evcnt.h>
 #include <sys/kthread.h>
 #include <sys/cpu.h>
+#include <sys/atomic.h>

 #ifdef _RUMPKERNEL
 #include "rump_private.h"
@@ -334,10 +353,12 @@ xc_wait(uint64_t where)
                xc = &xc_low_pri;
        }

+#ifdef __HAVE_ATOMIC64_LOADSTORE
        /* Fast path, if already done. */
-       if (xc->xc_donep >= where) {
+       if (atomic_load_acquire(&xc->xc_donep) >= where) {
                return;
        }
+#endif

        /* Slow path: block until awoken. */
        mutex_enter(&xc->xc_lock);
@@ -422,7 +443,11 @@ xc_thread(void *cookie)
                (*func)(arg1, arg2);

                mutex_enter(&xc->xc_lock);
+#ifdef __HAVE_ATOMIC64_LOADSTORE
+               atomic_store_release(&xc->xc_donep, xc->xc_donep + 1);
+#else
                xc->xc_donep++;
+#endif
        }
        /* NOTREACHED */
 }
@@ -462,7 +487,6 @@ xc__highpri_intr(void *dummy)
         * Lock-less fetch of function and its arguments.
         * Safe since it cannot change at this point.
         */
-       KASSERT(xc->xc_donep < xc->xc_headp);
        func = xc->xc_func;
        arg1 = xc->xc_arg1;
        arg2 = xc->xc_arg2;
@@ -475,7 +499,13 @@ xc__highpri_intr(void *dummy)
         * cross-call has been processed - notify waiters, if any.
         */
        mutex_enter(&xc->xc_lock);
-       if (++xc->xc_donep == xc->xc_headp) {
+       KASSERT(xc->xc_donep < xc->xc_headp);
+#ifdef __HAVE_ATOMIC64_LOADSTORE
+       atomic_store_release(&xc->xc_donep, xc->xc_donep + 1);
+#else
+       xc->xc_donep++;
+#endif
+       if (xc->xc_donep == xc->xc_headp) {
                cv_broadcast(&xc->xc_busy);
        }
        mutex_exit(&xc->xc_lock);


To generate a diff of this commit:
cvs rdiff -u -r1.31 -r1.32 src/sys/kern/subr_xcall.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.




Home | Main Index | Thread Index | Old Index