wait_event_interruptible() seems non-atomic
From: Jan Engelhardt
Date: Sat Nov 20 2004 - 10:37:00 EST
Hi list,
upon reviewing some of my code for a device driver, I've come across:
static ssize_t uif_read(struct file *filp, char __user *buf,
size_t count, loff_t *ppos)
{
// Nothing read, nothing done
if(count == 0) { return 0; }
// Must sleep as long as there is no data
if(down_interruptible(&Buffer_lock)) { return -ERESTARTSYS; }
while(BufRP == BufWP) {
up(&Buffer_lock);
if(filp->f_flags & O_NONBLOCK) { return -EAGAIN; }
// hm, the condition is not atomic or locked...
if(wait_event_interruptible(Pull_queue, (BufRP != BufWP))) {
return -ERESTARTSYS;
}
if(down_interruptible(&Buffer_lock)) { return -ERESTARTSYS; }
}
// Data is available, so give it to the user
...
}
As you can see, I lock Buffer_lock and then check BufRP == BufWP. I do that
because in an SMP environment, either of BufRP or BufWP might have been
updated. (I.e. one CPU currently does "mov BufRP to eax; mov BufWP to ebx; cmp
eax, ebx" while another does "inc BufWP")
I would like to also lock Buffer_lock around BufRP != BufWP, but don't see a
way on how to accomplish this.
Does anybody know a way how this could be achieved?
Jan Engelhardt
--
Gesellschaft fÃr Wissenschaftliche Datenverarbeitung
Am Fassberg, 37077 GÃttingen, www.gwdg.de
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/