From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755292AbdLVIHD (ORCPT ); Fri, 22 Dec 2017 03:07:03 -0500 Received: from bombadil.infradead.org ([65.50.211.133]:41122 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753732AbdLVIHC (ORCPT ); Fri, 22 Dec 2017 03:07:02 -0500 Date: Fri, 22 Dec 2017 09:06:56 +0100 From: Peter Zijlstra To: NeilBrown Cc: Ingo Molnar , linux-kernel@vger.kernel.org, lustre Subject: Re: [PATCH 1/2] sched/wait: add wait_event_idle() functions. Message-ID: <20171222080656.5p54fdhxqqxdtvyo@hirez.programming.kicks-ass.net> References: <151391203805.23157.8332034037737592042.stgit@noble> <151391226402.23157.5260361528373791240.stgit@noble> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <151391226402.23157.5260361528373791240.stgit@noble> User-Agent: NeoMutt/20170609 (1.8.3) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, Dec 22, 2017 at 02:11:04PM +1100, NeilBrown wrote: > The new TASK_IDLE state (TASK_UNINTERRUPTIBLE | __TASK_NOLOAD) > is not much used. One way to make it easier to use is to > add wait_event*() family functions that make use of it. > This patch adds: > wait_event_idle() > wait_event_idle_timeout() > wait_event_idle_exclusive() > > This set were chosen because lustre needs them before > it can discard its own l_wait_event() macro. Seems sane enough; please take through the tree that introduces the first users of this. Acked-by: Peter Zijlstra (Intel) > Signed-off-by: NeilBrown > --- > include/linux/wait.h | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 77 insertions(+) > > diff --git a/include/linux/wait.h b/include/linux/wait.h > index 158715445ffb..3aea0780c9d0 100644 > --- a/include/linux/wait.h > +++ b/include/linux/wait.h > @@ -597,6 +597,83 @@ do { \ > __ret; \ > }) > > +/** > + * wait_event_idle - wait for a condition with contributing to system load > + * @wq_head: the waitqueue to wait on > + * @condition: a C expression for the event to wait for > + * > + * The process is put to sleep (TASK_IDLE) until the > + * @condition evaluates to true. > + * The @condition is checked each time the waitqueue @wq_head is woken up. > + * > + * wake_up() has to be called after changing any variable that could > + * change the result of the wait condition. > + * > + */ > +#define wait_event_idle(wq_head, condition) \ > +do { \ > + might_sleep(); \ > + if (!(condition)) \ > + ___wait_event(wq_head, condition, TASK_IDLE, 0, 0, schedule()); \ > +} while (0) > + > +/** > + * wait_event_idle_exclusive - wait for a condition with contributing to system load > + * @wq_head: the waitqueue to wait on > + * @condition: a C expression for the event to wait for > + * > + * The process is put to sleep (TASK_IDLE) until the > + * @condition evaluates to true. > + * The @condition is checked each time the waitqueue @wq_head is woken up. > + * > + * The process is put on the wait queue with an WQ_FLAG_EXCLUSIVE flag > + * set thus when other process waits process on the list if this > + * process is awaken further processes are not considered. > + * > + * wake_up() has to be called after changing any variable that could > + * change the result of the wait condition. > + * > + */ > +#define wait_event_idle_exclusive(wq_head, condition) \ > +do { \ > + might_sleep(); \ > + if (!(condition)) \ > + ___wait_event(wq_head, condition, TASK_IDLE, 1, 0, schedule()); \ > +} while (0) > + > +#define __wait_event_idle_timeout(wq_head, condition, timeout) \ > + ___wait_event(wq_head, ___wait_cond_timeout(condition), \ > + TASK_IDLE, 0, timeout, \ > + __ret = schedule_timeout(__ret)) > + > +/** > + * wait_event_idle_timeout - sleep without load until a condition gets true or a timeout elapses > + * @wq_head: the waitqueue to wait on > + * @condition: a C expression for the event to wait for > + * @timeout: timeout, in jiffies > + * > + * The process is put to sleep (TASK_IDLE) until the > + * @condition evaluates to true. The @condition is checked each time > + * the waitqueue @wq_head is woken up. > + * > + * wake_up() has to be called after changing any variable that could > + * change the result of the wait condition. > + * > + * Returns: > + * 0 if the @condition evaluated to %false after the @timeout elapsed, > + * 1 if the @condition evaluated to %true after the @timeout elapsed, > + * or the remaining jiffies (at least 1) if the @condition evaluated > + * to %true before the @timeout elapsed. > + */ > +#define wait_event_idle_timeout(wq_head, condition, timeout) \ > +({ \ > + long __ret = timeout; \ > + might_sleep(); \ > + if (!___wait_cond_timeout(condition)) \ > + __ret = __wait_event_timeout(wq_head, condition, timeout); \ > + __ret; \ > +}) > + > extern int do_wait_intr(wait_queue_head_t *, wait_queue_entry_t *); > extern int do_wait_intr_irq(wait_queue_head_t *, wait_queue_entry_t *); > > >