watchdog阅读记录

watchdog


总结 watchdog的代码,大概是几个关键变量和两个关键任务:

  • 定时器任务更新定时器中断数
  • 定期器任务唤醒每CPU线程,每CPU线程进行软中断数更新以及时间戳更新
  • 定时器任务中根据时间戳判断是否进入软锁,软锁时打印相关信息

在这里插入图片描述

所以陷入soft lockuop的情况直接表现就是每CPU的watchdog_touch_ts时间戳长时间没有被更新,更新这个时间戳的是在每CPU线程watchdog里面执行的,每CPU线程watchdog是由hrtimer定时器的工作任务watchdog_timer_fn唤醒,也就是说出现soft lockuop应该是由上面几个阶段条件触发导致的:

  • 每CPU线程watchdog得不到唤醒
  • 工作任务watchdog_timer_fn得不到执行

定时器中断任务优先级高于内核线程优先级。如果是NMI中断,NMI中断优先级高于定时器中断优先级。

关于第一个条件,每CPU线程watchdogSCHED_FIFO调度策略,优先级为最高的99,利用chrt命令或者看内核代码一样可以看到相关的信息:

在这里插入图片描述

如果当前这个线程得不到调度,有可能是在一些不可抢占的上下文中占用了CPU,比如:

  • 某些内核线程死循环?
  • 软中断占用CPU时间过长?
  • 过量的耗时timer任务?
  • 关中断调度的自旋锁?

当前内核配置抢占是没有开启的:

# CONFIG_PREEMPT is not set

发现看了代码出现问题时也不一定能很快排查到,实际还是需要多复现结合实际的情况去排查,待问题解决的话看看能不能写一篇解决过程的吧。

lockup检测的初始化

初始化流程:

start_kernel()
 -> rest_init()
  -> kernel_init()
   -> kernel_init_freeable()
    -> lockup_detector_init()
     

lockup_detector_init()是看门狗初始化的入口,设置高精度定时器的定时时间后,在所有的CPU上使能看门狗。

在这里插入图片描述

转换watchdog_thresh时间为ns级别的:

在这里插入图片描述

设置soft lockup的超时时间是hard lockup的两倍,注释解释说是soft lockup出现的情况比较极端:

在这里插入图片描述

默认的watchdog_thresh时间是10

在这里插入图片描述

高精度定时器的初始化

在初始化过程中,为每一个CPU上都创建一个线程:

在这里插入图片描述

这个结构体里面,数据没有CPU私有,函数共享,私有的数据指向的是文件开头静态定义的每CPU变量softlockup_watchdog

在这里插入图片描述

smpboot_thread_fn()函数中,会先调用setup回调,即watchdog_enable()函数,初始化一个高精度定时器,设置工作任务为watchdog_timer_fn()函数。

在这里插入图片描述

watchdog_nmi_enable()为弱定义,本代码配置中没有配置CONFIG_HARDLOCKUP_DETECTOR,所有没有走/kernel/watchdog_hld.c里面的函数。

在这里插入图片描述

修改当前线程的优先级和调度策略:(这个进程应该是通过smpboot_register_percpu_thread_cpumask()注册的每一个CPU的进程)

在这里插入图片描述

__touch_watchdog()记录时间戳到本地CPU的变量上:

在这里插入图片描述

高精度定时器任务

函数第一部分获取本CPU看门狗线程上次更新的时间戳,更新本地的hrtimer_interrupts数目,唤醒本CPU的看门狗线程去更新时间戳和高精度定时器的中断数。

在这里插入图片描述

调用watchdog_interrupt_count()更新本地CPU的hrtimer_interrupts中断数:

在这里插入图片描述

第二部分检查是否陷入了soft lockup的过程,如果陷入了soft lockup,判断是否以及被警告过了,如果被警告过了,如果当前进程与保存的进程信息不一致,设置为未被警告,更新看门狗时间。

在这里插入图片描述

判断是否陷入soft lockup的函数是根据当前时间戳和上一次看门狗线程更新的时间戳进行比较来判断的:

在这里插入图片描述

第三部分是打印soft lockup相关的信息,比如当前CPU、进程信息、模块信息、寄存器信息等,如果设置了panic,打印panic信息。

在这里插入图片描述

看门狗线程的初始化

smpboot_thread_fn()函数中,会调用thread_should_run()去判断条件是否满足,满足时执行thread_fn回调函数:

在这里插入图片描述

在这个看门狗中,当本地 CPU 记录的高精度定时器的值与看门狗线程写入的值不相等时视为条件满足,smpboot_thread_fn()函数应该就会执行watchdog()函数。

在这里插入图片描述

看门狗线程的任务

看门狗线程主要是更新高精度定时器的中断数到本地CPU,并更新本地CPU的记录的时间戳:

在这里插入图片描述

sysctl控制参数

/proc/sys/kernel下,有控制watchdog相关的参数,比如watchdog_threshsoftlockup_panic等,在代码中也有表现。

几个sysctl控制参数:

在这里插入图片描述

更新watchdog_thresh周期:

在这里插入图片描述

更新CPU掩码,使能或禁止某些CPU上的看门狗线程:

在这里插入图片描述

proc_watchdog_common()函数如下:

在这里插入图片描述

在这里插入图片描述

使能或者禁止看门狗:

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值