Linux死锁调试之softlockup
2016-05-04 14:41
633 查看
Kernel branch: 3.0.35
概要:
softlockup 主要用于检测内核的进程调度是否正常,当发生softlockup时,内核不能被调度,
但是中断还是可以响应,而hrtimer属于中断的下半部,所以此情况下也可以响应。
原理:
系统在每个cpu上创建一个内核线程,当hrtimer定期执行的回调后会尝试唤醒此线程,如果线程有被正常调度而被唤醒,
它会更新时间变量watchdog_touch_ts,如果没有则不会更新。在hrtimer的回调函数中会判断watchdog_touch_ts和当前
时间差,如果超过给定值,那就证明内核调度失败,接着就打印异常log。
code流程大概:
lockup_detector_init ->
cpu_callback -> //action CPU_UP_PREPARE
watchdog_prepare_cpu -> //hrtimer对应function是watchdog_timer_fn
cpu_callback ->
watchdog_enable ->
kthread_create -> //为每个cpu创建名字叫watchdog/x的thread, x是cpu number,对应function为watchdog().
watchdog ->
sched_priority = MAX_RT_PRIO-1 //设置线程优先级成最高
__touch_watchdog //初始化watchdog_touch_ts为当前时间
hrtimer_start //启动timer,时间周期从get_sample_period(),由watchdog_thresh决定,
除5是在触发hardlockup之前给hrtimer5次机会触发,后面文章会提到hardlockup。
__touch_watchdog //重新更新时间戳。
schedule //睡眠等待设置时间后hrtimer触发
watchdog_timer_fn -> //hrtimer被触发
wake_up_process //唤醒前面休眠的进程
hrtimer_forward_now //重新设置hrtimer
is_softlockup //如果计算时间差超过了最大时间,证明没有进程调度了、
print_modules //打印信息。
dump_stack //打印堆栈信息。
另一方面,watchdog线程会被唤醒,然后执行__touch_watchdog 会重新更新watchdog_touch_ts。
测试例子:
在某个线程里添加如下语句:
preempt_disable();
while(1);
然后过会就会打印如下log:
[ 28.548865] BUG: soft lockup - CPU#1 stuck for 22s! [us kthread:1106]
[ 28.555378] Modules linked in:
[ 28.558566]
[ 28.560173] Pid: 1106, comm: us kthread
[ 28.564951] CPU: 1 Not tainted (3.0.35-00007-g60f7071-dirty #153)
[ 28.571528] PC is at ks103_ultrasonic_thread+0x18/0x1c
[ 28.576750] LR is at kthread+0x80/0x88
[ 28.580566] pc : [<c0357084>] lr : [<c00ab1c8>] psr: 60000013
[ 28.580571] sp : d441bfc8 ip : c08ba7d0 fp : 00000000
[ 28.592249] r10: 00000000 r9 : 00000000 r8 : 00000000
[ 28.597599] r7 : 00000013 r6 : c035706c r5 : 00000000 r4 : d402fe94
[ 28.604202] r3 : d441a000 r2 : 00000001 r1 : d4044560 r0 : 00000000
[ 28.610854] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
[ 28.618287] Control: 10c53c7d Table: 1000404a DAC: 00000015
[ 28.624095]
[ 28.624098] PC: 0xc0357004:
[ 28.628502] 7004 ebffffaa e58d0004 eaffffd7 e59f1034 e59f0040 eb0c4e8a e3a00003 ebffffa3
[ 28.637449] 7024 e59f2034 e59f101c e1a03000 e59f002c e3530000 e58d3004 01a02000 e59f0020
[ 28.646433] 7044 eb0c4e7f eaffffc8 c06a73cc c07e9fdc c07e9ffc c07ea018 c07ea038 c07e9fc4
[ 28.655417] 7064 c07e9fd4 c07ea058 e1a0200d e3c23d7f e3c3303f e5932004 e2822001 e5832004
[ 28.664414] 7084 eafffffe e92d4008 e3a00000 e59f1008 ebfe1658 e3a00000 e8bd8008 c0972128
[ 28.673356] 70a4 e92d4008 e3a00000 e59f100c ebfe2136 e3500000 13e0000f e8bd8008 c0972128
[ 28.682303] 70c4 e3a03001 e3443004 e1510003 e92d4010 e1a04002 0a000007 e3a03002 e3443004
[ 28.691325] 70e4 e1510003 0a000012 e59f00b4 eb0c4e54 e3e00015 e8bd8010 e59f00a8 eb0c6694
参考:
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=14528823&id=4215888
概要:
softlockup 主要用于检测内核的进程调度是否正常,当发生softlockup时,内核不能被调度,
但是中断还是可以响应,而hrtimer属于中断的下半部,所以此情况下也可以响应。
原理:
系统在每个cpu上创建一个内核线程,当hrtimer定期执行的回调后会尝试唤醒此线程,如果线程有被正常调度而被唤醒,
它会更新时间变量watchdog_touch_ts,如果没有则不会更新。在hrtimer的回调函数中会判断watchdog_touch_ts和当前
时间差,如果超过给定值,那就证明内核调度失败,接着就打印异常log。
code流程大概:
lockup_detector_init ->
cpu_callback -> //action CPU_UP_PREPARE
watchdog_prepare_cpu -> //hrtimer对应function是watchdog_timer_fn
cpu_callback ->
watchdog_enable ->
kthread_create -> //为每个cpu创建名字叫watchdog/x的thread, x是cpu number,对应function为watchdog().
watchdog ->
sched_priority = MAX_RT_PRIO-1 //设置线程优先级成最高
__touch_watchdog //初始化watchdog_touch_ts为当前时间
hrtimer_start //启动timer,时间周期从get_sample_period(),由watchdog_thresh决定,
除5是在触发hardlockup之前给hrtimer5次机会触发,后面文章会提到hardlockup。
__touch_watchdog //重新更新时间戳。
schedule //睡眠等待设置时间后hrtimer触发
watchdog_timer_fn -> //hrtimer被触发
wake_up_process //唤醒前面休眠的进程
hrtimer_forward_now //重新设置hrtimer
is_softlockup //如果计算时间差超过了最大时间,证明没有进程调度了、
print_modules //打印信息。
dump_stack //打印堆栈信息。
另一方面,watchdog线程会被唤醒,然后执行__touch_watchdog 会重新更新watchdog_touch_ts。
测试例子:
在某个线程里添加如下语句:
preempt_disable();
while(1);
然后过会就会打印如下log:
[ 28.548865] BUG: soft lockup - CPU#1 stuck for 22s! [us kthread:1106]
[ 28.555378] Modules linked in:
[ 28.558566]
[ 28.560173] Pid: 1106, comm: us kthread
[ 28.564951] CPU: 1 Not tainted (3.0.35-00007-g60f7071-dirty #153)
[ 28.571528] PC is at ks103_ultrasonic_thread+0x18/0x1c
[ 28.576750] LR is at kthread+0x80/0x88
[ 28.580566] pc : [<c0357084>] lr : [<c00ab1c8>] psr: 60000013
[ 28.580571] sp : d441bfc8 ip : c08ba7d0 fp : 00000000
[ 28.592249] r10: 00000000 r9 : 00000000 r8 : 00000000
[ 28.597599] r7 : 00000013 r6 : c035706c r5 : 00000000 r4 : d402fe94
[ 28.604202] r3 : d441a000 r2 : 00000001 r1 : d4044560 r0 : 00000000
[ 28.610854] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
[ 28.618287] Control: 10c53c7d Table: 1000404a DAC: 00000015
[ 28.624095]
[ 28.624098] PC: 0xc0357004:
[ 28.628502] 7004 ebffffaa e58d0004 eaffffd7 e59f1034 e59f0040 eb0c4e8a e3a00003 ebffffa3
[ 28.637449] 7024 e59f2034 e59f101c e1a03000 e59f002c e3530000 e58d3004 01a02000 e59f0020
[ 28.646433] 7044 eb0c4e7f eaffffc8 c06a73cc c07e9fdc c07e9ffc c07ea018 c07ea038 c07e9fc4
[ 28.655417] 7064 c07e9fd4 c07ea058 e1a0200d e3c23d7f e3c3303f e5932004 e2822001 e5832004
[ 28.664414] 7084 eafffffe e92d4008 e3a00000 e59f1008 ebfe1658 e3a00000 e8bd8008 c0972128
[ 28.673356] 70a4 e92d4008 e3a00000 e59f100c ebfe2136 e3500000 13e0000f e8bd8008 c0972128
[ 28.682303] 70c4 e3a03001 e3443004 e1510003 e92d4010 e1a04002 0a000007 e3a03002 e3443004
[ 28.691325] 70e4 e1510003 0a000012 e59f00b4 eb0c4e54 e3e00015 e8bd8010 e59f00a8 eb0c6694
参考:
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=14528823&id=4215888
相关文章推荐
- 小何讲进程: 编写Linux守护进程方法详解
- Centos 6.5 - Red Hat 6.5 时区更改
- vmlinux,vmlinuz,bzimage,zimage,initrd.img的区别与联系
- CentOS系统中把PHP 5.3.x更新到PHP 5.4.x
- 关于linux的动态共享库的设置--/etc/ld.so.conf和/etc/ld.so.cache
- CentOS下将MySQL 5.1升级到MySQL 5.5
- 【已解决】Navicat 远程连接 Linux服务器上的MySQL数据库
- linux ping命令
- Linux实用操作总结
- Linux分区类型EXT2、EXT3、EXT4详解
- 在基于ZedBoard的Linux系统下添加自定义硬件IP(3)——建立交叉编译环境
- 根文件系统(rootfs)梳理
- 深入理解Linux内核day07--内存管理
- linux命令大全(2)
- linux内核kgdb调试
- linux服务器 Zabbix监控部署
- linux 系统无法启动的基本解决方法
- centos install lamp step
- linux指令备忘录
- linux 常用命令总结