From owner-svn-src-projects@FreeBSD.ORG Thu Feb 5 02:16:06 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 355C0106566B; Thu, 5 Feb 2009 02:16:06 +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 240628FC0A; Thu, 5 Feb 2009 02:16:06 +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 n152G6DJ005435; Thu, 5 Feb 2009 02:16:06 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n152G6fN005434; Thu, 5 Feb 2009 02:16:06 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <200902050216.n152G6fN005434@svn.freebsd.org> From: Kip Macy Date: Thu, 5 Feb 2009 02:16:06 +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: r188137 - projects/release_6_3_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:16:06 -0000 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); }