Module Name: src Committed By: riastradh Date: Mon Jul 17 21:51:45 UTC 2023
Modified Files: src/sys/kern: kern_tc.c Log Message: timecounter(9): Sprinkle membar_consumer around th->th_generation. This code was apparently written under the misapprehension that membar_producer on one side is good enough, but that doesn't accomplish anything other than making the code unnecessarily obscure. For semantics, you always always always need memory barriers to come in pairs, with membar_consumer on the reading side if you want the membar_producer to have on the writing side to have any useful effect. It is unfortunate that this might hurt performance, but that's an unfortunate consequence of the design made without understanding memory barriers, not an unfortunate consequence of the memory barriers. If it is really critical for the read side to avoid memory barriers, then the write side needs to issue an IPI or xcall to effect memory barriers -- at higher cost to the write side, of course. To generate a diff of this commit: cvs rdiff -u -r1.72 -r1.73 src/sys/kern/kern_tc.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/kern_tc.c diff -u src/sys/kern/kern_tc.c:1.72 src/sys/kern/kern_tc.c:1.73 --- src/sys/kern/kern_tc.c:1.72 Mon Jul 17 21:51:30 2023 +++ src/sys/kern/kern_tc.c Mon Jul 17 21:51:45 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_tc.c,v 1.72 2023/07/17 21:51:30 riastradh Exp $ */ +/* $NetBSD: kern_tc.c,v 1.73 2023/07/17 21:51:45 riastradh Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -40,7 +40,7 @@ #include <sys/cdefs.h> /* __FBSDID("$FreeBSD: src/sys/kern/kern_tc.c,v 1.166 2005/09/19 22:16:31 andre Exp $"); */ -__KERNEL_RCSID(0, "$NetBSD: kern_tc.c,v 1.72 2023/07/17 21:51:30 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_tc.c,v 1.73 2023/07/17 21:51:45 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_ntp.h" @@ -457,6 +457,10 @@ binuptime(struct bintime *bt) * updating timecounter_removals will issue a broadcast cross call * before inspecting our l_tcgen value (this elides memory ordering * issues). + * + * XXX If the author of the above comment knows how to make it + * safe to avoid memory barriers around the access to + * th->th_generation, I'm all ears. */ l = curlwp; lgen = l->l_tcgen; @@ -468,8 +472,10 @@ binuptime(struct bintime *bt) do { th = atomic_load_consume(&timehands); gen = th->th_generation; + membar_consumer(); *bt = th->th_offset; bintime_addx(bt, th->th_scale * tc_delta(th)); + membar_consumer(); } while (gen == 0 || gen != th->th_generation); __insn_barrier(); @@ -537,7 +543,9 @@ getbinuptime(struct bintime *bt) do { th = atomic_load_consume(&timehands); gen = th->th_generation; + membar_consumer(); *bt = th->th_offset; + membar_consumer(); } while (gen == 0 || gen != th->th_generation); } @@ -551,7 +559,9 @@ getnanouptime(struct timespec *tsp) do { th = atomic_load_consume(&timehands); gen = th->th_generation; + membar_consumer(); bintime2timespec(&th->th_offset, tsp); + membar_consumer(); } while (gen == 0 || gen != th->th_generation); } @@ -565,7 +575,9 @@ getmicrouptime(struct timeval *tvp) do { th = atomic_load_consume(&timehands); gen = th->th_generation; + membar_consumer(); bintime2timeval(&th->th_offset, tvp); + membar_consumer(); } while (gen == 0 || gen != th->th_generation); } @@ -580,7 +592,9 @@ getbintime(struct bintime *bt) do { th = atomic_load_consume(&timehands); gen = th->th_generation; + membar_consumer(); *bt = th->th_offset; + membar_consumer(); } while (gen == 0 || gen != th->th_generation); getbinboottime(&boottime); bintime_add(bt, &boottime); @@ -596,7 +610,9 @@ dogetnanotime(struct timespec *tsp) do { th = atomic_load_consume(&timehands); gen = th->th_generation; + membar_consumer(); *tsp = th->th_nanotime; + membar_consumer(); } while (gen == 0 || gen != th->th_generation); } @@ -626,7 +642,9 @@ getmicrotime(struct timeval *tvp) do { th = atomic_load_consume(&timehands); gen = th->th_generation; + membar_consumer(); *tvp = th->th_microtime; + membar_consumer(); } while (gen == 0 || gen != th->th_generation); }