softlock_up以及时钟中断问题记录

一. 背景介绍:

softlock_up:
内核开关, 打开之后可以检测软锁。软锁发生之后, 当cpu在设定的时间间隔中没有发生时间中断的话, 该机制就会发送一个nmi中断, 让系统重启。该机制用看门狗机制实现。
nohz_full:
内核开关, 用于消除某个cpu上的时钟中断, 可以在uboot的cmdline里指定想要关闭时钟中断的cpu核心序号。该功能主要应用于一些对时间性能很敏感的系统, 因为任务切换会伴随着时钟中断, 其中的上下文切换会对任务的性能和实时性产生影响, 若应用需要强性能和强实时性, 最好的情况是一个任务独占一个cpu, 不做任何时间片切换。
一般该内核开关会伴随着核隔离使用, 下面是一个例子:

setenv bootargs '... isolcpus=5-7 nohz_full=5-7 rw'

arch_timer:
系统时钟

二. 问题描述

在一个需求中, dpdk需要在nohz_full和核隔离的情况使用。但是发现在4.19内核上打开了softlock_up和nohz_full隔离5~7号cpu。然而发现当两个内核开关打开的时候, 5 ~ 7号cpu依旧有来自于arch_timer的系统时钟。
使用cat /proc/interrupts | grep arch_timer命令可以发现该中断在cpu 5 ~ 7 上增加。
但是根据内核文档[3], 发现该现象是和该模块设计思路相悖的, 于是开始调查。

默认情况下所有在线cpu上都会运行一个watchdog线程。不过在内核配置了”NO_HZ_FULL“的
情况下watchdog线程默认只会运行在管家(housekeeping)cpu上,而”nohz_full“启动参数指
定的cpu上则不会有watchdog线程运行。试想,如果我们允许watchdog线程在”nohz_full“指
定的cpu上运行,这些cpu上必须得运行时钟定时器来激发watchdog线程调度;这样一来就会
使”nohz_full“保护用户程序免受内核干扰的功能失效。当然,副作用就是”nohz_full“指定
的cpu即使在内核产生了lockup问题我们也无法检测到。不过,至少我们可以允许watchdog
线程在管家(non-tickless)核上继续运行以便我们能继续正常的监测这些cpus上的lockups
事件。

三. 调查

首先调查softlock_up相关代码, 发现具体实现在 kernel/watchdog.c里, 其中开启softlock_up的watchdog入口函数为static void watchdog_enable(unsigned int cpu), 在同一个c文件里搜索其调用, 发现两处调用,
以下是整理的两条调用链,
①:
kernel_init

kernel_init_freeable

lockup_detector_init watchdog.c

lockup_detector_setup

lockup_detector_reconfigure

softlockup_start_all

softlockup_start_fn

watchdog_enable

②:
lockup_detector_online_cpu

watchdog_enable

查看watchdog_enable的①②上一级调用函数softlockup_start_alllockup_detector_online_cpu:

static void softlockup_start_all(void)
{
	int cpu;

	cpumask_copy(&watchdog_allowed_mask, &watchdog_cpumask);
	for_each_cpu(cpu, &watchdog_allowed_mask)
		smp_call_on_cpu(cpu, softlockup_start_fn, NULL, false);
}
int lockup_detector_online_cpu(unsigned int cpu)
{
	watchdog_enable(cpu);
	return 0;
}

发现①是用了cpu mask的, ②是没有使用cpu mask的。
在两处添加打印, 发现softlockup_start_all在0~4号cpu上放置watchdog, 而lockup_detector_online_cpu在0 ~ 7上都放置了watchdog。所以第二个应该是和该模块设计思路不符合的, 应该是内的一个纰漏。
查看5.15内核版本, 发现该问题已经被修复, 5.15版本lockup_detector_online_cpu函数为:

int lockup_detector_online_cpu(unsigned int cpu)
{
	if (cpumask_test_cpu(cpu, &watchdog_allowed_mask))
		watchdog_enable(cpu);
	return 0;
}

已经使用了cpu mask。
将该函数放在4.19内核上, 问题修复。

再来分析一下为什么watchdog会影响NOHZ_FULL机制

static void tick_sched_handle(struct tick_sched *ts, struct pt_regs *regs)
{
#ifdef CONFIG_NO_HZ_COMMON
	/*
	 * When we are idle and the tick is stopped, we have to touch
	 * the watchdog as we might not schedule for a really long
	 * time. This happens on complete idle SMP systems while
	 * waiting on the login prompt. We also increment the "start of
	 * idle" jiffy stamp so the idle accounting adjustment we do
	 * when we go busy again does not account too much ticks.
	 */
	if (ts->tick_stopped) {
		touch_softlockup_watchdog_sched();

...
}
			

从代码中可以看到, 当打开了NO_HZ_COMMON开关(NOHZ_FULL相关), 当发现该cpu是idle状态下, 且watchdog打开了的话, 必须调用touch_softlockup_watchdog_sched();函数告诉softlockup_watchdog我没有问题, 不需要对系统进行修正。
下面是touch_softlockup_watchdog_sched()的代码, 从注释中也可以看出该代码的用处:

/**
 * touch_softlockup_watchdog_sched - touch watchdog on scheduler stalls
 *
 * Call when the scheduler may have stalled for legitimate reasons
 * preventing the watchdog task from executing - e.g. the scheduler
 * entering idle state.  This should only be used for scheduler events.
 * Use touch_softlockup_watchdog() for everything else.
 */
notrace void touch_softlockup_watchdog_sched(void)
{
	/*
	 * Preemption can be enabled.  It doesn't matter which CPU's watchdog
	 * report period gets restarted here, so use the raw_ operation.
	 */
	raw_cpu_write(watchdog_report_ts, SOFTLOCKUP_DELAY_REPORT);
}

因此, 开了watchdog的cpu得接受arch_timer发过来的中断, 因为得定期通知softlock_up_watchdog.

四. 参考:

内核文档:
[1] Linux NO_HZ_FULL NO_HZ 框架实现分析
[2] (Nearly) full tickless operation in 3.10
[3]内核代码文档:Documentation/translations/zh_CN/admin-guide/lockup-watchdogs.rst
[4] linux 内核Lockup机制浅析

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值