aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/hung_task.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/kernel/hung_task.c b/kernel/hung_task.c
index e0f90c2b57aa..d234022805dc 100644
--- a/kernel/hung_task.c
+++ b/kernel/hung_task.c
@@ -185,10 +185,12 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
185 rcu_read_unlock(); 185 rcu_read_unlock();
186} 186}
187 187
188static unsigned long timeout_jiffies(unsigned long timeout) 188static long hung_timeout_jiffies(unsigned long last_checked,
189 unsigned long timeout)
189{ 190{
190 /* timeout of 0 will disable the watchdog */ 191 /* timeout of 0 will disable the watchdog */
191 return timeout ? timeout * HZ : MAX_SCHEDULE_TIMEOUT; 192 return timeout ? last_checked - jiffies + timeout * HZ :
193 MAX_SCHEDULE_TIMEOUT;
192} 194}
193 195
194/* 196/*
@@ -224,18 +226,21 @@ EXPORT_SYMBOL_GPL(reset_hung_task_detector);
224 */ 226 */
225static int watchdog(void *dummy) 227static int watchdog(void *dummy)
226{ 228{
229 unsigned long hung_last_checked = jiffies;
230
227 set_user_nice(current, 0); 231 set_user_nice(current, 0);
228 232
229 for ( ; ; ) { 233 for ( ; ; ) {
230 unsigned long timeout = sysctl_hung_task_timeout_secs; 234 unsigned long timeout = sysctl_hung_task_timeout_secs;
235 long t = hung_timeout_jiffies(hung_last_checked, timeout);
231 236
232 while (schedule_timeout_interruptible(timeout_jiffies(timeout))) 237 if (t <= 0) {
233 timeout = sysctl_hung_task_timeout_secs; 238 if (!atomic_xchg(&reset_hung_task, 0))
234 239 check_hung_uninterruptible_tasks(timeout);
235 if (atomic_xchg(&reset_hung_task, 0)) 240 hung_last_checked = jiffies;
236 continue; 241 continue;
237 242 }
238 check_hung_uninterruptible_tasks(timeout); 243 schedule_timeout_interruptible(t);
239 } 244 }
240 245
241 return 0; 246 return 0;