From a701e5dfafb22455e8cfbca0e7f2f834808b1a9d Mon Sep 17 00:00:00 2001 From: bluhm Date: Tue, 18 Sep 2018 20:47:11 +0000 Subject: [PATCH] Updating time counters without memory barriers is wrong. Put membar_producer() into tc_windup() and membar_consumer() into the uptime functions. They order the visibility of the time and generation number updates. This is a combination of what NetBSD and FreeBSD do. OK kettenis@ --- sys/kern/kern_tc.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c index 9aa44703ac4..3d02cf70224 100644 --- a/sys/kern/kern_tc.c +++ b/sys/kern/kern_tc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_tc.c,v 1.33 2018/05/28 18:05:42 guenther Exp $ */ +/* $OpenBSD: kern_tc.c,v 1.34 2018/09/18 20:47:11 bluhm Exp $ */ /* * Copyright (c) 2000 Poul-Henning Kamp @@ -22,6 +22,7 @@ */ #include +#include #include #include #include @@ -141,8 +142,10 @@ binuptime(struct bintime *bt) do { th = 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); } @@ -199,7 +202,9 @@ getnanouptime(struct timespec *tsp) do { th = timehands; gen = th->th_generation; + membar_consumer(); bintime2timespec(&th->th_offset, tsp); + membar_consumer(); } while (gen == 0 || gen != th->th_generation); } @@ -212,7 +217,9 @@ getmicrouptime(struct timeval *tvp) do { th = timehands; gen = th->th_generation; + membar_consumer(); bintime2timeval(&th->th_offset, tvp); + membar_consumer(); } while (gen == 0 || gen != th->th_generation); } @@ -225,7 +232,9 @@ getnanotime(struct timespec *tsp) do { th = timehands; gen = th->th_generation; + membar_consumer(); *tsp = th->th_nanotime; + membar_consumer(); } while (gen == 0 || gen != th->th_generation); } @@ -238,7 +247,9 @@ getmicrotime(struct timeval *tvp) do { th = timehands; gen = th->th_generation; + membar_consumer(); *tvp = th->th_microtime; + membar_consumer(); } while (gen == 0 || gen != th->th_generation); } @@ -390,6 +401,7 @@ tc_windup(void) th = tho->th_next; ogen = th->th_generation; th->th_generation = 0; + membar_producer(); memcpy(th, tho, offsetof(struct timehands, th_generation)); /* @@ -481,11 +493,13 @@ tc_windup(void) */ if (++ogen == 0) ogen = 1; + membar_producer(); th->th_generation = ogen; /* Go live with the new struct timehands. */ time_second = th->th_microtime.tv_sec; time_uptime = th->th_offset.sec; + membar_producer(); timehands = th; } -- 2.20.1