summaryrefslogtreecommitdiff
path: root/sound/core/seq/seq_timer.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2018-01-15 16:48:36 +0100
committerTakashi Iwai <tiwai@suse.de>2018-01-15 16:48:36 +0100
commit671ec859e5ee06ab0bf968e639a25576b18865ad (patch)
tree43385603e1e54f05587ec7f6fe0eb63bba9498a9 /sound/core/seq/seq_timer.c
parent4ea5553a51e55664f86bed29e62e67ecb45bedd8 (diff)
ALSA: seq: Process queue tempo/ppq change in a shot
The SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO ioctl sets the tempo and the ppq in a single call, while the current implementation updates each value one by one. This is a bit racy, and also suboptimal from the performance POV, as each call does re-acquire the lock and invokes the update of ALSA timer resolution. This patch reorganizes the code slightly so that we change both the tempo and the ppq in a shot. The skew value can be put into the same lock, but this is rather a rarely used feature and completely independent from the temp/ppq (it's evaluated only in the interrupt), so it's left as it was. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core/seq/seq_timer.c')
-rw-r--r--sound/core/seq/seq_timer.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index b80985fbc334..23167578231f 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -191,14 +191,15 @@ int snd_seq_timer_set_tempo(struct snd_seq_timer * tmr, int tempo)
return 0;
}
-/* set current ppq */
-int snd_seq_timer_set_ppq(struct snd_seq_timer * tmr, int ppq)
+/* set current tempo and ppq in a shot */
+int snd_seq_timer_set_tempo_ppq(struct snd_seq_timer *tmr, int tempo, int ppq)
{
+ int changed;
unsigned long flags;
if (snd_BUG_ON(!tmr))
return -EINVAL;
- if (ppq <= 0)
+ if (tempo <= 0 || ppq <= 0)
return -EINVAL;
spin_lock_irqsave(&tmr->lock, flags);
if (tmr->running && (ppq != tmr->ppq)) {
@@ -208,9 +209,11 @@ int snd_seq_timer_set_ppq(struct snd_seq_timer * tmr, int ppq)
pr_debug("ALSA: seq: cannot change ppq of a running timer\n");
return -EBUSY;
}
-
+ changed = (tempo != tmr->tempo) || (ppq != tmr->ppq);
+ tmr->tempo = tempo;
tmr->ppq = ppq;
- snd_seq_timer_set_tick_resolution(tmr);
+ if (changed)
+ snd_seq_timer_set_tick_resolution(tmr);
spin_unlock_irqrestore(&tmr->lock, flags);
return 0;
}