Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 5 Feb 2009 02:16:06 +0000 (UTC)
From:      Kip Macy <kmacy@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r188137 - projects/release_6_3_xen/sys/i386/xen
Message-ID:  <200902050216.n152G6fN005434@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kmacy
Date: Thu Feb  5 02:16:05 2009
New Revision: 188137
URL: http://svn.freebsd.org/changeset/base/188137

Log:
  change the way that blocking is handled to avoid missing timer interrupts

Modified:
  projects/release_6_3_xen/sys/i386/xen/clock.c

Modified: projects/release_6_3_xen/sys/i386/xen/clock.c
==============================================================================
--- projects/release_6_3_xen/sys/i386/xen/clock.c	Thu Feb  5 02:08:12 2009	(r188136)
+++ projects/release_6_3_xen/sys/i386/xen/clock.c	Thu Feb  5 02:16:05 2009	(r188137)
@@ -253,24 +253,29 @@ static void __get_time_values_from_xen(v
 	shared_info_t           *s = HYPERVISOR_shared_info;
 	struct vcpu_time_info   *src;
 	struct shadow_time_info *dst;
+	uint32_t pre_version, post_version;
 
 	src = &s->vcpu_info[smp_processor_id()].time;
 	dst = &per_cpu(shadow_time, smp_processor_id());
 
+	spinlock_enter();
 	do {
-		dst->version = src->version;
+	        pre_version = dst->version = src->version;
 		rmb();
 		dst->tsc_timestamp     = src->tsc_timestamp;
 		dst->system_timestamp  = src->system_time;
 		dst->tsc_to_nsec_mul   = src->tsc_to_system_mul;
 		dst->tsc_shift         = src->tsc_shift;
 		rmb();
+		post_version = src->version;
 	}
-	while ((src->version & 1) | (dst->version ^ src->version));
+	while ((pre_version & 1) | (pre_version ^ post_version));
 
 	dst->tsc_to_usec_mul = dst->tsc_to_nsec_mul / 1000;
+	spinlock_exit();
 }
 
+
 static inline int time_values_up_to_date(int cpu)
 {
 	struct vcpu_time_info   *src;
@@ -318,12 +323,15 @@ clkintr(void *arg)
 	}
 	
 	/* Process elapsed ticks since last call. */
-	if (delta >= NS_PER_TICK) {
-		processed_system_time += (delta / NS_PER_TICK) * NS_PER_TICK;
-		per_cpu(processed_system_time, cpu) += (delta_cpu / NS_PER_TICK) * NS_PER_TICK;
+	while (delta >= NS_PER_TICK) {
+	        delta -= NS_PER_TICK;
+		processed_system_time += NS_PER_TICK;
+		per_cpu(processed_system_time, cpu) +=  NS_PER_TICK;
+		if (PCPU_GET(cpuid) == 0)
+			hardclock(frame);
+		else
+			hardclock_process(frame);
 	}
-	hardclock(frame);
-
 	/*
 	 * Take synchronised time from Xen once a minute if we're not
 	 * synchronised ourselves, and we haven't chosen to keep an independent
@@ -335,16 +343,26 @@ clkintr(void *arg)
 		tc_setclock(&shadow_tv);
 	}
 	
-	/* XXX TODO */
 }
-
 static uint32_t
 getit(void)
 {
 	struct shadow_time_info *shadow;
+	uint64_t time;
+	uint32_t local_time_version;
+
 	shadow = &per_cpu(shadow_time, smp_processor_id());
-	__get_time_values_from_xen();
-	return shadow->system_timestamp + get_nsec_offset(shadow);
+
+	do {
+	  local_time_version = shadow->version;
+	  barrier();
+	  time = shadow->system_timestamp + get_nsec_offset(shadow);
+	  if (!time_values_up_to_date(cpu))
+	    __get_time_values_from_xen(/*cpu */);
+	  barrier();
+	} while (local_time_version != shadow->version);
+
+	  return (time);
 }
 
 
@@ -504,7 +522,6 @@ startrtclock()
         timer_freq = xen_timecounter.tc_frequency = 1000000000LL;
         tc_init(&xen_timecounter);
 
-
 	rdtscll(alarm);
 }
 
@@ -953,11 +970,42 @@ xen_get_offset(void)
 	return edx;
 }
 #endif
+
+/* Convert jiffies to system time. */
+static uint64_t 
+ticks_to_system_time(unsigned long newticks)
+{
+#if 0
+  unsigned long seq;
+#endif
+  long delta;
+  uint64_t st;
+
+
+    delta = newticks - ticks;
+    if (delta < 1) {
+      /* Triggers in some wrap-around cases, but that's okay:
+       * we just end up with a shorter timeout. */
+      st = processed_system_time + NS_PER_TICK;
+    } else if (((unsigned long)delta >> (BITS_PER_LONG-3)) != 0) {
+      /* Very long timeout means there is no pending timer.
+       * We indicate this to Xen by passing zero timeout. */
+      st = 0;
+    } else {
+      st = processed_system_time + delta * (uint64_t)NS_PER_TICK;
+    }
+
+    return (st);
+}
+
 void
 idle_block(void)
 {
+  uint64_t timeout;
 
-	__get_time_values_from_xen();
-	PANIC_IF(HYPERVISOR_set_timer_op(processed_system_time + NS_PER_TICK) != 0);
-	HYPERVISOR_sched_op(SCHEDOP_block, 0);
+  timeout = ticks_to_system_time(ticks + 1)  + NS_PER_TICK/2;
+
+  __get_time_values_from_xen();
+  PANIC_IF(HYPERVISOR_set_timer_op(timeout) != 0);
+  HYPERVISOR_sched_op(SCHEDOP_block, 0);
 }



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