休眠失败排查

1 休眠唤醒测试时休眠失败
大体情况:

内核:Linux 4.19
硬件:32bit ARM SOC
问题:某板子在休眠唤醒流程验证的过程中,休眠失败;
复现:echo standby > /sys/power/state
其中,异常日志如下:


# echo standby > /sys/power/state
PM: suspend entry (shallow)
PM: Syncing filesystems ... done.
Freezing user space processes ...
Freezing of tasks failed after 20.003 seconds (1 tasks refusing to freeze, wq_busy=0):
jempty_test    R runing task  ...
[] (__schedule) from [] (preempt_schedule_common+0x1c/0x2c)
[] (preempt_schedule_common) from [] (_cond_resched+0x34/0x48)
[] (_cond_resched) from [] (jempty_msgctl_message_ioctl+0x76c/0x938)
[] (jempty_msgctl_message_ioctl) from [] (vfs_ioctl+0x28/0x3c)
[] (vfs_ioctl) from [] (do_vfs_ioctl+0x90/0x84c)
[] (do_vfs_ioctl) from [] (ksys_ioctl+0x38/0x54)
[] (ksys_ioctl) from [] (ret_fast_syscall+0x0/0x54)
Exception stack (0x... to 0x...)
...
oom killer enabled.
Restarting tasks • • • done.
PM: suspend exit
sh: write error: Device or resource busy

2 休眠异常日志分析
好了,我们有了第一现场,开始分析问题:

2.1 根据现场 Log,找到出问题的代码位置
这里使用了 gdb+vmlinux,找到了异常代码的位置,也就是出错(jempty_msgctl_message_ioctl+0x76c)所在代码行。

(gdb) list *(jempty_msgctl_message_ioctl+0x76c)
 0xc0407034 is in jempty_msgctl_message_ioctl (...:191)
 186             ret = -EFAULT;
 187            }
 188 else {
   
 189            spin_unlock_irqrestore(&tdev->read_lock, flags);
 190            if (tdev->block_read) {
   
 191                    wait_event_interruptible(tdev->read_waitq, s_mbox_data_ready);
 192                    goto re_read;
 193            } else {
   
 194                    rx_msg->len = 0;

异常位置在 Driver 中的第 191 行,这里该模块在等待另一个 CPU 核的中断唤醒它,即 wake_up_interruptible,唤醒以后进行下一步处理;所以此时该进程是陷入了内核态,并一直处于内核态,没有机会退出。

更多定位代码行位置的方法请阅读历史文章:如何快速定位 Linux Panic 出错的代码行。

2.2 分析跟用户态进程唤醒相关的内核代码
关于休眠唤醒的全部流程就不细细分析了,这里仅分析该进程休眠失败的原因。

根据现场 Log 来看,这是进入 standby 失败的现场,导致 standby 失败的原因是进程(jempty_test)拒绝 freeze;这里需要进一步看一下 freeze 进程的 code,才能找到出现这个问题的具体原因,来到代码。

首先,对应的 call stack 是酱紫的:``

pm_suspend ->
    suspend_freeze_processes ->
        try_to_freeze_tasks->
            freeze_task(到这里进行本案的用户空间进程的冻结)

接下来分析 try_to_freeze_tasks。

static int try_to_freeze_tasks(bool user_only)
{
   
    if (!user_only)   
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值