linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Paul Gortmaker <paul.gortmaker@windriver.com>
To: <linux-rt-users@vger.kernel.org>
Cc: <linux-kernel@vger.kernel.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
	"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>,
	Steven Rostedt <rostedt@goodmis.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Paul Gortmaker <paul.gortmaker@windriver.com>
Subject: [PATCH 6/7] simplewait: don't run a possibly infinite number of wake under raw lock
Date: Fri, 17 Oct 2014 20:23:01 -0400	[thread overview]
Message-ID: <1413591782-23453-7-git-send-email-paul.gortmaker@windriver.com> (raw)
In-Reply-To: <1413591782-23453-1-git-send-email-paul.gortmaker@windriver.com>

The simple wait queues use a raw lock in order to be functional
for the preempt-rt kernels.  PeterZ suggested[1] the following
change to ensure we come up for air now and again in order to be
deterministic.

I'm not really in love with the solution of passing the flags around,
but couldn't think of anything cleaner to achieve the same thing.

[1] http://marc.info/?l=linux-kernel&m=138089860308430

Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>

diff --git a/include/linux/wait.h b/include/linux/wait.h
index 2a57e00250f9..46e2591c22b6 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -262,7 +262,7 @@ void __swake_up(struct swait_head *q, unsigned int mode, int nr);
 void __cwake_up_locked_key(struct cwait_head *q, unsigned int mode, void *key);
 void __cwake_up_sync_key(struct cwait_head *q, unsigned int mode, int nr, void *key);
 void __cwake_up_locked(struct cwait_head *q, unsigned int mode, int nr);
-void __swake_up_locked(struct swait_head *q, unsigned int mode, int nr);
+void __swake_up_locked(struct swait_head *q, unsigned int mode, int nr, unsigned long *flags);
 void __cwake_up_sync(struct cwait_head *q, unsigned int mode, int nr);
 void __cwake_up_bit(struct cwait_head *, void *, int);
 int __cwait_on_bit(struct cwait_head *, struct cwait_bit *, cwait_bit_action_f *, unsigned);
diff --git a/kernel/sched/completion.c b/kernel/sched/completion.c
index 7a165c697956..87ef42158fdf 100644
--- a/kernel/sched/completion.c
+++ b/kernel/sched/completion.c
@@ -32,7 +32,7 @@ void complete(struct completion *x)
 
 	raw_spin_lock_irqsave(&x->wait.lock, flags);
 	x->done++;
-	__swake_up_locked(&x->wait, TASK_NORMAL, 1);
+	__swake_up_locked(&x->wait, TASK_NORMAL, 1, &flags);
 	raw_spin_unlock_irqrestore(&x->wait.lock, flags);
 }
 EXPORT_SYMBOL(complete);
@@ -52,7 +52,7 @@ void complete_all(struct completion *x)
 
 	raw_spin_lock_irqsave(&x->wait.lock, flags);
 	x->done += UINT_MAX/2;
-	__swake_up_locked(&x->wait, TASK_NORMAL, 0);
+	__swake_up_locked(&x->wait, TASK_NORMAL, 0, &flags);
 	raw_spin_unlock_irqrestore(&x->wait.lock, flags);
 }
 EXPORT_SYMBOL(complete_all);
diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c
index 634427c25945..25e5886ed8d9 100644
--- a/kernel/sched/wait.c
+++ b/kernel/sched/wait.c
@@ -123,8 +123,12 @@ static void __cwake_up_common(struct cwait_head *q, unsigned int mode,
 	}
 }
 
+/*
+ * The swait version gets the extra flags arg so that we can mitigate
+ * against a possibly large number of wakeups done under a raw lock.
+ */
 static void __swake_up_common(struct swait_head *q, unsigned int mode,
-			      int nr_exclusive)
+			      int nr_exclusive, unsigned long *flags)
 {
 	struct swait *curr, *next;
 	int woken = 0;
@@ -146,6 +150,10 @@ static void __swake_up_common(struct swait_head *q, unsigned int mode,
 				break;
 		}
 
+		if (need_resched()) {
+			raw_spin_unlock_irqrestore(&q->lock, *flags);
+			raw_spin_lock_irqsave(&q->lock, *flags);
+		}
 	}
 }
 
@@ -178,7 +186,7 @@ void __swake_up(struct swait_head *q, unsigned int mode, int nr_exclusive)
 		return;
 
 	raw_spin_lock_irqsave(&q->lock, flags);
-	__swake_up_common(q, mode, nr_exclusive);
+	__swake_up_common(q, mode, nr_exclusive, &flags);
 	raw_spin_unlock_irqrestore(&q->lock, flags);
 }
 EXPORT_SYMBOL(__swake_up);
@@ -192,12 +200,13 @@ void __cwake_up_locked(struct cwait_head *q, unsigned int mode, int nr)
 }
 EXPORT_SYMBOL_GPL(__cwake_up_locked);
 
-void __swake_up_locked(struct swait_head *q, unsigned int state, int nr)
+void __swake_up_locked(struct swait_head *q, unsigned int state, int nr,
+		       unsigned long *flags)
 {
 	if (!swait_active(q))
 		return;
 
-	__swake_up_common(q, state, nr);
+	__swake_up_common(q, state, nr, flags);
 }
 EXPORT_SYMBOL_GPL(__swake_up_locked);
 
-- 
1.9.2


  parent reply	other threads:[~2014-10-18  0:28 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-18  0:22 [PATCH v2 0/7] simple wait queue support (from -rt) Paul Gortmaker
2014-10-18  0:22 ` [PATCH 1/7] wait.h: mark complex wait functions to prepare for simple wait Paul Gortmaker
2014-10-18  0:22 ` [PATCH 2/7] wait.c: " Paul Gortmaker
2014-10-18  0:22 ` [PATCH 3/7] wait.[ch]: Introduce the simple waitqueue (swait) implementation Paul Gortmaker
2014-10-18 21:34   ` Peter Zijlstra
2014-10-18 23:05     ` Steven Rostedt
2014-10-20 15:21       ` Paul Gortmaker
2014-10-20 15:40         ` Steven Rostedt
2014-10-20 16:05           ` Paul Gortmaker
2014-10-20 16:47             ` Steven Rostedt
2014-10-20 13:44     ` Paul Gortmaker
2015-01-14 10:38   ` Peter Zijlstra
2015-01-14 14:18     ` Steven Rostedt
2015-01-14 14:31       ` Peter Zijlstra
2015-01-14 15:01         ` Steven Rostedt
2015-01-14 15:29           ` Peter Zijlstra
2014-10-18  0:22 ` [PATCH 4/7] sched/completion: convert completions to use simple wait queues Paul Gortmaker
2014-10-18  0:23 ` [PATCH 5/7] rcu: use simple wait queues where possible in rcutree Paul Gortmaker
2014-10-18  0:23 ` Paul Gortmaker [this message]
2014-10-18  0:23 ` [PATCH 7/7] simplewait: do we make barriers reflect what was in use in -rt? Paul Gortmaker

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1413591782-23453-7-git-send-email-paul.gortmaker@windriver.com \
    --to=paul.gortmaker@windriver.com \
    --cc=bigeasy@linutronix.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rt-users@vger.kernel.org \
    --cc=paulmck@linux.vnet.ibm.com \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).