Port-alpha archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Alpha timecounter
> Date: Wed, 1 Nov 2017 16:41:29 +0000
> From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
>
> The attached compile-tested patch attempts to fix it by enforcing a
> global ordering, and calling tc_gonebad if the calibration fails to
> keep it within 1sec. The patch is for code that is nominally MI,
> kern_cctr.c, but only alpha uses it.
Made a mistake in a little tweak just before I sent it, so that the
timecounter would pretty much unconditionally conclude the timecounter
has gone bad. Attached patch should avoid that.
Index: sys/kern/kern_cctr.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_cctr.c,v
retrieving revision 1.9
diff -p -u -r1.9 kern_cctr.c
--- sys/kern/kern_cctr.c 3 Jan 2009 03:31:23 -0000 1.9
+++ sys/kern/kern_cctr.c 1 Nov 2017 17:04:58 -0000
@@ -95,6 +95,12 @@ void cc_calibrate_cpu(struct cpu_info *)
static int64_t cc_cal_val; /* last calibrate time stamp */
+/*
+ * Highest cc witnessed globally. We assume the calibration happens
+ * once a second.
+ */
+static volatile u_int cc_global __cacheline_aligned;
+
static struct timecounter cc_timecounter = {
.tc_get_timecount = cc_get_timecount,
.tc_poll_pps = cc_calibrate,
@@ -132,8 +138,8 @@ cc_init(timecounter_get_t getcc, uint64_
/*
* pick up tick count scaled to reference tick count
*/
-u_int
-cc_get_timecount(struct timecounter *tc)
+static u_int
+cc_get_timecount_local(struct timecounter *tc)
{
struct cpu_info *ci;
int64_t rcc, cc, ncsw;
@@ -186,6 +192,37 @@ cc_get_timecount(struct timecounter *tc)
}
/*
+ * advance the global view of the clock by our tick count and return it
+ */
+u_int
+cc_get_timecount(struct timecounter *tc)
+{
+ u_int freq = tc->tc_frequency;
+ u_int local, global, result;
+
+ do {
+ local = cc_get_timecount_local(tc);
+ global = cc_global;
+ if ((local - global) < freq) {
+ /* We're ahead, so use our counter. */
+ result = local;
+ } else {
+ /* We're behind or desynced, so use the global. */
+ result = global + 1;
+ }
+ } while (atomic_cas_uint(&cc_global, global, result) != global);
+
+ if (__predict_false((local - global) > freq &&
+ (global - local) > freq)) {
+ /* More than 1sec away from global: bad. */
+ printf("%s: local cc desynchronized\n", tc->tc_name);
+ tc_gonebad(tc);
+ }
+
+ return result;
+}
+
+/*
* called once per clock tick via the pps callback
* for the calibration of the TSC counters.
* it is called only for the PRIMARY cpu. all
Home |
Main Index |
Thread Index |
Old Index