diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2015-09-25 13:03:57 +0000 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-10-12 07:04:10 +0200 |
commit | f013c1476e3c1184aa18d7e33fd219e253db192f (patch) | |
tree | b4f5916548b24555011755f9cd52f82c2b7f669e /cpukit/score/src | |
parent | timecounter: Merge FreeBSD change r304285 (diff) | |
download | rtems-f013c1476e3c1184aa18d7e33fd219e253db192f.tar.bz2 |
timecounter: Merge FreeBSD change r288216
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
Update #3175.
Diffstat (limited to 'cpukit/score/src')
-rw-r--r-- | cpukit/score/src/kern_tc.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c index e6e952facd..1e8189acea 100644 --- a/cpukit/score/src/kern_tc.c +++ b/cpukit/score/src/kern_tc.c @@ -2183,20 +2183,27 @@ SYSINIT(timecounter, SI_SUB_CLOCKS, SI_ORDER_SECOND, inittimecounter, NULL); 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 |