嵌入式技术
Linux内核softlockup机制介绍
与hardlockup机制类似, softlockup也是在watchdog框架下关注于某个task一直处于内核态而不给其它task运行机会的一种debug机制.具体的超时判断时间一般为20S,也可以通过sysctrl 来进行修改.
当触发softlockup机制时内核会打印当前堆栈信息,如果有配置panic,则会触发panic. 同样可以通过sysctrl来动态配置,也可以通过CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC进行编译时配置打开.
softlockup机制实现基础
a) watchdog的内核框架
b) 高精度timer框架
softlockup实现原理以及框架
softlockup实现机制
softlockup实现源代码解析
在Linux内核HardLockUp机制解析中我们已经介绍过了watchdog_hrtimer的启动过程, 我们这里再主要解析一下hrtimer的成员function函数watchdog_timer_fn, 当watchdog_timer_fn的返回为HRTIMER_RESTART时,该hrtimer 会以hrtimer_start 的第二个参数的间隔再次触发.下来我们直接分析watchdog_timer_fn源代码是如何检测softlockup的
//kernel/watchdog.c
static DEFINE_PER_CPU(unsigned long, watchdog_touch_ts);
static DEFINE_PER_CPU(bool, soft_watchdog_warn);
static DEFINE_PER_CPU(struct task_struct *, softlockup_task_ptr_saved);
//hrtimer的callback函数.如果返回HRTIMER_RESTART,则会固定周期重复触发执行
static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
{
//每个核都有一份独一无二的watchdog_touch_ts
unsigned long touch_ts = __this_cpu_read(watchdog_touch_ts);
...
//duration如果不为0,则表示触发了,druation为超时时间,我们稍后分析is_softlockup源码
duration = is_softlockup(touch_ts);
if (unlikely(duration)) {
...//我们在这抛开kvm等其它虚拟机case
/* only warn once 多个processes 引起额softlockup只处处一次 */
if (__this_cpu_read(soft_watchdog_warn) == true)
{
// 判断改core上本次触发的task(即current)与上次在该核上触发的是否为同一个task
// 如果不是同一个,则重置soft_watchdog_warn 然后更新 watchdog_touch_ts
if (__this_cpu_read(softlockup_task_ptr_saved) !=current)
{
__this_cpu_write(soft_watchdog_warn, false);
__touch_watchdog();//更新watchdog_touch_ts
}
return HRTIMER_RESTART;
}
...//如果一个cpu核已经在dump backtrace了,防止多个softlockup报告生成,需要通过sysctrl打开
//印我们需要的各种异常信息.
pr_emerg("BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\\n",
smp_processor_id(), duration,
current- >comm, task_pid_nr(current));
__this_cpu_write(softlockup_task_ptr_saved, current);
print_modules();
print_irqtrace_events(current);
if (regs)
show_regs(regs);
else
dump_stack();
...
if (softlockup_panic) //如果打开kernel panic, 则触发kernel panic
panic("softlockup: hung tasks");
...
}else{
//如果没有连续触发警告标志置为false
__this_cpu_write(soft_watchdog_warn, false);
}
return HRTIMER_RESTART;
}
上述我们看到判断是否超时的关键函数is_softlockup, 下面我们来详解一下
//kernel/watchdog.c
static int is_softlockup(unsigned long touch_ts)
{
unsigned long now = get_timestamp();
if ((watchdog_enabled & SOFT_WATCHDOG_ENABLED) && watchdog_thresh){
/* Warn about unreasonable delays. */
//判断当前时间是否在上次watchdog_touch_ts更新之后的时间+watchdog_thresh * 2之后默认20s
if (time_after(now, touch_ts + get_softlockup_thresh()))
return now - touch_ts; //返回超时时间.
}
return 0;
}
所以重点就是watchdog_touch_ts的时间,这个就是在调度器切换时会call touch_softlockup_watchdog_sched进行更新的, 关于调度器更新的时机我们在后面分析task_struct的调度切换时再做介绍. 上述就是softlockup机制的检测过程.
总结
通过源码分析我们知道了, softlockup是关注于某个task_struct是否有hung的问题而hardlockup关注的是某个中断是否正常的问题.
两者都有用到相同的hrtimer, softlockup在这个timer中断中检测是否有发过task的切换, 而hardlockup 则在该hrtimer中更新中断次数, PerfEvent中使用的不可中断(NMI)中断定时触发来进行检测hrtimer是否有更新来检测中断是否有异常占用.
全部0条评论
快来发表一下你的评论吧 !