From: Jaroslav Kysela Date: Thu, 21 Jan 2010 09:32:15 +0000 (+0100) Subject: ALSA: pcm_core: Fix wake_up() optimization X-Git-Tag: firefly_0821_release~9833^2~2092^2~2^2~58 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=c91a988dc6551c66418690e36b2a23cdb0255da8;p=firefly-linux-kernel-4.4.55.git ALSA: pcm_core: Fix wake_up() optimization 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 --- diff --git a/include/sound/pcm.h b/include/sound/pcm.h index e26fb3c58037..3bc9bca771ec 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -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 -- */ diff --git a/sound/core/pcm.c b/sound/core/pcm.c index df57a0e30bf2..0d428d0896db 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -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; diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 5417f7dce834..e2a817eac2a9 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -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); diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 27284f628361..56ec35e8510b 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -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 = {