最近遇到一个问题,在zynq上跑起linux 4.4的kernel出现如下状况:
板子出现死机,在串口上无法敲命令,最后60s后被watchdog 复位。这个状况出现频率不固定。
/*****************************************************************************/
请教了一个kernel大神,初步怀疑是deadlock。
排除步骤如下
首先要先考虑deadlock是hard lock还是soft lock引起。首先找一个按键中断控制gpio灯,当出现死机时候,按下按键,如果点灯ok,说明没有关中断,只是soft lock,可以开softlock lockdep(还没学习),会进行死锁检测,找到两个死锁进程进行分析。Hardlock 关中断比较难弄。
后续我通过gitlog 发现有我在网卡中断中不停的ioremap和unmap,ioremap设置kmalloc 且标志位GFP_KERNEL,也就是可能会引起睡眠。我把ioremap在注册驱动中的函数实现,目前还没有出现死机问题。且加了中断控制led灯还没起到检测作用。
/*****************************************************************************/
模拟出现问题:
1.我在中断中加入睡眠函数,会主动调度。进程上下文和中断上下文,两个不同的东东,中断的优先级一定高于进程,且中断里面没有进程(task struct)概念,所以中断里面无法完成调度工作。Schedule函数如下:
asmlinkage void __sched schedule(void)
{
struct task_struct *prev, *next;
struct prio_array *array;
struct list_head *queue;
unsigned long long now;
unsigned long run_time;
int cpu, idx, new_prio;
long *switch_count;
struct rq *rq;
/*
* Test if we are atomic. Since do_exit() needs to call into
* schedule() atomically, we ignore that path for now.
* Otherwise, whine if we are scheduling when we should not be.
*/
if (unlikely(in_atomic() && !current->exit_state)) {
printk(KERN_ERR "BUG: scheduling while atomic: "
"%s/0x%08x/%d\n",
current->comm, preempt_count(), current->pid);
debug_show_held_locks(current);
if (irqs_disabled())
print_irqtrace_events(current);
dump_stack();
}
...............................................................
}
打印如下:
"BUG: scheduling while atomic: swapper1/0/0x00010002
2.故意使用spin_lock造成死锁。
此现象和 问题出现的一致,但是中断指示灯还是亮的。就是spin_lock关抢占引起。又试验了mutex_lock(学习下区别呗),会进入D状态(uninterruptible sleep),确实,系统不会挂掉只是进入不可中断睡眠。
后续我又写成了AB-BA死锁,由于我是双核的SMP,所以只有线程p获得A且线程B获取B锁,才会造成死锁(有点儿随机哦,不是必现)。
现在状况:
现象还是没有复现,但是怀疑不是中断函数里面睡眠引起的。