Skip to content

Commit

Permalink
ALSA: emu10k1: Fix deadlock in synth voice lookup
Browse files Browse the repository at this point in the history
The emu10k1 voice allocator takes voice_lock spinlock.  When there is
no empty stream available, it tries to release a voice used by synth,
and calls get_synth_voice.  The callback function,
snd_emu10k1_synth_get_voice(), however, also takes the voice_lock,
thus it deadlocks.

The fix is simply removing the voice_lock holds in
snd_emu10k1_synth_get_voice(), as this is always called in the
spinlock context.

Reported-and-tested-by: Arthur Marsh <[email protected]>
Cc: <[email protected]>
Signed-off-by: Takashi Iwai <[email protected]>
  • Loading branch information
tiwai committed Oct 14, 2014
1 parent 811deed commit 9592603
Showing 1 changed file with 2 additions and 4 deletions.
6 changes: 2 additions & 4 deletions sound/pci/emu10k1/emu10k1_callback.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,19 @@ snd_emu10k1_ops_setup(struct snd_emux *emux)
* get more voice for pcm
*
* terminate most inactive voice and give it as a pcm voice.
*
* voice_lock is already held.
*/
int
snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw)
{
struct snd_emux *emu;
struct snd_emux_voice *vp;
struct best_voice best[V_END];
unsigned long flags;
int i;

emu = hw->synth;

spin_lock_irqsave(&emu->voice_lock, flags);
lookup_voices(emu, hw, best, 1); /* no OFF voices */
for (i = 0; i < V_END; i++) {
if (best[i].voice >= 0) {
Expand All @@ -113,11 +113,9 @@ snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw)
vp->emu->num_voices--;
vp->ch = -1;
vp->state = SNDRV_EMUX_ST_OFF;
spin_unlock_irqrestore(&emu->voice_lock, flags);
return ch;
}
}
spin_unlock_irqrestore(&emu->voice_lock, flags);

/* not found */
return -ENOMEM;
Expand Down

0 comments on commit 9592603

Please sign in to comment.