Linux内核SoftLockUp机制解析

嵌入式技术

1372人已加入

描述

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是否有更新来检测中断是否有异常占用.

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分