diff options
| author | Arnd Bergmann <arnd@arndb.de> | 2011-10-20 15:30:55 +0200 | 
|---|---|---|
| committer | Arnd Bergmann <arnd@arndb.de> | 2011-10-20 15:30:55 +0200 | 
| commit | 29ea35969b92a4be122a58c4aceea8c5e2c388d9 (patch) | |
| tree | 8285c0e98e7bb03868d390b58180e3cab876a8db /sound/core/pcm_lib.c | |
| parent | 112d17d6f75b93e1dcaec2e2232a411148b3bf71 (diff) | |
| parent | b4cbb8a4e602ea77b0525d06eff89c6a6070dab3 (diff) | |
Merge branch 'imx/devel' into next/devel
Diffstat (limited to 'sound/core/pcm_lib.c')
| -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;  | 
