From patchwork Tue Jul 17 22:05:34 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: john stultz X-Patchwork-Id: 10098 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 98B7F23F2A for ; Tue, 17 Jul 2012 22:09:38 +0000 (UTC) Received: from mail-yw0-f52.google.com (mail-yw0-f52.google.com [209.85.213.52]) by fiordland.canonical.com (Postfix) with ESMTP id 533F1A1828B for ; Tue, 17 Jul 2012 22:09:38 +0000 (UTC) Received: by yhpp61 with SMTP id p61so1059079yhp.11 for ; Tue, 17 Jul 2012 15:09:37 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:from:to:cc :subject:date:message-id:x-mailer:in-reply-to:references :x-content-scanned:x-cbid:x-gm-message-state; bh=0SNlHrjigrR8l7CS1uoxC/ueTh799C1xfi7usoXFsJ8=; b=N08aSZqCVvYh1fq+/lkWZdwkYHJ3LLndWdnKvRH74rt3V0/REg/n0ih9jLCkXMGXbb CkXNBZ3TWAtE5mzY3b8KWoXC/EyeZT6f3bBTIMMHB+PiijLuFIUCBMBFRi3sfhIJuhtm UMUNkEBHH/Iws/WEYe26tws14frNtm3KjWMJLnYIfcTYlfUezG2Mz2T3zjBJwP/kccUz xyuOPwD6AAWvIeVxdJHgPSp6dw9sPTHom3VHWHOoLHyyj7AeWXuErOPHPuvqTfNhkumd pBpeXPGJMqE/OR9jbGYLe9zO95XC9wbViTVZQbHbUaLUEi0NDbGDE6QSCEKMp+C2gAdK drFA== Received: by 10.50.40.193 with SMTP id z1mr290375igk.0.1342562977373; Tue, 17 Jul 2012 15:09:37 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.231.241.2 with SMTP id lc2csp25070ibb; Tue, 17 Jul 2012 15:09:36 -0700 (PDT) Received: by 10.50.85.196 with SMTP id j4mr228199igz.30.1342562976551; Tue, 17 Jul 2012 15:09:36 -0700 (PDT) Received: from e1.ny.us.ibm.com (e1.ny.us.ibm.com. [32.97.182.141]) by mx.google.com with ESMTPS id v8si1802326ict.74.2012.07.17.15.09.36 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 17 Jul 2012 15:09:36 -0700 (PDT) Received-SPF: pass (google.com: domain of johnstul@us.ibm.com designates 32.97.182.141 as permitted sender) client-ip=32.97.182.141; Authentication-Results: mx.google.com; spf=pass (google.com: domain of johnstul@us.ibm.com designates 32.97.182.141 as permitted sender) smtp.mail=johnstul@us.ibm.com Received: from /spool/local by e1.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 17 Jul 2012 18:09:35 -0400 Received: from d01dlp03.pok.ibm.com (9.56.224.17) by e1.ny.us.ibm.com (192.168.1.101) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 17 Jul 2012 18:05:50 -0400 Received: from d01relay01.pok.ibm.com (d01relay01.pok.ibm.com [9.56.227.233]) by d01dlp03.pok.ibm.com (Postfix) with ESMTP id 2040CC9006D for ; Tue, 17 Jul 2012 18:05:44 -0400 (EDT) Received: from d01av03.pok.ibm.com (d01av03.pok.ibm.com [9.56.224.217]) by d01relay01.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q6HM5iFB424846 for ; Tue, 17 Jul 2012 18:05:44 -0400 Received: from d01av03.pok.ibm.com (loopback [127.0.0.1]) by d01av03.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q6HM5h8E023000 for ; Tue, 17 Jul 2012 19:05:43 -0300 Received: from kernel.stglabs.ibm.com (kernel.stglabs.ibm.com [9.114.214.19]) by d01av03.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id q6HM5hMi022948; Tue, 17 Jul 2012 19:05:43 -0300 From: John Stultz To: stable@vger.kernel.org Cc: John Stultz , Thomas Gleixner , Prarit Bhargava , Linux Kernel Subject: [PATCH 10/11] 2.6.32.x: hrtimer: Update hrtimer base offsets each hrtimer_interrupt Date: Tue, 17 Jul 2012 18:05:34 -0400 Message-Id: <1342562735-55870-11-git-send-email-johnstul@us.ibm.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1342562735-55870-1-git-send-email-johnstul@us.ibm.com> References: <1342562735-55870-1-git-send-email-johnstul@us.ibm.com> X-Content-Scanned: Fidelis XPS MAILER x-cbid: 12071722-6078-0000-0000-00000D4DFC5F X-Gm-Message-State: ALoCoQmk/XqookloaqSfu2CbMUmBaa81QhxsuO/NWY17VcBwwC8M4gQtZKsggVcgARbPVquaNB4n This is a backport of 5baefd6d84163443215f4a99f6a20f054ef11236 The update of the hrtimer base offsets on all cpus cannot be made atomically from the timekeeper.lock held and interrupt disabled region as smp function calls are not allowed there. clock_was_set(), which enforces the update on all cpus, is called either from preemptible process context in case of do_settimeofday() or from the softirq context when the offset modification happened in the timer interrupt itself due to a leap second. In both cases there is a race window for an hrtimer interrupt between dropping timekeeper lock, enabling interrupts and clock_was_set() issuing the updates. Any interrupt which arrives in that window will see the new time but operate on stale offsets. So we need to make sure that an hrtimer interrupt always sees a consistent state of time and offsets. ktime_get_update_offsets() allows us to get the current monotonic time and update the per cpu hrtimer base offsets from hrtimer_interrupt() to capture a consistent state of monotonic time and the offsets. The function replaces the existing ktime_get() calls in hrtimer_interrupt(). The overhead of the new function vs. ktime_get() is minimal as it just adds two store operations. This ensures that any changes to realtime or boottime offsets are noticed and stored into the per-cpu hrtimer base structures, prior to any hrtimer expiration and guarantees that timers are not expired early. Signed-off-by: John Stultz Reviewed-by: Ingo Molnar Acked-by: Peter Zijlstra Acked-by: Prarit Bhargava Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/1341960205-56738-8-git-send-email-johnstul@us.ibm.com Signed-off-by: Thomas Gleixner Cc: Prarit Bhargava Cc: Thomas Gleixner Cc: Linux Kernel Signed-off-by: John Stultz --- kernel/hrtimer.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 8ba6d31..2818422 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -603,6 +603,12 @@ static int hrtimer_reprogram(struct hrtimer *timer, return res; } +static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base) +{ + ktime_t *offs_real = &base->clock_base[CLOCK_REALTIME].offset; + + return ktime_get_update_offsets(offs_real); +} /* * Retrigger next event is called after clock was set @@ -612,26 +618,15 @@ static int hrtimer_reprogram(struct hrtimer *timer, static void retrigger_next_event(void *arg) { struct hrtimer_cpu_base *base; - struct timespec realtime_offset; - unsigned long seq; if (!hrtimer_hres_active()) return; - do { - seq = read_seqbegin(&xtime_lock); - set_normalized_timespec(&realtime_offset, - -wall_to_monotonic.tv_sec, - -wall_to_monotonic.tv_nsec); - } while (read_seqretry(&xtime_lock, seq)); - base = &__get_cpu_var(hrtimer_bases); /* Adjust CLOCK_REALTIME offset */ spin_lock(&base->lock); - base->clock_base[CLOCK_REALTIME].offset = - timespec_to_ktime(realtime_offset); - + hrtimer_update_base(base); hrtimer_force_reprogram(base, 0); spin_unlock(&base->lock); } @@ -731,7 +726,6 @@ static int hrtimer_switch_to_hres(void) base->clock_base[CLOCK_MONOTONIC].resolution = KTIME_HIGH_RES; tick_setup_sched_timer(); - /* "Retrigger" the interrupt to get things going */ retrigger_next_event(NULL); local_irq_restore(flags); @@ -1264,7 +1258,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) dev->next_event.tv64 = KTIME_MAX; spin_lock(&cpu_base->lock); - entry_time = now = ktime_get(); + entry_time = now = hrtimer_update_base(cpu_base); retry: expires_next.tv64 = KTIME_MAX; /* @@ -1340,9 +1334,12 @@ retry: * We need to prevent that we loop forever in the hrtimer * interrupt routine. We give it 3 attempts to avoid * overreacting on some spurious event. + * + * Acquire base lock for updating the offsets and retrieving + * the current time. */ spin_lock(&cpu_base->lock); - now = ktime_get(); + now = hrtimer_update_base(cpu_base); cpu_base->nr_retries++; if (++retries < 3) goto retry;