From: Takashi Iwai Date: Fri, 18 Nov 2005 17:52:14 +0000 (+0100) Subject: [ALSA] Fix possible races in timer callbacks X-Git-Tag: v2.6.16-rc1~474^2~22^2~3^2~84 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b32425ac93370e1ba5556110e662f896b2e143b3;p=linux-2.6 [ALSA] Fix possible races in timer callbacks Fix possible races in timer callbacks. Signed-off-by: Takashi Iwai --- diff --git a/sound/core/timer.c b/sound/core/timer.c index 74637cef6d..6aad411dd7 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -662,12 +662,13 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) struct snd_timer_instance *ti, *ts; unsigned long resolution, ticks; struct list_head *p, *q, *n, *ack_list_head; + unsigned long flags; int use_tasklet = 0; if (timer == NULL) return; - spin_lock(&timer->lock); + spin_lock_irqsave(&timer->lock, flags); /* remember the current resolution */ if (timer->hw.c_resolution) @@ -752,7 +753,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) /* do we have any slow callbacks? */ use_tasklet = !list_empty(&timer->sack_list_head); - spin_unlock(&timer->lock); + spin_unlock_irqrestore(&timer->lock, flags); if (use_tasklet) tasklet_hi_schedule(&timer->task_queue); diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index a276f7c803..1861175717 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -231,8 +231,9 @@ static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream) static void snd_card_dummy_pcm_timer_function(unsigned long data) { struct snd_dummy_pcm *dpcm = (struct snd_dummy_pcm *)data; + unsigned long flags; - spin_lock(&dpcm->lock); + spin_lock_irqsave(&dpcm->lock, flags); dpcm->timer.expires = 1 + jiffies; add_timer(&dpcm->timer); dpcm->pcm_irq_pos += dpcm->pcm_jiffie; @@ -240,11 +241,10 @@ static void snd_card_dummy_pcm_timer_function(unsigned long data) dpcm->pcm_buf_pos %= dpcm->pcm_size; if (dpcm->pcm_irq_pos >= dpcm->pcm_count) { dpcm->pcm_irq_pos %= dpcm->pcm_count; - spin_unlock(&dpcm->lock); + spin_unlock_irqrestore(&dpcm->lock, flags); snd_pcm_period_elapsed(dpcm->substream); - spin_lock(&dpcm->lock); - } - spin_unlock(&dpcm->lock); + } else + spin_unlock_irqrestore(&dpcm->lock, flags); } static snd_pcm_uframes_t snd_card_dummy_pcm_pointer(struct snd_pcm_substream *substream) diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index ee67b522d2..8687ae3c66 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c @@ -133,12 +133,13 @@ irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *reg static void snd_mpu401_uart_timer(unsigned long data) { struct snd_mpu401 *mpu = (struct snd_mpu401 *)data; + unsigned long flags; - spin_lock(&mpu->timer_lock); + spin_lock_irqsave(&mpu->timer_lock, flags); /*mpu->mode |= MPU401_MODE_TIMER;*/ mpu->timer.expires = 1 + jiffies; add_timer(&mpu->timer); - spin_unlock(&mpu->timer_lock); + spin_unlock_irqrestore(&mpu->timer_lock, flags); if (mpu->rmidi) _snd_mpu401_uart_interrupt(mpu); } diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c index 48c480e050..1b6f227af3 100644 --- a/sound/drivers/opl3/opl3_midi.c +++ b/sound/drivers/opl3/opl3_midi.c @@ -238,10 +238,11 @@ void snd_opl3_timer_func(unsigned long data) { struct snd_opl3 *opl3 = (struct snd_opl3 *)data; + unsigned long flags; int again = 0; int i; - spin_lock(&opl3->sys_timer_lock); + spin_lock_irqsave(&opl3->sys_timer_lock, flags); for (i = 0; i < opl3->max_voices; i++) { struct snd_opl3_voice *vp = &opl3->voices[i]; if (vp->state > 0 && vp->note_off_check) { @@ -257,7 +258,7 @@ void snd_opl3_timer_func(unsigned long data) } else { opl3->sys_timer_status = 0; } - spin_unlock(&opl3->sys_timer_lock); + spin_unlock_irqrestore(&opl3->sys_timer_lock, flags); } /* diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index a8a6a5c41a..4eddb512c1 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -609,8 +609,9 @@ static void snd_korg1212_SendStopAndWait(struct snd_korg1212 *korg1212) static void snd_korg1212_timer_func(unsigned long data) { struct snd_korg1212 *korg1212 = (struct snd_korg1212 *) data; + unsigned long flags; - spin_lock(&korg1212->lock); + spin_lock_irqsave(&korg1212->lock, flags); if (korg1212->sharedBufferPtr->cardCommand == 0) { /* ack'ed */ korg1212->stop_pending_cnt = 0; @@ -632,7 +633,7 @@ static void snd_korg1212_timer_func(unsigned long data) stateName[korg1212->cardState]); } } - spin_unlock(&korg1212->lock); + spin_unlock_irqrestore(&korg1212->lock, flags); } static int snd_korg1212_TurnOnIdleMonitor(struct snd_korg1212 *korg1212) diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c index c387a83a65..24705d15eb 100644 --- a/sound/synth/emux/emux_synth.c +++ b/sound/synth/emux/emux_synth.c @@ -205,9 +205,10 @@ void snd_emux_timer_callback(unsigned long data) { struct snd_emux *emu = (struct snd_emux *) data; struct snd_emux_voice *vp; + unsigned long flags; int ch, do_again = 0; - spin_lock(&emu->voice_lock); + spin_lock_irqsave(&emu->voice_lock, flags); for (ch = 0; ch < emu->max_voices; ch++) { vp = &emu->voices[ch]; if (vp->state == SNDRV_EMUX_ST_PENDING) { @@ -225,7 +226,7 @@ void snd_emux_timer_callback(unsigned long data) emu->timer_active = 1; } else emu->timer_active = 0; - spin_unlock(&emu->voice_lock); + spin_unlock_irqrestore(&emu->voice_lock, flags); } /*