From mboxrd@z Thu Jan 1 00:00:00 1970 From: Oleg Nesterov Subject: Re: [PATCH] x86 spinlock: Fix memory corruption on completing completions Date: Tue, 10 Feb 2015 15:24:17 +0100 Message-ID: <20150210142417.GA1449@redhat.com> References: <1423234148-13886-1-git-send-email-raghavendra.kt@linux.vnet.ibm.com> <54D7D19B.1000103@goop.org> <54D87F1E.9060307@linux.vnet.ibm.com> <20150209120227.GT21418@twins.programming.kicks-ass.net> <54D9CFC7.5020007@linux.vnet.ibm.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Content-Disposition: inline In-Reply-To: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: virtualization-bounces@lists.linux-foundation.org Errors-To: virtualization-bounces@lists.linux-foundation.org To: Denys Vlasenko Cc: Jeremy Fitzhardinge , the arch/x86 maintainers , KVM list , Peter Zijlstra , virtualization , Paul Gortmaker , Peter Anvin , Davidlohr Bueso , Andrey Ryabinin , Raghavendra K T , Christian Borntraeger , Ingo Molnar , Sasha Levin , Paul McKenney , Rik van Riel , Konrad Rzeszutek Wilk , Andi Kleen , xen-devel@lists.xenproject.org, Dave Jones , Thomas Gleixner , Waiman Long , Linux Kernel Mailing List List-Id: virtualization@lists.linuxfoundation.org On 02/10, Denys Vlasenko wrote: > > # define HEAD_MASK (TICKET_SLOWPATH_FLAG-1) > > ... > unlock_again: > > val = xadd((&lock->ticket.head_tail, TICKET_LOCK_INC); > if (unlikely(!(val & HEAD_MASK))) { > /* overflow. we inadvertently incremented the tail word. > * tail's lsb is TICKET_SLOWPATH_FLAG. > * Increment inverted this bit, fix it up. > * (inc _may_ have messed up tail counter too, > * will deal with it after kick.) > */ > val ^= TICKET_SLOWPATH_FLAG; > } > > if (unlikely(val & TICKET_SLOWPATH_FLAG)) { > ...kick the waiting task... > > val -= TICKET_SLOWPATH_FLAG; > if (unlikely(!(val & HEAD_MASK))) { > /* overflow. we inadvertently incremented tail word, *and* > * TICKET_SLOWPATH_FLAG was set, increment overflowed > * that bit too and incremented tail counter. > * This means we (inadvertently) taking the lock again! > * Oh well. Take it, and unlock it again... > */ > while (1) { > if (READ_ONCE(lock->tickets.head) != TICKET_TAIL(val)) > cpu_relax(); > } > goto unlock_again; > } > > > Granted, this looks ugly. complicated ;) But "Take it, and unlock it again" simply can't work, this can deadlock. Note that unlock() can be called after successful try_lock(). And other problems with lock-ordering, like lock(X); lock(Y); unlock(X); Oleg.