svn commit: r288216 - head/sys/kern
Konstantin Belousov
kib at FreeBSD.org
Fri Sep 25 13:03:58 UTC 2015
Author: kib
Date: Fri Sep 25 13:03:57 2015
New Revision: 288216
URL: https://svnweb.freebsd.org/changeset/base/288216
Log:
Use per-cpu values for base and last in tc_cpu_ticks(). The values
are updated lockess, different CPUs write its own view of timecounter
state. The critical section is done for safety, callers of
tc_cpu_ticks() are supposed to already enter critical section, or to
own a spinlock.
The change fixes sporadical reports of too high values reported for
the (W)CPU on platforms that do not provide cpu ticker and use
tc_cpu_ticks(), in particular, arm*.
Diagnosed and reviewed by: jhb
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Modified:
head/sys/kern/kern_tc.c
Modified: head/sys/kern/kern_tc.c
==============================================================================
--- head/sys/kern/kern_tc.c Fri Sep 25 10:14:39 2015 (r288215)
+++ head/sys/kern/kern_tc.c Fri Sep 25 13:03:57 2015 (r288216)
@@ -1924,20 +1924,27 @@ SYSINIT(timecounter, SI_SUB_CLOCKS, SI_O
static int cpu_tick_variable;
static uint64_t cpu_tick_frequency;
+static DPCPU_DEFINE(uint64_t, tc_cpu_ticks_base);
+static DPCPU_DEFINE(unsigned, tc_cpu_ticks_last);
+
static uint64_t
tc_cpu_ticks(void)
{
- static uint64_t base;
- static unsigned last;
- unsigned u;
struct timecounter *tc;
+ uint64_t res, *base;
+ unsigned u, *last;
+ critical_enter();
+ base = DPCPU_PTR(tc_cpu_ticks_base);
+ last = DPCPU_PTR(tc_cpu_ticks_last);
tc = timehands->th_counter;
u = tc->tc_get_timecount(tc) & tc->tc_counter_mask;
- if (u < last)
- base += (uint64_t)tc->tc_counter_mask + 1;
- last = u;
- return (u + base);
+ if (u < *last)
+ *base += (uint64_t)tc->tc_counter_mask + 1;
+ *last = u;
+ res = u + *base;
+ critical_exit();
+ return (res);
}
void
More information about the svn-src-head
mailing list