I am writing a device driver for a custom piece of hardware using the Linux kernel 2.6.33. I need am using DMA to transfer data to and from the device. For the output DMA, I was thinking that I would keep track of several output buffers using the Linked List API (struct list_head, list_add(), etc.).
When the device finished the DMA transfer, it raises an interrupt. The interrupt handler would then retrieve item in the linked list to transfer, and remove it from the list.
My question is, is this actually a safe thing to do inside of an interrupt handler? Or are there inherent race conditions in this API that would make it not safe?
The small section in Linux Device Drivers, 3rd Ed. doesn't make mention of this. The section in Essential Linux Device Drivers is more complete but also does not touch on this subject.
Edit: I am beginning to think that it may very well not be race condition free as msh suggests, due to a note listed in the list_empty_careful() function:
* NOTE: using list_empty_careful() without synchronization
* can only be safe if the only activity that can happen
* to the list entry is list_del_init(). Eg. it cannot be used
* if another CPU could re-list_add() it.
http://lxr.free-electrons.com/source/include/linux/list.h?v=2.6.33;a=powerpc#L202
Note that I plan to add to the queue in process context and remove from the queue in interrupt context. Do you really not need synchronization around the functions for a list?