Messages in this thread | | | Date | Sat, 20 Nov 2004 16:35:04 +0100 (MET) | From | Jan Engelhardt <> | Subject | wait_event_interruptible() seems non-atomic |
| |
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@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |