您的位置:首页 > 运维架构 > Linux

欢迎使用CSDN-markdown编辑器

2016-12-06 20:22 337 查看

K项目中断异常定位总结

背景

K项目在开发阶段遇到的问题。由于K项目处理器与F项目处理器相同,均为freescale T4240,因此BSP代码移植主要参考F项目代码。在注册并使能5ms以及80ms后,串口大量打印80ms内5ms个数错误的打印。在我们的架构中,5ms以及80ms中断均由外部设备产生,通过外部中断引脚接入处理器。在BSP代码中,通过request_irq向系统注册中断响应函数,在中断响应函数中通过激活等待队列的方式,激活用户态线程。在我们的项目中,5ms中断和80ms中断是对齐的,也就是一个80ms中断内,应该有16个5ms中断。

定位过程

检查了bsp的代码。在5ms中断处理时,对一个全局变量进行++,如果其等于16,则将其赋值为0。在80ms中断处理时,判断这个全局变量是否为0,如果其不是0,则将其清为0并打印。从异常时的打印来看,大多数情况全局变量为1,也有情况全局变量大于16。

全局变量为1还可以理解为多产生了1个5ms中断,大于16的情况就比较诡异了。因为按照代码逻辑,每次++,等于16就会被清回0。唯一的一种可能性,就是存在多线程执行,在++后线程A被打断,线程B进行++操作,导致在线程A恢复后,计数跳变为17。

首先联系硬件同事,使用示波器测量中断管脚的波形,未发现问题。

针对多线程调用的情况,在5ms内核态处理中加入一个全局变量flag。在进入时将其置为1,退出时置为0,判断是否存在多线程调用的情况。发现确实存在多线程调用。

同时,删除5ms内核态处理,只保留5ms中断计数,发现出现异常的概率明显下降。针对5ms内核态进行了打点,发现异常出现只与访问EPLD有关。在F项目中的5ms处理中,同样有访问EPLD的操作,但是并没有出现问题。

另外,为了排除内核态printk对处理流程的影响,删除掉内核态printk打印,改为在用户态ssd中增加对中断唤醒间隔的判断,如果中断间隔小于4ms大于6ms则打印。发现如果在5ms内核态处理中访问EPLD,则会在5ms中断触发后,间隔10us左右再次触发5ms中断。如果在5ms内核态处理中不访问EPLD,则用户态的中断间隔基本一致正常。如果在控制台,通过调用某些bsp接口,触发了内核态printk打印,则也会多触发一次5ms中断,中断触发的点与控制台输入有关。

综合以上,有如下结论:

(1) 相对慢速的调用(访问EPLD、printk),会有一定几率导致多触发一次5ms中断;

(2) 5ms内核态中断处理中存在多线程调用的情况;

(3) 5ms中断波形正常。

由于基本已经确定是多触发了5ms中断,需要明确是LINUX、BSP、上层应用哪里多触发了。LINUX系统中的中断计数可以通过/proc/interrupts查看。在BSP的5ms处理中以及用户态的5ms处理中均加入了中断计数。发现用户态和LINUX的计数相比要多一些,多的个数恰好为用户态打印5ms异常间隔的次数。而BSP记录的5ms中断计数,要远远大于SSD以及LINUX的计数。在这过程中,突然注意到在K项目上/proc/interrupts中的中断计数,是24个核都触发的,而在F项目上/proc/interrupts只有1个核触发。

至此,严重怀疑一个5ms,触发了24个核调用BSP的处理函数,导致看起来像是多线程调用的情况。由于内核态通过等待队列唤醒用户线程,如果24个线程同时运行,且运行时间很快,则基本会在统一时刻置等待队列条件,然后被用户态清除,在这种情况下,用户态只会被唤醒一次。但是,如果中间有慢速的调用,则会导致24个线程处理有先后,用户态被唤醒后,再次被延后处理的再次唤醒。导致了如上现象。

问题引入

这个问题的引入,是由于两个项目的中断唤醒的机制不同,在F项目上,只将中断绑定到1个CPU上,由BSP去依次唤醒各个进程。而在K项目上,由于项目需求,需要尽快唤醒进程,每个进程绑定在不同的CPU上,因此修改为将中断绑定到多个CPU上,各个CPU独自唤醒各个进程。而在移植时,KERNEL部分修改为PERCPU的,而BSP部分依然使用了F项目的,导致本应执行1次的中断处理函数,被同一时刻由不同CPU多次调用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  LINUX中断