All of lore.kernel.org
 help / color / mirror / Atom feed
From: tip-bot for Peter Zijlstra <tipbot@zytor.com>
To: linux-tip-commits@vger.kernel.org
Cc: hpa@zytor.com, peterz@infradead.org, mingo@kernel.org,
	tglx@linutronix.de, torvalds@linux-foundation.org,
	linux-kernel@vger.kernel.org
Subject: [tip:sched/core] sched/swait: Switch to full exclusive mode
Date: Wed, 20 Jun 2018 02:40:20 -0700	[thread overview]
Message-ID: <tip-0abf17bc7790dd0467ed0e38522242f23c5da1c4@git.kernel.org> (raw)
In-Reply-To: <20180612083909.209762413@infradead.org>

Commit-ID:  0abf17bc7790dd0467ed0e38522242f23c5da1c4
Gitweb:     https://git.kernel.org/tip/0abf17bc7790dd0467ed0e38522242f23c5da1c4
Author:     Peter Zijlstra <peterz@infradead.org>
AuthorDate: Tue, 12 Jun 2018 10:34:51 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 20 Jun 2018 11:35:56 +0200

sched/swait: Switch to full exclusive mode

Linus noted that swait basically implements exclusive mode -- because
swake_up() only wakes a single waiter. And because of that it should
take care to properly deal with the interruptible case.

In short, the problem is that swake_up() can race with a signal. In
this this case it is possible the swake_up() 'wakes' the waiter that
is already on the way out because it just got a signal and the wakeup
gets lost.

The normal wait code is very careful and avoids this situation, make
sure we do too.

Copy the exact exclusive semantics from wait.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: bigeasy@linutronix.de
Cc: oleg@redhat.com
Cc: paulmck@linux.vnet.ibm.com
Cc: pbonzini@redhat.com
Link: https://lkml.kernel.org/r/20180612083909.209762413@infradead.org

---
 include/linux/swait.h | 11 ++++++-----
 kernel/sched/swait.c  | 22 +++++++++++++++++-----
 2 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/include/linux/swait.h b/include/linux/swait.h
index d6a5e949e4ca..dd032061112d 100644
--- a/include/linux/swait.h
+++ b/include/linux/swait.h
@@ -38,8 +38,8 @@
  *    all wakeups are TASK_NORMAL in order to avoid O(n) lookups for the right
  *    sleeper state.
  *
- *  - the exclusive mode; because this requires preserving the list order
- *    and this is hard.
+ *  - the !exclusive mode; because that leads to O(n) wakeups, everything is
+ *    exclusive.
  *
  *  - custom wake callback functions; because you cannot give any guarantees
  *    about random code. This also allows swait to be used in RT, such that
@@ -167,9 +167,10 @@ extern long prepare_to_swait_event(struct swait_queue_head *q, struct swait_queu
 extern void __finish_swait(struct swait_queue_head *q, struct swait_queue *wait);
 extern void finish_swait(struct swait_queue_head *q, struct swait_queue *wait);
 
-/* as per ___wait_event() but for swait, therefore "exclusive == 0" */
+/* as per ___wait_event() but for swait, therefore "exclusive == 1" */
 #define ___swait_event(wq, condition, state, ret, cmd)			\
 ({									\
+	__label__ __out;						\
 	struct swait_queue __wait;					\
 	long __ret = ret;						\
 									\
@@ -182,13 +183,13 @@ extern void finish_swait(struct swait_queue_head *q, struct swait_queue *wait);
 									\
 		if (___wait_is_interruptible(state) && __int) {		\
 			__ret = __int;					\
-			break;						\
+			goto __out;					\
 		}							\
 									\
 		cmd;							\
 	}								\
 	finish_swait(&wq, &__wait);					\
-	__ret;								\
+__out:	__ret;								\
 })
 
 #define __swait_event(wq, condition)					\
diff --git a/kernel/sched/swait.c b/kernel/sched/swait.c
index e68bb1398b05..66890de93ee5 100644
--- a/kernel/sched/swait.c
+++ b/kernel/sched/swait.c
@@ -73,7 +73,7 @@ static void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *w
 {
 	wait->task = current;
 	if (list_empty(&wait->task_list))
-		list_add(&wait->task_list, &q->task_list);
+		list_add_tail(&wait->task_list, &q->task_list);
 }
 
 void prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait, int state)
@@ -89,12 +89,24 @@ EXPORT_SYMBOL(prepare_to_swait);
 
 long prepare_to_swait_event(struct swait_queue_head *q, struct swait_queue *wait, int state)
 {
-	if (signal_pending_state(state, current))
-		return -ERESTARTSYS;
+	unsigned long flags;
+	long ret = 0;
 
-	prepare_to_swait(q, wait, state);
+	raw_spin_lock_irqsave(&q->lock, flags);
+	if (unlikely(signal_pending_state(state, current))) {
+		/*
+		 * See prepare_to_wait_event(). TL;DR, subsequent swake_up()
+		 * must not see us.
+		 */
+		list_del_init(&wait->task_list);
+		ret = -ERESTARTSYS;
+	} else {
+		__prepare_to_swait(q, wait);
+		set_current_state(state);
+	}
+	raw_spin_unlock_irqrestore(&q->lock, flags);
 
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL(prepare_to_swait_event);
 

  reply	other threads:[~2018-06-20  9:40 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-06-12  8:34 [PATCH 0/3] sched/swait: Convert to full exclusive mode Peter Zijlstra
2018-06-12  8:34 ` [PATCH 1/3] sched/swait: Remove __prepare_to_swait Peter Zijlstra
2018-06-20  9:39   ` [tip:sched/core] " tip-bot for Peter Zijlstra
2018-06-12  8:34 ` [PATCH 2/3] sched/swait: Switch to full exclusive mode Peter Zijlstra
2018-06-20  9:40   ` tip-bot for Peter Zijlstra [this message]
2018-06-12  8:34 ` [PATCH 3/3] sched/swait: Rename to exclusive Peter Zijlstra
2018-06-20  9:40   ` [tip:sched/core] " tip-bot for Peter Zijlstra
2018-06-12 16:47 ` [PATCH 0/3] sched/swait: Convert to full exclusive mode Linus Torvalds
2018-06-12 17:14   ` Quilt vs gmail (Was: [PATCH 0/3] sched/swait: Convert to full exclusive mode) Peter Zijlstra
2018-06-13 12:32     ` Jean Delvare
2018-06-13 13:27       ` Andreas Grünbacher
2018-06-13 13:48         ` Linus Torvalds
2018-06-13 14:40         ` Jean Delvare
2018-06-12 18:52   ` [PATCH 0/3] sched/swait: Convert to full exclusive mode Andreas Grünbacher
     [not found]     ` <CA+55aFx81igOjFZcvO03mvDFd3=pxsq2QuNrWrPW+4pvJy780A@mail.gmail.com>
2018-06-12 19:43       ` Thomas Gleixner
2018-06-12 21:54         ` Sebastian Andrzej Siewior
2018-06-12 22:03           ` Linus Torvalds
2018-06-12 22:55             ` Randy Dunlap
2018-06-13 13:00       ` [Quilt-dev] Quilt vs gmail Jean Delvare
2018-06-13 13:35         ` Greg KH
2018-06-14  1:27 ` [PATCH 0/3] sched/swait: Convert to full exclusive mode Paul E. McKenney
2018-06-19 14:49   ` Paul E. McKenney

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=tip-0abf17bc7790dd0467ed0e38522242f23c5da1c4@git.kernel.org \
    --to=tipbot@zytor.com \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-tip-commits@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.