Re: [PATCH 23/25] ALSA/dummy: Replace tasklet with softirq hrtimer
From: Takashi Sakamoto
Date: Thu Aug 31 2017 - 10:21:27 EST
Hi,
On Aug 31 2017 21:23, Anna-Maria Gleixner wrote:
> From: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
>
> The tasklet is used to defer the execution of snd_pcm_period_elapsed() to
> the softirq context. Using the CLOCK_MONOTONIC_SOFT base invokes the timer
> callback in softirq context as well which renders the tasklet useless.
>
> Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
> Signed-off-by: Anna-Maria Gleixner <anna-maria@xxxxxxxxxxxxx>
> Cc: Jaroslav Kysela <perex@xxxxxxxx>
> Cc: Takashi Iwai <tiwai@xxxxxxxx>
> Cc: Takashi Sakamoto <o-takashi@xxxxxxxxxxxxx>
> Cc: alsa-devel@xxxxxxxxxxxxxxxx
> ---
> sound/drivers/dummy.c | 16 +++-------------
> 1 file changed, 3 insertions(+), 13 deletions(-)
I prefer this patch as long as this driver can still receive callbacks
from hrtimer subsystem.
Reviewed-by: Takashi Sakamoto <o-takashi@xxxxxxxxxxxxx>
Unfortunately, I have too poor machine to compile whole kernel now, thus
didn't do any tests, sorry.
I note that ALSA pcsp driver uses a combination of hrtimer/tasklet for the
same purpose. I think we can simplify it, too. Please refer to a patch in
the end of this message. (But not tested yet for the above reason...)
> --- a/sound/drivers/dummy.c
> +++ b/sound/drivers/dummy.c
> @@ -376,17 +376,9 @@ struct dummy_hrtimer_pcm {
> ktime_t period_time;
> atomic_t running;
> struct hrtimer timer;
> - struct tasklet_struct tasklet;
> struct snd_pcm_substream *substream;
> };
>
> -static void dummy_hrtimer_pcm_elapsed(unsigned long priv)
> -{
> - struct dummy_hrtimer_pcm *dpcm = (struct dummy_hrtimer_pcm *)priv;
> - if (atomic_read(&dpcm->running))
> - snd_pcm_period_elapsed(dpcm->substream);
> -}
> -
> static enum hrtimer_restart dummy_hrtimer_callback(struct hrtimer *timer)
> {
> struct dummy_hrtimer_pcm *dpcm;
> @@ -394,7 +386,8 @@ static enum hrtimer_restart dummy_hrtime
> dpcm = container_of(timer, struct dummy_hrtimer_pcm, timer);
> if (!atomic_read(&dpcm->running))
> return HRTIMER_NORESTART;
> - tasklet_schedule(&dpcm->tasklet);
> +
> + snd_pcm_period_elapsed(dpcm->substream);
> hrtimer_forward_now(timer, dpcm->period_time);
> return HRTIMER_RESTART;
> }
> @@ -421,7 +414,6 @@ static int dummy_hrtimer_stop(struct snd
> static inline void dummy_hrtimer_sync(struct dummy_hrtimer_pcm *dpcm)
> {
> hrtimer_cancel(&dpcm->timer);
> - tasklet_kill(&dpcm->tasklet);
> }
>
> static snd_pcm_uframes_t
> @@ -466,12 +458,10 @@ static int dummy_hrtimer_create(struct s
> if (!dpcm)
> return -ENOMEM;
> substream->runtime->private_data = dpcm;
> - hrtimer_init(&dpcm->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> + hrtimer_init(&dpcm->timer, CLOCK_MONOTONIC_SOFT, HRTIMER_MODE_REL);
> dpcm->timer.function = dummy_hrtimer_callback;
> dpcm->substream = substream;
> atomic_set(&dpcm->running, 0);
> - tasklet_init(&dpcm->tasklet, dummy_hrtimer_pcm_elapsed,
> - (unsigned long)dpcm);
> return 0;
> }