ALSA: seq: Process queue tempo/ppq change in a shot
authorTakashi Iwai <tiwai@suse.de>
Mon, 15 Jan 2018 15:48:36 +0000 (16:48 +0100)
committerTakashi Iwai <tiwai@suse.de>
Mon, 15 Jan 2018 15:48:36 +0000 (16:48 +0100)
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>
sound/core/seq/seq_queue.c
sound/core/seq/seq_timer.c
sound/core/seq/seq_timer.h

index 79e0c56..0428e90 100644 (file)
@@ -497,9 +497,7 @@ int snd_seq_queue_timer_set_tempo(int queueid, int client,
                return -EPERM;
        }
 
-       result = snd_seq_timer_set_tempo(q->timer, info->tempo);
-       if (result >= 0)
-               result = snd_seq_timer_set_ppq(q->timer, info->ppq);
+       result = snd_seq_timer_set_tempo_ppq(q->timer, info->tempo, info->ppq);
        if (result >= 0 && info->skew_base > 0)
                result = snd_seq_timer_set_skew(q->timer, info->skew_value,
                                                info->skew_base);
index b80985f..2316757 100644 (file)
@@ -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;
 }
index 9506b66..62f3906 100644 (file)
@@ -131,7 +131,7 @@ int snd_seq_timer_stop(struct snd_seq_timer *tmr);
 int snd_seq_timer_start(struct snd_seq_timer *tmr);
 int snd_seq_timer_continue(struct snd_seq_timer *tmr);
 int snd_seq_timer_set_tempo(struct snd_seq_timer *tmr, int tempo);
-int snd_seq_timer_set_ppq(struct snd_seq_timer *tmr, int ppq);
+int snd_seq_timer_set_tempo_ppq(struct snd_seq_timer *tmr, int tempo, int ppq);
 int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr, snd_seq_tick_time_t position);
 int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr, snd_seq_real_time_t position);
 int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew, unsigned int base);