From owner-svn-src-projects@FreeBSD.ORG Thu Feb 5 02:08:12 2009 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5ACD0106564A; Thu, 5 Feb 2009 02:08:12 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 499948FC16; Thu, 5 Feb 2009 02:08:12 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n1528CtT004632; Thu, 5 Feb 2009 02:08:12 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n1528CTN004631; Thu, 5 Feb 2009 02:08:12 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <200902050208.n1528CTN004631@svn.freebsd.org> From: Kip Macy Date: Thu, 5 Feb 2009 02:08:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r188136 - projects/releng_7_xen/sys/i386/xen X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 05 Feb 2009 02:08:12 -0000 Author: kmacy Date: Thu Feb 5 02:08:12 2009 New Revision: 188136 URL: http://svn.freebsd.org/changeset/base/188136 Log: adjust the way that idle happens so as to avoid missing timer interrupts on block Modified: projects/releng_7_xen/sys/i386/xen/clock.c Modified: projects/releng_7_xen/sys/i386/xen/clock.c ============================================================================== --- projects/releng_7_xen/sys/i386/xen/clock.c Thu Feb 5 02:06:27 2009 (r188135) +++ projects/releng_7_xen/sys/i386/xen/clock.c Thu Feb 5 02:08:12 2009 (r188136) @@ -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,11 +871,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); }