From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752386AbbKKSnv (ORCPT ); Wed, 11 Nov 2015 13:43:51 -0500 Received: from mx1.redhat.com ([209.132.183.28]:52907 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751861AbbKKSnt (ORCPT ); Wed, 11 Nov 2015 13:43:49 -0500 Date: Wed, 11 Nov 2015 20:39:53 +0100 From: Oleg Nesterov To: Peter Zijlstra Cc: Boqun Feng , mingo@kernel.org, linux-kernel@vger.kernel.org, paulmck@linux.vnet.ibm.com, corbet@lwn.net, mhocko@kernel.org, dhowells@redhat.com, torvalds@linux-foundation.org, will.deacon@arm.com Subject: Re: [PATCH 4/4] locking: Introduce smp_cond_acquire() Message-ID: <20151111193953.GA23515@redhat.com> References: <20151102132901.157178466@infradead.org> <20151102134941.005198372@infradead.org> <20151103175958.GA4800@redhat.com> <20151111093939.GA6314@fixme-laptop.cn.ibm.com> <20151111121232.GN17308@twins.programming.kicks-ass.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20151111121232.GN17308@twins.programming.kicks-ass.net> User-Agent: Mutt/1.5.18 (2008-05-17) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 11/11, Peter Zijlstra wrote: > > On Wed, Nov 11, 2015 at 05:39:40PM +0800, Boqun Feng wrote: > > > Just be curious, should spin_unlock_wait() semantically be an ACQUIRE? > > I did wonder the same thing, it would simplify a number of things if > this were so. Yes, me too. Sometimes I even think it should have both ACQUIRE + RELEASE semantics. IOW, it should be "equivalent" to spin_lock() + spin_unlock(). Consider this code: object_t *object; spinlock_t lock; void update(void) { object_t *o; spin_lock(&lock); o = READ_ONCE(object); if (o) { BUG_ON(o->dead); do_something(o); } spin_unlock(&lock); } void destroy(void) // can be called only once, can't race with itself { object_t *o; o = object; object = NULL; /* * pairs with lock/ACQUIRE. The next update() must see * object == NULL after spin_lock(); */ smp_mb(); spin_unlock_wait(&lock); /* * pairs with unlock/RELEASE. The previous update() has * already passed BUG_ON(o->dead). * * (Yes, yes, in this particular case it is not needed, * we can rely on the control dependency). */ smp_mb(); o->dead = true; } I believe the code above is correct and it needs the barriers on both sides. If it is wrong, then task_work_run() is buggy: it relies on mb() implied by cmpxchg() before spin_unlock_wait() the same way: the next task_work_cancel() should see the result of our cmpxchg(), it must not try to read work->next or work->func. Hmm. Not sure I really understand what I am trying to say... Perhaps in fact I mean that unlock_wait() should be removed because it is too subtle for me ;) Oleg.