[alsa-devel] [PATCH] ALSA: aloop - do not reschedule timer if deleted
Omair Mohammed Abdullah
omair.m.abdullah at linux.intel.com
Wed Oct 17 15:35:46 CEST 2012
If the timer is deleted while the timer handler is running, it may get
rescheduled and an unnecessary period elapsed will be sent.
Add a flag to reschedule the timer only if it has not been stopped.
Signed-off-by: Omair Mohammed Abdullah <omair.m.abdullah at linux.intel.com>
Signed-off-by: Vinod Koul <vinod.koul at linux.intel.com>
---
sound/drivers/aloop.c | 21 ++++++++++++++++++---
1 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index 0fe6d64..fec4e17 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -121,6 +121,7 @@ struct loopback_pcm {
unsigned long last_jiffies;
struct timer_list timer;
spinlock_t timer_lock;
+ bool timer_stopped;
};
static struct platform_device *devices[SNDRV_CARDS];
@@ -166,12 +167,11 @@ static inline unsigned int get_rate_shift(struct loopback_pcm *dpcm)
return get_setup(dpcm)->rate_shift;
}
-static void loopback_timer_start(struct loopback_pcm *dpcm)
+static void do_timer_start(struct loopback_pcm *dpcm)
{
unsigned long tick;
unsigned int rate_shift = get_rate_shift(dpcm);
- spin_lock(&dpcm->timer_lock);
if (rate_shift != dpcm->pcm_rate_shift) {
dpcm->pcm_rate_shift = rate_shift;
dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size);
@@ -184,6 +184,13 @@ static void loopback_timer_start(struct loopback_pcm *dpcm)
tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps;
dpcm->timer.expires = jiffies + tick;
add_timer(&dpcm->timer);
+}
+
+static inline void loopback_timer_start(struct loopback_pcm *dpcm)
+{
+ spin_lock(&dpcm->timer_lock);
+ dpcm->timer_stopped = false;
+ do_timer_start(dpcm);
spin_unlock(&dpcm->timer_lock);
}
@@ -192,6 +199,7 @@ static inline void loopback_timer_stop(struct loopback_pcm *dpcm)
spin_lock(&dpcm->timer_lock);
del_timer(&dpcm->timer);
dpcm->timer.expires = 0;
+ dpcm->timer_stopped = true;
spin_unlock(&dpcm->timer_lock);
}
@@ -540,7 +548,13 @@ static void loopback_timer_function(unsigned long data)
running = loopback_pos_update(dpcm->cable);
if (running & (1 << dpcm->substream->stream)) {
- loopback_timer_start(dpcm);
+ spin_lock(&dpcm->timer_lock);
+ if (dpcm->timer_stopped) {
+ spin_unlock(&dpcm->timer_lock);
+ return;
+ }
+ do_timer_start(dpcm);
+ spin_unlock(&dpcm->timer_lock);
if (dpcm->period_update_pending) {
dpcm->period_update_pending = 0;
snd_pcm_period_elapsed(dpcm->substream);
@@ -670,6 +684,7 @@ static int loopback_open(struct snd_pcm_substream *substream)
}
dpcm->loopback = loopback;
dpcm->substream = substream;
+ dpcm->timer_stopped = true;
setup_timer(&dpcm->timer, loopback_timer_function,
(unsigned long)dpcm);
spin_lock_init(&dpcm->timer_lock);
--
1.7.4.1
More information about the Alsa-devel
mailing list