diff options
Diffstat (limited to 'kernel/hung_task.c')
-rw-r--r-- | kernel/hung_task.c | 20 |
1 files changed, 9 insertions, 11 deletions
diff --git a/kernel/hung_task.c b/kernel/hung_task.c index cb8e3e8ac7b9..4a9191617076 100644 --- a/kernel/hung_task.c +++ b/kernel/hung_task.c | |||
@@ -34,7 +34,7 @@ int __read_mostly sysctl_hung_task_check_count = PID_MAX_LIMIT; | |||
34 | * is disabled during the critical section. It also controls the size of | 34 | * is disabled during the critical section. It also controls the size of |
35 | * the RCU grace period. So it needs to be upper-bound. | 35 | * the RCU grace period. So it needs to be upper-bound. |
36 | */ | 36 | */ |
37 | #define HUNG_TASK_BATCHING 1024 | 37 | #define HUNG_TASK_LOCK_BREAK (HZ / 10) |
38 | 38 | ||
39 | /* | 39 | /* |
40 | * Zero means infinite timeout - no checking done: | 40 | * Zero means infinite timeout - no checking done: |
@@ -112,8 +112,11 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout) | |||
112 | 112 | ||
113 | trace_sched_process_hang(t); | 113 | trace_sched_process_hang(t); |
114 | 114 | ||
115 | if (!sysctl_hung_task_warnings && !sysctl_hung_task_panic) | 115 | if (sysctl_hung_task_panic) { |
116 | return; | 116 | console_verbose(); |
117 | hung_task_show_lock = true; | ||
118 | hung_task_call_panic = true; | ||
119 | } | ||
117 | 120 | ||
118 | /* | 121 | /* |
119 | * Ok, the task did not get scheduled for more than 2 minutes, | 122 | * Ok, the task did not get scheduled for more than 2 minutes, |
@@ -135,11 +138,6 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout) | |||
135 | } | 138 | } |
136 | 139 | ||
137 | touch_nmi_watchdog(); | 140 | touch_nmi_watchdog(); |
138 | |||
139 | if (sysctl_hung_task_panic) { | ||
140 | hung_task_show_lock = true; | ||
141 | hung_task_call_panic = true; | ||
142 | } | ||
143 | } | 141 | } |
144 | 142 | ||
145 | /* | 143 | /* |
@@ -173,7 +171,7 @@ static bool rcu_lock_break(struct task_struct *g, struct task_struct *t) | |||
173 | static void check_hung_uninterruptible_tasks(unsigned long timeout) | 171 | static void check_hung_uninterruptible_tasks(unsigned long timeout) |
174 | { | 172 | { |
175 | int max_count = sysctl_hung_task_check_count; | 173 | int max_count = sysctl_hung_task_check_count; |
176 | int batch_count = HUNG_TASK_BATCHING; | 174 | unsigned long last_break = jiffies; |
177 | struct task_struct *g, *t; | 175 | struct task_struct *g, *t; |
178 | 176 | ||
179 | /* | 177 | /* |
@@ -188,10 +186,10 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout) | |||
188 | for_each_process_thread(g, t) { | 186 | for_each_process_thread(g, t) { |
189 | if (!max_count--) | 187 | if (!max_count--) |
190 | goto unlock; | 188 | goto unlock; |
191 | if (!--batch_count) { | 189 | if (time_after(jiffies, last_break + HUNG_TASK_LOCK_BREAK)) { |
192 | batch_count = HUNG_TASK_BATCHING; | ||
193 | if (!rcu_lock_break(g, t)) | 190 | if (!rcu_lock_break(g, t)) |
194 | goto unlock; | 191 | goto unlock; |
192 | last_break = jiffies; | ||
195 | } | 193 | } |
196 | /* use "==" to skip the TASK_KILLABLE tasks waiting on NFS */ | 194 | /* use "==" to skip the TASK_KILLABLE tasks waiting on NFS */ |
197 | if (t->state == TASK_UNINTERRUPTIBLE) | 195 | if (t->state == TASK_UNINTERRUPTIBLE) |