Commit 6ba3934d authored by Richard Larocque's avatar Richard Larocque Committed by Greg Kroah-Hartman

alarmtimer: Lock k_itimer during timer callback

commit 474e941b upstream.

Locks the k_itimer's it_lock member when handling the alarm timer's
expiry callback.

The regular posix timers defined in posix-timers.c have this lock held
during timout processing because their callbacks are routed through
posix_timer_fn().  The alarm timers follow a different path, so they
ought to grab the lock somewhere else.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Sharvil Nanavati <sharvil@google.com>
Signed-off-by: default avatarRichard Larocque <rlarocque@google.com>
Signed-off-by: default avatarJohn Stultz <john.stultz@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f11d2259
...@@ -464,8 +464,12 @@ static enum alarmtimer_type clock2alarm(clockid_t clockid) ...@@ -464,8 +464,12 @@ static enum alarmtimer_type clock2alarm(clockid_t clockid)
static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm, static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm,
ktime_t now) ktime_t now)
{ {
unsigned long flags;
struct k_itimer *ptr = container_of(alarm, struct k_itimer, struct k_itimer *ptr = container_of(alarm, struct k_itimer,
it.alarm.alarmtimer); it.alarm.alarmtimer);
enum alarmtimer_restart result = ALARMTIMER_NORESTART;
spin_lock_irqsave(&ptr->it_lock, flags);
if ((ptr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) { if ((ptr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) {
if (posix_timer_event(ptr, 0) != 0) if (posix_timer_event(ptr, 0) != 0)
ptr->it_overrun++; ptr->it_overrun++;
...@@ -475,9 +479,11 @@ static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm, ...@@ -475,9 +479,11 @@ static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm,
if (ptr->it.alarm.interval.tv64) { if (ptr->it.alarm.interval.tv64) {
ptr->it_overrun += alarm_forward(alarm, now, ptr->it_overrun += alarm_forward(alarm, now,
ptr->it.alarm.interval); ptr->it.alarm.interval);
return ALARMTIMER_RESTART; result = ALARMTIMER_RESTART;
} }
return ALARMTIMER_NORESTART; spin_unlock_irqrestore(&ptr->it_lock, flags);
return result;
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment