Source-Changes-HG archive

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

[src/prg-localcount2]: src/sys/kern When we're draining the localcount's refe...



details:   https://anonhg.NetBSD.org/src/rev/d25a1e8fb7cb
branches:  prg-localcount2
changeset: 823540:d25a1e8fb7cb
user:      pgoyette <pgoyette%NetBSD.org@localhost>
date:      Fri May 12 22:12:23 2017 +0000

description:
When we're draining the localcount's references, transfer the local
CPU's reference count to the global total, and then zero it.  Any
further calls to localcount_release() will adjust only the global
counter.

Avoids a race condition which depends on having localcount_release()
being aware of whether the local CPU's contribution has already been
accounted for.  Thanks to Kengo NAKAHARA for bringing up the question,
and to riastradh@ for the solution.

diffstat:

 sys/kern/subr_localcount.c |  17 ++++++++++++-----
 1 files changed, 12 insertions(+), 5 deletions(-)

diffs (52 lines):

diff -r 7e4e53b99635 -r d25a1e8fb7cb sys/kern/subr_localcount.c
--- a/sys/kern/subr_localcount.c        Fri May 12 06:24:53 2017 +0000
+++ b/sys/kern/subr_localcount.c        Fri May 12 22:12:23 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: subr_localcount.c,v 1.1.6.4 2017/05/11 21:31:12 pgoyette Exp $ */
+/*     $NetBSD: subr_localcount.c,v 1.1.6.5 2017/05/12 22:12:23 pgoyette Exp $ */
 
 /*-
  * Copyright (c) 2016 The NetBSD Foundation, Inc.
@@ -44,7 +44,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_localcount.c,v 1.1.6.4 2017/05/11 21:31:12 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_localcount.c,v 1.1.6.5 2017/05/12 22:12:23 pgoyette Exp $");
 
 #include <sys/param.h>
 #include <sys/localcount.h>
@@ -148,6 +148,14 @@
        percpu_free(lc->lc_percpu, sizeof(uint64_t));
 }
 
+/*
+ * localcount_xc(cookie0, cookie1)
+ *
+ *     Accumulate and transfer the per-CPU reference counts to a
+ *     global total, resetting the per-CPU counter to zero.  Once
+ *     localcount_drain() has started, we only maintain the total
+ *     count in localcount_release().
+ */
 static void
 localcount_xc(void *cookie0, void *cookie1)
 {
@@ -158,6 +166,7 @@
        mutex_enter(interlock);
        localp = percpu_getref(lc->lc_percpu);
        *lc->lc_totalp += *localp;
+       *localp -= *localp;             /* ie, *localp = 0; */
        percpu_putref(lc->lc_percpu);
        mutex_exit(interlock);
 }
@@ -235,9 +244,7 @@
                 * the last reference.
                 */
                mutex_enter(interlock);
-               localcount_adjust(lc, -1);
-               *lc->lc_totalp -= 1;
-               if (*lc->lc_totalp == 0)
+               if (--*lc->lc_totalp == 0)
                        cv_broadcast(cv);
                mutex_exit(interlock);
                goto out;



Home | Main Index | Thread Index | Old Index