aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-07-16 09:44:29 -0400
committerIngo Molnar <mingo@elte.hu>2009-07-18 09:51:42 -0400
commite4aafea2d4bde8b44d6500c4ee7195bbfc51269e (patch)
treebf0c9df18b9f63bb10da0096d81ba80712a71665
parente09758fae8ccde97e026c704319eaa18d488dc86 (diff)
sched: Add a preempt count base offset to __might_sleep()
Add a preempt count base offset to compare against the current preempt level count. It prepares to pull up the might_sleep check from cond_resched() to cond_resched_lock() and cond_resched_bh(). For these two helpers, we need to respectively ensure that once we'll unlock the given spinlock / reenable local softirqs, we will reach a sleepable state. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> [ Move and rename preempt_count_equals() ] Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <1247725694-6082-4-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--include/linux/kernel.h6
-rw-r--r--kernel/sched.c15
2 files changed, 14 insertions, 7 deletions
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index b804f694ae6a..2b5b1e0899a8 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -125,7 +125,7 @@ extern int _cond_resched(void);
125#endif 125#endif
126 126
127#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP 127#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
128 void __might_sleep(char *file, int line); 128 void __might_sleep(char *file, int line, int preempt_offset);
129/** 129/**
130 * might_sleep - annotation for functions that can sleep 130 * might_sleep - annotation for functions that can sleep
131 * 131 *
@@ -137,9 +137,9 @@ extern int _cond_resched(void);
137 * supposed to. 137 * supposed to.
138 */ 138 */
139# define might_sleep() \ 139# define might_sleep() \
140 do { __might_sleep(__FILE__, __LINE__); might_resched(); } while (0) 140 do { __might_sleep(__FILE__, __LINE__, 0); might_resched(); } while (0)
141#else 141#else
142 static inline void __might_sleep(char *file, int line) { } 142 static inline void __might_sleep(char *file, int line, int preempt_offset) { }
143# define might_sleep() do { might_resched(); } while (0) 143# define might_sleep() do { might_resched(); } while (0)
144#endif 144#endif
145 145
diff --git a/kernel/sched.c b/kernel/sched.c
index 370a6c31c5e1..3ff4d004bd95 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -6610,7 +6610,7 @@ static inline int should_resched(void)
6610 6610
6611static void __cond_resched(void) 6611static void __cond_resched(void)
6612{ 6612{
6613 __might_sleep(__FILE__, __LINE__); 6613 __might_sleep(__FILE__, __LINE__, 0);
6614 6614
6615 add_preempt_count(PREEMPT_ACTIVE); 6615 add_preempt_count(PREEMPT_ACTIVE);
6616 schedule(); 6616 schedule();
@@ -9429,13 +9429,20 @@ void __init sched_init(void)
9429} 9429}
9430 9430
9431#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP 9431#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
9432void __might_sleep(char *file, int line) 9432static inline int preempt_count_equals(int preempt_offset)
9433{
9434 int nested = preempt_count() & ~PREEMPT_ACTIVE;
9435
9436 return (nested == PREEMPT_INATOMIC_BASE + preempt_offset);
9437}
9438
9439void __might_sleep(char *file, int line, int preempt_offset)
9433{ 9440{
9434#ifdef in_atomic 9441#ifdef in_atomic
9435 static unsigned long prev_jiffy; /* ratelimiting */ 9442 static unsigned long prev_jiffy; /* ratelimiting */
9436 9443
9437 if ((!in_atomic() && !irqs_disabled()) || 9444 if ((preempt_count_equals(preempt_offset) && !irqs_disabled()) ||
9438 system_state != SYSTEM_RUNNING || oops_in_progress) 9445 system_state != SYSTEM_RUNNING || oops_in_progress)
9439 return; 9446 return;
9440 if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy) 9447 if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
9441 return; 9448 return;