diff options
author | Richard Larocque <rlarocque@google.com> | 2014-09-09 21:31:05 -0400 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2014-09-12 16:59:12 -0400 |
commit | 474e941bed9262f5fa2394f9a4a67e24499e5926 (patch) | |
tree | 1295960e17591bead96c9ae706d15c51bd68e468 /kernel | |
parent | 265b81d23a46c39df0a735a3af4238954b41a4c2 (diff) |
alarmtimer: Lock k_itimer during timer callback
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: stable@vger.kernel.org
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: Richard Larocque <rlarocque@google.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/time/alarmtimer.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 41a925396830..a7077d3ae52f 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c | |||
@@ -464,8 +464,12 @@ static enum alarmtimer_type clock2alarm(clockid_t clockid) | |||
464 | static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm, | 464 | static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm, |
465 | ktime_t now) | 465 | ktime_t now) |
466 | { | 466 | { |
467 | unsigned long flags; | ||
467 | struct k_itimer *ptr = container_of(alarm, struct k_itimer, | 468 | struct k_itimer *ptr = container_of(alarm, struct k_itimer, |
468 | it.alarm.alarmtimer); | 469 | it.alarm.alarmtimer); |
470 | enum alarmtimer_restart result = ALARMTIMER_NORESTART; | ||
471 | |||
472 | spin_lock_irqsave(&ptr->it_lock, flags); | ||
469 | if ((ptr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) { | 473 | if ((ptr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) { |
470 | if (posix_timer_event(ptr, 0) != 0) | 474 | if (posix_timer_event(ptr, 0) != 0) |
471 | ptr->it_overrun++; | 475 | ptr->it_overrun++; |
@@ -475,9 +479,11 @@ static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm, | |||
475 | if (ptr->it.alarm.interval.tv64) { | 479 | if (ptr->it.alarm.interval.tv64) { |
476 | ptr->it_overrun += alarm_forward(alarm, now, | 480 | ptr->it_overrun += alarm_forward(alarm, now, |
477 | ptr->it.alarm.interval); | 481 | ptr->it.alarm.interval); |
478 | return ALARMTIMER_RESTART; | 482 | result = ALARMTIMER_RESTART; |
479 | } | 483 | } |
480 | return ALARMTIMER_NORESTART; | 484 | spin_unlock_irqrestore(&ptr->it_lock, flags); |
485 | |||
486 | return result; | ||
481 | } | 487 | } |
482 | 488 | ||
483 | /** | 489 | /** |