我正在研究Linux设备驱动程序代码。我无法透露这个代码究竟是用于什么的。我会尽力解释我的情况。当我们收到USB中断声明USB有一些数据时,下面的代码将在中断上下文中执行。数据将以URB的形式到达,我们将它们转换为块,将它们添加到Linux Circular Doubly链表中以便进一步处理。
spin_lock(&demod->demod_lock);
/* Delete node from free list */
list_del(&chunk->list_head);
/* Add it to full list */
list_add_tail(&chunk->list_head,&demod->ChunkRefList.full);
/* Update chunk status */
chunk->status=CHUNKDESC_FULL_LIST;
/* Increment the chunks assigned to application */
demod->stats.assigned.c++;
spin_unlock(&demod->demod_lock);
printk("Value returned by list_empty is %d ",list_empty(&demod->ChunkRefList.full));
我再说一遍,这段代码在中断上下文中执行。我使用此代码作为嵌入式系统的一部分,显示音频和放大器。视频(AV)永远。
大约12小时后,AV被冻结,当我分析时,我看到返回的list_empty(& demod-> ChunkRefList.full)的值永远是0x1。通常在AV播放正常的工作情况下,其值为0x0,表明列表不为空。
正如您所看到的,当上面的代码被执行时,它首先将一个节点添加到完整列表并检查完整列表是否为空。理想情况下,该值应始终为0x0。为什么它的值是0x1
我使用timedoctor应用程序监视list_empty(& demod-> ChunkRefList.full)的值,该应用程序不会在中断上下文中引入任何开销。我使用上面的printk让你明白我正在打印它的价值。
答案 0 :(得分:0)
最后,我能够找出问题所在。
由于代码是在中断上下文中实现的,因此使用list_del后跟list_add_tail会导致问题。
所以,我删除了这两个宏并引入了list_move_tail宏来解决这个问题。
通过使用list_move_tail,我们无需删除节点并将其添加到新列表中。内核将负责这两项操作。
因此,总而言之,最好在中断环境中尽可能减少Linux链接列表操作。