Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751437AbcLEIgt (ORCPT ); Mon, 5 Dec 2016 03:36:49 -0500 Received: from bombadil.infradead.org ([198.137.202.9]:39897 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750951AbcLEIgr (ORCPT ); Mon, 5 Dec 2016 03:36:47 -0500 Date: Mon, 5 Dec 2016 09:36:05 +0100 From: Peter Zijlstra To: Davidlohr Bueso Cc: mingo@kernel.org, oleg@redhat.com, john.stultz@linaro.org, dimitrysh@google.com, linux-kernel@vger.kernel.org, Davidlohr Bueso Subject: Re: [PATCH v2 2/3] locking/percpu-rwsem: Rework writer block/wake to not use wait-queues Message-ID: <20161205083605.GQ3092@twins.programming.kicks-ass.net> References: <1479495277-9075-1-git-send-email-dave@stgolabs.net> <1479495277-9075-3-git-send-email-dave@stgolabs.net> <20161203021839.GB30078@linux-80c1.suse> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20161203021839.GB30078@linux-80c1.suse> User-Agent: Mutt/1.5.23.1 (2014-03-12) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1347 Lines: 50 On Fri, Dec 02, 2016 at 06:18:39PM -0800, Davidlohr Bueso wrote: > @@ -102,8 +103,13 @@ void __percpu_up_read(struct percpu_rw_semaphore *sem) > */ > __this_cpu_dec(*sem->read_count); > > + rcu_read_lock(); > + writer = rcu_dereference(sem->writer); Don't think this is correct, I think Oleg suggested using task_rcu_dereference(), which is a giant pile of magic. The problem is that task_struct isn't RCU protected as such. > + > /* Prod writer to recheck readers_active */ > - wake_up(&sem->writer); > + if (writer) > + wake_up_process(writer); > + rcu_read_unlock(); > } > EXPORT_SYMBOL_GPL(__percpu_up_read); > > @@ -159,8 +165,18 @@ void percpu_down_write(struct percpu_rw_semaphore *sem) > * will wait for them. > */ > > - /* Wait for all now active readers to complete. */ > - wait_event(sem->writer, readers_active_check(sem)); > + WRITE_ONCE(sem->writer, current); So this one matches rcu_dereference(), which is weird, because you now have unmatched barriers. > + for (;;) { > + set_current_state(TASK_UNINTERRUPTIBLE); > + > + if (readers_active_check(sem)) > + break; > + > + schedule(); > + } > + > + rcu_assign_pointer(sem->writer, NULL); And this one does not, and the value being NULL this actually reverts to WRITE_ONCE(). > + __set_current_state(TASK_RUNNING); > } > EXPORT_SYMBOL_GPL(percpu_down_write);