From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751229AbcEIFAb (ORCPT ); Mon, 9 May 2016 01:00:31 -0400 Received: from smtp2.provo.novell.com ([137.65.250.81]:37496 "EHLO smtp2.provo.novell.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751120AbcEIFA0 (ORCPT ); Mon, 9 May 2016 01:00:26 -0400 From: Davidlohr Bueso To: mingo@kernel.org, peterz@infradead.org, tglx@linutronix.de Cc: Waiman.Long@hpe.com, jason.low2@hp.com, dave@stgolabs.net, linux-kernel@vger.kernel.org, Davidlohr Bueso Subject: [PATCH 4/4] locking/rwsem: Rework zeroing reader waiter->task Date: Sun, 8 May 2016 21:56:10 -0700 Message-Id: <1462769770-29363-5-git-send-email-dave@stgolabs.net> X-Mailer: git-send-email 2.8.1 In-Reply-To: <1462769770-29363-1-git-send-email-dave@stgolabs.net> References: <1462769770-29363-1-git-send-email-dave@stgolabs.net> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Readers that are awoken will expect a nil ->task indicating that a wakeup has occurred. There is a mismatch between the smp_mb() and its documentation, in that the serialization is done between reading the task and the nil store. Furthermore, in addition to having the overlapping of loads and stores to waiter->task guaranteed to be ordered within that CPU, both wake_up_process() originally and now wake_q_add() already imply barriers upon successful calls, which serves the comment. Just atomically do a xchg() and simplify the whole thing. We can use relaxed semantics as before mentioned in addition to the barrier provided by wake_q_add(), delaying there is no risk in reordering with the actual wakeup. Signed-off-by: Davidlohr Bueso --- kernel/locking/rwsem-xadd.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c index 1b8c1285a2aa..96e53cb4a4db 100644 --- a/kernel/locking/rwsem-xadd.c +++ b/kernel/locking/rwsem-xadd.c @@ -126,7 +126,6 @@ __rwsem_mark_wake(struct rw_semaphore *sem, enum rwsem_wake_type wake_type, struct wake_q_head *wake_q) { struct rwsem_waiter *waiter; - struct task_struct *tsk; struct list_head *next; long oldcount, woken, loop, adjustment; @@ -190,24 +189,18 @@ __rwsem_mark_wake(struct rw_semaphore *sem, next = sem->wait_list.next; loop = woken; do { + struct task_struct *tsk; + waiter = list_entry(next, struct rwsem_waiter, list); next = waiter->list.next; - tsk = waiter->task; - /* - * Make sure we do not wakeup the next reader before - * setting the nil condition to grant the next reader; - * otherwise we could miss the wakeup on the other - * side and end up sleeping again. See the pairing - * in rwsem_down_read_failed(). - */ - smp_mb(); - waiter->task = NULL; + + tsk = xchg_relaxed(&waiter->task, NULL); wake_q_add(wake_q, tsk); } while (--loop); sem->wait_list.next = next; next->prev = &sem->wait_list; - out: +out: return sem; } -- 2.8.1