diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-07-19 12:25:03 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-07-19 12:25:03 -0400 |
| commit | b495c23cd4ed0a7ad827eb07c7c9f61767f6674f (patch) | |
| tree | 01f711ddc0aaa6a42b75ccab99499b78a18e580d /kernel | |
| parent | da5b99b4545e2bae9a08876e6e827589dbfdcd9a (diff) | |
| parent | 16927776ae757d0d132bdbfabbfe2c498342bd59 (diff) | |
Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer fix from Thomas Gleixner:
"A single fix for a long standing issue in the alarm timer subsystem,
which was noticed recently when people finally started to use alarm
timers for serious work"
* 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
alarmtimer: Fix bug where relative alarm timers were treated as absolute
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/time/alarmtimer.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 88c9c65a430d..fe75444ae7ec 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c | |||
| @@ -585,9 +585,14 @@ static int alarm_timer_set(struct k_itimer *timr, int flags, | |||
| 585 | struct itimerspec *new_setting, | 585 | struct itimerspec *new_setting, |
| 586 | struct itimerspec *old_setting) | 586 | struct itimerspec *old_setting) |
| 587 | { | 587 | { |
| 588 | ktime_t exp; | ||
| 589 | |||
| 588 | if (!rtcdev) | 590 | if (!rtcdev) |
| 589 | return -ENOTSUPP; | 591 | return -ENOTSUPP; |
| 590 | 592 | ||
| 593 | if (flags & ~TIMER_ABSTIME) | ||
| 594 | return -EINVAL; | ||
| 595 | |||
| 591 | if (old_setting) | 596 | if (old_setting) |
| 592 | alarm_timer_get(timr, old_setting); | 597 | alarm_timer_get(timr, old_setting); |
| 593 | 598 | ||
| @@ -597,8 +602,16 @@ static int alarm_timer_set(struct k_itimer *timr, int flags, | |||
| 597 | 602 | ||
| 598 | /* start the timer */ | 603 | /* start the timer */ |
| 599 | timr->it.alarm.interval = timespec_to_ktime(new_setting->it_interval); | 604 | timr->it.alarm.interval = timespec_to_ktime(new_setting->it_interval); |
| 600 | alarm_start(&timr->it.alarm.alarmtimer, | 605 | exp = timespec_to_ktime(new_setting->it_value); |
| 601 | timespec_to_ktime(new_setting->it_value)); | 606 | /* Convert (if necessary) to absolute time */ |
| 607 | if (flags != TIMER_ABSTIME) { | ||
| 608 | ktime_t now; | ||
| 609 | |||
| 610 | now = alarm_bases[timr->it.alarm.alarmtimer.type].gettime(); | ||
| 611 | exp = ktime_add(now, exp); | ||
| 612 | } | ||
| 613 | |||
| 614 | alarm_start(&timr->it.alarm.alarmtimer, exp); | ||
| 602 | return 0; | 615 | return 0; |
| 603 | } | 616 | } |
| 604 | 617 | ||
| @@ -730,6 +743,9 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags, | |||
| 730 | if (!alarmtimer_get_rtcdev()) | 743 | if (!alarmtimer_get_rtcdev()) |
| 731 | return -ENOTSUPP; | 744 | return -ENOTSUPP; |
| 732 | 745 | ||
| 746 | if (flags & ~TIMER_ABSTIME) | ||
| 747 | return -EINVAL; | ||
| 748 | |||
| 733 | if (!capable(CAP_WAKE_ALARM)) | 749 | if (!capable(CAP_WAKE_ALARM)) |
| 734 | return -EPERM; | 750 | return -EPERM; |
| 735 | 751 | ||
