svn commit: r188134 - head/sys/i386/xen

Kip Macy kmacy at FreeBSD.org
Wed Feb 4 18:01:19 PST 2009


Author: kmacy
Date: Thu Feb  5 02:01:18 2009
New Revision: 188134
URL: http://svn.freebsd.org/changeset/base/188134

Log:
  adjust the way that idle happens so as to avoid missing timer interrupts

Modified:
  head/sys/i386/xen/clock.c

Modified: head/sys/i386/xen/clock.c
==============================================================================
--- head/sys/i386/xen/clock.c	Thu Feb  5 01:59:28 2009	(r188133)
+++ head/sys/i386/xen/clock.c	Thu Feb  5 02:01:18 2009	(r188134)
@@ -246,24 +246,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;
@@ -311,15 +316,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(TRAPF_USERMODE(frame), TRAPF_PC(frame));
+		else
+		      hardclock_cpu(TRAPF_USERMODE(frame));
 	}
-	if (PCPU_GET(cpuid) == 0)
-		hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
-	else
-		hardclock_cpu(TRAPF_USERMODE(frame));
-
 	/*
 	 * Take synchronised time from Xen once a minute if we're not
 	 * synchronised ourselves, and we haven't chosen to keep an independent
@@ -334,61 +339,25 @@ clkintr(void *arg)
 	/* XXX TODO */
 	return (FILTER_HANDLED);
 }
-
-int clkintr2(void *arg);
-
-int 
-clkintr2(void *arg)
-{
-	int64_t delta_cpu, delta;
-	struct trapframe *frame = (struct trapframe *)arg;
-	int cpu = smp_processor_id();
-	struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu);
-
-	do {
-		__get_time_values_from_xen();
-		
-		delta = delta_cpu = 
-			shadow->system_timestamp + get_nsec_offset(shadow);
-		delta     -= processed_system_time;
-		delta_cpu -= per_cpu(processed_system_time, cpu);
-
-	} while (!time_values_up_to_date(cpu));
-	
-	if (unlikely(delta < (int64_t)0) || unlikely(delta_cpu < (int64_t)0)) {
-		printf("Timer ISR: Time went backwards: %lld\n", delta);
-		return (FILTER_HANDLED);
-	}
-	
-	/* 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;
-	}
-	hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
-
-	/*
-	 * Take synchronised time from Xen once a minute if we're not
-	 * synchronised ourselves, and we haven't chosen to keep an independent
-	 * time base.
-	 */
-	
-	if (shadow_tv_version != HYPERVISOR_shared_info->wc_version) {
-		update_wallclock();
-		tc_setclock(&shadow_tv);
-	}
-	
-	/* XXX TODO */
-	return (FILTER_HANDLED);
-}
-
 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);
 }
 
 
@@ -552,7 +521,6 @@ startrtclock()
         timer_freq = xen_timecounter.tc_frequency = 1000000000LL;
         tc_init(&xen_timecounter);
 
-
 	rdtscll(alarm);
 }
 
@@ -903,13 +871,44 @@ 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);
 }
 
 int


More information about the svn-src-head mailing list