简单地说,在一个read
方法中,我检查一个变量是否为0,如果我将当前进程置于睡眠状态:
static ssize_t soc2e_read(struct file *filp, char __user *buf,
size_t count, loff_t * ppos)
{
...
struct soc2e_dev *soc2e = (struct soc2e_dev *)filp->private_data;
if (soc2e->bytes == 0)
{
if (wait_event_interruptible(soc2e->wlist, (soc2e->bytes > 0)))
return -ERESTARTSYS;
}
...
}
我必须在中断处理程序中唤醒进程:
static irqreturn_t soc2e_irq_handler(int irq, void *dev)
{
...
struct soc2e_dev *soc2e = dev;
...
soc2e->bytes += read_bytes;
wake_up_interruptible(&soc2e->wlist);
return IRQ_HANDLED;
}
我认为(并且还证实)这可能是原子性问题。如果在if (soc2e->bytes == 0)
方法read
和wait_event_interruptible
调用之间发生中断,会发生什么情况。也许这个过程在下次中断之前不会被唤醒。解决此问题的最佳方法是什么?
答案 0 :(得分:3)
wait_event_interruptible
宏已经非常小心避免你描述的种族。事实上,您不需要对bytes
成员进行初步检查 - 您只需用read
方法撰写:
if (wait_event_interruptible(soc2e->wlist, soc2e->bytes > 0))
return -ERESTARTSYS;
因为如果条件为真,wait_event_interruptible()
实际上不会进入睡眠状态(或者在进入睡眠状态时变为真)。