diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-03 19:14:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-03 19:14:51 -0400 |
commit | 1b044f1cfc65a7d90b209dfabd57e16d98b58c5b (patch) | |
tree | ad657c911b563f9176b17578c0b88a1ea9916a02 /kernel/time/alarmtimer.c | |
parent | e0f3e8f14da868047c524a0cf11e08b95fd1b008 (diff) | |
parent | 2287d8664fe7345ead891017eccd879fc605305e (diff) |
Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer updates from Thomas Gleixner:
"A rather large update for timers/timekeeping:
- compat syscall consolidation (Al Viro)
- Posix timer consolidation (Christoph Helwig / Thomas Gleixner)
- Cleanup of the device tree based initialization for clockevents and
clocksources (Daniel Lezcano)
- Consolidation of the FTTMR010 clocksource/event driver (Linus
Walleij)
- The usual set of small fixes and updates all over the place"
* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (93 commits)
timers: Make the cpu base lock raw
clocksource/drivers/mips-gic-timer: Fix an error code in 'gic_clocksource_of_init()'
clocksource/drivers/fsl_ftm_timer: Unmap region obtained by of_iomap
clocksource/drivers/tcb_clksrc: Make IO endian agnostic
clocksource/drivers/sun4i: Switch to the timer-of common init
clocksource/drivers/timer-of: Fix invalid iomap check
Revert "ktime: Simplify ktime_compare implementation"
clocksource/drivers: Fix uninitialized variable use in timer_of_init
kselftests: timers: Add test for frequency step
kselftests: timers: Fix inconsistency-check to not ignore first timestamp
time: Add warning about imminent deprecation of CONFIG_GENERIC_TIME_VSYSCALL_OLD
time: Clean up CLOCK_MONOTONIC_RAW time handling
posix-cpu-timers: Make timespec to nsec conversion safe
itimer: Make timeval to nsec conversion range limited
timers: Fix parameter description of try_to_del_timer_sync()
ktime: Simplify ktime_compare implementation
clocksource/drivers/fttmr010: Factor out clock read code
clocksource/drivers/fttmr010: Implement delay timer
clocksource/drivers: Add timer-of common init routine
clocksource/drivers/tcb_clksrc: Save timer context on suspend/resume
...
Diffstat (limited to 'kernel/time/alarmtimer.c')
-rw-r--r-- | kernel/time/alarmtimer.c | 381 |
1 files changed, 161 insertions, 220 deletions
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index ee2f4202d82a..c991cf212c6d 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c | |||
@@ -27,6 +27,9 @@ | |||
27 | #include <linux/posix-timers.h> | 27 | #include <linux/posix-timers.h> |
28 | #include <linux/workqueue.h> | 28 | #include <linux/workqueue.h> |
29 | #include <linux/freezer.h> | 29 | #include <linux/freezer.h> |
30 | #include <linux/compat.h> | ||
31 | |||
32 | #include "posix-timers.h" | ||
30 | 33 | ||
31 | #define CREATE_TRACE_POINTS | 34 | #define CREATE_TRACE_POINTS |
32 | #include <trace/events/alarmtimer.h> | 35 | #include <trace/events/alarmtimer.h> |
@@ -45,11 +48,13 @@ static struct alarm_base { | |||
45 | clockid_t base_clockid; | 48 | clockid_t base_clockid; |
46 | } alarm_bases[ALARM_NUMTYPE]; | 49 | } alarm_bases[ALARM_NUMTYPE]; |
47 | 50 | ||
51 | #if defined(CONFIG_POSIX_TIMERS) || defined(CONFIG_RTC_CLASS) | ||
48 | /* freezer information to handle clock_nanosleep triggered wakeups */ | 52 | /* freezer information to handle clock_nanosleep triggered wakeups */ |
49 | static enum alarmtimer_type freezer_alarmtype; | 53 | static enum alarmtimer_type freezer_alarmtype; |
50 | static ktime_t freezer_expires; | 54 | static ktime_t freezer_expires; |
51 | static ktime_t freezer_delta; | 55 | static ktime_t freezer_delta; |
52 | static DEFINE_SPINLOCK(freezer_delta_lock); | 56 | static DEFINE_SPINLOCK(freezer_delta_lock); |
57 | #endif | ||
53 | 58 | ||
54 | static struct wakeup_source *ws; | 59 | static struct wakeup_source *ws; |
55 | 60 | ||
@@ -307,38 +312,6 @@ static int alarmtimer_resume(struct device *dev) | |||
307 | } | 312 | } |
308 | #endif | 313 | #endif |
309 | 314 | ||
310 | static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type) | ||
311 | { | ||
312 | struct alarm_base *base; | ||
313 | unsigned long flags; | ||
314 | ktime_t delta; | ||
315 | |||
316 | switch(type) { | ||
317 | case ALARM_REALTIME: | ||
318 | base = &alarm_bases[ALARM_REALTIME]; | ||
319 | type = ALARM_REALTIME_FREEZER; | ||
320 | break; | ||
321 | case ALARM_BOOTTIME: | ||
322 | base = &alarm_bases[ALARM_BOOTTIME]; | ||
323 | type = ALARM_BOOTTIME_FREEZER; | ||
324 | break; | ||
325 | default: | ||
326 | WARN_ONCE(1, "Invalid alarm type: %d\n", type); | ||
327 | return; | ||
328 | } | ||
329 | |||
330 | delta = ktime_sub(absexp, base->gettime()); | ||
331 | |||
332 | spin_lock_irqsave(&freezer_delta_lock, flags); | ||
333 | if (!freezer_delta || (delta < freezer_delta)) { | ||
334 | freezer_delta = delta; | ||
335 | freezer_expires = absexp; | ||
336 | freezer_alarmtype = type; | ||
337 | } | ||
338 | spin_unlock_irqrestore(&freezer_delta_lock, flags); | ||
339 | } | ||
340 | |||
341 | |||
342 | /** | 315 | /** |
343 | * alarm_init - Initialize an alarm structure | 316 | * alarm_init - Initialize an alarm structure |
344 | * @alarm: ptr to alarm to be initialized | 317 | * @alarm: ptr to alarm to be initialized |
@@ -488,6 +461,38 @@ u64 alarm_forward_now(struct alarm *alarm, ktime_t interval) | |||
488 | } | 461 | } |
489 | EXPORT_SYMBOL_GPL(alarm_forward_now); | 462 | EXPORT_SYMBOL_GPL(alarm_forward_now); |
490 | 463 | ||
464 | #ifdef CONFIG_POSIX_TIMERS | ||
465 | |||
466 | static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type) | ||
467 | { | ||
468 | struct alarm_base *base; | ||
469 | unsigned long flags; | ||
470 | ktime_t delta; | ||
471 | |||
472 | switch(type) { | ||
473 | case ALARM_REALTIME: | ||
474 | base = &alarm_bases[ALARM_REALTIME]; | ||
475 | type = ALARM_REALTIME_FREEZER; | ||
476 | break; | ||
477 | case ALARM_BOOTTIME: | ||
478 | base = &alarm_bases[ALARM_BOOTTIME]; | ||
479 | type = ALARM_BOOTTIME_FREEZER; | ||
480 | break; | ||
481 | default: | ||
482 | WARN_ONCE(1, "Invalid alarm type: %d\n", type); | ||
483 | return; | ||
484 | } | ||
485 | |||
486 | delta = ktime_sub(absexp, base->gettime()); | ||
487 | |||
488 | spin_lock_irqsave(&freezer_delta_lock, flags); | ||
489 | if (!freezer_delta || (delta < freezer_delta)) { | ||
490 | freezer_delta = delta; | ||
491 | freezer_expires = absexp; | ||
492 | freezer_alarmtype = type; | ||
493 | } | ||
494 | spin_unlock_irqrestore(&freezer_delta_lock, flags); | ||
495 | } | ||
491 | 496 | ||
492 | /** | 497 | /** |
493 | * clock2alarm - helper that converts from clockid to alarmtypes | 498 | * clock2alarm - helper that converts from clockid to alarmtypes |
@@ -511,22 +516,26 @@ static enum alarmtimer_type clock2alarm(clockid_t clockid) | |||
511 | static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm, | 516 | static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm, |
512 | ktime_t now) | 517 | ktime_t now) |
513 | { | 518 | { |
514 | unsigned long flags; | ||
515 | struct k_itimer *ptr = container_of(alarm, struct k_itimer, | 519 | struct k_itimer *ptr = container_of(alarm, struct k_itimer, |
516 | it.alarm.alarmtimer); | 520 | it.alarm.alarmtimer); |
517 | enum alarmtimer_restart result = ALARMTIMER_NORESTART; | 521 | enum alarmtimer_restart result = ALARMTIMER_NORESTART; |
522 | unsigned long flags; | ||
523 | int si_private = 0; | ||
518 | 524 | ||
519 | spin_lock_irqsave(&ptr->it_lock, flags); | 525 | spin_lock_irqsave(&ptr->it_lock, flags); |
520 | if ((ptr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) { | ||
521 | if (IS_ENABLED(CONFIG_POSIX_TIMERS) && | ||
522 | posix_timer_event(ptr, 0) != 0) | ||
523 | ptr->it_overrun++; | ||
524 | } | ||
525 | 526 | ||
526 | /* Re-add periodic timers */ | 527 | ptr->it_active = 0; |
527 | if (ptr->it.alarm.interval) { | 528 | if (ptr->it_interval) |
528 | ptr->it_overrun += alarm_forward(alarm, now, | 529 | si_private = ++ptr->it_requeue_pending; |
529 | ptr->it.alarm.interval); | 530 | |
531 | if (posix_timer_event(ptr, si_private) && ptr->it_interval) { | ||
532 | /* | ||
533 | * Handle ignored signals and rearm the timer. This will go | ||
534 | * away once we handle ignored signals proper. | ||
535 | */ | ||
536 | ptr->it_overrun += alarm_forward_now(alarm, ptr->it_interval); | ||
537 | ++ptr->it_requeue_pending; | ||
538 | ptr->it_active = 1; | ||
530 | result = ALARMTIMER_RESTART; | 539 | result = ALARMTIMER_RESTART; |
531 | } | 540 | } |
532 | spin_unlock_irqrestore(&ptr->it_lock, flags); | 541 | spin_unlock_irqrestore(&ptr->it_lock, flags); |
@@ -535,6 +544,72 @@ static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm, | |||
535 | } | 544 | } |
536 | 545 | ||
537 | /** | 546 | /** |
547 | * alarm_timer_rearm - Posix timer callback for rearming timer | ||
548 | * @timr: Pointer to the posixtimer data struct | ||
549 | */ | ||
550 | static void alarm_timer_rearm(struct k_itimer *timr) | ||
551 | { | ||
552 | struct alarm *alarm = &timr->it.alarm.alarmtimer; | ||
553 | |||
554 | timr->it_overrun += alarm_forward_now(alarm, timr->it_interval); | ||
555 | alarm_start(alarm, alarm->node.expires); | ||
556 | } | ||
557 | |||
558 | /** | ||
559 | * alarm_timer_forward - Posix timer callback for forwarding timer | ||
560 | * @timr: Pointer to the posixtimer data struct | ||
561 | * @now: Current time to forward the timer against | ||
562 | */ | ||
563 | static int alarm_timer_forward(struct k_itimer *timr, ktime_t now) | ||
564 | { | ||
565 | struct alarm *alarm = &timr->it.alarm.alarmtimer; | ||
566 | |||
567 | return (int) alarm_forward(alarm, timr->it_interval, now); | ||
568 | } | ||
569 | |||
570 | /** | ||
571 | * alarm_timer_remaining - Posix timer callback to retrieve remaining time | ||
572 | * @timr: Pointer to the posixtimer data struct | ||
573 | * @now: Current time to calculate against | ||
574 | */ | ||
575 | static ktime_t alarm_timer_remaining(struct k_itimer *timr, ktime_t now) | ||
576 | { | ||
577 | struct alarm *alarm = &timr->it.alarm.alarmtimer; | ||
578 | |||
579 | return ktime_sub(now, alarm->node.expires); | ||
580 | } | ||
581 | |||
582 | /** | ||
583 | * alarm_timer_try_to_cancel - Posix timer callback to cancel a timer | ||
584 | * @timr: Pointer to the posixtimer data struct | ||
585 | */ | ||
586 | static int alarm_timer_try_to_cancel(struct k_itimer *timr) | ||
587 | { | ||
588 | return alarm_try_to_cancel(&timr->it.alarm.alarmtimer); | ||
589 | } | ||
590 | |||
591 | /** | ||
592 | * alarm_timer_arm - Posix timer callback to arm a timer | ||
593 | * @timr: Pointer to the posixtimer data struct | ||
594 | * @expires: The new expiry time | ||
595 | * @absolute: Expiry value is absolute time | ||
596 | * @sigev_none: Posix timer does not deliver signals | ||
597 | */ | ||
598 | static void alarm_timer_arm(struct k_itimer *timr, ktime_t expires, | ||
599 | bool absolute, bool sigev_none) | ||
600 | { | ||
601 | struct alarm *alarm = &timr->it.alarm.alarmtimer; | ||
602 | struct alarm_base *base = &alarm_bases[alarm->type]; | ||
603 | |||
604 | if (!absolute) | ||
605 | expires = ktime_add_safe(expires, base->gettime()); | ||
606 | if (sigev_none) | ||
607 | alarm->node.expires = expires; | ||
608 | else | ||
609 | alarm_start(&timr->it.alarm.alarmtimer, expires); | ||
610 | } | ||
611 | |||
612 | /** | ||
538 | * alarm_clock_getres - posix getres interface | 613 | * alarm_clock_getres - posix getres interface |
539 | * @which_clock: clockid | 614 | * @which_clock: clockid |
540 | * @tp: timespec to fill | 615 | * @tp: timespec to fill |
@@ -591,97 +666,6 @@ static int alarm_timer_create(struct k_itimer *new_timer) | |||
591 | } | 666 | } |
592 | 667 | ||
593 | /** | 668 | /** |
594 | * alarm_timer_get - posix timer_get interface | ||
595 | * @new_timer: k_itimer pointer | ||
596 | * @cur_setting: itimerspec data to fill | ||
597 | * | ||
598 | * Copies out the current itimerspec data | ||
599 | */ | ||
600 | static void alarm_timer_get(struct k_itimer *timr, | ||
601 | struct itimerspec64 *cur_setting) | ||
602 | { | ||
603 | ktime_t relative_expiry_time = | ||
604 | alarm_expires_remaining(&(timr->it.alarm.alarmtimer)); | ||
605 | |||
606 | if (ktime_to_ns(relative_expiry_time) > 0) { | ||
607 | cur_setting->it_value = ktime_to_timespec64(relative_expiry_time); | ||
608 | } else { | ||
609 | cur_setting->it_value.tv_sec = 0; | ||
610 | cur_setting->it_value.tv_nsec = 0; | ||
611 | } | ||
612 | |||
613 | cur_setting->it_interval = ktime_to_timespec64(timr->it.alarm.interval); | ||
614 | } | ||
615 | |||
616 | /** | ||
617 | * alarm_timer_del - posix timer_del interface | ||
618 | * @timr: k_itimer pointer to be deleted | ||
619 | * | ||
620 | * Cancels any programmed alarms for the given timer. | ||
621 | */ | ||
622 | static int alarm_timer_del(struct k_itimer *timr) | ||
623 | { | ||
624 | if (!rtcdev) | ||
625 | return -ENOTSUPP; | ||
626 | |||
627 | if (alarm_try_to_cancel(&timr->it.alarm.alarmtimer) < 0) | ||
628 | return TIMER_RETRY; | ||
629 | |||
630 | return 0; | ||
631 | } | ||
632 | |||
633 | /** | ||
634 | * alarm_timer_set - posix timer_set interface | ||
635 | * @timr: k_itimer pointer to be deleted | ||
636 | * @flags: timer flags | ||
637 | * @new_setting: itimerspec to be used | ||
638 | * @old_setting: itimerspec being replaced | ||
639 | * | ||
640 | * Sets the timer to new_setting, and starts the timer. | ||
641 | */ | ||
642 | static int alarm_timer_set(struct k_itimer *timr, int flags, | ||
643 | struct itimerspec64 *new_setting, | ||
644 | struct itimerspec64 *old_setting) | ||
645 | { | ||
646 | ktime_t exp; | ||
647 | |||
648 | if (!rtcdev) | ||
649 | return -ENOTSUPP; | ||
650 | |||
651 | if (flags & ~TIMER_ABSTIME) | ||
652 | return -EINVAL; | ||
653 | |||
654 | if (old_setting) | ||
655 | alarm_timer_get(timr, old_setting); | ||
656 | |||
657 | /* If the timer was already set, cancel it */ | ||
658 | if (alarm_try_to_cancel(&timr->it.alarm.alarmtimer) < 0) | ||
659 | return TIMER_RETRY; | ||
660 | |||
661 | /* start the timer */ | ||
662 | timr->it.alarm.interval = timespec64_to_ktime(new_setting->it_interval); | ||
663 | |||
664 | /* | ||
665 | * Rate limit to the tick as a hot fix to prevent DOS. Will be | ||
666 | * mopped up later. | ||
667 | */ | ||
668 | if (timr->it.alarm.interval < TICK_NSEC) | ||
669 | timr->it.alarm.interval = TICK_NSEC; | ||
670 | |||
671 | exp = timespec64_to_ktime(new_setting->it_value); | ||
672 | /* Convert (if necessary) to absolute time */ | ||
673 | if (flags != TIMER_ABSTIME) { | ||
674 | ktime_t now; | ||
675 | |||
676 | now = alarm_bases[timr->it.alarm.alarmtimer.type].gettime(); | ||
677 | exp = ktime_add_safe(now, exp); | ||
678 | } | ||
679 | |||
680 | alarm_start(&timr->it.alarm.alarmtimer, exp); | ||
681 | return 0; | ||
682 | } | ||
683 | |||
684 | /** | ||
685 | * alarmtimer_nsleep_wakeup - Wakeup function for alarm_timer_nsleep | 669 | * alarmtimer_nsleep_wakeup - Wakeup function for alarm_timer_nsleep |
686 | * @alarm: ptr to alarm that fired | 670 | * @alarm: ptr to alarm that fired |
687 | * | 671 | * |
@@ -705,8 +689,10 @@ static enum alarmtimer_restart alarmtimer_nsleep_wakeup(struct alarm *alarm, | |||
705 | * | 689 | * |
706 | * Sets the alarm timer and sleeps until it is fired or interrupted. | 690 | * Sets the alarm timer and sleeps until it is fired or interrupted. |
707 | */ | 691 | */ |
708 | static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp) | 692 | static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp, |
693 | enum alarmtimer_type type) | ||
709 | { | 694 | { |
695 | struct restart_block *restart; | ||
710 | alarm->data = (void *)current; | 696 | alarm->data = (void *)current; |
711 | do { | 697 | do { |
712 | set_current_state(TASK_INTERRUPTIBLE); | 698 | set_current_state(TASK_INTERRUPTIBLE); |
@@ -719,36 +705,25 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp) | |||
719 | 705 | ||
720 | __set_current_state(TASK_RUNNING); | 706 | __set_current_state(TASK_RUNNING); |
721 | 707 | ||
722 | return (alarm->data == NULL); | 708 | if (!alarm->data) |
723 | } | ||
724 | |||
725 | |||
726 | /** | ||
727 | * update_rmtp - Update remaining timespec value | ||
728 | * @exp: expiration time | ||
729 | * @type: timer type | ||
730 | * @rmtp: user pointer to remaining timepsec value | ||
731 | * | ||
732 | * Helper function that fills in rmtp value with time between | ||
733 | * now and the exp value | ||
734 | */ | ||
735 | static int update_rmtp(ktime_t exp, enum alarmtimer_type type, | ||
736 | struct timespec __user *rmtp) | ||
737 | { | ||
738 | struct timespec rmt; | ||
739 | ktime_t rem; | ||
740 | |||
741 | rem = ktime_sub(exp, alarm_bases[type].gettime()); | ||
742 | |||
743 | if (rem <= 0) | ||
744 | return 0; | 709 | return 0; |
745 | rmt = ktime_to_timespec(rem); | ||
746 | 710 | ||
747 | if (copy_to_user(rmtp, &rmt, sizeof(*rmtp))) | 711 | if (freezing(current)) |
748 | return -EFAULT; | 712 | alarmtimer_freezerset(absexp, type); |
713 | restart = ¤t->restart_block; | ||
714 | if (restart->nanosleep.type != TT_NONE) { | ||
715 | struct timespec rmt; | ||
716 | ktime_t rem; | ||
717 | |||
718 | rem = ktime_sub(absexp, alarm_bases[type].gettime()); | ||
749 | 719 | ||
750 | return 1; | 720 | if (rem <= 0) |
721 | return 0; | ||
722 | rmt = ktime_to_timespec(rem); | ||
751 | 723 | ||
724 | return nanosleep_copyout(restart, &rmt); | ||
725 | } | ||
726 | return -ERESTART_RESTARTBLOCK; | ||
752 | } | 727 | } |
753 | 728 | ||
754 | /** | 729 | /** |
@@ -760,32 +735,12 @@ static int update_rmtp(ktime_t exp, enum alarmtimer_type type, | |||
760 | static long __sched alarm_timer_nsleep_restart(struct restart_block *restart) | 735 | static long __sched alarm_timer_nsleep_restart(struct restart_block *restart) |
761 | { | 736 | { |
762 | enum alarmtimer_type type = restart->nanosleep.clockid; | 737 | enum alarmtimer_type type = restart->nanosleep.clockid; |
763 | ktime_t exp; | 738 | ktime_t exp = restart->nanosleep.expires; |
764 | struct timespec __user *rmtp; | ||
765 | struct alarm alarm; | 739 | struct alarm alarm; |
766 | int ret = 0; | ||
767 | 740 | ||
768 | exp = restart->nanosleep.expires; | ||
769 | alarm_init(&alarm, type, alarmtimer_nsleep_wakeup); | 741 | alarm_init(&alarm, type, alarmtimer_nsleep_wakeup); |
770 | 742 | ||
771 | if (alarmtimer_do_nsleep(&alarm, exp)) | 743 | return alarmtimer_do_nsleep(&alarm, exp, type); |
772 | goto out; | ||
773 | |||
774 | if (freezing(current)) | ||
775 | alarmtimer_freezerset(exp, type); | ||
776 | |||
777 | rmtp = restart->nanosleep.rmtp; | ||
778 | if (rmtp) { | ||
779 | ret = update_rmtp(exp, type, rmtp); | ||
780 | if (ret <= 0) | ||
781 | goto out; | ||
782 | } | ||
783 | |||
784 | |||
785 | /* The other values in restart are already filled in */ | ||
786 | ret = -ERESTART_RESTARTBLOCK; | ||
787 | out: | ||
788 | return ret; | ||
789 | } | 744 | } |
790 | 745 | ||
791 | /** | 746 | /** |
@@ -798,11 +753,10 @@ out: | |||
798 | * Handles clock_nanosleep calls against _ALARM clockids | 753 | * Handles clock_nanosleep calls against _ALARM clockids |
799 | */ | 754 | */ |
800 | static int alarm_timer_nsleep(const clockid_t which_clock, int flags, | 755 | static int alarm_timer_nsleep(const clockid_t which_clock, int flags, |
801 | struct timespec64 *tsreq, | 756 | const struct timespec64 *tsreq) |
802 | struct timespec __user *rmtp) | ||
803 | { | 757 | { |
804 | enum alarmtimer_type type = clock2alarm(which_clock); | 758 | enum alarmtimer_type type = clock2alarm(which_clock); |
805 | struct restart_block *restart; | 759 | struct restart_block *restart = ¤t->restart_block; |
806 | struct alarm alarm; | 760 | struct alarm alarm; |
807 | ktime_t exp; | 761 | ktime_t exp; |
808 | int ret = 0; | 762 | int ret = 0; |
@@ -825,35 +779,36 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags, | |||
825 | exp = ktime_add(now, exp); | 779 | exp = ktime_add(now, exp); |
826 | } | 780 | } |
827 | 781 | ||
828 | if (alarmtimer_do_nsleep(&alarm, exp)) | 782 | ret = alarmtimer_do_nsleep(&alarm, exp, type); |
829 | goto out; | 783 | if (ret != -ERESTART_RESTARTBLOCK) |
830 | 784 | return ret; | |
831 | if (freezing(current)) | ||
832 | alarmtimer_freezerset(exp, type); | ||
833 | 785 | ||
834 | /* abs timers don't set remaining time or restart */ | 786 | /* abs timers don't set remaining time or restart */ |
835 | if (flags == TIMER_ABSTIME) { | 787 | if (flags == TIMER_ABSTIME) |
836 | ret = -ERESTARTNOHAND; | 788 | return -ERESTARTNOHAND; |
837 | goto out; | ||
838 | } | ||
839 | 789 | ||
840 | if (rmtp) { | ||
841 | ret = update_rmtp(exp, type, rmtp); | ||
842 | if (ret <= 0) | ||
843 | goto out; | ||
844 | } | ||
845 | |||
846 | restart = ¤t->restart_block; | ||
847 | restart->fn = alarm_timer_nsleep_restart; | 790 | restart->fn = alarm_timer_nsleep_restart; |
848 | restart->nanosleep.clockid = type; | 791 | restart->nanosleep.clockid = type; |
849 | restart->nanosleep.expires = exp; | 792 | restart->nanosleep.expires = exp; |
850 | restart->nanosleep.rmtp = rmtp; | ||
851 | ret = -ERESTART_RESTARTBLOCK; | ||
852 | |||
853 | out: | ||
854 | return ret; | 793 | return ret; |
855 | } | 794 | } |
856 | 795 | ||
796 | const struct k_clock alarm_clock = { | ||
797 | .clock_getres = alarm_clock_getres, | ||
798 | .clock_get = alarm_clock_get, | ||
799 | .timer_create = alarm_timer_create, | ||
800 | .timer_set = common_timer_set, | ||
801 | .timer_del = common_timer_del, | ||
802 | .timer_get = common_timer_get, | ||
803 | .timer_arm = alarm_timer_arm, | ||
804 | .timer_rearm = alarm_timer_rearm, | ||
805 | .timer_forward = alarm_timer_forward, | ||
806 | .timer_remaining = alarm_timer_remaining, | ||
807 | .timer_try_to_cancel = alarm_timer_try_to_cancel, | ||
808 | .nsleep = alarm_timer_nsleep, | ||
809 | }; | ||
810 | #endif /* CONFIG_POSIX_TIMERS */ | ||
811 | |||
857 | 812 | ||
858 | /* Suspend hook structures */ | 813 | /* Suspend hook structures */ |
859 | static const struct dev_pm_ops alarmtimer_pm_ops = { | 814 | static const struct dev_pm_ops alarmtimer_pm_ops = { |
@@ -879,23 +834,9 @@ static int __init alarmtimer_init(void) | |||
879 | struct platform_device *pdev; | 834 | struct platform_device *pdev; |
880 | int error = 0; | 835 | int error = 0; |
881 | int i; | 836 | int i; |
882 | struct k_clock alarm_clock = { | ||
883 | .clock_getres = alarm_clock_getres, | ||
884 | .clock_get = alarm_clock_get, | ||
885 | .timer_create = alarm_timer_create, | ||
886 | .timer_set = alarm_timer_set, | ||
887 | .timer_del = alarm_timer_del, | ||
888 | .timer_get = alarm_timer_get, | ||
889 | .nsleep = alarm_timer_nsleep, | ||
890 | }; | ||
891 | 837 | ||
892 | alarmtimer_rtc_timer_init(); | 838 | alarmtimer_rtc_timer_init(); |
893 | 839 | ||
894 | if (IS_ENABLED(CONFIG_POSIX_TIMERS)) { | ||
895 | posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock); | ||
896 | posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock); | ||
897 | } | ||
898 | |||
899 | /* Initialize alarm bases */ | 840 | /* Initialize alarm bases */ |
900 | alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME; | 841 | alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME; |
901 | alarm_bases[ALARM_REALTIME].gettime = &ktime_get_real; | 842 | alarm_bases[ALARM_REALTIME].gettime = &ktime_get_real; |