From patchwork Thu Dec 13 14:09:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Andrzej Siewior X-Patchwork-Id: 153643 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp846144ljp; Thu, 13 Dec 2018 06:10:02 -0800 (PST) X-Google-Smtp-Source: AFSGD/UzBjagMTLwst9c2tQEgWrZ18/ZXwR7bMxv7dWVXQ7h1AE6vDYtprlIM5eEL9xI3nWgF/7v X-Received: by 2002:a17:902:128c:: with SMTP id g12mr22719375pla.146.1544710202382; Thu, 13 Dec 2018 06:10:02 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544710202; cv=none; d=google.com; s=arc-20160816; b=QTQGJbM5GVYgjJ50HFUwzMdp2VKo832FWOoFvHufV1G/mvIO7zzJYRB+VAwoZ/Jtyf nAXfNFUB2c3/bRN1H8kL/nGpbjrGACfRglHyp4cbm0TpymwNLyUoqZ6JR4VqilDN1W/a 1wDw7i2ShOFIqrsw/rTfozTaVg7mmkSo0ypkOZzvYWS9G/XRtsOiEgNEJEJ09l2428eu 7rf4vbCNsGnTNL8njoeClbp8bWJADU6/fuGBqdsSpovnQxoBt7DRJBrAruSY2mfx1d3+ 0imYF/QdEC5msyvof78a3qpjtkeNpmugLKnh2hn4x2xkO+8ykR3eONmilpYLrVHdIz/h ai+A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :illegal-object:reply-to:references:in-reply-to:message-id:date :subject:cc:to:from; bh=BTlZUDnDtaNAs2upqp08v36e/ko42YXu043vOrcoCCs=; b=0SyEnwdVF8beJLqN5qaroZ/sEQ6dTVkkyhS5hUYsR/Xgbh7bWTo47YwXFY4o7gKmwS G8VG8glPVcDv7yxrOtYlj3Blsgi3J+hMkDmVPrTeHUiM7nfO676lKxkn6lm+A+issPx+ reZ5LxoWCNOfXOk4lnWQfL3Yhl6sW0pFGTfDnOY7EnTCUR2sf75bUV/Qg1ggg9YjfS6H LeCNTw5Yd74mE5Codg4waVIxfqzfxmHMvGdBRQUAdMXmlCQPT+Trww06qeaPX0dBasIe H4fx2s0JpuPVpVegWNMt5wu5T84U56ahlV4F7AEPRTZHpW+NGISgk45ZNRXmI6S4BIWR CKcg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t16si1817482pfk.139.2018.12.13.06.10.02; Thu, 13 Dec 2018 06:10:02 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728445AbeLMOJk (ORCPT + 15 others); Thu, 13 Dec 2018 09:09:40 -0500 Received: from Galois.linutronix.de ([146.0.238.70]:46509 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727757AbeLMOJk (ORCPT ); Thu, 13 Dec 2018 09:09:40 -0500 Received: from localhost ([127.0.0.1] helo=bazinga.breakpoint.cc) by Galois.linutronix.de with esmtp (Exim 4.80) (envelope-from ) id 1gXRgE-0001G3-NI; Thu, 13 Dec 2018 15:09:34 +0100 From: Sebastian Andrzej Siewior To: stable@vger.kernel.org Cc: Peter Zijlstra , Will Deacon , Thomas Gleixner , Daniel Wagner , Linus Torvalds , Ingo Molnar , Sebastian Andrzej Siewior Subject: [PATCH STABLE v4.9 02/10] locking/qspinlock: Ensure node is initialised before updating prev->next Date: Thu, 13 Dec 2018 15:09:17 +0100 Message-Id: <20181213140925.6179-3-bigeasy@linutronix.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20181213140925.6179-1-bigeasy@linutronix.de> References: <20181213140925.6179-1-bigeasy@linutronix.de> Reply-To: [PATCH STABLE v4.9 00/10], Backport, for, cache line starvation on x86 Illegal-Object: Syntax error in Reply-To: address found on vger.kernel.org: Reply-To: cache line starvation on x86 ^-extraneous tokens in address MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Will Deacon commit 95bcade33a8af38755c9b0636e36a36ad3789fe6 upstream. When a locker ends up queuing on the qspinlock locking slowpath, we initialise the relevant mcs node and publish it indirectly by updating the tail portion of the lock word using xchg_tail. If we find that there was a pre-existing locker in the queue, we subsequently update their ->next field to point at our node so that we are notified when it's our turn to take the lock. This can be roughly illustrated as follows: /* Initialise the fields in node and encode a pointer to node in tail */ tail = initialise_node(node); /* * Exchange tail into the lockword using an atomic read-modify-write * operation with release semantics */ old = xchg_tail(lock, tail); /* If there was a pre-existing waiter ... */ if (old & _Q_TAIL_MASK) { prev = decode_tail(old); smp_read_barrier_depends(); /* ... then update their ->next field to point to node. WRITE_ONCE(prev->next, node); } The conditional update of prev->next therefore relies on the address dependency from the result of xchg_tail ensuring order against the prior initialisation of node. However, since the release semantics of the xchg_tail operation apply only to the write portion of the RmW, then this ordering is not guaranteed and it is possible for the CPU to return old before the writes to node have been published, consequently allowing us to point prev->next to an uninitialised node. This patch fixes the problem by making the update of prev->next a RELEASE operation, which also removes the reliance on dependency ordering. Signed-off-by: Will Deacon Acked-by: Peter Zijlstra (Intel) Cc: Linus Torvalds Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1518528177-19169-2-git-send-email-will.deacon@arm.com Signed-off-by: Ingo Molnar Signed-off-by: Sebastian Andrzej Siewior --- kernel/locking/qspinlock.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) -- 2.20.0 diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c index 8710fbe8d26c0..6fce84401dba1 100644 --- a/kernel/locking/qspinlock.c +++ b/kernel/locking/qspinlock.c @@ -532,14 +532,15 @@ void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val) */ if (old & _Q_TAIL_MASK) { prev = decode_tail(old); - /* - * The above xchg_tail() is also a load of @lock which - * generates, through decode_tail(), a pointer. The address - * dependency matches the RELEASE of xchg_tail() such that - * the subsequent access to @prev happens after. - */ - WRITE_ONCE(prev->next, node); + /* + * We must ensure that the stores to @node are observed before + * the write to prev->next. The address dependency from + * xchg_tail is not sufficient to ensure this because the read + * component of xchg_tail is unordered with respect to the + * initialisation of @node. + */ + smp_store_release(&prev->next, node); pv_wait_node(node, prev); arch_mcs_spin_lock_contended(&node->locked); From patchwork Thu Dec 13 14:09:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Andrzej Siewior X-Patchwork-Id: 153648 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp846247ljp; Thu, 13 Dec 2018 06:10:06 -0800 (PST) X-Google-Smtp-Source: AFSGD/UX0x9cH98WTrw0Z7HyF8kT+MLm8+JqRoDF14hchGLAE7tMSYKRWSgeYJKcm1HFzJs1cFdE X-Received: by 2002:a17:902:42e4:: with SMTP id h91mr24221264pld.18.1544710206426; Thu, 13 Dec 2018 06:10:06 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544710206; cv=none; d=google.com; s=arc-20160816; b=OjIzlMdqjWeGzJol1M38R1FViwA8cG1wVjGajwL8w4jzB5jTV2ekPEZQ/VnzAuMvpb 9mLyHO7TaDHD18JBN0s6JnNHjtY+PbPYIjiQ7qBx39XARfJFb/AcwX2MADZnesiCQCvk JcXNml6Lnf9ocYptKUUg29Mn/I8MDMZqwUUj92IeKiuUGAaEJgN5C9Z0xZPhQwxsAjgd g6zv9uyMWbxODMCXZ46WNK8wwha6jDeFBmxHOOqkc3mjODIpN4Hg7kApkDZBYtr9Q8Lz zJnCp8CHFKFMtHY1HZ+MZrzxRq70EJEHbzCHsR0h/0N+79K+MubqBFx/4nQJymi5kYY9 fkFg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :illegal-object:reply-to:references:in-reply-to:message-id:date :subject:cc:to:from; bh=0zIfLmGoCvZwqrUpKDEOts4xD3mlmKbhvmQQIwO2IW0=; b=EpUd2WW+fwqmIgBUwLVnsZT027BjHS0AuY80RTFpC0UldGHByMXiSajaJTMhrfLHSv AKZZGIwbpA910y4rJUJyU5m/SyOt0+pwEePxGcyRlhiEjPkUm9Dgl2sZku1cGID3hZUe 1uicfewtfIdDPJ7B5botstn9aBHtFwBYMpwzaCwBKHAmGgYE9t2AaYkhJBKLMA1GFyRj R7BwGc7qGhR+SKgPUfg5DJ7R+4YKLy9+zC3uSVkeeZM767CmMiqeaRKp1oInqpSeBHJJ /myArmNapehxFTE5wVk8a39pI4Emh5u8NIY8LR+hIdz7MaKVeyA1CcZ8GKFsLWwDGvqk n2yA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t16si1817482pfk.139.2018.12.13.06.10.06; Thu, 13 Dec 2018 06:10:06 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728663AbeLMOJt (ORCPT + 15 others); Thu, 13 Dec 2018 09:09:49 -0500 Received: from Galois.linutronix.de ([146.0.238.70]:46534 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728596AbeLMOJt (ORCPT ); Thu, 13 Dec 2018 09:09:49 -0500 Received: from localhost ([127.0.0.1] helo=bazinga.breakpoint.cc) by Galois.linutronix.de with esmtp (Exim 4.80) (envelope-from ) id 1gXRgF-0001G3-CD; Thu, 13 Dec 2018 15:09:35 +0100 From: Sebastian Andrzej Siewior To: stable@vger.kernel.org Cc: Peter Zijlstra , Will Deacon , Thomas Gleixner , Daniel Wagner , Waiman Long , Linus Torvalds , boqun.feng@gmail.com, linux-arm-kernel@lists.infradead.org, paulmck@linux.vnet.ibm.com, Ingo Molnar , Sebastian Andrzej Siewior Subject: [PATCH STABLE v4.9 03/10] locking/qspinlock: Bound spinning on pending->locked transition in slowpath Date: Thu, 13 Dec 2018 15:09:18 +0100 Message-Id: <20181213140925.6179-4-bigeasy@linutronix.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20181213140925.6179-1-bigeasy@linutronix.de> References: <20181213140925.6179-1-bigeasy@linutronix.de> Reply-To: [PATCH STABLE v4.9 00/10], Backport, for, cache line starvation on x86 Illegal-Object: Syntax error in Reply-To: address found on vger.kernel.org: Reply-To: cache line starvation on x86 ^-extraneous tokens in address MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Will Deacon commit 6512276d97b160d90b53285bd06f7f201459a7e3 upstream. If a locker taking the qspinlock slowpath reads a lock value indicating that only the pending bit is set, then it will spin whilst the concurrent pending->locked transition takes effect. Unfortunately, there is no guarantee that such a transition will ever be observed since concurrent lockers could continuously set pending and hand over the lock amongst themselves, leading to starvation. Whilst this would probably resolve in practice, it means that it is not possible to prove liveness properties about the lock and means that lock acquisition time is unbounded. Rather than removing the pending->locked spinning from the slowpath altogether (which has been shown to heavily penalise a 2-threaded locking stress test on x86), this patch replaces the explicit spinning with a call to atomic_cond_read_relaxed and allows the architecture to provide a bound on the number of spins. For architectures that can respond to changes in cacheline state in their smp_cond_load implementation, it should be sufficient to use the default bound of 1. Suggested-by: Waiman Long Signed-off-by: Will Deacon Acked-by: Peter Zijlstra (Intel) Acked-by: Waiman Long Cc: Linus Torvalds Cc: Thomas Gleixner Cc: boqun.feng@gmail.com Cc: linux-arm-kernel@lists.infradead.org Cc: paulmck@linux.vnet.ibm.com Link: http://lkml.kernel.org/r/1524738868-31318-4-git-send-email-will.deacon@arm.com Signed-off-by: Ingo Molnar Signed-off-by: Sebastian Andrzej Siewior --- kernel/locking/qspinlock.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) -- 2.20.0 diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c index 6fce84401dba1..a8da1fc5222eb 100644 --- a/kernel/locking/qspinlock.c +++ b/kernel/locking/qspinlock.c @@ -75,6 +75,18 @@ #define MAX_NODES 4 #endif +/* + * The pending bit spinning loop count. + * This heuristic is used to limit the number of lockword accesses + * made by atomic_cond_read_relaxed when waiting for the lock to + * transition out of the "== _Q_PENDING_VAL" state. We don't spin + * indefinitely because there's no guarantee that we'll make forward + * progress. + */ +#ifndef _Q_PENDING_LOOPS +#define _Q_PENDING_LOOPS 1 +#endif + /* * Per-CPU queue node structures; we can never have more than 4 nested * contexts: task, softirq, hardirq, nmi. @@ -422,13 +434,15 @@ void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val) return; /* - * wait for in-progress pending->locked hand-overs + * Wait for in-progress pending->locked hand-overs with a bounded + * number of spins so that we guarantee forward progress. * * 0,1,0 -> 0,0,1 */ if (val == _Q_PENDING_VAL) { - while ((val = atomic_read(&lock->val)) == _Q_PENDING_VAL) - cpu_relax(); + int cnt = _Q_PENDING_LOOPS; + val = smp_cond_load_acquire(&lock->val.counter, + (VAL != _Q_PENDING_VAL) || !cnt--); } /* From patchwork Thu Dec 13 14:09:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Andrzej Siewior X-Patchwork-Id: 153647 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp846231ljp; Thu, 13 Dec 2018 06:10:06 -0800 (PST) X-Google-Smtp-Source: AFSGD/XbDkKXcdIUAM7HPSTQJMbnA3/SvFePM+glc95uIWH5t0gAOLUAks03YEia4bq5fXmJTJiN X-Received: by 2002:a62:7e93:: with SMTP id z141mr23733297pfc.239.1544710206059; Thu, 13 Dec 2018 06:10:06 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544710206; cv=none; d=google.com; s=arc-20160816; b=aBbCGRA/dFLMuclhZFmninXvO2vyngkcNrkCnO4OD47tlu2HotYDgJ5HwRXGU/RwQF oubArGArKW5a5UXsZ6gMNnu5tzdaws56krKdtVlatgzW03xadWA1E+41dR/gNk2zBfTg pNisacaCD83MPjwuNjzD58Hq7PxGe6otFbCiSwUonwmfkuBIRPJ2teTxuijXNG6ZWqrZ VA9UIsI9cjmgvsmmZlp9Oh0IOZzhEzmWJGouha+6eChGnH/uYgYSzSgL0GoiF3QCh5qw UDMrK3MxtEUBqvzE2n0XwWe4zAqZrjpg7Xc0CxJ0uoiPA8EtxRHoXx89aeNQamGStzZv 0mgQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :illegal-object:reply-to:references:in-reply-to:message-id:date :subject:cc:to:from; bh=xN8fo+WWeMuaaI8n/CALojYR0BbykRXlHMcqCecHtyk=; b=DPmU/Nsqq51FNH1ZNcPJKRsmJtAbEa2l5u/5deEESK2ze7j80mwbkhzgGyRwI2xZyz 3NZyGPSA6hRSepn+9YlGzHhvuIACf2M6fxhp3NzvuK9NhhQnHgRPwor3ZOfJy4fIj6Tw AF4AXSMd9aINSusnTALIZ8gYhiYU9HB/vqcZLPMTggpqdYCXw6sWHP9wc4EM8KWPlQFN 2rTHTQkpF5PEH4LMgP60JD3fwL2GRKRm8kZfVdXSnOQY30iZ+361ZDe8gfvtlYpnJ7Al jZMQ4VgmoNqEzQKfo+5QSwg5PWPlZa5Q9oC5hij5aujb7wMDAO8nc4lcPLaXlm4WG/Wc xUTw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t16si1817482pfk.139.2018.12.13.06.10.05; Thu, 13 Dec 2018 06:10:06 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727707AbeLMOJs (ORCPT + 15 others); Thu, 13 Dec 2018 09:09:48 -0500 Received: from Galois.linutronix.de ([146.0.238.70]:46511 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728097AbeLMOJl (ORCPT ); Thu, 13 Dec 2018 09:09:41 -0500 Received: from localhost ([127.0.0.1] helo=bazinga.breakpoint.cc) by Galois.linutronix.de with esmtp (Exim 4.80) (envelope-from ) id 1gXRgF-0001G3-TB; Thu, 13 Dec 2018 15:09:36 +0100 From: Sebastian Andrzej Siewior To: stable@vger.kernel.org Cc: Peter Zijlstra , Will Deacon , Thomas Gleixner , Daniel Wagner , Waiman Long , Boqun Feng , Linus Torvalds , linux-arm-kernel@lists.infradead.org, paulmck@linux.vnet.ibm.com, Ingo Molnar , Sebastian Andrzej Siewior Subject: [PATCH STABLE v4.9 04/10] locking/qspinlock: Merge 'struct __qspinlock' into 'struct qspinlock' Date: Thu, 13 Dec 2018 15:09:19 +0100 Message-Id: <20181213140925.6179-5-bigeasy@linutronix.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20181213140925.6179-1-bigeasy@linutronix.de> References: <20181213140925.6179-1-bigeasy@linutronix.de> Reply-To: [PATCH STABLE v4.9 00/10], Backport, for, cache line starvation on x86 Illegal-Object: Syntax error in Reply-To: address found on vger.kernel.org: Reply-To: cache line starvation on x86 ^-extraneous tokens in address MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Will Deacon commit 625e88be1f41b53cec55827c984e4a89ea8ee9f9 upstream. 'struct __qspinlock' provides a handy union of fields so that subcomponents of the lockword can be accessed by name, without having to manage shifts and masks explicitly and take endianness into account. This is useful in qspinlock.h and also potentially in arch headers, so move the 'struct __qspinlock' into 'struct qspinlock' and kill the extra definition. Signed-off-by: Will Deacon Acked-by: Peter Zijlstra (Intel) Acked-by: Waiman Long Acked-by: Boqun Feng Cc: Linus Torvalds Cc: Thomas Gleixner Cc: linux-arm-kernel@lists.infradead.org Cc: paulmck@linux.vnet.ibm.com Link: http://lkml.kernel.org/r/1524738868-31318-3-git-send-email-will.deacon@arm.com Signed-off-by: Ingo Molnar Signed-off-by: Sebastian Andrzej Siewior --- arch/x86/include/asm/qspinlock.h | 2 +- arch/x86/include/asm/qspinlock_paravirt.h | 3 +- include/asm-generic/qspinlock_types.h | 32 +++++++++++++++- kernel/locking/qspinlock.c | 46 ++--------------------- kernel/locking/qspinlock_paravirt.h | 34 ++++++----------- 5 files changed, 46 insertions(+), 71 deletions(-) -- 2.20.0 diff --git a/arch/x86/include/asm/qspinlock.h b/arch/x86/include/asm/qspinlock.h index eaba080760300..e07cc206919d4 100644 --- a/arch/x86/include/asm/qspinlock.h +++ b/arch/x86/include/asm/qspinlock.h @@ -14,7 +14,7 @@ */ static inline void native_queued_spin_unlock(struct qspinlock *lock) { - smp_store_release((u8 *)lock, 0); + smp_store_release(&lock->locked, 0); } #ifdef CONFIG_PARAVIRT_SPINLOCKS diff --git a/arch/x86/include/asm/qspinlock_paravirt.h b/arch/x86/include/asm/qspinlock_paravirt.h index 9d55f9b6e167c..fc75415ae9719 100644 --- a/arch/x86/include/asm/qspinlock_paravirt.h +++ b/arch/x86/include/asm/qspinlock_paravirt.h @@ -21,8 +21,7 @@ PV_CALLEE_SAVE_REGS_THUNK(__pv_queued_spin_unlock_slowpath); * * void __pv_queued_spin_unlock(struct qspinlock *lock) * { - * struct __qspinlock *l = (void *)lock; - * u8 lockval = cmpxchg(&l->locked, _Q_LOCKED_VAL, 0); + * u8 lockval = cmpxchg(&lock->locked, _Q_LOCKED_VAL, 0); * * if (likely(lockval == _Q_LOCKED_VAL)) * return; diff --git a/include/asm-generic/qspinlock_types.h b/include/asm-generic/qspinlock_types.h index 034acd0c4956b..0763f065b975a 100644 --- a/include/asm-generic/qspinlock_types.h +++ b/include/asm-generic/qspinlock_types.h @@ -29,13 +29,41 @@ #endif typedef struct qspinlock { - atomic_t val; + union { + atomic_t val; + + /* + * By using the whole 2nd least significant byte for the + * pending bit, we can allow better optimization of the lock + * acquisition for the pending bit holder. + */ +#ifdef __LITTLE_ENDIAN + struct { + u8 locked; + u8 pending; + }; + struct { + u16 locked_pending; + u16 tail; + }; +#else + struct { + u16 tail; + u16 locked_pending; + }; + struct { + u8 reserved[2]; + u8 pending; + u8 locked; + }; +#endif + }; } arch_spinlock_t; /* * Initializier */ -#define __ARCH_SPIN_LOCK_UNLOCKED { ATOMIC_INIT(0) } +#define __ARCH_SPIN_LOCK_UNLOCKED { .val = ATOMIC_INIT(0) } /* * Bitfields in the atomic value: diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c index a8da1fc5222eb..cc98050e8bec0 100644 --- a/kernel/locking/qspinlock.c +++ b/kernel/locking/qspinlock.c @@ -125,40 +125,6 @@ static inline __pure struct mcs_spinlock *decode_tail(u32 tail) #define _Q_LOCKED_PENDING_MASK (_Q_LOCKED_MASK | _Q_PENDING_MASK) -/* - * By using the whole 2nd least significant byte for the pending bit, we - * can allow better optimization of the lock acquisition for the pending - * bit holder. - * - * This internal structure is also used by the set_locked function which - * is not restricted to _Q_PENDING_BITS == 8. - */ -struct __qspinlock { - union { - atomic_t val; -#ifdef __LITTLE_ENDIAN - struct { - u8 locked; - u8 pending; - }; - struct { - u16 locked_pending; - u16 tail; - }; -#else - struct { - u16 tail; - u16 locked_pending; - }; - struct { - u8 reserved[2]; - u8 pending; - u8 locked; - }; -#endif - }; -}; - #if _Q_PENDING_BITS == 8 /** * clear_pending_set_locked - take ownership and clear the pending bit. @@ -170,9 +136,7 @@ struct __qspinlock { */ static __always_inline void clear_pending_set_locked(struct qspinlock *lock) { - struct __qspinlock *l = (void *)lock; - - WRITE_ONCE(l->locked_pending, _Q_LOCKED_VAL); + WRITE_ONCE(lock->locked_pending, _Q_LOCKED_VAL); } /* @@ -187,13 +151,11 @@ static __always_inline void clear_pending_set_locked(struct qspinlock *lock) */ static __always_inline u32 xchg_tail(struct qspinlock *lock, u32 tail) { - struct __qspinlock *l = (void *)lock; - /* * Use release semantics to make sure that the MCS node is properly * initialized before changing the tail code. */ - return (u32)xchg_release(&l->tail, + return (u32)xchg_release(&lock->tail, tail >> _Q_TAIL_OFFSET) << _Q_TAIL_OFFSET; } @@ -248,9 +210,7 @@ static __always_inline u32 xchg_tail(struct qspinlock *lock, u32 tail) */ static __always_inline void set_locked(struct qspinlock *lock) { - struct __qspinlock *l = (void *)lock; - - WRITE_ONCE(l->locked, _Q_LOCKED_VAL); + WRITE_ONCE(lock->locked, _Q_LOCKED_VAL); } diff --git a/kernel/locking/qspinlock_paravirt.h b/kernel/locking/qspinlock_paravirt.h index e3b5520005db7..3e33336911ffe 100644 --- a/kernel/locking/qspinlock_paravirt.h +++ b/kernel/locking/qspinlock_paravirt.h @@ -69,10 +69,8 @@ struct pv_node { #define queued_spin_trylock(l) pv_queued_spin_steal_lock(l) static inline bool pv_queued_spin_steal_lock(struct qspinlock *lock) { - struct __qspinlock *l = (void *)lock; - if (!(atomic_read(&lock->val) & _Q_LOCKED_PENDING_MASK) && - (cmpxchg(&l->locked, 0, _Q_LOCKED_VAL) == 0)) { + (cmpxchg(&lock->locked, 0, _Q_LOCKED_VAL) == 0)) { qstat_inc(qstat_pv_lock_stealing, true); return true; } @@ -87,16 +85,12 @@ static inline bool pv_queued_spin_steal_lock(struct qspinlock *lock) #if _Q_PENDING_BITS == 8 static __always_inline void set_pending(struct qspinlock *lock) { - struct __qspinlock *l = (void *)lock; - - WRITE_ONCE(l->pending, 1); + WRITE_ONCE(lock->pending, 1); } static __always_inline void clear_pending(struct qspinlock *lock) { - struct __qspinlock *l = (void *)lock; - - WRITE_ONCE(l->pending, 0); + WRITE_ONCE(lock->pending, 0); } /* @@ -106,10 +100,8 @@ static __always_inline void clear_pending(struct qspinlock *lock) */ static __always_inline int trylock_clear_pending(struct qspinlock *lock) { - struct __qspinlock *l = (void *)lock; - - return !READ_ONCE(l->locked) && - (cmpxchg(&l->locked_pending, _Q_PENDING_VAL, _Q_LOCKED_VAL) + return !READ_ONCE(lock->locked) && + (cmpxchg(&lock->locked_pending, _Q_PENDING_VAL, _Q_LOCKED_VAL) == _Q_PENDING_VAL); } #else /* _Q_PENDING_BITS == 8 */ @@ -353,7 +345,6 @@ static void pv_wait_node(struct mcs_spinlock *node, struct mcs_spinlock *prev) static void pv_kick_node(struct qspinlock *lock, struct mcs_spinlock *node) { struct pv_node *pn = (struct pv_node *)node; - struct __qspinlock *l = (void *)lock; /* * If the vCPU is indeed halted, advance its state to match that of @@ -372,7 +363,7 @@ static void pv_kick_node(struct qspinlock *lock, struct mcs_spinlock *node) * the hash table later on at unlock time, no atomic instruction is * needed. */ - WRITE_ONCE(l->locked, _Q_SLOW_VAL); + WRITE_ONCE(lock->locked, _Q_SLOW_VAL); (void)pv_hash(lock, pn); } @@ -387,7 +378,6 @@ static u32 pv_wait_head_or_lock(struct qspinlock *lock, struct mcs_spinlock *node) { struct pv_node *pn = (struct pv_node *)node; - struct __qspinlock *l = (void *)lock; struct qspinlock **lp = NULL; int waitcnt = 0; int loop; @@ -438,13 +428,13 @@ pv_wait_head_or_lock(struct qspinlock *lock, struct mcs_spinlock *node) * * Matches the smp_rmb() in __pv_queued_spin_unlock(). */ - if (xchg(&l->locked, _Q_SLOW_VAL) == 0) { + if (xchg(&lock->locked, _Q_SLOW_VAL) == 0) { /* * The lock was free and now we own the lock. * Change the lock value back to _Q_LOCKED_VAL * and unhash the table. */ - WRITE_ONCE(l->locked, _Q_LOCKED_VAL); + WRITE_ONCE(lock->locked, _Q_LOCKED_VAL); WRITE_ONCE(*lp, NULL); goto gotlock; } @@ -452,7 +442,7 @@ pv_wait_head_or_lock(struct qspinlock *lock, struct mcs_spinlock *node) WRITE_ONCE(pn->state, vcpu_hashed); qstat_inc(qstat_pv_wait_head, true); qstat_inc(qstat_pv_wait_again, waitcnt); - pv_wait(&l->locked, _Q_SLOW_VAL); + pv_wait(&lock->locked, _Q_SLOW_VAL); /* * Because of lock stealing, the queue head vCPU may not be @@ -477,7 +467,6 @@ pv_wait_head_or_lock(struct qspinlock *lock, struct mcs_spinlock *node) __visible void __pv_queued_spin_unlock_slowpath(struct qspinlock *lock, u8 locked) { - struct __qspinlock *l = (void *)lock; struct pv_node *node; if (unlikely(locked != _Q_SLOW_VAL)) { @@ -506,7 +495,7 @@ __pv_queued_spin_unlock_slowpath(struct qspinlock *lock, u8 locked) * Now that we have a reference to the (likely) blocked pv_node, * release the lock. */ - smp_store_release(&l->locked, 0); + smp_store_release(&lock->locked, 0); /* * At this point the memory pointed at by lock can be freed/reused, @@ -532,7 +521,6 @@ __pv_queued_spin_unlock_slowpath(struct qspinlock *lock, u8 locked) #ifndef __pv_queued_spin_unlock __visible void __pv_queued_spin_unlock(struct qspinlock *lock) { - struct __qspinlock *l = (void *)lock; u8 locked; /* @@ -540,7 +528,7 @@ __visible void __pv_queued_spin_unlock(struct qspinlock *lock) * unhash. Otherwise it would be possible to have multiple @lock * entries, which would be BAD. */ - locked = cmpxchg_release(&l->locked, _Q_LOCKED_VAL, 0); + locked = cmpxchg_release(&lock->locked, _Q_LOCKED_VAL, 0); if (likely(locked == _Q_LOCKED_VAL)) return; From patchwork Thu Dec 13 14:09:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Andrzej Siewior X-Patchwork-Id: 153645 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp846184ljp; Thu, 13 Dec 2018 06:10:04 -0800 (PST) X-Google-Smtp-Source: AFSGD/U0ckn0wnWUKY7DaceEJyroJmEPljOyPKY2oyFd/cYYl0kSIah1nbxSO4rauttYO/Qgt96r X-Received: by 2002:a17:902:b112:: with SMTP id q18mr23828971plr.255.1544710204220; Thu, 13 Dec 2018 06:10:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544710204; cv=none; d=google.com; s=arc-20160816; b=qLc/BpfbXZuwwMMCIAcXugXJBZnjYRWh1N2M3mdjn0Jy5GoHg/jDHNTYoAZrC7w1wR jEqTRf+rxN0OKD2fnJI3/fXhEzncD4mYw1wgczAuHAc4Xn3kN6VyhzWRH8Tc/R1WN2di QVH3J0jnw1+1mdRDoZ+vyix7bJBhf/ILLHuKPjXfsoMsKlyfmmCi2L9LbPQQDOAyd6KK HEada9lJI8eQQ+dFSsgTv3fBsa+drmesg8ENM01m+m8ru1yLfYAPhsOYowwJhdpyQUoj Nva6au5j+Qv4ld6YSHdz2erE7fJ2ACyvO7OiWfiiwUSmwV3dZjOqyTPjg74HiDePy/6E l2lg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :illegal-object:reply-to:references:in-reply-to:message-id:date :subject:cc:to:from; bh=1mpDb7q8roojJAzY3JuQ94q90jtgmqUcVJobdJ0fjZs=; b=jV5ESH+J5jJyrIaJVH/323xy7YZCmxLSf7vrMJXV86M+zQXoec1WgyaPVFZpUSUB9V F7xMWABEOmHqYS/WZAPLfcPiIhKN8Ebg9z+UEqI85Fo0CpwwS1j1dAxlUgMcl2dkan4R ECnkaJpEU8ZqAeoDZ062KOKKHLgrlPde7L4sE7Ek37EX8kW+MGRYn8KHzNdZoJXV5Mba kPuEz+tEU03a55RL2gBw6pDc/5j/Z6fFF0UMzAZUXv6H/oDgPzxJLZpswyWcms6ayYCG Ys/5DLYKXW8GTXGjgB4bdjKh05b+86mHi5Hg9x9VIOuhFc9IDWdAyR+Pw77GINDeu4Lj qnpw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t16si1817482pfk.139.2018.12.13.06.10.03; Thu, 13 Dec 2018 06:10:04 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728515AbeLMOJq (ORCPT + 15 others); Thu, 13 Dec 2018 09:09:46 -0500 Received: from Galois.linutronix.de ([146.0.238.70]:46514 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728288AbeLMOJm (ORCPT ); Thu, 13 Dec 2018 09:09:42 -0500 Received: from localhost ([127.0.0.1] helo=bazinga.breakpoint.cc) by Galois.linutronix.de with esmtp (Exim 4.80) (envelope-from ) id 1gXRgG-0001G3-VI; Thu, 13 Dec 2018 15:09:37 +0100 From: Sebastian Andrzej Siewior To: stable@vger.kernel.org Cc: Peter Zijlstra , Will Deacon , Thomas Gleixner , Daniel Wagner , Waiman Long , Linus Torvalds , boqun.feng@gmail.com, linux-arm-kernel@lists.infradead.org, paulmck@linux.vnet.ibm.com, Ingo Molnar , Sebastian Andrzej Siewior Subject: [PATCH STABLE v4.9 05/10] locking/qspinlock: Remove unbounded cmpxchg() loop from locking slowpath Date: Thu, 13 Dec 2018 15:09:20 +0100 Message-Id: <20181213140925.6179-6-bigeasy@linutronix.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20181213140925.6179-1-bigeasy@linutronix.de> References: <20181213140925.6179-1-bigeasy@linutronix.de> Reply-To: [PATCH STABLE v4.9 00/10], Backport, for, cache line starvation on x86 Illegal-Object: Syntax error in Reply-To: address found on vger.kernel.org: Reply-To: cache line starvation on x86 ^-extraneous tokens in address MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Will Deacon commit 59fb586b4a07b4e1a0ee577140ab4842ba451acd upstream. The qspinlock locking slowpath utilises a "pending" bit as a simple form of an embedded test-and-set lock that can avoid the overhead of explicit queuing in cases where the lock is held but uncontended. This bit is managed using a cmpxchg() loop which tries to transition the uncontended lock word from (0,0,0) -> (0,0,1) or (0,0,1) -> (0,1,1). Unfortunately, the cmpxchg() loop is unbounded and lockers can be starved indefinitely if the lock word is seen to oscillate between unlocked (0,0,0) and locked (0,0,1). This could happen if concurrent lockers are able to take the lock in the cmpxchg() loop without queuing and pass it around amongst themselves. This patch fixes the problem by unconditionally setting _Q_PENDING_VAL using atomic_fetch_or, and then inspecting the old value to see whether we need to spin on the current lock owner, or whether we now effectively hold the lock. The tricky scenario is when concurrent lockers end up queuing on the lock and the lock becomes available, causing us to see a lockword of (n,0,0). With pending now set, simply queuing could lead to deadlock as the head of the queue may not have observed the pending flag being cleared. Conversely, if the head of the queue did observe pending being cleared, then it could transition the lock from (n,0,0) -> (0,0,1) meaning that any attempt to "undo" our setting of the pending bit could race with a concurrent locker trying to set it. We handle this race by preserving the pending bit when taking the lock after reaching the head of the queue and leaving the tail entry intact if we saw pending set, because we know that the tail is going to be updated shortly. Signed-off-by: Will Deacon Acked-by: Peter Zijlstra (Intel) Acked-by: Waiman Long Cc: Linus Torvalds Cc: Thomas Gleixner Cc: boqun.feng@gmail.com Cc: linux-arm-kernel@lists.infradead.org Cc: paulmck@linux.vnet.ibm.com Link: http://lkml.kernel.org/r/1524738868-31318-6-git-send-email-will.deacon@arm.com Signed-off-by: Ingo Molnar Signed-off-by: Sebastian Andrzej Siewior --- kernel/locking/qspinlock.c | 102 ++++++++++++++++------------ kernel/locking/qspinlock_paravirt.h | 5 -- 2 files changed, 58 insertions(+), 49 deletions(-) -- 2.20.0 diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c index cc98050e8bec0..e7ab99a1f4387 100644 --- a/kernel/locking/qspinlock.c +++ b/kernel/locking/qspinlock.c @@ -126,6 +126,17 @@ static inline __pure struct mcs_spinlock *decode_tail(u32 tail) #define _Q_LOCKED_PENDING_MASK (_Q_LOCKED_MASK | _Q_PENDING_MASK) #if _Q_PENDING_BITS == 8 +/** + * clear_pending - clear the pending bit. + * @lock: Pointer to queued spinlock structure + * + * *,1,* -> *,0,* + */ +static __always_inline void clear_pending(struct qspinlock *lock) +{ + WRITE_ONCE(lock->pending, 0); +} + /** * clear_pending_set_locked - take ownership and clear the pending bit. * @lock: Pointer to queued spinlock structure @@ -161,6 +172,17 @@ static __always_inline u32 xchg_tail(struct qspinlock *lock, u32 tail) #else /* _Q_PENDING_BITS == 8 */ +/** + * clear_pending - clear the pending bit. + * @lock: Pointer to queued spinlock structure + * + * *,1,* -> *,0,* + */ +static __always_inline void clear_pending(struct qspinlock *lock) +{ + atomic_andnot(_Q_PENDING_VAL, &lock->val); +} + /** * clear_pending_set_locked - take ownership and clear the pending bit. * @lock: Pointer to queued spinlock structure @@ -382,7 +404,7 @@ EXPORT_SYMBOL(queued_spin_unlock_wait); void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val) { struct mcs_spinlock *prev, *next, *node; - u32 new, old, tail; + u32 old, tail; int idx; BUILD_BUG_ON(CONFIG_NR_CPUS >= (1U << _Q_TAIL_CPU_BITS)); @@ -405,59 +427,51 @@ void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val) (VAL != _Q_PENDING_VAL) || !cnt--); } + /* + * If we observe any contention; queue. + */ + if (val & ~_Q_LOCKED_MASK) + goto queue; + /* * trylock || pending * * 0,0,0 -> 0,0,1 ; trylock * 0,0,1 -> 0,1,1 ; pending */ - for (;;) { + val = atomic_fetch_or_acquire(_Q_PENDING_VAL, &lock->val); + if (!(val & ~_Q_LOCKED_MASK)) { /* - * If we observe any contention; queue. + * We're pending, wait for the owner to go away. + * + * *,1,1 -> *,1,0 + * + * this wait loop must be a load-acquire such that we match the + * store-release that clears the locked bit and create lock + * sequentiality; this is because not all + * clear_pending_set_locked() implementations imply full + * barriers. */ - if (val & ~_Q_LOCKED_MASK) - goto queue; - - new = _Q_LOCKED_VAL; - if (val == new) - new |= _Q_PENDING_VAL; + if (val & _Q_LOCKED_MASK) { + smp_cond_load_acquire(&lock->val.counter, + !(VAL & _Q_LOCKED_MASK)); + } /* - * Acquire semantic is required here as the function may - * return immediately if the lock was free. + * take ownership and clear the pending bit. + * + * *,1,0 -> *,0,1 */ - old = atomic_cmpxchg_acquire(&lock->val, val, new); - if (old == val) - break; - - val = old; + clear_pending_set_locked(lock); + return; } /* - * we won the trylock + * If pending was clear but there are waiters in the queue, then + * we need to undo our setting of pending before we queue ourselves. */ - if (new == _Q_LOCKED_VAL) - return; - - /* - * we're pending, wait for the owner to go away. - * - * *,1,1 -> *,1,0 - * - * this wait loop must be a load-acquire such that we match the - * store-release that clears the locked bit and create lock - * sequentiality; this is because not all clear_pending_set_locked() - * implementations imply full barriers. - */ - smp_cond_load_acquire(&lock->val.counter, !(VAL & _Q_LOCKED_MASK)); - - /* - * take ownership and clear the pending bit. - * - * *,1,0 -> *,0,1 - */ - clear_pending_set_locked(lock); - return; + if (!(val & _Q_PENDING_MASK)) + clear_pending(lock); /* * End of pending bit optimistic spinning and beginning of MCS @@ -561,15 +575,15 @@ void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val) * claim the lock: * * n,0,0 -> 0,0,1 : lock, uncontended - * *,0,0 -> *,0,1 : lock, contended + * *,*,0 -> *,*,1 : lock, contended * - * If the queue head is the only one in the queue (lock value == tail), - * clear the tail code and grab the lock. Otherwise, we only need - * to grab the lock. + * If the queue head is the only one in the queue (lock value == tail) + * and nobody is pending, clear the tail code and grab the lock. + * Otherwise, we only need to grab the lock. */ for (;;) { /* In the PV case we might already have _Q_LOCKED_VAL set */ - if ((val & _Q_TAIL_MASK) != tail) { + if ((val & _Q_TAIL_MASK) != tail || (val & _Q_PENDING_MASK)) { set_locked(lock); break; } diff --git a/kernel/locking/qspinlock_paravirt.h b/kernel/locking/qspinlock_paravirt.h index 3e33336911ffe..9c07c72fb10e9 100644 --- a/kernel/locking/qspinlock_paravirt.h +++ b/kernel/locking/qspinlock_paravirt.h @@ -88,11 +88,6 @@ static __always_inline void set_pending(struct qspinlock *lock) WRITE_ONCE(lock->pending, 1); } -static __always_inline void clear_pending(struct qspinlock *lock) -{ - WRITE_ONCE(lock->pending, 0); -} - /* * The pending bit check in pv_queued_spin_steal_lock() isn't a memory * barrier. Therefore, an atomic cmpxchg() is used to acquire the lock From patchwork Thu Dec 13 14:09:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Andrzej Siewior X-Patchwork-Id: 153646 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp846204ljp; Thu, 13 Dec 2018 06:10:05 -0800 (PST) X-Google-Smtp-Source: AFSGD/UNF8FFCeGi4sbeuQMGjfEljxu7knP7j9nCg3xxx5J9AYZkr/RmTf5n+lFT/ytOw2Y5EMZt X-Received: by 2002:a63:e21:: with SMTP id d33mr771582pgl.272.1544710205188; Thu, 13 Dec 2018 06:10:05 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544710205; cv=none; d=google.com; s=arc-20160816; b=aG10zJHpjY1Rp1KtSoNcIRwg7/GJzEMGIUx+utXiSgA/RD6CGeZ69BFyrpd9Xr0q9O +d2G3wPfAtCPpgfWUQ1pw9WsLfNaC9j9WGnz/gjnU2+umlvpU1otm/1duajSmPUONz/1 /J2EEzBFK84yGMaNEOhemu/6XykO5LDxJ3xaD+vo+/LmRV0FORlJvXkPtltYiI40NWYh dtCB+37DL6L9x4vSP3W3B1PdqudfBmKym1eSweT+L9R8CxyHWjovGEVBZ1wF7xXct/jI j4vjOCk2aCqJcEQCvkGuH6/Jq26VIO3DoCSNGQToKUsk16aFieF6ktw5NlAvWSvGJ4Gx 1sjA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :illegal-object:reply-to:references:in-reply-to:message-id:date :subject:cc:to:from; bh=KJaYXGPWaIz/oDET0dgR+wUqU2B6GFZlX8cgobDxj6g=; b=Uf7CUNT25gdNvPdZDInb4Ym+Wp8xKBtaEGxt5bPePteo8gH3KcA844rTRQy+2LZubB QpAoRxHbkUuyHUUZsXD++B+kT8saRQpZoSYSZ+ZJezxMV03/RoI0NZr6bVqD1o52ptOU /nC96uzHJ07rPztuF2jvgDHJWIZG6e7b5Z6T0TaOgb3da4R7yuxGSjDSYOIbqUaBoRY0 3TVYka42jmOFl9HhOqL9TEY+CGy7CFxWwFx4r3li+bhiU8HmVAxE08QkC+izq+box3+f nWM3f2KqKqACTKAR/WOdz41WQv912zvv5cwMJcYywKTSf2l7ccdYcJHEwAJXfISNe5+O pekQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t16si1817482pfk.139.2018.12.13.06.10.04; Thu, 13 Dec 2018 06:10:05 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728654AbeLMOJs (ORCPT + 15 others); Thu, 13 Dec 2018 09:09:48 -0500 Received: from Galois.linutronix.de ([146.0.238.70]:46533 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728288AbeLMOJr (ORCPT ); Thu, 13 Dec 2018 09:09:47 -0500 Received: from localhost ([127.0.0.1] helo=bazinga.breakpoint.cc) by Galois.linutronix.de with esmtp (Exim 4.80) (envelope-from ) id 1gXRgI-0001G3-4l; Thu, 13 Dec 2018 15:09:38 +0100 From: Sebastian Andrzej Siewior To: stable@vger.kernel.org Cc: Peter Zijlstra , Will Deacon , Thomas Gleixner , Daniel Wagner , Waiman Long , Linus Torvalds , boqun.feng@gmail.com, linux-arm-kernel@lists.infradead.org, paulmck@linux.vnet.ibm.com, Ingo Molnar , Sebastian Andrzej Siewior Subject: [PATCH STABLE v4.9 06/10] locking/qspinlock: Remove duplicate clear_pending() function from PV code Date: Thu, 13 Dec 2018 15:09:21 +0100 Message-Id: <20181213140925.6179-7-bigeasy@linutronix.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20181213140925.6179-1-bigeasy@linutronix.de> References: <20181213140925.6179-1-bigeasy@linutronix.de> Reply-To: [PATCH STABLE v4.9 00/10], Backport, for, cache line starvation on x86 Illegal-Object: Syntax error in Reply-To: address found on vger.kernel.org: Reply-To: cache line starvation on x86 ^-extraneous tokens in address MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Will Deacon commit 3bea9adc96842b8a7345c7fb202c16ae9c8d5b25 upstream. The native clear_pending() function is identical to the PV version, so the latter can simply be removed. This fixes the build for systems with >= 16K CPUs using the PV lock implementation. Reported-by: Waiman Long Signed-off-by: Will Deacon Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: boqun.feng@gmail.com Cc: linux-arm-kernel@lists.infradead.org Cc: paulmck@linux.vnet.ibm.com Link: http://lkml.kernel.org/r/20180427101619.GB21705@arm.com Signed-off-by: Ingo Molnar Signed-off-by: Sebastian Andrzej Siewior --- kernel/locking/qspinlock_paravirt.h | 5 ----- 1 file changed, 5 deletions(-) -- 2.20.0 diff --git a/kernel/locking/qspinlock_paravirt.h b/kernel/locking/qspinlock_paravirt.h index 9c07c72fb10e9..af2a24d484aab 100644 --- a/kernel/locking/qspinlock_paravirt.h +++ b/kernel/locking/qspinlock_paravirt.h @@ -105,11 +105,6 @@ static __always_inline void set_pending(struct qspinlock *lock) atomic_or(_Q_PENDING_VAL, &lock->val); } -static __always_inline void clear_pending(struct qspinlock *lock) -{ - atomic_andnot(_Q_PENDING_VAL, &lock->val); -} - static __always_inline int trylock_clear_pending(struct qspinlock *lock) { int val = atomic_read(&lock->val); From patchwork Thu Dec 13 14:09:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Andrzej Siewior X-Patchwork-Id: 153644 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp846161ljp; Thu, 13 Dec 2018 06:10:03 -0800 (PST) X-Google-Smtp-Source: AFSGD/Vh3L8hHjZG9lq15rd8xq4EDpopfI2dITtBWwyNGkT/+AM3d6Ixqb7279Bd1HB2LBRGZA7/ X-Received: by 2002:a17:902:6502:: with SMTP id b2mr23409299plk.44.1544710203133; Thu, 13 Dec 2018 06:10:03 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544710203; cv=none; d=google.com; s=arc-20160816; b=LO0Uy1Z02Z1NufARSWOv4e+cNxY5+oUHWr2BMtO2dN09+KAWBZgIdjJmOpYmauVNKe tSc3MHAn75f9ghnKD0NFJya8g1q0P12awD730bxbtOYYB3jdxUW3znMYHEY+Eu6WvBgE 5U/R+Ub/h9QXd9I2xioonHbdIexJd6DH6mX/rLryrrfCEihJzep8IlhZ6rsB8NGiNrzw h+froO3i6SFx3c8JHgiAT7IkC+/iDZIKSyF9tt/XgOJqvjqY+/OCxJJTqSxiTQFHWl9U NTJAjfZMRIdqXnNzbLKEN618cJfXXVJz/psSs5oIVtEaz1rcT0HXz7IhpWhKjnkAGWs0 FpxA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :illegal-object:reply-to:references:in-reply-to:message-id:date :subject:cc:to:from; bh=7f+cbSfiLLXJ81KnA6/y7WrHOafjTUa1VHuPl7Vf25s=; b=a9Iis8RbGWdjMEwsQ2Q4Q/0wvg2FfSSlZveFuCyXkY/yENa+uyUH2zrHZ8NzNif7d7 MbUnkwY4FYJS413HKSm/+Jlz+YbdMByASsCG6DbllMgNQGbBnLmxV+OBdbHT9NuWiREL nba2OWwXWmlXd98/bLqiwhaYXLkX/vyPlI0DE4WfYdhDZh1Q85phmOkiweu4slrKIVoG f4PlwOSa97UcxoF3X9AK5321IVORRD4ieI5fUJKMnCg2AroodHvhhkxE22KqUC4+rLPw 80PSedZ5XA+Zxn7P2jfPYHgc2qRcZ2XMfojCtMbpJSVEXnvkiCXY/gWqVYZXryVlvXUs OlWw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t16si1817482pfk.139.2018.12.13.06.10.02; Thu, 13 Dec 2018 06:10:03 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727757AbeLMOJn (ORCPT + 15 others); Thu, 13 Dec 2018 09:09:43 -0500 Received: from Galois.linutronix.de ([146.0.238.70]:46519 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728596AbeLMOJn (ORCPT ); Thu, 13 Dec 2018 09:09:43 -0500 Received: from localhost ([127.0.0.1] helo=bazinga.breakpoint.cc) by Galois.linutronix.de with esmtp (Exim 4.80) (envelope-from ) id 1gXRgJ-0001G3-5h; Thu, 13 Dec 2018 15:09:39 +0100 From: Sebastian Andrzej Siewior To: stable@vger.kernel.org Cc: Peter Zijlstra , Will Deacon , Thomas Gleixner , Daniel Wagner , Waiman Long , Linus Torvalds , boqun.feng@gmail.com, linux-arm-kernel@lists.infradead.org, paulmck@linux.vnet.ibm.com, Ingo Molnar , Sebastian Andrzej Siewior Subject: [PATCH STABLE v4.9 07/10] locking/qspinlock: Kill cmpxchg() loop when claiming lock from head of queue Date: Thu, 13 Dec 2018 15:09:22 +0100 Message-Id: <20181213140925.6179-8-bigeasy@linutronix.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20181213140925.6179-1-bigeasy@linutronix.de> References: <20181213140925.6179-1-bigeasy@linutronix.de> Reply-To: [PATCH STABLE v4.9 00/10], Backport, for, cache line starvation on x86 Illegal-Object: Syntax error in Reply-To: address found on vger.kernel.org: Reply-To: cache line starvation on x86 ^-extraneous tokens in address MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Will Deacon commit c61da58d8a9ba9238250a548f00826eaf44af0f7 upstream. When a queued locker reaches the head of the queue, it claims the lock by setting _Q_LOCKED_VAL in the lockword. If there isn't contention, it must also clear the tail as part of this operation so that subsequent lockers can avoid taking the slowpath altogether. Currently this is expressed as a cmpxchg() loop that practically only runs up to two iterations. This is confusing to the reader and unhelpful to the compiler. Rewrite the cmpxchg() loop without the loop, so that a failed cmpxchg() implies that there is contention and we just need to write to _Q_LOCKED_VAL without considering the rest of the lockword. Signed-off-by: Will Deacon Acked-by: Peter Zijlstra (Intel) Acked-by: Waiman Long Cc: Linus Torvalds Cc: Thomas Gleixner Cc: boqun.feng@gmail.com Cc: linux-arm-kernel@lists.infradead.org Cc: paulmck@linux.vnet.ibm.com Link: http://lkml.kernel.org/r/1524738868-31318-7-git-send-email-will.deacon@arm.com Signed-off-by: Ingo Molnar Signed-off-by: Sebastian Andrzej Siewior --- kernel/locking/qspinlock.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) -- 2.20.0 diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c index e7ab99a1f4387..ba5dc86a4d831 100644 --- a/kernel/locking/qspinlock.c +++ b/kernel/locking/qspinlock.c @@ -581,24 +581,21 @@ void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val) * and nobody is pending, clear the tail code and grab the lock. * Otherwise, we only need to grab the lock. */ - for (;;) { - /* In the PV case we might already have _Q_LOCKED_VAL set */ - if ((val & _Q_TAIL_MASK) != tail || (val & _Q_PENDING_MASK)) { - set_locked(lock); - break; - } + + /* In the PV case we might already have _Q_LOCKED_VAL set */ + if ((val & _Q_TAIL_MASK) == tail) { /* * The smp_cond_load_acquire() call above has provided the - * necessary acquire semantics required for locking. At most - * two iterations of this loop may be ran. + * necessary acquire semantics required for locking. */ old = atomic_cmpxchg_relaxed(&lock->val, val, _Q_LOCKED_VAL); if (old == val) - goto release; /* No contention */ - - val = old; + goto release; /* No contention */ } + /* Either somebody is queued behind us or _Q_PENDING_VAL is set */ + set_locked(lock); + /* * contended path; wait for next if not observed yet, release. */ From patchwork Thu Dec 13 14:09:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Andrzej Siewior X-Patchwork-Id: 153649 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp846267ljp; Thu, 13 Dec 2018 06:10:07 -0800 (PST) X-Google-Smtp-Source: AFSGD/WDOApFujqK2ffkg2If3pl7fbAUxuH1lon3NnYK5iDvIpAakXi2wCzQJbJvHbxKgLr//HQA X-Received: by 2002:a17:902:6b83:: with SMTP id p3mr23599496plk.118.1544710207504; Thu, 13 Dec 2018 06:10:07 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544710207; cv=none; d=google.com; s=arc-20160816; b=QRR66QqEiCeVsF23V367aYB+PV76K0PmJosqnHxlRRe5AG8XcgQkWUbWb/SbRuoyaZ M50ZVouknAA+VXG5HXLqLc70726BTgcOY1bJvkx68tGBnGsEVvLhAAl4Sgv0KFECUCfY oNLyblOuZXWf2r2qzi1JMZFfdJ9YuUFdpKe+rFnulcex7SjhBu280/kDvGH0KbmlIlJ4 ysK4f0HmcyevxUrbNrqNyIESh7lb9pbVZe1wAc4I8IFWJdw7+yeeAzg+kLQQXmQQomz0 70YANIMH2UcSVj4+blwceB8/pPfZ8I8muofdKWeKY33fvecQI4O9HJjyzyXXTwVq6mgG 80eQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :illegal-object:reply-to:references:in-reply-to:message-id:date :subject:cc:to:from; bh=L9t8W1ECP18lz3Fks93eqLxztSdSNs4ONKnrzfc25H4=; b=bhu2Eq4ZJ4MPn6fyc2xRNnJczaIfGxjofLy/Nr6WpZ9jvESHWkPfrGUAbITUxxL2+y diEXpKNhiNQJWm490Ev/FaCbZ9ky0DKeu5yyUiXGKoruaDTl+3bVwkanDJhmjEURoBib fijVEM+yksqiZ2/62RCngU1bVi3KOrtTxA+ca+mW8ljXMtyh9sDAtyDXDERokslrGUua jS4hxXfNPva8blYUzYj6qYYmeeCdkT998AJ2wuJBN9G0K0LkEnllXaCiF0marCnhSs7w URHPcHFtqOcZpjRj7iwYB48jvVbBYVjtMO6Xwu64Hu6lKmtYYyoj/NkO3+Kup8H43luJ MO7w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t16si1817482pfk.139.2018.12.13.06.10.07; Thu, 13 Dec 2018 06:10:07 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728611AbeLMOJy (ORCPT + 15 others); Thu, 13 Dec 2018 09:09:54 -0500 Received: from Galois.linutronix.de ([146.0.238.70]:46572 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728596AbeLMOJy (ORCPT ); Thu, 13 Dec 2018 09:09:54 -0500 Received: from localhost ([127.0.0.1] helo=bazinga.breakpoint.cc) by Galois.linutronix.de with esmtp (Exim 4.80) (envelope-from ) id 1gXRgL-0001G3-6j; Thu, 13 Dec 2018 15:09:41 +0100 From: Sebastian Andrzej Siewior To: stable@vger.kernel.org Cc: Peter Zijlstra , Will Deacon , Thomas Gleixner , Daniel Wagner , Waiman Long , Linus Torvalds , boqun.feng@gmail.com, linux-arm-kernel@lists.infradead.org, paulmck@linux.vnet.ibm.com, Ingo Molnar , Sebastian Andrzej Siewior Subject: [PATCH STABLE v4.9 09/10] locking/qspinlock/x86: Increase _Q_PENDING_LOOPS upper bound Date: Thu, 13 Dec 2018 15:09:24 +0100 Message-Id: <20181213140925.6179-10-bigeasy@linutronix.de> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20181213140925.6179-1-bigeasy@linutronix.de> References: <20181213140925.6179-1-bigeasy@linutronix.de> Reply-To: [PATCH STABLE v4.9 00/10], Backport, for, cache line starvation on x86 Illegal-Object: Syntax error in Reply-To: address found on vger.kernel.org: Reply-To: cache line starvation on x86 ^-extraneous tokens in address MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Will Deacon commit b247be3fe89b6aba928bf80f4453d1c4ba8d2063 upstream. On x86, atomic_cond_read_relaxed will busy-wait with a cpu_relax() loop, so it is desirable to increase the number of times we spin on the qspinlock lockword when it is found to be transitioning from pending to locked. According to Waiman Long: | Ideally, the spinning times should be at least a few times the typical | cacheline load time from memory which I think can be down to 100ns or | so for each cacheline load with the newest systems or up to several | hundreds ns for older systems. which in his benchmarking corresponded to 512 iterations. Suggested-by: Waiman Long Signed-off-by: Will Deacon Acked-by: Peter Zijlstra (Intel) Acked-by: Waiman Long Cc: Linus Torvalds Cc: Thomas Gleixner Cc: boqun.feng@gmail.com Cc: linux-arm-kernel@lists.infradead.org Cc: paulmck@linux.vnet.ibm.com Link: http://lkml.kernel.org/r/1524738868-31318-5-git-send-email-will.deacon@arm.com Signed-off-by: Ingo Molnar Signed-off-by: Sebastian Andrzej Siewior --- arch/x86/include/asm/qspinlock.h | 2 ++ 1 file changed, 2 insertions(+) -- 2.20.0 diff --git a/arch/x86/include/asm/qspinlock.h b/arch/x86/include/asm/qspinlock.h index e07cc206919d4..8b1ba1607091c 100644 --- a/arch/x86/include/asm/qspinlock.h +++ b/arch/x86/include/asm/qspinlock.h @@ -5,6 +5,8 @@ #include #include +#define _Q_PENDING_LOOPS (1 << 9) + #define queued_spin_unlock queued_spin_unlock /** * queued_spin_unlock - release a queued spinlock