From d3ba5a9a345b1243276f8a982e1bce557c2504fd Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 26 May 2017 12:03:11 +0300 Subject: posix-timers: Make posix_clocks immutable There are no more modular users providing a posix clock. The register function is now pointless so the posix clock array can be initialized statically at compile time and the array including the various k_clock structs can be marked 'const'. Inspired by changes in the Grsecurity patch set, but done proper. [ tglx: Massaged changelog and fixed the POSIX_TIMER=n case ] Signed-off-by: Christoph Hellwig Signed-off-by: Thomas Gleixner Cc: Mike Travis Cc: Dimitri Sivanich Link: http://lkml.kernel.org/r/20170526090311.3377-3-hch@lst.de --- kernel/time/alarmtimer.c | 89 +++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 46 deletions(-) (limited to 'kernel/time/alarmtimer.c') diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 5cb5b0008d97..4f4cc3509b30 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -307,38 +307,6 @@ static int alarmtimer_resume(struct device *dev) } #endif -static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type) -{ - struct alarm_base *base; - unsigned long flags; - ktime_t delta; - - switch(type) { - case ALARM_REALTIME: - base = &alarm_bases[ALARM_REALTIME]; - type = ALARM_REALTIME_FREEZER; - break; - case ALARM_BOOTTIME: - base = &alarm_bases[ALARM_BOOTTIME]; - type = ALARM_BOOTTIME_FREEZER; - break; - default: - WARN_ONCE(1, "Invalid alarm type: %d\n", type); - return; - } - - delta = ktime_sub(absexp, base->gettime()); - - spin_lock_irqsave(&freezer_delta_lock, flags); - if (!freezer_delta || (delta < freezer_delta)) { - freezer_delta = delta; - freezer_expires = absexp; - freezer_alarmtype = type; - } - spin_unlock_irqrestore(&freezer_delta_lock, flags); -} - - /** * alarm_init - Initialize an alarm structure * @alarm: ptr to alarm to be initialized @@ -488,6 +456,38 @@ u64 alarm_forward_now(struct alarm *alarm, ktime_t interval) } EXPORT_SYMBOL_GPL(alarm_forward_now); +#ifdef CONFIG_POSIX_TIMERS + +static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type) +{ + struct alarm_base *base; + unsigned long flags; + ktime_t delta; + + switch(type) { + case ALARM_REALTIME: + base = &alarm_bases[ALARM_REALTIME]; + type = ALARM_REALTIME_FREEZER; + break; + case ALARM_BOOTTIME: + base = &alarm_bases[ALARM_BOOTTIME]; + type = ALARM_BOOTTIME_FREEZER; + break; + default: + WARN_ONCE(1, "Invalid alarm type: %d\n", type); + return; + } + + delta = ktime_sub(absexp, base->gettime()); + + spin_lock_irqsave(&freezer_delta_lock, flags); + if (!freezer_delta || (delta < freezer_delta)) { + freezer_delta = delta; + freezer_expires = absexp; + freezer_alarmtype = type; + } + spin_unlock_irqrestore(&freezer_delta_lock, flags); +} /** * clock2alarm - helper that converts from clockid to alarmtypes @@ -846,6 +846,17 @@ out: return ret; } +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, + .nsleep = alarm_timer_nsleep, +}; +#endif /* CONFIG_POSIX_TIMERS */ + /* Suspend hook structures */ static const struct dev_pm_ops alarmtimer_pm_ops = { @@ -871,23 +882,9 @@ static int __init alarmtimer_init(void) struct platform_device *pdev; int error = 0; int i; - 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, - .nsleep = alarm_timer_nsleep, - }; alarmtimer_rtc_timer_init(); - if (IS_ENABLED(CONFIG_POSIX_TIMERS)) { - posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock); - posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock); - } - /* Initialize alarm bases */ alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME; alarm_bases[ALARM_REALTIME].gettime = &ktime_get_real; -- cgit From b6b3b80fceb175c825ad6c72659e0a72e201fc5f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Sat, 27 May 2017 12:23:47 +0200 Subject: alarmtimer: Fix posix-timer constification fallout Some freezer related variables are only used when either CONFIG_POSIX_TIMER or CONFIG_RTC_CLASS are enabled. Hide them when both are off. Fixes: d3ba5a9a345b ("posix-timers: Make posix_clocks immutable") Reported-by: Ingo Molnar Signed-off-by: Thomas Gleixner Cc: Christoph Helwig --- kernel/time/alarmtimer.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'kernel/time/alarmtimer.c') diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 4f4cc3509b30..4cfebfff848d 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -45,11 +45,13 @@ static struct alarm_base { clockid_t base_clockid; } alarm_bases[ALARM_NUMTYPE]; +#if defined(CONFIG_POSIX_TIMERS) || defined(CONFIG_RTC_CLASS) /* freezer information to handle clock_nanosleep triggered wakeups */ static enum alarmtimer_type freezer_alarmtype; static ktime_t freezer_expires; static ktime_t freezer_delta; static DEFINE_SPINLOCK(freezer_delta_lock); +#endif static struct wakeup_source *ws; -- cgit From 18c700c4e3d0a37c43a2df8b8f740121d4dac645 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 30 May 2017 23:15:36 +0200 Subject: alarmtimer: Remove pointless config conditional Having a IF_ENABLED(CONFIG_POSIX_TIMERS) inside of a #ifdef CONFIG_POSIX_TIMERS section is pointless. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: John Stultz Link: http://lkml.kernel.org/r/20170530211655.975218056@linutronix.de --- kernel/time/alarmtimer.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'kernel/time/alarmtimer.c') diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index e645dcc7d4ee..2a8675f9aac5 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -520,8 +520,7 @@ static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm, spin_lock_irqsave(&ptr->it_lock, flags); if ((ptr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) { - if (IS_ENABLED(CONFIG_POSIX_TIMERS) && - posix_timer_event(ptr, 0) != 0) + if (posix_timer_event(ptr, 0)) ptr->it_overrun++; } -- cgit From bab0aae9dcba9466dcc968b8bd21914f8f691631 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 30 May 2017 23:15:41 +0200 Subject: posix-timers: Move posix-timer internals to core None of these declarations is required outside of kernel/time. Move them to an internal header. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: John Stultz Cc: Christoph Hellwig Link: http://lkml.kernel.org/r/20170530211656.394803853@linutronix.de --- kernel/time/alarmtimer.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'kernel/time/alarmtimer.c') diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 2a8675f9aac5..36855d675da5 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -28,6 +28,8 @@ #include #include +#include "posix-timers.h" + #define CREATE_TRACE_POINTS #include -- cgit From 80105cd0e62ba8a2caf8eebd52f42952c7c04046 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 30 May 2017 23:15:43 +0200 Subject: posix-timers: Move interval out of the union Preparatory patch to unify the alarm timer and hrtimer based posix interval timer handling. The interval is used as a criteria for rearming decisions so moving it out of the clock specific data structures allows later unification. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: John Stultz Link: http://lkml.kernel.org/r/20170530211656.563922908@linutronix.de --- kernel/time/alarmtimer.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'kernel/time/alarmtimer.c') diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 36855d675da5..5b8cf4b61854 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -527,9 +527,8 @@ static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm, } /* Re-add periodic timers */ - if (ptr->it.alarm.interval) { - ptr->it_overrun += alarm_forward(alarm, now, - ptr->it.alarm.interval); + if (ptr->it_interval) { + ptr->it_overrun += alarm_forward(alarm, now, ptr->it_interval); result = ALARMTIMER_RESTART; } spin_unlock_irqrestore(&ptr->it_lock, flags); @@ -613,7 +612,7 @@ static void alarm_timer_get(struct k_itimer *timr, cur_setting->it_value.tv_nsec = 0; } - cur_setting->it_interval = ktime_to_timespec64(timr->it.alarm.interval); + cur_setting->it_interval = ktime_to_timespec64(timr->it_interval); } /** @@ -662,14 +661,14 @@ static int alarm_timer_set(struct k_itimer *timr, int flags, return TIMER_RETRY; /* start the timer */ - timr->it.alarm.interval = timespec64_to_ktime(new_setting->it_interval); + 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.alarm.interval < TICK_NSEC) - timr->it.alarm.interval = TICK_NSEC; + 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 */ -- cgit From b3db80f77a95a45dbb2136f7b2a364dc797ea914 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 30 May 2017 23:15:54 +0200 Subject: alarmtimer: Implement timer_rearm() callback Preparatory change to utilize the common posix timer mechanisms. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: John Stultz Link: http://lkml.kernel.org/r/20170530211657.434598989@linutronix.de --- kernel/time/alarmtimer.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'kernel/time/alarmtimer.c') diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 5b8cf4b61854..be85e3cbfe1b 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -536,6 +536,18 @@ static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm, return result; } +/** + * alarm_timer_rearm - Posix timer callback for rearming timer + * @timr: Pointer to the posixtimer data struct + */ +static void alarm_timer_rearm(struct k_itimer *timr) +{ + struct alarm *alarm = &timr->it.alarm.alarmtimer; + + timr->it_overrun += alarm_forward_now(alarm, timr->it_interval); + alarm_start(alarm, alarm->node.expires); +} + /** * alarm_clock_getres - posix getres interface * @which_clock: clockid @@ -594,7 +606,7 @@ static int alarm_timer_create(struct k_itimer *new_timer) /** * alarm_timer_get - posix timer_get interface - * @new_timer: k_itimer pointer + * @timr: k_itimer pointer * @cur_setting: itimerspec data to fill * * Copies out the current itimerspec data @@ -863,6 +875,7 @@ const struct k_clock alarm_clock = { .timer_set = alarm_timer_set, .timer_del = alarm_timer_del, .timer_get = alarm_timer_get, + .timer_rearm = alarm_timer_rearm, .nsleep = alarm_timer_nsleep, }; #endif /* CONFIG_POSIX_TIMERS */ -- cgit From e7561f1633ac735df48c55ad09a2530e9ab9fab1 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 30 May 2017 23:15:55 +0200 Subject: alarmtimer: Implement forward callback Preparatory change to utilize the common posix timer mechanisms. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: John Stultz Link: http://lkml.kernel.org/r/20170530211657.513694229@linutronix.de --- kernel/time/alarmtimer.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'kernel/time/alarmtimer.c') diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index be85e3cbfe1b..6082cf1af876 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -548,6 +548,18 @@ static void alarm_timer_rearm(struct k_itimer *timr) alarm_start(alarm, alarm->node.expires); } +/** + * alarm_timer_forward - Posix timer callback for forwarding timer + * @timr: Pointer to the posixtimer data struct + * @now: Current time to forward the timer against + */ +static int alarm_timer_forward(struct k_itimer *timr, ktime_t now) +{ + struct alarm *alarm = &timr->it.alarm.alarmtimer; + + return (int) alarm_forward(alarm, timr->it_interval, now); +} + /** * alarm_clock_getres - posix getres interface * @which_clock: clockid @@ -876,6 +888,7 @@ const struct k_clock alarm_clock = { .timer_del = alarm_timer_del, .timer_get = alarm_timer_get, .timer_rearm = alarm_timer_rearm, + .timer_forward = alarm_timer_forward, .nsleep = alarm_timer_nsleep, }; #endif /* CONFIG_POSIX_TIMERS */ -- cgit From d653d8457c76da11f047af1f66256ac9b8421b69 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 30 May 2017 23:15:56 +0200 Subject: alarmtimer: Implement remaining callback Preparatory change to utilize the common posix timer mechanisms. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: John Stultz Link: http://lkml.kernel.org/r/20170530211657.592676753@linutronix.de --- kernel/time/alarmtimer.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'kernel/time/alarmtimer.c') diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 6082cf1af876..02ddc40f19fe 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -560,6 +560,18 @@ static int alarm_timer_forward(struct k_itimer *timr, ktime_t now) return (int) alarm_forward(alarm, timr->it_interval, now); } +/** + * alarm_timer_remaining - Posix timer callback to retrieve remaining time + * @timr: Pointer to the posixtimer data struct + * @now: Current time to calculate against + */ +static ktime_t alarm_timer_remaining(struct k_itimer *timr, ktime_t now) +{ + struct alarm *alarm = &timr->it.alarm.alarmtimer; + + return ktime_sub(now, alarm->node.expires); +} + /** * alarm_clock_getres - posix getres interface * @which_clock: clockid @@ -881,15 +893,16 @@ out: } 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_rearm = alarm_timer_rearm, - .timer_forward = alarm_timer_forward, - .nsleep = alarm_timer_nsleep, + .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_rearm = alarm_timer_rearm, + .timer_forward = alarm_timer_forward, + .timer_remaining = alarm_timer_remaining, + .nsleep = alarm_timer_nsleep, }; #endif /* CONFIG_POSIX_TIMERS */ -- cgit From e344c9e76bc6af997926171bfd90d25bbae0a2c5 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 30 May 2017 23:15:57 +0200 Subject: alarmtimer: Implement try_to_cancel callback Preparatory change to utilize the common posix timer mechanisms. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: John Stultz Link: http://lkml.kernel.org/r/20170530211657.670026824@linutronix.de --- kernel/time/alarmtimer.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'kernel/time/alarmtimer.c') diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 02ddc40f19fe..374bd855a488 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -572,6 +572,15 @@ static ktime_t alarm_timer_remaining(struct k_itimer *timr, ktime_t now) return ktime_sub(now, alarm->node.expires); } +/** + * alarm_timer_try_to_cancel - Posix timer callback to cancel a timer + * @timr: Pointer to the posixtimer data struct + */ +static int alarm_timer_try_to_cancel(struct k_itimer *timr) +{ + return alarm_try_to_cancel(&timr->it.alarm.alarmtimer); +} + /** * alarm_clock_getres - posix getres interface * @which_clock: clockid @@ -902,6 +911,7 @@ const struct k_clock alarm_clock = { .timer_rearm = alarm_timer_rearm, .timer_forward = alarm_timer_forward, .timer_remaining = alarm_timer_remaining, + .timer_try_to_cancel = alarm_timer_try_to_cancel, .nsleep = alarm_timer_nsleep, }; #endif /* CONFIG_POSIX_TIMERS */ -- cgit From b3bf6f369d50ece9dec6338741648005d95c19e4 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 30 May 2017 23:15:58 +0200 Subject: alarmtimer: Implement arm callback Preparatory change to utilize the common posix timer mechanisms. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: John Stultz Link: http://lkml.kernel.org/r/20170530211657.747567162@linutronix.de --- kernel/time/alarmtimer.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'kernel/time/alarmtimer.c') diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 374bd855a488..c618a44bb054 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -581,6 +581,27 @@ static int alarm_timer_try_to_cancel(struct k_itimer *timr) return alarm_try_to_cancel(&timr->it.alarm.alarmtimer); } +/** + * alarm_timer_arm - Posix timer callback to arm a timer + * @timr: Pointer to the posixtimer data struct + * @expires: The new expiry time + * @absolute: Expiry value is absolute time + * @sigev_none: Posix timer does not deliver signals + */ +static void alarm_timer_arm(struct k_itimer *timr, ktime_t expires, + bool absolute, bool sigev_none) +{ + struct alarm *alarm = &timr->it.alarm.alarmtimer; + struct alarm_base *base = &alarm_bases[alarm->type]; + + if (!absolute) + expires = ktime_add_safe(expires, base->gettime()); + if (sigev_none) + alarm->node.expires = expires; + else + alarm_start(&timr->it.alarm.alarmtimer, expires); +} + /** * alarm_clock_getres - posix getres interface * @which_clock: clockid @@ -908,6 +929,7 @@ const struct k_clock alarm_clock = { .timer_set = alarm_timer_set, .timer_del = alarm_timer_del, .timer_get = alarm_timer_get, + .timer_arm = alarm_timer_arm, .timer_rearm = alarm_timer_rearm, .timer_forward = alarm_timer_forward, .timer_remaining = alarm_timer_remaining, -- cgit From f2c45807d3992fe0f173f34af9c347d907c31686 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 30 May 2017 23:15:59 +0200 Subject: alarmtimer: Switch over to generic set/get/rearm routine 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 Cc: Peter Zijlstra Cc: John Stultz Link: http://lkml.kernel.org/r/20170530211657.825471962@linutronix.de --- kernel/time/alarmtimer.c | 121 +++++++---------------------------------------- 1 file changed, 18 insertions(+), 103 deletions(-) (limited to 'kernel/time/alarmtimer.c') diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index c618a44bb054..d8a7a7e214de 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -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, -- cgit From 15f27ce24cb613e6e01ce27c4094c55e55dde5d4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 7 Jun 2017 09:42:27 +0100 Subject: alarmtimer: Move copyout and freeze handling into alarmtimer_do_nsleep() The alarmtimer nanosleep() implementation can be simplified by moving the copy out of the remaining time to alarmtimer_do_nsleep() which is shared between the real nanosleep function and the restart function. The pointer to the timespec64 which is updated has to be stored in the restart block anyway. Instead of storing it only in the restart case, store it before calling alarmtimer_do_nsleep() and copy the remaining time in the signal exit path. [ tglx: Added changelog ] Signed-off-by: Al Viro Signed-off-by: Thomas Gleixner Cc: John Stultz Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20170607084241.28657-2-viro@ZenIV.linux.org.uk --- kernel/time/alarmtimer.c | 102 +++++++++++++++-------------------------------- 1 file changed, 32 insertions(+), 70 deletions(-) (limited to 'kernel/time/alarmtimer.c') diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index d8a7a7e214de..ac6e9bc6cc59 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -688,8 +688,10 @@ static enum alarmtimer_restart alarmtimer_nsleep_wakeup(struct alarm *alarm, * * Sets the alarm timer and sleeps until it is fired or interrupted. */ -static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp) +static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp, + enum alarmtimer_type type) { + struct timespec __user *rmtp; alarm->data = (void *)current; do { set_current_state(TASK_INTERRUPTIBLE); @@ -702,36 +704,26 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp) __set_current_state(TASK_RUNNING); - return (alarm->data == NULL); -} - - -/** - * update_rmtp - Update remaining timespec value - * @exp: expiration time - * @type: timer type - * @rmtp: user pointer to remaining timepsec value - * - * Helper function that fills in rmtp value with time between - * now and the exp value - */ -static int update_rmtp(ktime_t exp, enum alarmtimer_type type, - struct timespec __user *rmtp) -{ - struct timespec rmt; - ktime_t rem; - - rem = ktime_sub(exp, alarm_bases[type].gettime()); - - if (rem <= 0) + if (!alarm->data) return 0; - rmt = ktime_to_timespec(rem); - if (copy_to_user(rmtp, &rmt, sizeof(*rmtp))) - return -EFAULT; + if (freezing(current)) + alarmtimer_freezerset(absexp, type); + rmtp = current->restart_block.nanosleep.rmtp; + if (rmtp) { + struct timespec rmt; + ktime_t rem; - return 1; + rem = ktime_sub(absexp, alarm_bases[type].gettime()); + if (rem <= 0) + return 0; + rmt = ktime_to_timespec(rem); + + if (copy_to_user(rmtp, &rmt, sizeof(*rmtp))) + return -EFAULT; + } + return -ERESTART_RESTARTBLOCK; } /** @@ -743,32 +735,12 @@ static int update_rmtp(ktime_t exp, enum alarmtimer_type type, static long __sched alarm_timer_nsleep_restart(struct restart_block *restart) { enum alarmtimer_type type = restart->nanosleep.clockid; - ktime_t exp; - struct timespec __user *rmtp; + ktime_t exp = restart->nanosleep.expires; struct alarm alarm; - int ret = 0; - exp = restart->nanosleep.expires; alarm_init(&alarm, type, alarmtimer_nsleep_wakeup); - if (alarmtimer_do_nsleep(&alarm, exp)) - goto out; - - if (freezing(current)) - alarmtimer_freezerset(exp, type); - - rmtp = restart->nanosleep.rmtp; - if (rmtp) { - ret = update_rmtp(exp, type, rmtp); - if (ret <= 0) - goto out; - } - - - /* The other values in restart are already filled in */ - ret = -ERESTART_RESTARTBLOCK; -out: - return ret; + return alarmtimer_do_nsleep(&alarm, exp, type); } /** @@ -785,11 +757,16 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags, struct timespec __user *rmtp) { enum alarmtimer_type type = clock2alarm(which_clock); - struct restart_block *restart; + struct restart_block *restart = ¤t->restart_block; struct alarm alarm; ktime_t exp; int ret = 0; + if (flags & TIMER_ABSTIME) + rmtp = NULL; + + restart->nanosleep.rmtp = rmtp; + if (!alarmtimer_get_rtcdev()) return -ENOTSUPP; @@ -808,32 +785,17 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags, exp = ktime_add(now, exp); } - if (alarmtimer_do_nsleep(&alarm, exp)) - goto out; - - if (freezing(current)) - alarmtimer_freezerset(exp, type); + ret = alarmtimer_do_nsleep(&alarm, exp, type); + if (ret != -ERESTART_RESTARTBLOCK) + return ret; /* abs timers don't set remaining time or restart */ - if (flags == TIMER_ABSTIME) { - ret = -ERESTARTNOHAND; - goto out; - } - - if (rmtp) { - ret = update_rmtp(exp, type, rmtp); - if (ret <= 0) - goto out; - } + if (flags == TIMER_ABSTIME) + return -ERESTARTNOHAND; - restart = ¤t->restart_block; restart->fn = alarm_timer_nsleep_restart; restart->nanosleep.clockid = type; restart->nanosleep.expires = exp; - restart->nanosleep.rmtp = rmtp; - ret = -ERESTART_RESTARTBLOCK; - -out: return ret; } -- cgit From 99e6c0e6ec349575886ca7daffc9cb7ec583176f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 7 Jun 2017 09:42:30 +0100 Subject: posix-timers: Store rmtp into restart_block in sys_clock_nanosleep() ... instead of doing that in every ->nsleep() instance Signed-off-by: Al Viro Signed-off-by: Thomas Gleixner Cc: John Stultz Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20170607084241.28657-5-viro@ZenIV.linux.org.uk --- kernel/time/alarmtimer.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'kernel/time/alarmtimer.c') diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index ac6e9bc6cc59..d859a3601ddd 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -753,8 +753,7 @@ static long __sched alarm_timer_nsleep_restart(struct restart_block *restart) * Handles clock_nanosleep calls against _ALARM clockids */ static int alarm_timer_nsleep(const clockid_t which_clock, int flags, - struct timespec64 *tsreq, - struct timespec __user *rmtp) + struct timespec64 *tsreq) { enum alarmtimer_type type = clock2alarm(which_clock); struct restart_block *restart = ¤t->restart_block; @@ -762,11 +761,6 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags, ktime_t exp; int ret = 0; - if (flags & TIMER_ABSTIME) - rmtp = NULL; - - restart->nanosleep.rmtp = rmtp; - if (!alarmtimer_get_rtcdev()) return -ENOTSUPP; -- cgit From edbeda46322fbcb15af2d2d0f2daffb0cd349a5a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 7 Jun 2017 09:42:31 +0100 Subject: time/posix-timers: Move the compat copyouts to the nanosleep implementations Turn restart_block.nanosleep.{rmtp,compat_rmtp} into a tagged union (kind = 1 -> native, kind = 2 -> compat, kind = 0 -> nothing) and make the places doing actual copyout handle compat as well as native (that will become a helper in the next commit). Result: compat wrappers, messing with reassignments, etc. are gone. [ tglx: Folded in a variant of Peter Zijlstras enum patch ] Signed-off-by: Al Viro Signed-off-by: Thomas Gleixner Cc: John Stultz Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20170607084241.28657-6-viro@ZenIV.linux.org.uk --- kernel/time/alarmtimer.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'kernel/time/alarmtimer.c') diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index d859a3601ddd..57bcf94ee132 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "posix-timers.h" @@ -691,7 +692,7 @@ static enum alarmtimer_restart alarmtimer_nsleep_wakeup(struct alarm *alarm, static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp, enum alarmtimer_type type) { - struct timespec __user *rmtp; + struct restart_block *restart; alarm->data = (void *)current; do { set_current_state(TASK_INTERRUPTIBLE); @@ -709,8 +710,8 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp, if (freezing(current)) alarmtimer_freezerset(absexp, type); - rmtp = current->restart_block.nanosleep.rmtp; - if (rmtp) { + restart = ¤t->restart_block; + if (restart->nanosleep.type != TT_NONE) { struct timespec rmt; ktime_t rem; @@ -720,7 +721,14 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp, return 0; rmt = ktime_to_timespec(rem); - if (copy_to_user(rmtp, &rmt, sizeof(*rmtp))) +#ifdef CONFIG_COMPAT + if (restart->nanosleep.type == TT_COMPAT) { + if (compat_put_timespec(&rmt, + restart->nanosleep.compat_rmtp)) + return -EFAULT; + } else +#endif + if (copy_to_user(restart->nanosleep.rmtp, &rmt, sizeof(rmt))) return -EFAULT; } return -ERESTART_RESTARTBLOCK; -- cgit From ce41aaf47af3d28c4c958e07675a3e0a51f09bd3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 7 Jun 2017 09:42:32 +0100 Subject: hrtimers/posix-timers: Merge nanosleep timespec copyout logics into a new helper Signed-off-by: Al Viro Signed-off-by: Thomas Gleixner Cc: John Stultz Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20170607084241.28657-7-viro@ZenIV.linux.org.uk --- kernel/time/alarmtimer.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'kernel/time/alarmtimer.c') diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 57bcf94ee132..7bed4e44f9bd 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -721,15 +721,7 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp, return 0; rmt = ktime_to_timespec(rem); -#ifdef CONFIG_COMPAT - if (restart->nanosleep.type == TT_COMPAT) { - if (compat_put_timespec(&rmt, - restart->nanosleep.compat_rmtp)) - return -EFAULT; - } else -#endif - if (copy_to_user(restart->nanosleep.rmtp, &rmt, sizeof(rmt))) - return -EFAULT; + return nanosleep_copyout(restart, &rmt); } return -ERESTART_RESTARTBLOCK; } -- cgit From 938e7cf2d569833a5acf689a8926faf507826253 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 13 Jun 2017 23:34:33 +0200 Subject: posix-timers: Make nanosleep timespec argument const No nanosleep implementation modifies the rqtp argument. Mark is const. Signed-off-by: Thomas Gleixner Cc: Al Viro Cc: John Stultz Cc: Peter Zijlstra --- kernel/time/alarmtimer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/time/alarmtimer.c') diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 7bed4e44f9bd..c991cf212c6d 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -753,7 +753,7 @@ static long __sched alarm_timer_nsleep_restart(struct restart_block *restart) * Handles clock_nanosleep calls against _ALARM clockids */ static int alarm_timer_nsleep(const clockid_t which_clock, int flags, - struct timespec64 *tsreq) + const struct timespec64 *tsreq) { enum alarmtimer_type type = clock2alarm(which_clock); struct restart_block *restart = ¤t->restart_block; -- cgit