mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 13:14:07 +08:00
[ALSA] Fix possible races in timer callbacks
Fix possible races in timer callbacks. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
2eb061f41c
commit
b32425ac93
@ -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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
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)
|
|||||||
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
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
|
|
||||||
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)
|
|||||||
} 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user