目录

lockup

一、watchdog看门狗

二、soft /hard  lockup

1、soft lockup

2、hard lockup

三、kernel's hung task

四、workqueue stall


lockup

        系统(在一个或多个CPU核上)保持在长时间无反应状态。可检测类型有watchdog、soft lockup、hard lockup、 hung task、workqueue stall 等。

一、watchdog看门狗

检测系统的健康状态,有能力重启系统。

CONFIG_SOFT_ WATCHDOG=m

查看内核中看门狗的运行

#ps -e | grep watch
    103 ?        00:00:00 watchdogd

二、soft /hard  lockup

Kernel hacking | Debug Oops, Lockups and Hangs

看门狗的配置

# sysctl -a | grep watchdog
//0:关闭NMI看门狗和硬件lockup检测
kernel.nmi_watchdog = 0
//开启软件lockup检测
kernel.soft_watchdog = 1
//1 开启两者(软/硬)
kernel.watchdog = 1
//
kernel.watchdog_cpumask = 0-127
//硬件lockup 超时,软件lockup 2*10
kernel.watchdog_thresh = 10

1、soft lockup

内核处于紧密的循环中,长时间不让其他任务得到调度

当检测到软锁定时

  • panic (内核配置nmi_watchdog=1;kernel.hardlockup_panic sysctl=1;BOOTPARAM_ SOFTLOCKUP_PANIC=1)
  • 发出大量的警告

测试程序 :自旋spin_(un)lock()

kernel_thread 线程中有如下循环,CPU密集型

        spin_lock(&spinlock);
                while (i < 10000000000) { 
                        i ++;
                        if (!(i%50000000))
                              PRINT_CTX();
                }

        spin_unlock(&spinlock);

检测输出

[  312.261567] watchdog: BUG: soft lockup - CPU#1 stuck for 22s! [lkd/kt_stuck:589]

[  354.256680] kthread_stuck:simple_kthread(): 001) [lkd/kt_stuck]:589   |  .N.0   /* simple_kthread() */
[  354.722453] kthread_stuck:simple_kthread(): 001) [lkd/kt_stuck]:589   |  .N.0   /* simple_kthread() */

2、hard lockup

在内核模式下运行的CPU内核仍处于紧密循环状态,不允许其他硬件中断运行;

系统检测到硬锁时

  • panic (内核配置nmi_watchdog=1;kernel.hardlockup_panic sysctl=1;BOOTPARAM_ SOFTLOCKUP_PANIC=1)
  • 发出大量的警告

内核配置

1、硬锁定只能由NMI,在本机x86_64上检测到;

2、必须启用NMI和NMI看门狗 nmi_ watchdog=1

3、CONFIG_RCU_CPU_STALL_TIMEOUT 值的范围 (3~300)在此时间内一定能检测到

4、CONFIG_RCU_STALL_COMMON=y

测试程序 自旋转IRQs、禁止抢占 spin_(un)lock_irq()

kernel_thread 线程中有如下循环,CPU密集型

        spin_lock_irq(&spinlock);
                while (i < 10000000000) { 
                        i ++;
                        if (!(i%50000000))
                              PRINT_CTX();
                }

        spin_unlock_irq(&spinlock);

检测输出

[ 4557.452812] rcu: INFO: rcu_sched detected stalls on CPUs/tasks:
[ 4557.454426] rcu: 	1-...0: (1 ticks this GP) idle=43e/1/0x4000000000000000 softirq=6242/6242 fqs=2599 
[ 4557.455684] rcu: 	(detected by 2, t=5252 jiffies, g=13033, q=119)
[ 4557.457412] Task dump for CPU 1:
[ 4557.458131] lkd/kt_stuck    R  running task        0   793      2 0x0000002a
[ 4557.459379] Call trace:
[ 4557.460526]  __switch_to+0xd0c/0xd44
[ 4557.461157]  logbuf_lock+0x0/0x4
[ 4557.464316] kthread_stuck:simple_kthread(): 001) [lkd/kt_stuck]:793   |  dN.0   /* simple_kthread() */

三、kernel's hung task

内核设置

        Kernel hacking | Debug Oops, Lockups and Hangs | Detect Hung Tasks

        配置见图二

参数解析

# sudo sysctl -a|grep hung_task
//如果设置1 则内核给所有核发送NMI中断,触发堆栈追溯
kernel.hung_task_all_cpu_backtrace = 0
//检测任务数的上线
kernel.hung_task_check_count = 4194304
//0 意味着挂起任务的值是kernel.hung_task_timeout_secs
kernel.hung_task_check_interval_secs = 0
//1:kernel panix  0:任务维持挂起状态
kernel.hung_task_panic = 0
//设置0 则禁止检测
kernel.hung_task_timeout_secs = 120
//报告的最大经过数
kernel.hung_task_warnings = 10

四、workqueue stall

内核设置

        Kernel hacking | Debug Oops, Lockups and Hangs | Detect Workqueue Stalls

        配置见图二

参数解析

        检测时间workqueue.watchdog_thresh  默认30秒,设置0 禁止检测

测试例子:在workqueue回调函数中,添加CPU密集型函数

static void work_func(struct work_struct *work)
{
        struct st_ctx *priv = container_of(work, struct st_ctx, work);
        u64 i = 0;
        PRINT_CTX();
        //CPU密集型执行
        while (1)
                i += 3;
}

static int __init workq_simple_init(void)
{
        ctx.data = INITIAL_VALUE;
        //初始化workqueue
        INIT_WORK(&ctx.work, work_func);
        return 0; 
}

测试输出

[  580.742603] BUG: workqueue lockup - pool cpus=1 node=0 flags=0x0 nice=0 stuck for 73s!
[  529.474102] rcu: INFO: rcu_sched self-detected stall on CPU
[  529.474499] rcu: 	1-....: (20464 ticks this GP) idle=fc6/1/0x4000000000000002 softirq=4407/4408 fqs=9074

Logo

更多推荐