diff options
author | Ingo Molnar <mingo@elte.hu> | 2011-10-04 11:08:16 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-10-04 11:09:08 +0200 |
commit | 22f92bacbeea24b20e447444c28e7cad9f1ac3f8 (patch) | |
tree | 5c3f2346804a186aa2d954f078fd2f4d44bcc26e /sound/core | |
parent | 557ab425429a5123d37f412ce3e6d6137cb621f8 (diff) | |
parent | 0f86267b79bc6e357b8606077c7f70239045ea9c (diff) |
Merge branch 'linus' into sched/core
Merge reason: pick up the latest fixes.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'sound/core')
-rw-r--r-- | sound/core/pcm_lib.c | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 86d0caf91b35..62e90b862a0d 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -1761,6 +1761,10 @@ static int wait_for_avail(struct snd_pcm_substream *substream, snd_pcm_uframes_t avail = 0; long wait_time, tout; + init_waitqueue_entry(&wait, current); + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&runtime->tsleep, &wait); + if (runtime->no_period_wakeup) wait_time = MAX_SCHEDULE_TIMEOUT; else { @@ -1771,16 +1775,32 @@ static int wait_for_avail(struct snd_pcm_substream *substream, } wait_time = msecs_to_jiffies(wait_time * 1000); } - init_waitqueue_entry(&wait, current); - add_wait_queue(&runtime->tsleep, &wait); + for (;;) { if (signal_pending(current)) { err = -ERESTARTSYS; break; } + + /* + * We need to check if space became available already + * (and thus the wakeup happened already) first to close + * the race of space already having become available. + * This check must happen after been added to the waitqueue + * and having current state be INTERRUPTIBLE. + */ + if (is_playback) + avail = snd_pcm_playback_avail(runtime); + else + avail = snd_pcm_capture_avail(runtime); + if (avail >= runtime->twake) + break; snd_pcm_stream_unlock_irq(substream); - tout = schedule_timeout_interruptible(wait_time); + + tout = schedule_timeout(wait_time); + snd_pcm_stream_lock_irq(substream); + set_current_state(TASK_INTERRUPTIBLE); switch (runtime->status->state) { case SNDRV_PCM_STATE_SUSPENDED: err = -ESTRPIPE; @@ -1806,14 +1826,9 @@ static int wait_for_avail(struct snd_pcm_substream *substream, err = -EIO; break; } - if (is_playback) - avail = snd_pcm_playback_avail(runtime); - else - avail = snd_pcm_capture_avail(runtime); - if (avail >= runtime->twake) - break; } _endloop: + set_current_state(TASK_RUNNING); remove_wait_queue(&runtime->tsleep, &wait); *availp = avail; return err; |