具有实时任务的多核中的c-Linux软锁定



我不确定这是否是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

查看回调跟踪,线程总是挂起条件变量wait,伪wait/signal函数如下

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/scheddebug时,会出现如下奇怪的信息。

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_OHER的使用更为广泛。

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

在FIFO实时调度模式中,线程拥有CPU,直到它自愿放弃。这与大多数软件编写的抢占式多任务处理截然不同。

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

最新更新