ALSA: timer: Wrap with spinlock for queue access
authorTakashi Iwai <tiwai@suse.de>
Fri, 2 Jun 2017 15:35:30 +0000 (17:35 +0200)
committerTakashi Iwai <tiwai@suse.de>
Wed, 7 Jun 2017 08:25:53 +0000 (10:25 +0200)
For accessing the snd_timer_user queue indices, we take tu->qlock.
But it's forgotten in a couple of places.

The one in snd_timer_user_params() should be safe without the
spinlock as the timer is already stopped.  But it's better for
consistency.

The one in poll is just a read-out, so it's not inevitably needed, but
it'd be good to make the result consistent, too.

Tested-by: Alexander Potapenko <glider@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/core/timer.c

index 96cffb1be57fd183579665d6634c8304d48d3b09..148290ace756b5425e3e083975daee7794285c03 100644 (file)
@@ -1755,6 +1755,7 @@ static int snd_timer_user_params(struct file *file,
                if (err < 0)
                        goto _end;
        }
+       spin_lock_irq(&tu->qlock);
        tu->qhead = tu->qtail = tu->qused = 0;
        if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) {
                if (tu->tread) {
@@ -1775,6 +1776,7 @@ static int snd_timer_user_params(struct file *file,
        }
        tu->filter = params.filter;
        tu->ticks = params.ticks;
+       spin_unlock_irq(&tu->qlock);
        err = 0;
  _end:
        if (copy_to_user(_params, &params, sizeof(params)))
@@ -2022,10 +2024,12 @@ static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait)
         poll_wait(file, &tu->qchange_sleep, wait);
 
        mask = 0;
+       spin_lock_irq(&tu->qlock);
        if (tu->qused)
                mask |= POLLIN | POLLRDNORM;
        if (tu->disconnected)
                mask |= POLLERR;
+       spin_unlock_irq(&tu->qlock);
 
        return mask;
 }