【问题标题】:Linux soft lockup in multi-core with realtime task具有实时任务的多核 Linux 软锁定
【发布时间】:2016-06-06 05:49:34
【问题描述】:

我不确定这是否是Linux内核错误,我搜索了很多文档但找不到任何提示。 我问这个问题是为了检查是否有人遇到过类似的问题以及如何解决这个问题。

Environment: 
Linux Kernel: 2.6.34.10 
CPU: MIPS 64 (total 8 cores)
application running in user space`

应用程序有严格的响应时间要求,所以应用程序线程被设置在 SCHED_FIFO 中,并且一些关键线程与专用 CPU 内核亲和,在这种情况下一切正常。后来有人发现在某些 CPU 内核中有时会出现 CPU 峰值(例如短峰值的 60%-80%)。为了解决这个问题,为 Linux 原生应用保留 CPU 0 和 CPU 7,并通过在引导行中添加“isolcpus=1-6”为我们的应用隔离 CPU 1-6,解决了 CPU 峰值问题,但它导致了以下问题.

在运行一段时间和系统挂起后,以下消息将在控制台中打印,但并非总是如此,而是偶尔出现。 (它可能发生在多个 CPU 内核中)

BUG: soft lockup - CPU#4 stuck for 61s! [swapper:0]
Modules linked in: hdml softdog cmt cmm pio clock linux_kernel_bde  linux_uk_proxy linux_bcm_core mpt2sas
Cpu 4
$ 0   : 0000000000000000 ffffffffc3600020 ffffffffc1000b00 c0000001006f0010
$ 4   : 0000000000000001 0000000000000001 000000005410f8e0 ffffffffbfff00fe
$ 8   : 000000000000001e ffffffffc15b3c80 0000000000000002 0d0d0d0d0d0d0d0d
$12   : 0000000000000000 000000004000f800 0000000000000000 c000000100768000
$16   : ffffffffc36108e0 0000000000000010 ffffffffc35f0000 0000000000000000
$20   : 0000000000000000 0000000000000000 0000000000000000 0000000000000000
$24   : 0000000000000007 ffffffffc103b3a0                                  
$28   : c0000001006f0000 c0000001006f3e38 0000000000000000 ffffffffc103d774
Hi    : 0000000000000000
Lo    : 003d0980b38a5000
epc   : ffffffffc1000b20 r4k_wait+0x20/0x40
    Not tainted
ra    : ffffffffc103d774 cpu_idle+0xbc/0xc8
Status: 5410f8e3    KX SX UX KERNEL EXL IE 
Cause : 40808000

查看回调跟踪,线程总是挂起条件变量等待,伪等待/信号函数如下

int xxx_ipc_wait(int target)    
{
struct timespec to;

.... /* other code */
clock_gettime(CLOCK_MONOTONIC, &to);
timespec_add_ns(&to, 1000000);
pthread_mutex_lock(&ipc_queue_mutex[target]);
ret = pthread_cond_timedwait (&ipc_queue_cond[target], &ipc_queue_mutex[target], &to);
pthread_mutex_unlock(&ipc_queue_mutex[target]);

return ret;
}

void xxx_ipc_signal_atonce(int target)
{
... 
pthread_mutex_lock(&ipc_queue_mutex[target]);
pthread_cond_signal(&ipc_queue_cond[target]);
pthread_mutex_unlock(&ipc_queue_mutex[target]);
}

这些等待无论如何都应该唤醒,因为它是超时条件变量。甚至创建了一个专用的 Linux 线程来及时通知这些条件变量,例如每 5 秒,问题仍然存在。

用“dmesg”检查内核日志,没有发现任何有价值的日志。开启内核调试,查看内核日志/proc/sched_debug,出现如下奇怪信息。

cpu#1   /* it is a normal CPU core */
  .nr_running                    : 1
  .load                          : 0
  .nr_switches                   : 1892378
  .nr_load_updates               : 167378
  .nr_uninterruptible            : 0
  .next_balance                  : 4295.060682
  .curr->pid                     : 235  /* it point to the runnable tasks */
            task   PID         tree-key  switches  prio     exec-runtime         sum-exec        sum-sleep
----------------------------------------------------------------------------------------------------------
R         aaTask   235         0.000000       157    49                0               0         

cpu#4
  .nr_running                    : 1  /* okay */
  .load                          : 0
  .nr_switches                   : 2120455  /* this value changes from time to time */
  .nr_load_updates               : 185729
  .nr_uninterruptible            : 0
  .next_balance                  : 4295.076207
  .curr->pid                     : 0   /* why this is ZERO since it has runable task */
  .clock                         : 746624.000000
  .cpu_load[0]                   : 0
  .cpu_load[1]                   : 0
  .cpu_load[2]                   : 0
  .cpu_load[3]                   : 0
  .cpu_load[4]                   : 0
cfs_rq[4]:/
  .exec_clock                    : 0.000000
  .MIN_vruntime                  : 0.000001
  .min_vruntime                  : 14.951424
  .max_vruntime                  : 0.000001
  .spread                        : 0.000000
  .spread0                       : -6833.777140
  .nr_running                    : 0
  .load                          : 0
  .nr_spread_over                : 0
  .shares                        : 0
 rt_rq[4]:/
  .rt_nr_running                 : 1
  .rt_throttled                  : 1
  .rt_time                       : 900.000000
  .rt_runtime                    : 897.915785

runnable tasks:
            task   PID         tree-key  switches  prio     exec-runtime         sum-exec        sum-sleep
----------------------------------------------------------------------------------------------------------
       bbbb_appl   299         6.664495   1059441    49               0               0               0.000000               0.000000               0.000000 /

我不知道Linux系统为什么会这样,最后我把任务优先级从SCHED_FIFO改为SCHED_OTHER,运行几个月后就没有出现这个问题了。由于 CPU 内核是隔离的,因此 SCHED_FIFO 和 SCHED_OTHER 之间的系统行为相似,因此 SCHED_OTHER 使用更广泛。

【问题讨论】:

    标签: c linux multithreading scheduling


    【解决方案1】:

    应用程序永远等待条件/互斥锁可能是优先级反转的标志,除非它使用启用优先级继承的同步原语。

    在 FIFO 实时调度模式中,线程拥有 CPU,直到它自愿放弃它。这与大多数软件所针对的抢先式多任务处理完全不同。

    除非您的软件在配置要求中明确包含 REALTIME_FIFO,否则我不会花时间而是坚持使用 RR 和/或 CPU 固定/隔离。

    【讨论】:

    • 本产品源于嵌入式RTOS,所以一开始就设置为实时。我完全同意你的观点,通过 CPU 隔离和关联/固定,我们的测试还表明应用程序不会被其他任务中断并且响应时间被提交。
    • 我在答案中添加了 PI 段落。在同步不同优先级的线程时,您能否确认您的应用是否使用了启用 PI 的同步?
    • 实际上只有一个运行在CPU核心上的应用程序线程卡住了,而每个CPU核心上都有一些内核线程运行,即使它是隔离的,例如文件系统线程。令我困惑的是,根据日志,CPU core 4 中有可用的可运行线程(这里我认为可运行意味着它没有挂起,它已被唤醒),但为什么 .curr->pid 为 0?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-09
    • 1970-01-01
    • 1970-01-01
    • 2014-03-19
    相关资源
    最近更新 更多