Debian 9 中的时钟不稳定(延伸)

Debian 9 中的时钟不稳定(延伸)

我有一台运行 Debian 8 (jessie) 的机器,降级到内核 3.2-rt。这是运行一个设置为实时优先级 (SCHED_RR) 的应用程序,每 1ms 唤醒一次以进行一些处理,并且每 100ms 向另一台 PC 发送一条串行消息。这非常有效。 (除了默认服务之外,该机器实际上并不运行任何其他东西;特别是它不是台式机。)

当尝试将其升级到内核为 4.9-rt 的 Debian 9(stretch)时,我遇到了相当多的问题;最大的问题之一是时钟稳定性。虽然最初似乎运行正常,但启动后不久我得到了这个:

clocksource: timekeeping watchdog on CPU0: Marking clocksource 'tsc' as unstable because the skew is too large:
clocksource:                       'acpi_pm' wd_now: 74c6dd wd_last: 8dd916 mask: ffffff
clocksource:                       'tsc' cs_now: 119ac91c7b1 cs_last: 1158a25441d mask: ffffffffffffffff
clocksource: Switched to clocksource acpi_pm

第一次发生这种情况时,上述消息报告切换到“hpet”;发生此切换后,机器上的所有计时似乎都不稳定 - 代码用于clock_gettime(CLOCK_MONOTONIC, ...)计时,并且报告它现在每 4 毫秒而不是每 1 毫秒醒来,串行消息实际上是每 200 毫秒而不是每100 毫秒,但串行消息内的时间戳表明它认为每 66 毫秒发送一次。 (其中一些可能正在计算唤醒滴答声而不是实际的毫秒数。)

我尝试在 BIOS 中禁用 HPET,这导致了上面显示的错误,并且它在启动时再次运行正常,直到记录上述内容,此时虽然它看起来大部分运行正常,但有时一些计时器报告负持续时间。

另一个主要问题是,每 1 毫秒运行一次的处理代码在 Jessie 中运行大约需要 200us,但在 Stretch 中运行需要 900us,没有明显的原因。我尝试运行perf record它,它报告大部分时间(40% 的样本)都花在sys_clock_gettime.

两种情况下的硬件相同:Supermicro X11SSQ 主板,配备 AMD64 架构的 i7-7700K CPU。 CPU 节流在 BIOS 中被禁用,但它会报告constant_tscnonstop_tsc

可能感兴趣的是应用程序正在执行繁忙等待循环(if clock_gettime() < wakeup then sched_yield()简化的伪代码)来调度处理代码。

作为一个实验,我将其更改为睡眠(clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &wakeup)),至少到目前为止,时钟源错误没有再次发生,并且它仍然使用 tsc 时钟,它似乎工作正常(与其他时钟不同)。

然而,唤醒抖动现在恶化了 10 倍:睡眠时为 700-1200us (SD 36us),而忙等待时为 890-1120us (SD 2us)。

作为进一步的实验,我尝试将其更改为 SCHED_DEADLINE (使用单个sched_yield()),但这与clock_nanosleep 具有相同的行为。

知道为什么这种行为在 Jessie 和 Stretch 之间(或者更有可能在 3.2 和 4.9 之间)发生变化吗?有没有更好的方法来实现低抖动等待而又不会明显破坏系统时钟?

答案1

/etc/default/grub GRUB_CMDLINE_LINUX_DEFAULT 行添加“notsc Clocksource=acpi_pm”

我现在的情况是:

GRUB_CMDLINE_LINUX_DEFAULT="quiet notsc clocksource=acpi_pm"

然后做:sudo update-grub

您可以设置其他可用的时钟源:

cat /sys/devices/system/clocksource/clocksource0/available_clocksource

相关内容