From patchwork Tue Sep 30 17:40:11 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rik van Riel X-Patchwork-Id: 5005211 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 94B7C9F3EC for ; Tue, 30 Sep 2014 17:43:15 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A9BEF2024C for ; Tue, 30 Sep 2014 17:43:14 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C851120221 for ; Tue, 30 Sep 2014 17:43:13 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1XZ1QH-0004xH-Mx; Tue, 30 Sep 2014 17:41:13 +0000 Received: from mx1.redhat.com ([209.132.183.28]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1XZ1QE-0004p6-49 for linux-arm-kernel@lists.infradead.org; Tue, 30 Sep 2014 17:41:10 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s8UHeJal016568 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 30 Sep 2014 13:40:19 -0400 Received: from annuminas.surriel.com ([10.10.116.21]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s8UHeH31029966; Tue, 30 Sep 2014 13:40:17 -0400 Date: Tue, 30 Sep 2014 13:40:11 -0400 From: Rik van Riel To: Arnd Bergmann Subject: [PATCH] sched, time: fix build error with 64 bit cputime_t on 32 bit systems Message-ID: <20140930134011.232bc7bf@annuminas.surriel.com> In-Reply-To: <2547036.UshV4pXvhf@wuerfel> References: <2547036.UshV4pXvhf@wuerfel> Organization: Red Hat, Inc. MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140930_104110_209506_756EEF95 X-CRM114-Status: GOOD ( 19.21 ) X-Spam-Score: -5.7 (-----) Cc: atheurer@redhat.com, srao@redhat.com, Peter Zijlstra , fweisbec@gmail.com, oleg@redhat.com, Ingo Molnar , umgwanakikbuti@gmail.com, linux-arm-kernel@lists.infradead.org, akpm@linux-foundation.org, Linus Torvalds , lwoodman@redhat.com, linux-kernel@vger.kernel.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On Tue, 30 Sep 2014 13:56:37 +0200 Arnd Bergmann wrote: > A recent change to update the stime/utime members of task_struct > using atomic cmpxchg broke configurations on 32-bit machines with > CONFIG_VIRT_CPU_ACCOUNTING_GEN set, because that uses 64-bit > nanoseconds, leading to a link-time error: > > kernel/built-in.o: In function `cputime_adjust': > :(.text+0x25234): undefined reference to `__bad_cmpxchg' Arnd, this should fix your problem, while still ensuring that the cpu time counters only ever go forward. I do not have cross compiling toolchains set up here, but I assume this fixes your bug. Ingo & Peter, if this patch fixes the bug for Arnd, could you please merge it into -tip? Linus, the changeset causing the problem is only in -tip right now, and this patch will not apply to your tree. ---8<--- Subject: sched,time: fix build error with 64 bit cputime_t on 32 bit systems On 32 bit systems cmpxchg cannot handle 64 bit values, and cmpxchg64 needs to be used when full dynticks CPU accounting is enabled, since that turns cputime_t into a u64. With jiffies based CPU accounting, cputime_t is an unsigned long. On 64 bit systems, cputime_t is always the size of a long. Luckily the compiler can figure out whether we need to call cmpxchg or cmpxchg64. Signed-off-by: Rik van Riel Reported-by: Arnd Bergmann --- kernel/sched/cputime.c | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c index 64492df..db239c9 100644 --- a/kernel/sched/cputime.c +++ b/kernel/sched/cputime.c @@ -555,6 +555,29 @@ static cputime_t scale_stime(u64 stime, u64 rtime, u64 total) } /* + * Atomically advance counter to the new value. Interrupts, vcpu + * scheduling, and scaling inaccuracies can cause cputime_advance + * to be occasionally called with a new value smaller than counter. + * Let's enforce atomicity. + * + * Normally a caller will only go through this loop once, or not + * at all in case a previous caller updated counter the same jiffy. + */ +static void cputime_advance(cputime_t *counter, cputime_t new) +{ + cputime_t old; + + while (new > (old = ACCESS_ONCE(*counter))) { + /* The compiler will optimize away this branch. */ + if (sizeof(cputime_t) == sizeof(long)) + cmpxchg(counter, old, new); + else + /* 64 bit cputime_t on a 32 bit system... */ + cmpxchg64(counter, old, new); + } +} + +/* * Adjust tick based cputime random precision against scheduler * runtime accounting. */ @@ -599,16 +622,8 @@ static void cputime_adjust(struct task_cputime *curr, utime = rtime - stime; } - /* - * If the tick based count grows faster than the scheduler one, - * the result of the scaling may go backward. - * Let's enforce monotonicity. - * Atomic exchange protects against concurrent cputime_adjust(). - */ - while (stime > (rtime = ACCESS_ONCE(prev->stime))) - cmpxchg(&prev->stime, rtime, stime); - while (utime > (rtime = ACCESS_ONCE(prev->utime))) - cmpxchg(&prev->utime, rtime, utime); + cputime_advance(&prev->stime, stime); + cputime_advance(&prev->utime, utime); out: *ut = prev->utime;