list_empty returns 1(非零)如果列表不为空

list_empty returns 1 (non zero) if the list is not empty

我正在研究 Linux 设备驱动程序代码。我无法透露这段代码的具体用途。我会尽力解释我的情况。当我们收到一个 USB 中断表明有一些数据来自 USB 时,下面的代码将在中断上下文中执行。数据将以 URB 的形式到达,我们会将它们转换成块,将它们添加到 Linux 循环双向链表以进行进一步处理。

     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

I am monitoring the value of list_empty(&demod->ChunkRefList.full) using timedoctor applicaiton which doesn't introduce any overhead in interrupt context. I have used printk above to make you understand that I am printing its value.

终于,我找到了问题所在。

由于代码是在中断上下文中实现的,因此使用 list_del 后跟 list_add_tail 会导致问题。

所以,我删除了这两个宏并引入 list_move_tail 宏解决了这个问题。

通过使用list_move_tail,我们不需要删除节点并将其添加到新列表中。内核将负责这两个操作。

因此,总而言之,最好在中断上下文中使 Linux 链表操作尽可能少。