0

我给 linux 内核打了 4.14.103-rt55 preempt-rt 补丁。并通过设置 Y 启用 lockdep

CONFIG_UNINLINE_SPIN_UNLOCK=y
CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_PROVE_LOCKING=y
CONFIG_LOCKDEP=y
CONFIG_PROVE_RCU=y

而且我收到了带有不一致锁定统计信息的 lockdep 警告:

================================
警告:不一致的锁定状态
4.14.98-rt55 #1 污染:GS\

不一致的 {HARDIRQ-ON-W} -> {IN-HARDIRQ-W} 用法。
cpuhp/0/17 [HC1 1 :SC0[0]:HE0:SE1] 采用:
((pendingb_lock).lock){?.+.},在:[<ffffff80080c69d4>] queue_work_on+0x6c/0x150
{HARDIRQ-ON -W} 状态注册于:
lock_acquire+0x244/0x274
rt_spin_lock+0x50/
0x64 queue_delayed_work_on+0x70/0x15c
init_mm_internals+0x13c/0x258
kernel_init_freeable+0x13c/0x2bc kernel_init
+0x18/0x114
ret_from_fork+0x18 0x10
事件戳:
在 (179) 启用:[<ffffff80088de500>] trusty_irq_cpu_up+0x164/0x16c
hardirqs 最后在 (180) 禁用:[<ffffff8008082a3c>] el1_irq+0x7c/0x144
softirqs last enabled at (0): [<ffffff80080a1f8c>] copy_process.isra.6.part.7+0x4c8/0x17ec
softirqs last disabled at (0): [< (null)>] (null)

其他可能对我们有帮助的信息调试这个:
可能的不安全锁定场景:

CPU0
----
lock((pendingb_lock).lock);
<中断>
lock((pendingb_lock).lock);

*** DEADLOCK ***

cpuhp/0/17 持有的 1 个锁:
#0: (cpuhp_state-up){+.+.},位于:[<ffffff80080a680c>] cpuhp_thread_fun+0xd4/0x1e0

堆栈回溯:
CPU:0 PID:17 通讯:cpuhp/0 污染:GS 4.14.98-rt55 #1
硬件名称:板 (DT)
调用跟踪:
[<ffffff800808ae10>] dump_backtrace+0x0/0x240
[<ffffff800808b074>] show_stack+0x24/0x30
[<ffffff8008b9aba0>] dump_stack+0x94/0xd0
[<ffffff8008115d20>] print_usage_bug+0x1e8/0x29c
[<ffffff80081161e0>] mark_lock+0x40c/0x618
[<ffffff80081169cc>] __lock_acquire+0x3dc/0x14e4
[<ffffff80081184e8>] lock_acquire+0x244/0x274
[<ffffff8008bb530c>] rt_spin_lock+0x50/
0x64 [<ffffff80080c69d4>] queue_work_on+0x6c/0x150
[<ffffff80088dc3f4>] trusty_enqueue_nop+0x9c/0xdc
[<ffffff80088dd3ac>] trusty_irq_handler+0xb0/0x1e0
[<ffffff800812c2f8>] handle_percpu_devid_irq+0x23c/0x478
[<ffffff8008090dc0>] handle_custom_ipi_irq+0x6c/0x70
[<ffffff80081263fc>] generic_handle_irq+0x2c/0x44
[<ffffff8008126b2c>] __handle_domain_irq+0xf0/0xf4
[<ffffff80080916b4>] handle_IPI+0x194/0x3a8
[<ffffff8008081184>] gic_handle_irq+0x160/0x164
Exception stack(0xffffff800a70ba90 to 0xffffff800a70bbd0)
ba80: ffffffc0f953b680 ffffff8009e9c1c8
baa0: fffffffffffffeb0 0000000000000000 ffffff80095b5000 ffffff80095b51e8
bac0: ffffff80097ac1bc 0000000000009645 0000000000000000 0000000000009643
bae0: 0000000000009644 ffffff80097ac1bc 0000000000000028 00000040f6cd4000
bb00 :FFFFFF80095C4880 00000000000000000000000000000000000000000000000000000000000000000000000000000000
来不起
BB20:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000来
bb60: ffffff80088de39c 00000040f6cd4000 0000000000000000 ffffff800a70bcd0
bb80: ffffff80088de500 ffffff800a70bcd0 ffffff80088de504 0000000060c00145
bba0: ffffff8008126c30 00000000000001c0 ffffffffffffffff ffffffc0f276bd48
bbc0: ffffff800a70bcd0 ffffff80088de504
[<ffffff8008082a7c>] el1_irq+0xbc/0x144
[<ffffff80088de504>] trusty_irq_cpu_up+0x168/0x16c
[<ffffff80080a5938>] cpuhp_invoke_callback+0x54c /0xe18
[<ffffff80080a6804>] cpuhp_thread_fun+0xcc/0x1e0
[<ffffff80080d3308>] smpboot_thread_fn+0x254/0x270
[<ffffff80080ceaa0>] kthread+0x124/0x134 [<ffffff8001808497c>] 0x_from808497x10x
+

锁未决b_lock 已修补

rt-linux/community/0307-workqueue-Use-local-irq-lock-instead-of-irq-disable-.patch

此补丁使用local_lock_irqsave代替local_irq_save,也用于其解锁功能。

我从https://www.kernel.org/doc/html/latest/locking/locktypes.html获得了一些信息,local_lock * 函数不会禁用preempt-rt kernel中的抢占和中断。

所以我理解了lockdep警告:

  1. 进程A获取锁pendingb_lock
  2. hardirq 中断 B
  3. 中断 B 需要获取 lock pendingb_lock

然后内核将与 ABA 死锁。

但是,preempt-rt 内核中断处理程序不应该在线程中而不是在 hardirq 上下文中执行?

如果 Interrupt_B 的处理程序 thread_B 没有获得锁 A,它不应该被调度出 cpu 并执行 Process A continue 吗?为什么会出现死锁?

lockdep 在 preempt-rt linux 内核中有用吗?或者我有什么问题?

期待您的回复,谢谢。

4

0 回答 0