summaryrefslogtreecommitdiff
path: root/kernel/time/alarmtimer.c
diff options
context:
space:
mode:
authorRichard Larocque <rlarocque@google.com>2014-09-10 05:31:05 +0400
committerJohn Stultz <john.stultz@linaro.org>2014-09-13 00:59:12 +0400
commit474e941bed9262f5fa2394f9a4a67e24499e5926 (patch)
tree1295960e17591bead96c9ae706d15c51bd68e468 /kernel/time/alarmtimer.c
parent265b81d23a46c39df0a735a3af4238954b41a4c2 (diff)
downloadlinux-474e941bed9262f5fa2394f9a4a67e24499e5926.tar.xz
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/time/alarmtimer.c')
-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)
static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm,
ktime_t now)
{
+ unsigned long flags;
struct k_itimer *ptr = container_of(alarm, struct k_itimer,
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 (posix_timer_event(ptr, 0) != 0)
ptr->it_overrun++;
@@ -475,9 +479,11 @@ static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm,
if (ptr->it.alarm.interval.tv64) {
ptr->it_overrun += alarm_forward(alarm, now,
ptr->it.alarm.interval);
- return ALARMTIMER_RESTART;
+ result = ALARMTIMER_RESTART;
}
- return ALARMTIMER_NORESTART;
+ spin_unlock_irqrestore(&ptr->it_lock, flags);
+
+ return result;
}
/**