ALSA: seq: More protection for concurrent write and ioctl races
[pandora-kernel.git] / sound / core / seq / seq_memory.c
index 6fc211d..ce5d003 100644 (file)
@@ -221,7 +221,8 @@ void snd_seq_cell_free(struct snd_seq_event_cell * cell)
  */
 static int snd_seq_cell_alloc(struct snd_seq_pool *pool,
                              struct snd_seq_event_cell **cellp,
-                             int nonblock, struct file *file)
+                             int nonblock, struct file *file,
+                             struct mutex *mutexp)
 {
        struct snd_seq_event_cell *cell;
        unsigned long flags;
@@ -245,7 +246,11 @@ static int snd_seq_cell_alloc(struct snd_seq_pool *pool,
                set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&pool->output_sleep, &wait);
                spin_unlock_irq(&pool->lock);
+               if (mutexp)
+                       mutex_unlock(mutexp);
                schedule();
+               if (mutexp)
+                       mutex_lock(mutexp);
                spin_lock_irq(&pool->lock);
                remove_wait_queue(&pool->output_sleep, &wait);
                /* interrupted? */
@@ -288,7 +293,7 @@ __error:
  */
 int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
                      struct snd_seq_event_cell **cellp, int nonblock,
-                     struct file *file)
+                     struct file *file, struct mutex *mutexp)
 {
        int ncells, err;
        unsigned int extlen;
@@ -305,7 +310,7 @@ int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
        if (ncells >= pool->total_elements)
                return -ENOMEM;
 
-       err = snd_seq_cell_alloc(pool, &cell, nonblock, file);
+       err = snd_seq_cell_alloc(pool, &cell, nonblock, file, mutexp);
        if (err < 0)
                return err;
 
@@ -331,7 +336,8 @@ int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
                        int size = sizeof(struct snd_seq_event);
                        if (len < size)
                                size = len;
-                       err = snd_seq_cell_alloc(pool, &tmp, nonblock, file);
+                       err = snd_seq_cell_alloc(pool, &tmp, nonblock, file,
+                                                mutexp);
                        if (err < 0)
                                goto __error;
                        if (cell->event.data.ext.ptr == NULL)