summaryrefslogtreecommitdiffstats
path: root/cpukit/score/src
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2015-09-25 13:03:57 +0000
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-10-12 07:04:10 +0200
commitf013c1476e3c1184aa18d7e33fd219e253db192f (patch)
treeb4f5916548b24555011755f9cd52f82c2b7f669e /cpukit/score/src
parenttimecounter: Merge FreeBSD change r304285 (diff)
downloadrtems-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.c21
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