Source-Changes-HG archive

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

[src/trunk]: src/sys/kern - pserialize_switchpoint: check for passing twice, ...



details:   https://anonhg.NetBSD.org/src/rev/e31c80d2166f
branches:  trunk
changeset: 784736:e31c80d2166f
user:      rmind <rmind%NetBSD.org@localhost>
date:      Thu Feb 07 23:37:58 2013 +0000

description:
- pserialize_switchpoint: check for passing twice, not more than needed.
- pserialize_perform: avoid a possible race with softint handler.
Reported by hannken@.

diffstat:

 sys/kern/subr_pserialize.c |  43 +++++++++++++++++--------------------------
 1 files changed, 17 insertions(+), 26 deletions(-)

diffs (117 lines):

diff -r d883aa5652f5 -r e31c80d2166f sys/kern/subr_pserialize.c
--- a/sys/kern/subr_pserialize.c        Thu Feb 07 21:56:36 2013 +0000
+++ b/sys/kern/subr_pserialize.c        Thu Feb 07 23:37:58 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: subr_pserialize.c,v 1.6 2013/01/07 23:21:32 rmind Exp $        */
+/*     $NetBSD: subr_pserialize.c,v 1.7 2013/02/07 23:37:58 rmind Exp $        */
 
 /*-
  * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_pserialize.c,v 1.6 2013/01/07 23:21:32 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_pserialize.c,v 1.7 2013/02/07 23:37:58 rmind Exp $");
 
 #include <sys/param.h>
 
@@ -48,13 +48,13 @@
 #include <sys/kmem.h>
 #include <sys/mutex.h>
 #include <sys/pserialize.h>
+#include <sys/proc.h>
 #include <sys/queue.h>
 #include <sys/xcall.h>
 
 struct pserialize {
        TAILQ_ENTRY(pserialize) psz_chain;
        lwp_t *                 psz_owner;
-       kcondvar_t              psz_notifier;
        kcpuset_t *             psz_target;
        kcpuset_t *             psz_pass;
 };
@@ -102,7 +102,6 @@
        pserialize_t psz;
 
        psz = kmem_zalloc(sizeof(struct pserialize), KM_SLEEP);
-       cv_init(&psz->psz_notifier, "psrlz");
        kcpuset_create(&psz->psz_target, true);
        kcpuset_create(&psz->psz_pass, true);
        psz->psz_owner = NULL;
@@ -121,7 +120,6 @@
 
        KASSERT(psz->psz_owner == NULL);
 
-       cv_destroy(&psz->psz_notifier);
        kcpuset_destroy(psz->psz_target);
        kcpuset_destroy(psz->psz_pass);
        kmem_free(psz, sizeof(struct pserialize));
@@ -163,27 +161,21 @@
        mutex_spin_enter(&psz_lock);
        TAILQ_INSERT_TAIL(&psz_queue0, psz, psz_chain);
        psz_work_todo++;
-       mutex_spin_exit(&psz_lock);
 
-       /*
-        * Force some context switch activity on every CPU, as the system
-        * may not be busy.  Note: should pass the point twice.
-        */
-       xc = xc_broadcast(XC_HIGHPRI, (xcfunc_t)nullop, NULL, NULL);
-       xc_wait(xc);
+       do {
+               mutex_spin_exit(&psz_lock);
 
-       /* No need to xc_wait() as we implement our own condvar. */
-       xc_broadcast(XC_HIGHPRI, (xcfunc_t)nullop, NULL, NULL);
+               /*
+                * Force some context switch activity on every CPU, as
+                * the system may not be busy.  Pause to not flood.
+                */
+               xc = xc_broadcast(XC_HIGHPRI, (xcfunc_t)nullop, NULL, NULL);
+               xc_wait(xc);
+               kpause("psrlz", false, 1, NULL);
 
-       /*
-        * Wait for all CPUs to cycle through mi_switch() twice.
-        * The last one through will remove our update from the
-        * queue and awaken us.
-        */
-       mutex_spin_enter(&psz_lock);
-       while (!kcpuset_iszero(psz->psz_target)) {
-               cv_wait(&psz->psz_notifier, &psz_lock);
-       }
+               mutex_spin_enter(&psz_lock);
+       } while (!kcpuset_iszero(psz->psz_target));
+
        psz_ev_excl.ev_count++;
        mutex_spin_exit(&psz_lock);
 
@@ -236,8 +228,8 @@
         */
        for (psz = TAILQ_FIRST(&psz_queue1); psz != NULL; psz = next) {
                next = TAILQ_NEXT(psz, psz_chain);
+               kcpuset_set(psz->psz_pass, cid);
                if (!kcpuset_match(psz->psz_pass, psz->psz_target)) {
-                       kcpuset_set(psz->psz_pass, cid);
                        continue;
                }
                kcpuset_zero(psz->psz_pass);
@@ -250,8 +242,8 @@
         */
        for (psz = TAILQ_FIRST(&psz_queue0); psz != NULL; psz = next) {
                next = TAILQ_NEXT(psz, psz_chain);
+               kcpuset_set(psz->psz_pass, cid);
                if (!kcpuset_match(psz->psz_pass, psz->psz_target)) {
-                       kcpuset_set(psz->psz_pass, cid);
                        continue;
                }
                kcpuset_zero(psz->psz_pass);
@@ -265,7 +257,6 @@
        while ((psz = TAILQ_FIRST(&psz_queue2)) != NULL) {
                TAILQ_REMOVE(&psz_queue2, psz, psz_chain);
                kcpuset_zero(psz->psz_target);
-               cv_signal(&psz->psz_notifier);
                psz_work_todo--;
        }
        mutex_spin_exit(&psz_lock);



Home | Main Index | Thread Index | Old Index