龙芯平台一次死锁分析过程

一.问题现象如图1所示:

                                                                                       图1 问题现象

1.根据问题现象初步分析:出现问题时epc的值为rt_spin_lock_slowlock函数中的地址,分析该函数的源代码及反汇编代码如图2和图3所示。

                                                                                        图2 函数源码

                                                                                         图3 函数汇编码

根据图1-3得出,由于函数task_blocks_on_rt_mutex返回非0值,导致函数进入BUG_ON时报出异常信息。

2.函数task_blocks_on_rt_mutex返回值存储在v0寄存器中,根据图1得出该返回值为0xffffffffffffffd3即-5,经过分析该函数的源码,该值为-EDEADLK。

二、分析过程(需要了解rt_mutex锁的工作机制)

1.分析函数task_blocks_on_rt_mutex中返回-EDEADLK值的代码处。添加调试信息,如图4所示。

                                                                               图4 返回EDEADLK代码

添加调试信息后继续复现问题,复现问题后的调试信息输出如图5所示。

                                                                                 图5 调试信息输出

根据图4和图5得出:ksoftirqd/0进程在申请锁,该锁的地址为0x98000000bc10d838,即bond->lock(标记为锁A)。

kworker/u2:0进程拥有锁bond→lock,进程的控制块的地址为0x98000000bc00af80。

systemd-resolve进程在申请锁bond→lock。

ksoftirqd/0进程申请锁A时,最终推导出systemd-resolve进程也在申请锁A。在kworker/u2:0进程和systemd-resolve进程之间还存在一把锁B,systemd-resolve进程拥有,kworker/u2:0进程申请。目前打印信息中并未打印该信息,需要通过kworker/u2:0进程的进程控制块来查找该进程所申请的锁B是什么。

第一步分析结论为:ksoftirqd/0进程申请锁A;而锁A的拥有者时kworker/u2:0,它在申请锁B;锁B的拥有者时systemd-resolve,它也在申请锁A。因而造成循环死锁。(在kworker 和systemd-resolve 之间可能还存在其它进程和锁)

2.分析kworker/u2:0进程正在申请的锁,根据进程控制块的地址打印出进程控制块中的pi_blocked_on的地址,如图6所示。

                                                          图6 kworker进程控制块pi_blocked_on地址

根据图6得出pi_blocked_on的地址为0x98000000bc02bc00,该地址内容如图7所示。

                                                                 图7 pi_blocked_on地址内容

根据图7得出pi_block_on->lock地址为0x98000000bc10d1f0(锁B)。该锁的具体内容如图8所示。

                                                                                       图8 锁B的具体内容

根据图8 lock->owner得出锁的拥有者为0x98000000bcc90000,该地址为某进程控制块的地址,继续打印出该地址如图9所示。

                                                                         图9 lock->owner具体内容

根据图9得出该锁的拥有者为systemd-resolve进程。

第二步分析结论:通过(kworker)task->pi_block_on->lock得出kworker进程申请的锁为0x98000000bc10d1f0(锁B)。根据lock->owner,得出该锁的拥有者为systemd-resolve。

3.分析进程systemd-resolve进程的调用栈,分析出锁B具体内容

根据task(systemd-resolve)→thread(进程被切换后最后的现场寄存器信息),具体内容如图10。

                                                                 图10 systemd-resolve 进程的thread信息

根据task→thread信息得出,该进程最后的sp值为0x98000000bcb67880。根据进程的sp信息,ra值0x809c9d5c和vmlinux的二进制反汇编推导出调用栈,如图11所示。

 

                                                                  图11 systemd-resolve进程调用栈

根据进程调用栈中的信息最终得出systemd-resolve拥有的锁B为net_dev(bond)->addr_list_lock。

第三的结论:systemd-resolve进程的调用栈为ipv6_dev_mc_inc->igmp6_group_added->__dev_mc_add->bond_set_multicast_list->rt_read_lock->rt_spinlock_slowlock。拥有锁B(netdev(bond)->addr_list_lock)与kworker申请的锁B地址一致。

 

根据1,2和3分析总结:ksoftirqd/0进程申请锁A;而锁A的拥有者时kworker/u2:0,它在申请锁B;锁B的拥有者时systemd-resolve,它也在申请锁A。因而造成循环死锁。锁A和锁B具体内容前面已提及。

 

4.分析systemd-resolve进程和kwoker进程的源代码。

分析锁申请和释放的相关流程。最终分析得出kworker进程调用bond_mii_monitor函数首先申请 锁A(bond->lock),再调用函数bond_mc_swap申请锁B(netdev->addr_list_lock)。进程systemd-resolve进程调用__dev_mc_add函数首先申请锁B,在调用函数 bond_set_multicast_list申请锁A。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值