LKML Archive on lore.kernel.org
 help / color / Atom feed
From: Peter Zijlstra <peterz@infradead.org>
To: mingo@kernel.org, oleg@redhat.com, torvalds@linux-foundation.org
Cc: tglx@linutronix.de, ilya.dryomov@inktank.com,
	umgwanakikbuti@gmail.com, linux-kernel@vger.kernel.org,
	Peter Zijlstra <peterz@infradead.org>
Subject: [PATCH 10/11] sched: Debug nested sleeps
Date: Wed, 24 Sep 2014 10:18:55 +0200
Message-ID: <20140924082242.591637616@infradead.org> (raw)
In-Reply-To: <20140924081845.572814794@infradead.org>


[-- Attachment #0: peterz-might_sleep_nesting.patch --]
[-- Type: text/plain, Size: 3739 bytes --]

Validate we call might_sleep() with TASK_RUNNING, which catches places
where we nest blocking primitives, eg. mutex usage in a wait loop.

Since all blocking is arranged through task_struct::state, nesting
this will cause the inner primitive to set TASK_RUNNING and the outer
will thus not block.

Another observed problem is calling a blocking function from
schedule()->sched_submit_work()->blk_schedule_flush_plug() which will
then destroy the task state for the actual __schedule() call that
comes after it.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
 include/linux/sched.h |   46 ++++++++++++++++++++++++++++++++++++++++++++--
 kernel/sched/core.c   |   13 +++++++++++++
 2 files changed, 57 insertions(+), 2 deletions(-)

--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -242,6 +242,43 @@ extern char ___assert_task_state[1 - 2*!
 				((task->state & TASK_UNINTERRUPTIBLE) != 0 && \
 				 (task->flags & PF_FROZEN) == 0)
 
+#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
+
+#define __set_task_state(tsk, state_value)			\
+	do {							\
+		(tsk)->task_state_change = _THIS_IP_;		\
+		(tsk)->state = (state_value);			\
+	} while (0)
+#define set_task_state(tsk, state_value)			\
+	do {							\
+		(tsk)->task_state_change = _THIS_IP_;		\
+		set_mb((tsk)->state, (state_value));		\
+	} while (0)
+
+/*
+ * set_current_state() includes a barrier so that the write of current->state
+ * is correctly serialised wrt the caller's subsequent test of whether to
+ * actually sleep:
+ *
+ *	set_current_state(TASK_UNINTERRUPTIBLE);
+ *	if (do_i_need_to_sleep())
+ *		schedule();
+ *
+ * If the caller does not need such serialisation then use __set_current_state()
+ */
+#define __set_current_state(state_value)			\
+	do {							\
+		current->task_state_change = _THIS_IP_;		\
+		current->state = (state_value);			\
+	} while (0)
+#define set_current_state(state_value)				\
+	do {							\
+		current->task_state_change = _THIS_IP_;		\
+		set_mb(current->state, (state_value));		\
+	} while (0)
+
+#else
+
 #define __set_task_state(tsk, state_value)		\
 	do { (tsk)->state = (state_value); } while (0)
 #define set_task_state(tsk, state_value)		\
@@ -258,11 +295,13 @@ extern char ___assert_task_state[1 - 2*!
  *
  * If the caller does not need such serialisation then use __set_current_state()
  */
-#define __set_current_state(state_value)			\
+#define __set_current_state(state_value)		\
 	do { current->state = (state_value); } while (0)
-#define set_current_state(state_value)		\
+#define set_current_state(state_value)			\
 	set_mb(current->state, (state_value))
 
+#endif
+
 /* Task command name length */
 #define TASK_COMM_LEN 16
 
@@ -1660,6 +1699,9 @@ struct task_struct {
 	unsigned int	sequential_io;
 	unsigned int	sequential_io_avg;
 #endif
+#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
+	unsigned long	task_state_change;
+#endif
 };
 
 /* Future-safe accessor for struct task_struct's cpus_allowed. */
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -7143,6 +7143,19 @@ void __might_sleep(const char *file, int
 {
 	static unsigned long prev_jiffy;	/* ratelimiting */
 
+	/*
+	 * Blocking primitives will set (and therefore destroy) current->state,
+	 * since we will exit with TASK_RUNNING make sure we enter with it,
+	 * otherwise we will destroy state.
+	 */
+	if (WARN(current->state != TASK_RUNNING,
+			"do not call blocking ops when !TASK_RUNNING; "
+			"state=%lx set at [<%p>] %pS\n",
+			current->state,
+			(void *)current->task_state_change,
+			(void *)current->task_state_change))
+		__set_current_state(TASK_RUNNING);
+
 	rcu_sleep_check(); /* WARN_ON_ONCE() by default, no rate limit reqd. */
 	if ((preempt_count_equals(preempt_offset) && !irqs_disabled() &&
 	     !is_idle_task(current)) ||



  parent reply index

Thread overview: 59+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-24  8:18 [PATCH 00/11] nested sleeps, fixes and debug infrastructure Peter Zijlstra
2014-09-24  8:18 ` [PATCH 01/11] locking/mutex: Dont assume TASK_RUNNING Peter Zijlstra
2014-10-28 11:09   ` [tip:sched/core] locking/mutex: Don't " tip-bot for Peter Zijlstra
2014-09-24  8:18 ` [PATCH 02/11] wait: Provide infrastructure to deal with nested blocking Peter Zijlstra
2014-09-29 21:02   ` Oleg Nesterov
2014-10-02  7:37     ` Peter Zijlstra
2014-10-02 21:21       ` Oleg Nesterov
2014-10-28 11:09   ` [tip:sched/core] sched/wait: " tip-bot for Peter Zijlstra
2014-09-24  8:18 ` [PATCH 03/11] wait: Add might_sleep() Peter Zijlstra
2014-10-28 11:09   ` [tip:sched/core] sched/wait: Add might_sleep() checks tip-bot for Peter Zijlstra
2014-09-24  8:18 ` [PATCH 04/11] exit: Deal with nested sleeps Peter Zijlstra
2014-10-28 11:10   ` [tip:sched/core] sched, " tip-bot for Peter Zijlstra
2014-09-24  8:18 ` [PATCH 05/11] inotify: " Peter Zijlstra
2014-10-28 11:10   ` [tip:sched/core] sched, " tip-bot for Peter Zijlstra
2014-09-24  8:18 ` [PATCH 06/11] tty: " Peter Zijlstra
2014-10-28 11:10   ` [tip:sched/core] sched, " tip-bot for Peter Zijlstra
2014-09-24  8:18 ` [PATCH 07/11] smp: Correctly deal " Peter Zijlstra
2014-10-28 11:11   ` [tip:sched/core] sched, " tip-bot for Peter Zijlstra
2014-09-24  8:18 ` [PATCH 08/11] module: Fix nested sleep Peter Zijlstra
2014-09-29 22:18   ` Oleg Nesterov
2014-09-30 13:43     ` Peter Zijlstra
2014-10-28 11:11   ` [tip:sched/core] sched, modules: Fix nested sleep in add_unformed_module() tip-bot for Peter Zijlstra
2014-09-24  8:18 ` [PATCH 09/11] net: Clean up sk_wait_event() vs might_sleep() Peter Zijlstra
2014-09-24  8:36   ` Peter Zijlstra
2014-10-28 11:11   ` [tip:sched/core] sched, net: Clean up sk_wait_event() vs. might_sleep() tip-bot for Peter Zijlstra
2014-09-24  8:18 ` Peter Zijlstra [this message]
2014-09-29 22:13   ` [PATCH 10/11] sched: Debug nested sleeps Oleg Nesterov
2014-09-30 13:49     ` Peter Zijlstra
2014-09-30 21:47       ` Oleg Nesterov
2014-10-01 16:10         ` Peter Zijlstra
2014-10-01 18:35           ` Oleg Nesterov
2014-10-02  9:07             ` Peter Zijlstra
2014-10-02 21:34               ` Oleg Nesterov
2014-10-28 11:11   ` [tip:sched/core] " tip-bot for Peter Zijlstra
2014-09-24  8:18 ` [PATCH 11/11] sched: Exclude cond_resched() from nested sleep test Peter Zijlstra
2014-10-28 11:12   ` [tip:sched/core] " tip-bot for Peter Zijlstra
2014-09-25  8:30 ` [PATCH 00/11] nested sleeps, fixes and debug infrastructure Mike Galbraith
2014-09-25  9:06   ` Peter Zijlstra
2014-09-25  9:10     ` Mike Galbraith
2014-09-25  9:15     ` Peter Zijlstra
2014-09-25  9:56       ` Mike Galbraith
2014-09-25 13:59         ` BUG: sleeping function called from invalid context at drivers/cpufreq/cpufreq.c:370 Mike Galbraith
2014-09-26  6:24           ` Mike Galbraith
2014-09-26  7:54             ` Mike Galbraith
2014-09-26 14:10               ` Rafael J. Wysocki
2014-09-26 22:44               ` Rafael J. Wysocki
2014-09-27  6:14                 ` Mike Galbraith
2014-09-27 19:57                   ` Rafael J. Wysocki
2014-10-02 10:22       ` [PATCH 00/11] nested sleeps, fixes and debug infrastructure Peter Zijlstra
2014-10-02 12:15         ` Peter Zijlstra
2014-10-27 13:41           ` Peter Zijlstra
2014-10-28  0:07             ` Oleg Nesterov
2014-10-28  8:23               ` Peter Zijlstra
2014-10-29  0:00                 ` Oleg Nesterov
2014-10-29  9:35                   ` Peter Zijlstra
2014-10-29 11:31                     ` Peter Zijlstra
2014-10-29 11:36                       ` Peter Zijlstra
2014-10-29 14:26                   ` Peter Zijlstra
2014-11-04 16:08         ` [tip:sched/core] audit, sched/wait: Fixup kauditd_thread() wait loop tip-bot for Peter Zijlstra

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=20140924082242.591637616@infradead.org \
    --to=peterz@infradead.org \
    --cc=ilya.dryomov@inktank.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=oleg@redhat.com \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    --cc=umgwanakikbuti@gmail.com \
    /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

LKML Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/lkml/0 lkml/git/0.git
	git clone --mirror https://lore.kernel.org/lkml/1 lkml/git/1.git
	git clone --mirror https://lore.kernel.org/lkml/2 lkml/git/2.git
	git clone --mirror https://lore.kernel.org/lkml/3 lkml/git/3.git
	git clone --mirror https://lore.kernel.org/lkml/4 lkml/git/4.git
	git clone --mirror https://lore.kernel.org/lkml/5 lkml/git/5.git
	git clone --mirror https://lore.kernel.org/lkml/6 lkml/git/6.git
	git clone --mirror https://lore.kernel.org/lkml/7 lkml/git/7.git
	git clone --mirror https://lore.kernel.org/lkml/8 lkml/git/8.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 lkml lkml/ https://lore.kernel.org/lkml \
		linux-kernel@vger.kernel.org
	public-inbox-index lkml

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-kernel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git