FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
linux/kernel/hung_task.c at master · crazywill/linux · GitHub
crazywill
/
linux
Public
forked from
torvalds/linux
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Pull requests
0
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
linux
/
kernel
/
hung_task.c
Copy path
More file actions
More file actions
Latest commit
History
History
History
228 lines (188 loc) · 5.26 KB
Breadcrumbs
linux
/
kernel
/
hung_task.c
Copy path
File metadata and controls
228 lines (188 loc) · 5.26 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
/*
* Detect Hung Task
*
* kernel/hung_task.c - kernel thread for detecting tasks stuck in D state
*
*/
#include
<linux/mm.h>
#include
<linux/cpu.h>
#include
<linux/nmi.h>
#include
<linux/init.h>
#include
<linux/delay.h>
#include
<linux/freezer.h>
#include
<linux/kthread.h>
#include
<linux/lockdep.h>
#include
<linux/export.h>
#include
<linux/sysctl.h>
/*
* The number of tasks checked:
*/
unsigned long
__read_mostly
sysctl_hung_task_check_count
=
PID_MAX_LIMIT
;
/*
* Limit number of tasks checked in a batch.
*
* This value controls the preemptibility of khungtaskd since preemption
* is disabled during the critical section. It also controls the size of
* the RCU grace period. So it needs to be upper-bound.
*/
#define
HUNG_TASK_BATCHING
1024
/*
* Zero means infinite timeout - no checking done:
*/
unsigned long
__read_mostly
sysctl_hung_task_timeout_secs
=
CONFIG_DEFAULT_HUNG_TASK_TIMEOUT
;
unsigned long
__read_mostly
sysctl_hung_task_warnings
=
10
;
static
int
__read_mostly
did_panic
;
static
struct
task_struct
*
watchdog_task
;
/*
* Should we panic (and reboot, if panic_timeout= is set) when a
* hung task is detected:
*/
unsigned
int
__read_mostly
sysctl_hung_task_panic
=
CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE
;
static
int
__init
hung_task_panic_setup
(
char
*
str
)
{
sysctl_hung_task_panic
=
simple_strtoul
(
str
,
NULL
,
0
);
return
1
;
}
__setup
(
"hung_task_panic="
,
hung_task_panic_setup
);
static
int
hung_task_panic
(
struct
notifier_block
*
this
,
unsigned long
event
,
void
*
ptr
)
{
did_panic
=
1
;
return
NOTIFY_DONE
;
}
static
struct
notifier_block
panic_block
=
{
.
notifier_call
=
hung_task_panic
,
};
static
void
check_hung_task
(
struct
task_struct
*
t
,
unsigned long
timeout
)
{
unsigned long
switch_count
=
t
->
nvcsw
+
t
->
nivcsw
;
/*
* Ensure the task is not frozen.
* Also, skip vfork and any other user process that freezer should skip.
*/
if
(
unlikely
(
t
->
flags
&
(
PF_FROZEN
|
PF_FREEZER_SKIP
)))
return
;
/*
* When a freshly created task is scheduled once, changes its state to
* TASK_UNINTERRUPTIBLE without having ever been switched out once, it
* musn't be checked.
*/
if
(
unlikely
(!
switch_count
))
return
;
if
(
switch_count
!=
t
->
last_switch_count
) {
t
->
last_switch_count
=
switch_count
;
return
;
}
if
(!
sysctl_hung_task_warnings
)
return
;
sysctl_hung_task_warnings
--
;
/*
* Ok, the task did not get scheduled for more than 2 minutes,
* complain:
*/
printk
(
KERN_ERR
"INFO: task %s:%d blocked for more than "
"%ld seconds.\n"
,
t
->
comm
,
t
->
pid
,
timeout
);
printk
(
KERN_ERR
"\"echo 0 > /proc/sys/kernel/hung_task_timeout_secs\""
" disables this message.\n"
);
sched_show_task
(
t
);
debug_show_held_locks
(
t
);
touch_nmi_watchdog
();
if
(
sysctl_hung_task_panic
) {
trigger_all_cpu_backtrace
();
panic
(
"hung_task: blocked tasks"
);
}
}
/*
* To avoid extending the RCU grace period for an unbounded amount of time,
* periodically exit the critical section and enter a new one.
*
* For preemptible RCU it is sufficient to call rcu_read_unlock in order
* to exit the grace period. For classic RCU, a reschedule is required.
*/
static
bool
rcu_lock_break
(
struct
task_struct
*
g
,
struct
task_struct
*
t
)
{
bool
can_cont
;
get_task_struct
(
g
);
get_task_struct
(
t
);
rcu_read_unlock
();
cond_resched
();
rcu_read_lock
();
can_cont
=
pid_alive
(
g
)
&&
pid_alive
(
t
);
put_task_struct
(
t
);
put_task_struct
(
g
);
return
can_cont
;
}
/*
* Check whether a TASK_UNINTERRUPTIBLE does not get woken up for
* a really long time (120 seconds). If that happens, print out
* a warning.
*/
static
void
check_hung_uninterruptible_tasks
(
unsigned long
timeout
)
{
int
max_count
=
sysctl_hung_task_check_count
;
int
batch_count
=
HUNG_TASK_BATCHING
;
struct
task_struct
*
g
,
*
t
;
/*
* If the system crashed already then all bets are off,
* do not report extra hung tasks:
*/
if
(
test_taint
(
TAINT_DIE
)
||
did_panic
)
return
;
rcu_read_lock
();
do_each_thread
(
g
,
t
) {
if
(!
max_count
--
)
goto
unlock
;
if
(!
--
batch_count
) {
batch_count
=
HUNG_TASK_BATCHING
;
if
(!
rcu_lock_break
(
g
,
t
))
goto
unlock
;
}
/* use "==" to skip the TASK_KILLABLE tasks waiting on NFS */
if
(
t
->
state
==
TASK_UNINTERRUPTIBLE
)
check_hung_task
(
t
,
timeout
);
}
while_each_thread
(
g
,
t
);
unlock
:
rcu_read_unlock
();
}
static
unsigned long
timeout_jiffies
(
unsigned long
timeout
)
{
/* timeout of 0 will disable the watchdog */
return
timeout
?
timeout
*
HZ
:
MAX_SCHEDULE_TIMEOUT
;
}
/*
* Process updating of timeout sysctl
*/
int
proc_dohung_task_timeout_secs
(
struct
ctl_table
*
table
,
int
write
,
void
__user
*
buffer
,
size_t
*
lenp
,
loff_t
*
ppos
)
{
int
ret
;
ret
=
proc_doulongvec_minmax
(
table
,
write
,
buffer
,
lenp
,
ppos
);
if
(
ret
||
!
write
)
goto
out
;
wake_up_process
(
watchdog_task
);
out
:
return
ret
;
}
/*
* kthread which checks for tasks stuck in D state
*/
static
int
watchdog
(
void
*
dummy
)
{
set_user_nice
(
current
,
0
);
for
( ; ; ) {
unsigned long
timeout
=
sysctl_hung_task_timeout_secs
;
while
(
schedule_timeout_interruptible
(
timeout_jiffies
(
timeout
)))
timeout
=
sysctl_hung_task_timeout_secs
;
check_hung_uninterruptible_tasks
(
timeout
);
}
return
0
;
}
static
int
__init
hung_task_init
(
void
)
{
atomic_notifier_chain_register
(
&
panic_notifier_list
,
&
panic_block
);
watchdog_task
=
kthread_run
(
watchdog
,
NULL
,
"khungtaskd"
);
return
0
;
}
module_init
(
hung_task_init
);
Back
|
FazBrowse Home
|
New Git URL