2

Briefly, in a read method i check if a variable is 0 and if it's i put the current process to sleep:

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;
    }
    ...
 }

I must wake up the process in an interrupt handler:

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;
}

I think (and also verified) that here could be a problem of atomicity. What happen if interrupt comes between if (soc2e->bytes == 0) in read method and the call to wait_event_interruptible. Maybe the process won't be waked up until next interrupt. What is the best way to resolve this issue?

MirkoBanchi
  • 2,173
  • 5
  • 35
  • 52

1 Answers1

3

The wait_event_interruptible macro is already pretty careful about avoiding the race you describe. In fact, you don't need the initial check of your bytes member -- you could just write in your read method:

  if (wait_event_interruptible(soc2e->wlist, soc2e->bytes > 0))
          return -ERESTARTSYS;

because wait_event_interruptible() will not actually go to sleep if the condition is true (or becomes true while it's in the middle of going to sleep).

Roland
  • 6,227
  • 23
  • 29
  • Cool! Thanks Roland. However should i retest the condition after that process waked up? If i have more processes, the bytes could be read by other consumers...maybe a semaphore could be sufficient? – MirkoBanchi Mar 22 '12 at 09:03
  • 1
    Yes, if the condition can change, you need to check it again. In general semaphores are usually not the right answer ... the kernel idiom would be to protect the condition with a lock, and do something like "lock_state(); while (!condition) { drop_lock(); wait_event...(); retake_lock(); }" – Roland Mar 26 '12 at 21:41