• Takashi Iwai's avatar
    ALSA: hrtimer: Handle start/stop more properly · d2c5cf88
    Takashi Iwai authored
    This patch tries to address the still remaining issues in ALSA hrtimer
    - Spurious use-after-free was detected in hrtimer callback
    - Incorrect rescheduling due to delayed start
    - WARN_ON() is triggered in hrtimer_forward() invoked in hrtimer
    The first issue happens only when the new timer is scheduled even
    while hrtimer is being closed.  It's related with the second and third
    items; since ALSA timer core invokes hw.start callback during hrtimer
    interrupt, this may result in the explicit call of hrtimer_start().
    Also, the similar problem is seen for the stop; ALSA timer core
    invokes hw.stop callback even in the hrtimer handler, too.  Since we
    must not call the synced hrtimer_cancel() in such a context, it's just
    a hrtimer_try_to_cancel() call that doesn't properly work.
    Another culprit of the second and third items is the call of
    hrtimer_forward_now() before snd_timer_interrupt().  The timer->stick
    value may change during snd_timer_interrupt() call, but this
    possibility is ignored completely.
    For covering these subtle and messy issues, the following changes have
    been done in this patch:
    - A new flag, in_callback, is introduced in the private data to
      indicate that the hrtimer handler is being processed.
    - Both start and stop callbacks skip when called from (during)
      in_callback flag.
    - The hrtimer handler returns properly HRTIMER_RESTART and NORESTART
      depending on the running state now.
    - The hrtimer handler reprograms the expiry properly after
      snd_timer_interrupt() call, instead of before.
    - The close callback clears running flag and sets in_callback flag
      to block any further start/stop calls.
    Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
hrtimer.c 4.24 KB