aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorRichard Larocque <rlarocque@google.com>2014-09-09 21:31:05 -0400
committerJohn Stultz <john.stultz@linaro.org>2014-09-12 16:59:12 -0400
commit474e941bed9262f5fa2394f9a4a67e24499e5926 (patch)
tree1295960e17591bead96c9ae706d15c51bd68e468 /kernel
parent265b81d23a46c39df0a735a3af4238954b41a4c2 (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.c10
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)
464static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm, 464static 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/**