svn commit: r188137 - projects/release_6_3_xen/sys/i386/xen
Kip Macy
kmacy at FreeBSD.org
Wed Feb 4 18:16:06 PST 2009
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);
}
More information about the svn-src-projects
mailing list