lkml.org 
[lkml]   [2009]   [Dec]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[027/151] ALSA: hrtimer - Fix lock-up
    2.6.32-stable review patch.  If anyone has any objections, please let us know.

    ------------------

    From: Takashi Iwai <tiwai@suse.de>

    commit fcfdebe70759c74e2e701f69aaa7f0e5e32cf5a6 upstream.

    The timer stop callback can be called from snd_timer_interrupt(), which
    is called from the hrtimer callback. Since hrtimer_cancel() waits for
    the callback completion, this eventually results in a lock-up.

    This patch fixes the problem by just toggling a flag at stop callback
    and call hrtimer_cancel() later.

    Reported-and-tested-by: Wojtek Zabolotny <W.Zabolotny@elka.pw.edu.pl>
    Signed-off-by: Takashi Iwai <tiwai@suse.de>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    sound/core/hrtimer.c | 15 +++++++++++++--
    1 file changed, 13 insertions(+), 2 deletions(-)

    --- a/sound/core/hrtimer.c
    +++ b/sound/core/hrtimer.c
    @@ -37,14 +37,22 @@ static unsigned int resolution;
    struct snd_hrtimer {
    struct snd_timer *timer;
    struct hrtimer hrt;
    + atomic_t running;
    };

    static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt)
    {
    struct snd_hrtimer *stime = container_of(hrt, struct snd_hrtimer, hrt);
    struct snd_timer *t = stime->timer;
    +
    + if (!atomic_read(&stime->running))
    + return HRTIMER_NORESTART;
    +
    hrtimer_forward_now(hrt, ns_to_ktime(t->sticks * resolution));
    snd_timer_interrupt(stime->timer, t->sticks);
    +
    + if (!atomic_read(&stime->running))
    + return HRTIMER_NORESTART;
    return HRTIMER_RESTART;
    }

    @@ -58,6 +66,7 @@ static int snd_hrtimer_open(struct snd_t
    hrtimer_init(&stime->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    stime->timer = t;
    stime->hrt.function = snd_hrtimer_callback;
    + atomic_set(&stime->running, 0);
    t->private_data = stime;
    return 0;
    }
    @@ -78,16 +87,18 @@ static int snd_hrtimer_start(struct snd_
    {
    struct snd_hrtimer *stime = t->private_data;

    + atomic_set(&stime->running, 0);
    + hrtimer_cancel(&stime->hrt);
    hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution),
    HRTIMER_MODE_REL);
    + atomic_set(&stime->running, 1);
    return 0;
    }

    static int snd_hrtimer_stop(struct snd_timer *t)
    {
    struct snd_hrtimer *stime = t->private_data;
    -
    - hrtimer_cancel(&stime->hrt);
    + atomic_set(&stime->running, 0);
    return 0;
    }




    \
     
     \ /
      Last update: 2009-12-17 05:57    [W:4.063 / U:0.396 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site