Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 25 Sep 2015 13:03:58 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r288216 - head/sys/kern
Message-ID:  <201509251303.t8PD3wjh038618@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201509251303.t8PD3wjh038618>