Linux soft lockup 和 hard lockup
一. 整体介绍
soft lockup:检测调度异常, 一般是驱动禁止调度或者阻塞比如while(1), 导致无法调度其他线程, 需要注意的是, 应用程序while(1)不会影响其调度, 只要有更高的优先级出现会在时间滴答(10ms)选中并切换进程,
但如果是在驱动也即内核态, 即使有更高优先级时间滴答也不会切换线程, 只不过会在该线程的task->flag 标志 NEED_RESHEDULE, 驱动还是会继续跑, 简单说就是驱动while(1) 会独占CPU 资源, CPU
不会调度到其他进程/线程, 只有中断产生, 才能打断其运行, soft lockup就是根据这个, 利用中断在中断上下文来判断调度是否阻塞了, 怎么判断呢? 先创建一个内核线程(watchdog/xx), 且优先级设置
实时优先级FIFO, 功能就只是更新时间戳到某个变量(watchdog_touch_ts), 这个线程在每一轮调度总能排在前面, 设想如果连这个线程都得不到运行, 其它普通线程还有机会么? 中断函数watchdog_timer_fn()
会读取这个变量watchdog_touch_ts存的时间戳和此时的时间戳, 如果相差大于20秒, 则说明进程阻塞了, 否则说明进程运行正常, 这里需要强调的是超过20秒是指线程watchdog/xx在20秒内都没得到运行,
可能是一个驱动while(1)导致的, 也可能是多个进程阻塞几秒钟, 全部累计时间超过20秒, 甚至是中断函数做一下耗时处理导致的, 总而言之是系统其他总时间超过20秒, 导致watchdog/xx没有被调度, 但这
并不一定意味是有问题的, 假设如果你的系统很变态, 跑了100个应用/进程, 每个耗时0.3秒, 那系统轮询所有的进程需要的时间就是30秒, 产生这个异常很正常, 所以要改这个默认20秒异常时间值, 可以
改成40秒就行了, 当然绝大部分系统20秒足够让进程轮了好多次了~~~
hard lockup:检测中断异常, 一般是禁止中断或者某个中断函数内阻塞, 导致其他中断无法得到执行, 中断是系统得以运行的重要保证, 出了异常系统不可控! 那问题来了, soft lockup是靠中断来监控进程, 那谁来监控
中断那就是NMI(不可屏蔽中断)或者FIQ(一般系统的中断都是IRQ), 总之就是要比普通中断更高级! 具体做法也简单, 上面已经有个中断监控函数watchdog_timer_fn() 里面除了判断soft lockup, 还会对
hrtimer_interrupts进行加1, 不可屏蔽中断watchdog_overflow_callback()会对上一次存放的值hrtimer_interrupts_saved和这次hrtimer_interrupts对比, 如果一样说明定时器中断函数watchdog_timer_fn()没有得到运行!
二. 源码分析
1. soft lockup:

其实就是为每个CPU创建内核线程--watchdog/xx, 里面就只是更新时间戳而已(__touch_watchdog()), 只不过这个线程内核会有个while(1)大循环, 没必要老更新时间戳,
所以多个判断函数 -- watchdog_should_run(), 当然也可以在线程函数改成msleep(4000)也行
如何判断线程调度超时呢?
static int is_softlockup(unsigned long touch_ts) //watchdog_touch_ts
{
unsigned long now = get_timestamp(); if (watchdog_enabled & SOFT_WATCHDOG_ENABLED) {
/* Warn about unreasonable delays. get_softlockup_thresh() = 20秒 */
if (time_after(now, touch_ts + get_softlockup_thresh()))
return now - touch_ts;
}
return ;
}
now就是此刻时间, 参数是线程上次更新后的时间戳值, get_softlockup_thresh() = 20秒, 如果if为true, 说明这个线程已经过了20秒都没更新时间戳, 有问题! 在哪里判断呢? 在定时器中断watchdog_timer_fn()函数中,
这个定时器中断也是每个CPU都有的, 所以也放置在线程的初始化函数内 -- .setup = watchdog_enable(), 同时设置改线程为SCHED_FIFO 实时进程!
static void watchdog_enable(unsigned int cpu)
{
struct hrtimer *hrtimer = raw_cpu_ptr(&watchdog_hrtimer); /* kick off the timer for the hardlockup detector */
hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
hrtimer->function = watchdog_timer_fn; /* Enable the perf event */
watchdog_nmi_enable(cpu); /* done here because hrtimer_start can only pin to smp_processor_id() */
hrtimer_start(hrtimer, ns_to_ktime(sample_period),
HRTIMER_MODE_REL_PINNED); /* initialize timestamp */
watchdog_set_prio(SCHED_FIFO, MAX_RT_PRIO - );
__touch_watchdog();
}
在中断函数中, 每产生一次中断, 判断该线程是否超时了, 超时的话就打印log“BUG: soft lockup - CPU#%d stuck for %us!”。 另外, 线程不是一直在跑, 只有在hrtimer_interrupts更新时候才会跑否则shedule出去, 所以在这更新后要唤醒线程!
static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
{
unsigned long touch_ts = __this_cpu_read(watchdog_touch_ts);
struct pt_regs *regs = get_irq_regs();
int duration;
int softlockup_all_cpu_backtrace = sysctl_softlockup_all_cpu_backtrace; /* kick the hardlockup detector hrtimer_interrupts++ */
watchdog_interrupt_count(); /* kick the softlockup detector */
wake_up_process(__this_cpu_read(softlockup_watchdog)); ...............
duration = is_softlockup(touch_ts);
}
2. hard lockup
hardlockup比较简单, 就是注册一个周期为10秒的不可屏蔽中断函数watchdog_overflow_callback(), 里面判断是否超时:
static int is_hardlockup(void)
{
unsigned long hrint = __this_cpu_read(hrtimer_interrupts); if (__this_cpu_read(hrtimer_interrupts_saved) == hrint)
return ; __this_cpu_write(hrtimer_interrupts_saved, hrint);
return ;
}
由于不可屏蔽中断是10秒产生一次, 而定时器中断每4秒产生一次, 所以hrtimer_interrupts必然不等于hrtimer_interrupts_saved, 且将hrtimer_interrupts赋值到hrtimer_interrupts_saved进行更新,
如果哪次相等, 说明这10秒钟内该定时器中断都没有被执行! 从而打印"Watchdog detected hard LOCKUP on cpu %d"
当然触发后是警告式打印还是panic挂死系统取决用户的配置! 毕竟前面我说了, 有可能触发是正常现象, 如果是正常现象用户应该更改超时时间阈值, 不过我习惯panic(), 早发现早解决!
三、测试代码
softlockup测试用例, 如果针对SMP, 可以多创建几个线程以及绑定CPU
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/delay.h>
#include <linux/kthread.h> int test_thread0(void *data)
{
int cnt=; printk("I will block CPU0\n");
msleep();
printk("block CPU0\n");
while(){
mdelay();
printk("[CPU%d]block CPU %ds\n", raw_smp_processor_id(), ++cnt);
} } static int test_init(void)
{
struct task_struct *test_task0; printk("Vedic init.....\n"); test_task0 = kthread_create(test_thread0, NULL, "test_thread0");
if(IS_ERR(test_task0)) {
printk("test_task0 fail\n");
return ;
}
kthread_bind(test_task0, );
wake_up_process(test_task0); return ;
} static void test_exit(void)
{
printk("Vedic exit......\n");
} module_init(test_init);
module_exit(test_exit); MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Vedic <FZKmxcz@163.com>");
四、 其他
a. 上面的测试用例我在单核上出现softlockup panic, 但双核却没有, 甚至我开两个线程分别绑定CPU0/CPU1都正常运行, 怀疑跟系统的负载均衡有关, 即线程绑定某个CPU不会一直就在该CPU上运行的!
b. 无论是soft还是hard触发打印当前的线程, 都不能判定就是凶手, 只能说系统有问题, 需要进一步排查。
c. hard lockup依赖处理器有没有NIM中断, 没有的话无法实现
Linux soft lockup 和 hard lockup的更多相关文章
- soft lockup和hard lockup介绍
转自:http://www.cnblogs.com/openix/p/4034530.html 转自:http://blog.csdn.net/panzhenjie/article/details/1 ...
- 内核如何检测SOFT LOCKUP与HARD LOCKUP?
内核如何检测SOFT LOCKUP与HARD LOCKUP? From article 所谓lockup,是指某段内核代码占着CPU不放.Lockup严重的情况下会导致整个系统失去响应.Lockup有 ...
- Linux soft lockup分析
关键词:watchdog.soft lockup.percpu thread.lockdep等. 近日遇到一个soft lockup问题,打印类似“[ 56.032356] NMI watchdog: ...
- linux soft
1.gdebi:可以使用gdebi来安装deb包,默认的deb安装使用的dpkg,dpkg 安装的缺点就是不解决包依赖关系 sudo apt-get install gdebi 当然也可以通过命令,使 ...
- CentOS7运行报错kernel:NMI watchdog: BUG: soft lockup - CPU#0 stuck for 26s
CentOS内核,对应的文件是/proc/sys/kernel/watchdog_thresh.CentOS内核和标准内核还有一个地方不一样,就是处理CPU占用时间过长的函数,CentOS下是watc ...
- 报错kernel:NMI watchdog: BUG: soft lockup - CPU#0 stuck for 26s
近期在服务器跑大量高负载程序,造成cpu soft lockup.如果确认不是软件的问题. 解决办法: #追加到配置文件中 echo 30 > /proc/sys/kernel/watchdog ...
- Linux网络驱动--snull
snull是<Linux Device Drivers>中的一个网络驱动的例子.这里引用这个例子学习Linux网络驱动. 因为snull的源码,网上已经更新到适合最新内核,而我自己用的还是 ...
- linux scp
scp是 secure copy的缩写, scp是linux系统下基于ssh登陆进行安全的远程文件拷贝命令.linux的scp命令可以在linux服务器之间复制文件和目录. scp命令的用处: scp ...
- Ubuntu Linux系统三种方法添加本地软件库
闲着没事教教大家以Ubuntu Linux系统三种方法添加本地软件库,ubuntu Linux使用本地软件包作为安装源——转2007-04-26 19:47新手重新系统的概率很高,每次重装系统后都要经 ...
随机推荐
- xadmin下设置“use_bootswatch = True”无效解决方法
from xadmin import viewsimport xadmin class BaseSetting(object): enable_themes=True use_bootswatch=T ...
- Cordova页面加载外网图片失败,Refused to load the image
原文:Cordova页面加载外网图片失败,Refused to load the image 1.使用Cordova页面加载外网图片失败,抛出异常 Refused to load the image ...
- Win10《芒果TV》商店版2016-2017春节大礼,每日前100名用户免费领取7天VIP
告别2016,喜迎2017,鸡年大吉,春节期间,每天登录Win10<芒果TV>商店版的前100位用户可领取一张芒果TV会员7天体验卡,先到先得. 芒果TV会员权益: 1.全站免广告 2.自 ...
- Win10《芒果TV》商店版更新v3.2.0:全新播放体验,跟着爸爸,想去哪就去哪
喜迎十一月黑五大促,跟着爸爸,想去哪就去哪,<芒果TV>UWP版迅速更新v3.2.0版,全新播放页华丽蜕变,新增互动评论.猜你喜欢.宽窄屏适配.多窗体模式切换. 芒果TV UWP V3.2 ...
- SQL Server根据字段查询不出记录
今天写了一条select语句,很奇怪的一件事,我写程序几年了,第一次碰到这个问题,就是数据库里有这个值,你根据这个值查询就是查询不出来这行记录. 所以我想是不是里面有空格,回车什么的,最后果然如此. ...
- RedHat 7.3 修改ASM磁盘绑定路径
RedHat 7中,很多命令发生了改变,绑定磁盘不再是start_udev,而是udevadm,具体绑定方式,请看另一篇博文: http://www.cnblogs.com/zx3212/p/6757 ...
- UWP入门(五)--控件模板
原文:UWP入门(五)--控件模板 通过在 XAML 框架中创建控件模板,你可以自定义控件的可视结构和可视行为(eg:勾选框的三种状态). 控件有多个属性,如 Background.Foregroun ...
- 【Windows10 IoT开发系列】“Hello,World!”指导
原文:[Windows10 IoT开发系列]"Hello,World!"指导 本文主要是介绍使用C#来开发一个可以运行在Raspberry Pi2上的一个基本项目. 1.在启动V ...
- uwp之拍照(使用后置摄像头)
参考:wp8.1之拍照(获取焦点,使用后置摄像头) uwp开启摄像头要借助CaptureElement呈现来自捕获设备(如照相机或网络摄像机)的流.今天讲讲如何打开摄像头,获取焦点,以及拍照.废话不多 ...
- 解决xp越来越慢的办法(其中有些自动备份的功能)
1.减少磁盘空间占用2.终止不常用的系统服务3.安全问题4.另外一些技巧 首先问一下,你是不是很想激活XP,不...准确的说你是不是想在ms的站上能够升级.如果答案是肯定的话,那我们就先来探讨一下安装 ...