Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753620AbbDGTqy (ORCPT ); Tue, 7 Apr 2015 15:46:54 -0400 Received: from www.linutronix.de ([62.245.132.108]:39875 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753469AbbDGTqw (ORCPT ); Tue, 7 Apr 2015 15:46:52 -0400 Date: Tue, 7 Apr 2015 21:47:13 +0200 (CEST) From: Thomas Gleixner To: Sebastian Andrzej Siewior cc: linux-kernel@vger.kernel.org, Peter Zijlstra , Ingo Molnar , Darren Hart , Steven Rostedt , fredrik.markstrom@windriver.com, Davidlohr Bueso , Manfred Spraul Subject: Re: [PATCH 2/3] futex: avoid double wake up in futex_wake() on -RT In-Reply-To: <1428419030-20030-3-git-send-email-bigeasy@linutronix.de> Message-ID: References: <1428419030-20030-1-git-send-email-bigeasy@linutronix.de> <1428419030-20030-3-git-send-email-bigeasy@linutronix.de> User-Agent: Alpine 2.11 (DEB 23 2013-08-11) MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Linutronix-Spam-Score: -1.0 X-Linutronix-Spam-Level: - X-Linutronix-Spam-Status: No , -1.0 points, 5.0 required, ALL_TRUSTED=-1,SHORTCIRCUIT=-0.0001 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2230 Lines: 83 On Tue, 7 Apr 2015, Sebastian Andrzej Siewior wrote: > futex_wake() wakes the waiter while holding the hb->lock. This leads to > a similar double wake up on -RT if the waiter has a higher priority than > the process perfroming the wake up. Well, the non pi wakeup is designed in a way that the waiter side does not take the hash bucket lock. So if you observe that hb->lock contention and the resulting PI boosting dance on RT, then it's not the wakeup/waiter exit path. That must be something like this: T1 T2 wakeup() -->preemption sys_exit(futex_wait) ... sys_enter(futex_wake); lock(hb->lock); > -/* > - * The hash bucket lock must be held when this is called. > - * Afterwards, the futex_q must not be accessed. > - */ The comment should stay here, because you are not allowed to access the futex_q after q->lock_ptr has been set to NULL and that happens in this function. > -static void wake_futex(struct futex_q *q) > +static struct task_struct *__wake_futex(struct futex_q *q) > { > struct task_struct *p = q->task; > > if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n")) > - return; > + return NULL; > > /* > * We set q->lock_ptr = NULL _before_ we wake up the task. If > @@ -1117,6 +1113,19 @@ static void wake_futex(struct futex_q *q) > */ > smp_wmb(); > q->lock_ptr = NULL; > + return p; ... > @@ -1256,14 +1266,23 @@ futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset) > if (!(this->bitset & bitset)) > continue; > > - wake_futex(this); > + if (nr_wake == 1) > + waiter = __wake_futex(this); > + else > + wake_futex(this); > if (++ret >= nr_wake) > break; > } > } > > spin_unlock(&hb->lock); > + > out_put_key: > + if (waiter) { > + wake_up_state(waiter, TASK_NORMAL); > + put_task_struct(waiter); > + } This should go before out_put_key, because none of the other code pathes which jump there can set waiter. Thanks, tglx -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/