alarmtimer: Switch over to generic set/get/rearm routine
authorThomas Gleixner <tglx@linutronix.de>
Tue, 30 May 2017 21:15:59 +0000 (23:15 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Sun, 4 Jun 2017 13:40:32 +0000 (15:40 +0200)
All required callbacks are in place. Switch the alarm timer based posix
interval timer callbacks to the common implementation and remove the
incorrect private implementation.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: John Stultz <john.stultz@linaro.org>
Link: http://lkml.kernel.org/r/20170530211657.825471962@linutronix.de
kernel/time/alarmtimer.c
kernel/time/posix-timers.c
kernel/time/posix-timers.h

index c618a44..d8a7a7e 100644 (file)
@@ -515,20 +515,26 @@ 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);
+                                           it.alarm.alarmtimer);
        enum alarmtimer_restart result = ALARMTIMER_NORESTART;
+       unsigned long flags;
+       int si_private = 0;
 
        spin_lock_irqsave(&ptr->it_lock, flags);
-       if ((ptr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) {
-               if (posix_timer_event(ptr, 0))
-                       ptr->it_overrun++;
-       }
 
-       /* Re-add periodic timers */
-       if (ptr->it_interval) {
-               ptr->it_overrun += alarm_forward(alarm, now, ptr->it_interval);
+       ptr->it_active = 0;
+       if (ptr->it_interval)
+               si_private = ++ptr->it_requeue_pending;
+
+       if (posix_timer_event(ptr, si_private) && ptr->it_interval) {
+               /*
+                * Handle ignored signals and rearm the timer. This will go
+                * away once we handle ignored signals proper.
+                */
+               ptr->it_overrun += alarm_forward_now(alarm, ptr->it_interval);
+               ++ptr->it_requeue_pending;
+               ptr->it_active = 1;
                result = ALARMTIMER_RESTART;
        }
        spin_unlock_irqrestore(&ptr->it_lock, flags);
@@ -658,97 +664,6 @@ static int alarm_timer_create(struct k_itimer *new_timer)
        return 0;
 }
 
-/**
- * alarm_timer_get - posix timer_get interface
- * @timr: k_itimer pointer
- * @cur_setting: itimerspec data to fill
- *
- * Copies out the current itimerspec data
- */
-static void alarm_timer_get(struct k_itimer *timr,
-                           struct itimerspec64 *cur_setting)
-{
-       ktime_t relative_expiry_time =
-               alarm_expires_remaining(&(timr->it.alarm.alarmtimer));
-
-       if (ktime_to_ns(relative_expiry_time) > 0) {
-               cur_setting->it_value = ktime_to_timespec64(relative_expiry_time);
-       } else {
-               cur_setting->it_value.tv_sec = 0;
-               cur_setting->it_value.tv_nsec = 0;
-       }
-
-       cur_setting->it_interval = ktime_to_timespec64(timr->it_interval);
-}
-
-/**
- * alarm_timer_del - posix timer_del interface
- * @timr: k_itimer pointer to be deleted
- *
- * Cancels any programmed alarms for the given timer.
- */
-static int alarm_timer_del(struct k_itimer *timr)
-{
-       if (!rtcdev)
-               return -ENOTSUPP;
-
-       if (alarm_try_to_cancel(&timr->it.alarm.alarmtimer) < 0)
-               return TIMER_RETRY;
-
-       return 0;
-}
-
-/**
- * alarm_timer_set - posix timer_set interface
- * @timr: k_itimer pointer to be deleted
- * @flags: timer flags
- * @new_setting: itimerspec to be used
- * @old_setting: itimerspec being replaced
- *
- * Sets the timer to new_setting, and starts the timer.
- */
-static int alarm_timer_set(struct k_itimer *timr, int flags,
-                          struct itimerspec64 *new_setting,
-                          struct itimerspec64 *old_setting)
-{
-       ktime_t exp;
-
-       if (!rtcdev)
-               return -ENOTSUPP;
-
-       if (flags & ~TIMER_ABSTIME)
-               return -EINVAL;
-
-       if (old_setting)
-               alarm_timer_get(timr, old_setting);
-
-       /* If the timer was already set, cancel it */
-       if (alarm_try_to_cancel(&timr->it.alarm.alarmtimer) < 0)
-               return TIMER_RETRY;
-
-       /* start the timer */
-       timr->it_interval = timespec64_to_ktime(new_setting->it_interval);
-
-       /*
-        * Rate limit to the tick as a hot fix to prevent DOS. Will be
-        * mopped up later.
-        */
-       if (timr->it_interval < TICK_NSEC)
-               timr->it_interval = TICK_NSEC;
-
-       exp = timespec64_to_ktime(new_setting->it_value);
-       /* Convert (if necessary) to absolute time */
-       if (flags != TIMER_ABSTIME) {
-               ktime_t now;
-
-               now = alarm_bases[timr->it.alarm.alarmtimer.type].gettime();
-               exp = ktime_add_safe(now, exp);
-       }
-
-       alarm_start(&timr->it.alarm.alarmtimer, exp);
-       return 0;
-}
-
 /**
  * alarmtimer_nsleep_wakeup - Wakeup function for alarm_timer_nsleep
  * @alarm: ptr to alarm that fired
@@ -926,9 +841,9 @@ const struct k_clock alarm_clock = {
        .clock_getres           = alarm_clock_getres,
        .clock_get              = alarm_clock_get,
        .timer_create           = alarm_timer_create,
-       .timer_set              = alarm_timer_set,
-       .timer_del              = alarm_timer_del,
-       .timer_get              = alarm_timer_get,
+       .timer_set              = common_timer_set,
+       .timer_del              = common_timer_del,
+       .timer_get              = common_timer_get,
        .timer_arm              = alarm_timer_arm,
        .timer_rearm            = alarm_timer_rearm,
        .timer_forward          = alarm_timer_forward,
index 8acc9ee..6e7a70b 100644 (file)
@@ -637,8 +637,7 @@ static int common_hrtimer_forward(struct k_itimer *timr, ktime_t now)
  * it is the same as a requeue pending timer WRT to what we should
  * report.
  */
-static void
-common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)
+void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)
 {
        const struct k_clock *kc = timr->kclock;
        ktime_t now, remaining, iv;
@@ -768,10 +767,9 @@ static int common_hrtimer_try_to_cancel(struct k_itimer *timr)
 }
 
 /* Set a POSIX.1b interval timer. */
-static int
-common_timer_set(struct k_itimer *timr, int flags,
-                struct itimerspec64 *new_setting,
-                struct itimerspec64 *old_setting)
+int common_timer_set(struct k_itimer *timr, int flags,
+                    struct itimerspec64 *new_setting,
+                    struct itimerspec64 *old_setting)
 {
        const struct k_clock *kc = timr->kclock;
        bool sigev_none;
@@ -855,7 +853,7 @@ retry:
        return error;
 }
 
-static int common_timer_del(struct k_itimer *timer)
+int common_timer_del(struct k_itimer *timer)
 {
        const struct k_clock *kc = timer->kclock;
 
index b0ad77e..b086f5b 100644 (file)
@@ -33,3 +33,9 @@ extern const struct k_clock clock_thread;
 extern const struct k_clock alarm_clock;
 
 int posix_timer_event(struct k_itimer *timr, int si_private);
+
+void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting);
+int common_timer_set(struct k_itimer *timr, int flags,
+                    struct itimerspec64 *new_setting,
+                    struct itimerspec64 *old_setting);
+int common_timer_del(struct k_itimer *timer);