ALSA: pcm_core: Fix wake_up() optimization
authorJaroslav Kysela <perex@perex.cz>
Thu, 21 Jan 2010 09:32:15 +0000 (10:32 +0100)
committerJaroslav Kysela <perex@perex.cz>
Thu, 21 Jan 2010 09:32:15 +0000 (10:32 +0100)
This change fixes the "ALSA: pcm_lib - optimize wake_up() calls for PCM I/O"
commit. New sleeping queue is introduced to separate user space and kernel
space wake_ups. runtime->nowake is renamed to twake (transfer wake).

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
include/sound/pcm.h
sound/core/pcm.c
sound/core/pcm_lib.c
sound/core/pcm_native.c

index e26fb3c58037cce43391cbcb0982ada3e019dad0..3bc9bca771ece4e24714d0481f63360fd52d009f 100644 (file)
@@ -311,8 +311,9 @@ struct snd_pcm_runtime {
        struct snd_pcm_mmap_control *control;
 
        /* -- locking / scheduling -- */
-       unsigned int nowake: 1;         /* no wakeup (data-copy in progress) */
-       wait_queue_head_t sleep;
+       unsigned int twake: 1;          /* do transfer (!poll) wakeup */
+       wait_queue_head_t sleep;        /* poll sleep */
+       wait_queue_head_t tsleep;       /* transfer sleep */
        struct fasync_struct *fasync;
 
        /* -- private section -- */
index df57a0e30bf2f7535d678a49d1d49f1c8cac6928..0d428d0896dbd564520f33f28f797912906b2c58 100644 (file)
@@ -894,6 +894,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
        memset((void*)runtime->control, 0, size);
 
        init_waitqueue_head(&runtime->sleep);
+       init_waitqueue_head(&runtime->tsleep);
 
        runtime->status->state = SNDRV_PCM_STATE_OPEN;
 
index 5417f7dce8340c750b8fdf28206a20fb63aab40a..e2a817eac2a9a3a7d4087599a8e6c147120a8a3d 100644 (file)
@@ -285,8 +285,8 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream,
                        return -EPIPE;
                }
        }
-       if (!runtime->nowake && avail >= runtime->control->avail_min)
-               wake_up(&runtime->sleep);
+       if (avail >= runtime->control->avail_min)
+               wake_up(runtime->twake ? &runtime->tsleep : &runtime->sleep);
        return 0;
 }
 
@@ -1692,7 +1692,7 @@ static int wait_for_avail_min(struct snd_pcm_substream *substream,
        long tout;
 
        init_waitqueue_entry(&wait, current);
-       add_wait_queue(&runtime->sleep, &wait);
+       add_wait_queue(&runtime->tsleep, &wait);
        for (;;) {
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
@@ -1735,7 +1735,7 @@ static int wait_for_avail_min(struct snd_pcm_substream *substream,
                        break;
        }
  _endloop:
-       remove_wait_queue(&runtime->sleep, &wait);
+       remove_wait_queue(&runtime->tsleep, &wait);
        *availp = avail;
        return err;
 }
@@ -1794,7 +1794,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
                goto _end_unlock;
        }
 
-       runtime->nowake = 1;
+       runtime->twake = 1;
        while (size > 0) {
                snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
                snd_pcm_uframes_t avail;
@@ -1816,7 +1816,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
                if (frames > cont)
                        frames = cont;
                if (snd_BUG_ON(!frames)) {
-                       runtime->nowake = 0;
+                       runtime->twake = 0;
                        snd_pcm_stream_unlock_irq(substream);
                        return -EINVAL;
                }
@@ -1855,7 +1855,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
                }
        }
  _end_unlock:
-       runtime->nowake = 0;
+       runtime->twake = 0;
        if (xfer > 0 && err >= 0)
                snd_pcm_update_state(substream, runtime);
        snd_pcm_stream_unlock_irq(substream);
@@ -2016,7 +2016,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
                goto _end_unlock;
        }
 
-       runtime->nowake = 1;
+       runtime->twake = 1;
        while (size > 0) {
                snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
                snd_pcm_uframes_t avail;
@@ -2045,7 +2045,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
                if (frames > cont)
                        frames = cont;
                if (snd_BUG_ON(!frames)) {
-                       runtime->nowake = 0;
+                       runtime->twake = 0;
                        snd_pcm_stream_unlock_irq(substream);
                        return -EINVAL;
                }
@@ -2078,7 +2078,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
                xfer += frames;
        }
  _end_unlock:
-       runtime->nowake = 0;
+       runtime->twake = 0;
        if (xfer > 0 && err >= 0)
                snd_pcm_update_state(substream, runtime);
        snd_pcm_stream_unlock_irq(substream);
index 27284f6283619e67271a0cb7772b24917dbd7a34..56ec35e8510b1fdf296c260245820ca1c89a1189 100644 (file)
@@ -919,6 +919,7 @@ static void snd_pcm_post_stop(struct snd_pcm_substream *substream, int state)
                runtime->status->state = state;
        }
        wake_up(&runtime->sleep);
+       wake_up(&runtime->tsleep);
 }
 
 static struct action_ops snd_pcm_action_stop = {
@@ -1004,6 +1005,7 @@ static void snd_pcm_post_pause(struct snd_pcm_substream *substream, int push)
                                         SNDRV_TIMER_EVENT_MPAUSE,
                                         &runtime->trigger_tstamp);
                wake_up(&runtime->sleep);
+               wake_up(&runtime->tsleep);
        } else {
                runtime->status->state = SNDRV_PCM_STATE_RUNNING;
                if (substream->timer)
@@ -1061,6 +1063,7 @@ static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, int state)
        runtime->status->suspended_state = runtime->status->state;
        runtime->status->state = SNDRV_PCM_STATE_SUSPENDED;
        wake_up(&runtime->sleep);
+       wake_up(&runtime->tsleep);
 }
 
 static struct action_ops snd_pcm_action_suspend = {