Commit b32425ac authored by Takashi Iwai's avatar Takashi Iwai Committed by Jaroslav Kysela

[ALSA] Fix possible races in timer callbacks

Fix possible races in timer callbacks.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 2eb061f4
...@@ -662,12 +662,13 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) ...@@ -662,12 +662,13 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
struct snd_timer_instance *ti, *ts; struct snd_timer_instance *ti, *ts;
unsigned long resolution, ticks; unsigned long resolution, ticks;
struct list_head *p, *q, *n, *ack_list_head; struct list_head *p, *q, *n, *ack_list_head;
unsigned long flags;
int use_tasklet = 0; int use_tasklet = 0;
if (timer == NULL) if (timer == NULL)
return; return;
spin_lock(&timer->lock); spin_lock_irqsave(&timer->lock, flags);
/* remember the current resolution */ /* remember the current resolution */
if (timer->hw.c_resolution) if (timer->hw.c_resolution)
...@@ -752,7 +753,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) ...@@ -752,7 +753,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
/* do we have any slow callbacks? */ /* do we have any slow callbacks? */
use_tasklet = !list_empty(&timer->sack_list_head); use_tasklet = !list_empty(&timer->sack_list_head);
spin_unlock(&timer->lock); spin_unlock_irqrestore(&timer->lock, flags);
if (use_tasklet) if (use_tasklet)
tasklet_hi_schedule(&timer->task_queue); tasklet_hi_schedule(&timer->task_queue);
......
...@@ -231,8 +231,9 @@ static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream) ...@@ -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) static void snd_card_dummy_pcm_timer_function(unsigned long data)
{ {
struct snd_dummy_pcm *dpcm = (struct snd_dummy_pcm *)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; dpcm->timer.expires = 1 + jiffies;
add_timer(&dpcm->timer); add_timer(&dpcm->timer);
dpcm->pcm_irq_pos += dpcm->pcm_jiffie; dpcm->pcm_irq_pos += dpcm->pcm_jiffie;
...@@ -240,11 +241,10 @@ static void snd_card_dummy_pcm_timer_function(unsigned long data) ...@@ -240,11 +241,10 @@ static void snd_card_dummy_pcm_timer_function(unsigned long data)
dpcm->pcm_buf_pos %= dpcm->pcm_size; dpcm->pcm_buf_pos %= dpcm->pcm_size;
if (dpcm->pcm_irq_pos >= dpcm->pcm_count) { if (dpcm->pcm_irq_pos >= dpcm->pcm_count) {
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); snd_pcm_period_elapsed(dpcm->substream);
spin_lock(&dpcm->lock); } else
} spin_unlock_irqrestore(&dpcm->lock, flags);
spin_unlock(&dpcm->lock);
} }
static snd_pcm_uframes_t snd_card_dummy_pcm_pointer(struct snd_pcm_substream *substream) static snd_pcm_uframes_t snd_card_dummy_pcm_pointer(struct snd_pcm_substream *substream)
......
...@@ -133,12 +133,13 @@ irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *reg ...@@ -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) static void snd_mpu401_uart_timer(unsigned long data)
{ {
struct snd_mpu401 *mpu = (struct snd_mpu401 *)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->mode |= MPU401_MODE_TIMER;*/
mpu->timer.expires = 1 + jiffies; mpu->timer.expires = 1 + jiffies;
add_timer(&mpu->timer); add_timer(&mpu->timer);
spin_unlock(&mpu->timer_lock); spin_unlock_irqrestore(&mpu->timer_lock, flags);
if (mpu->rmidi) if (mpu->rmidi)
_snd_mpu401_uart_interrupt(mpu); _snd_mpu401_uart_interrupt(mpu);
} }
......
...@@ -238,10 +238,11 @@ void snd_opl3_timer_func(unsigned long data) ...@@ -238,10 +238,11 @@ void snd_opl3_timer_func(unsigned long data)
{ {
struct snd_opl3 *opl3 = (struct snd_opl3 *)data; struct snd_opl3 *opl3 = (struct snd_opl3 *)data;
unsigned long flags;
int again = 0; int again = 0;
int i; int i;
spin_lock(&opl3->sys_timer_lock); spin_lock_irqsave(&opl3->sys_timer_lock, flags);
for (i = 0; i < opl3->max_voices; i++) { for (i = 0; i < opl3->max_voices; i++) {
struct snd_opl3_voice *vp = &opl3->voices[i]; struct snd_opl3_voice *vp = &opl3->voices[i];
if (vp->state > 0 && vp->note_off_check) { if (vp->state > 0 && vp->note_off_check) {
...@@ -257,7 +258,7 @@ void snd_opl3_timer_func(unsigned long data) ...@@ -257,7 +258,7 @@ void snd_opl3_timer_func(unsigned long data)
} else { } else {
opl3->sys_timer_status = 0; opl3->sys_timer_status = 0;
} }
spin_unlock(&opl3->sys_timer_lock); spin_unlock_irqrestore(&opl3->sys_timer_lock, flags);
} }
/* /*
......
...@@ -609,8 +609,9 @@ static void snd_korg1212_SendStopAndWait(struct snd_korg1212 *korg1212) ...@@ -609,8 +609,9 @@ static void snd_korg1212_SendStopAndWait(struct snd_korg1212 *korg1212)
static void snd_korg1212_timer_func(unsigned long data) static void snd_korg1212_timer_func(unsigned long data)
{ {
struct snd_korg1212 *korg1212 = (struct snd_korg1212 *) 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) { if (korg1212->sharedBufferPtr->cardCommand == 0) {
/* ack'ed */ /* ack'ed */
korg1212->stop_pending_cnt = 0; korg1212->stop_pending_cnt = 0;
...@@ -632,7 +633,7 @@ static void snd_korg1212_timer_func(unsigned long data) ...@@ -632,7 +633,7 @@ static void snd_korg1212_timer_func(unsigned long data)
stateName[korg1212->cardState]); stateName[korg1212->cardState]);
} }
} }
spin_unlock(&korg1212->lock); spin_unlock_irqrestore(&korg1212->lock, flags);
} }
static int snd_korg1212_TurnOnIdleMonitor(struct snd_korg1212 *korg1212) static int snd_korg1212_TurnOnIdleMonitor(struct snd_korg1212 *korg1212)
......
...@@ -205,9 +205,10 @@ void snd_emux_timer_callback(unsigned long data) ...@@ -205,9 +205,10 @@ void snd_emux_timer_callback(unsigned long data)
{ {
struct snd_emux *emu = (struct snd_emux *) data; struct snd_emux *emu = (struct snd_emux *) data;
struct snd_emux_voice *vp; struct snd_emux_voice *vp;
unsigned long flags;
int ch, do_again = 0; 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++) { for (ch = 0; ch < emu->max_voices; ch++) {
vp = &emu->voices[ch]; vp = &emu->voices[ch];
if (vp->state == SNDRV_EMUX_ST_PENDING) { if (vp->state == SNDRV_EMUX_ST_PENDING) {
...@@ -225,7 +226,7 @@ void snd_emux_timer_callback(unsigned long data) ...@@ -225,7 +226,7 @@ void snd_emux_timer_callback(unsigned long data)
emu->timer_active = 1; emu->timer_active = 1;
} else } else
emu->timer_active = 0; emu->timer_active = 0;
spin_unlock(&emu->voice_lock); spin_unlock_irqrestore(&emu->voice_lock, flags);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment