hrtimers: Handle remaining time correctly for CONFIG_TIME_LOW_RES=y
cover hrtimers: Handle remaining time correctly for CONFIG_TIME_LOW_RES=y
Helge reported, that timerfd returns occasionally remaining time larger than the relative time which was used to arm the timer. This is caused by the extra jiffy which we add in hrtimer_start_range_ns() if CONFIG_TIME_LOW_RES=y.
This is not only an issue for timerfd. We have the same problem in posix-timers and itimers.
This series adds infrastructure to the core to handle that cases and converts the users over to it.
Thanks,
tglx
--- fs/timerfd.c | 2 - include/linux/hrtimer.h | 34 +++++++++++++++++++++++++-- kernel/time/hrtimer.c | 55 ++++++++++++++++++++++++++++++--------------- kernel/time/itimer.c | 2 - kernel/time/posix-timers.c | 2 - kernel/time/timer_list.c | 2 - 6 files changed, 72 insertions(+), 25 deletions(-)
PATCH 1/4 hrtimer: Handle remaining time proper for TIME_LOW_RES
If CONFIG_TIME_LOW_RES is enabled we add a jiffie to the relative timeout to prevent short sleeps, but we do not account for that in interfaces which retrieve the remaining time.
Helge observed that timerfd can return a remaining time larger than the relative timeout. That's not expected and breaks userland test programs.
Store the information that the timer was armed relative and provide functions to adjust the remaining time. To avoid bloating the hrtimer struct make state a u8, which as a bonus results in better code on x86 at least.
--- include/linux/hrtimer.h | 34 ++++++++++++++++++++++++++--- kernel/time/hrtimer.c | 55 +++++++++++++++++++++++++++++++---------------- kernel/time/timer_list.c | 2 - 3 files changed, 69 insertions(+), 22 deletions(-)
include/linux/hrtimer.h +31 -3
@@ -87,7 +87,8 @@ enum hrtimer_restart {* @function: timer expiry callback function * @base: pointer to the timer base (per cpu and per clock) * @state: state information (See bit values above) -* @start_pid: timer statistics field to store the pid of the task which +* @is_rel: Set if the timer was armed relative +* @start_pid: timer statistics field to store the pid of the task which * started the timer * @start_site: timer statistics field to store the site where the timer * was started
@@ -101,7 +102,8 @@ struct hrtimer {ktime_t _softexpires;enum hrtimer_restart (*function)(struct hrtimer *);struct hrtimer_clock_base *base; -unsigned long state; +u8 state; +u8 is_rel;#ifdef CONFIG_TIMER_STATS int start_pid;void *start_site;
@@ -321,6 +323,27 @@ static inline void clock_was_set_delayed#endif +static inline ktime_t +__hrtimer_expires_remaining_adjusted (const struct hrtimer *timer,ktime_t now) +{ +ktime_t rem =ktime_sub (timer->node.expires, now); + +/* +* Adjust relative timers for the extra we added in +* hrtimer_start_range_ns() to prevent short timeouts. +*/ +if (IS_ENABLED (CONFIG_TIME_LOW_RES ) && timer->is_rel) + rem.tv64 -= hrtimer_resolution; +return rem; +} + +static inline ktime_t +hrtimer_expires_remaining_adjusted (const struct hrtimer *timer) +{ +return __hrtimer_expires_remaining_adjusted (timer, + timer->base->get_time ()); +} +extern void clock_was_set (void );#ifdef CONFIG_TIMERFD extern void timerfd_clock_was_set (void );
@@ -390,7 +413,12 @@ static inline void hrtimer_restart(struc }/* Query timers: */ -extern ktime_t hrtimer_get_remaining (const struct hrtimer *timer); +extern ktime_t __hrtimer_get_remaining (const struct hrtimer *timer,bool adjust); + +static inline ktime_t hrtimer_get_remaining (const struct hrtimer *timer) +{ +return __hrtimer_get_remaining (timer, false); +}extern u64 hrtimer_get_next_event (void );
kernel/time/hrtimer.c +37 -18
104 lines not on this page · raw message
kernel/time/timer_list.c +1 -1
@@ -69,7 +69,7 @@ print_timer(struct seq_file *m, struct hprint_name_offset (m, taddr);SEQ_printf (m,", " );print_name_offset (m, timer->function); -SEQ_printf (m,", S:%02lx" , timer->state); +SEQ_printf (m,", S:%02x" , timer->state);#ifdef CONFIG_TIMER_STATS SEQ_printf (m,", " );print_name_offset (m, timer->start_site);
Re: [patch 1/4] hrtimer: Handle remaining time proper for TIME_LOW_RES
Hi Thomas,
* Thomas Gleixner <[email protected]>:
Quoted 7 lines
If
CONFIG_TIME_LOW_RESis enabled we add a jiffie to the relative timeout to prevent short sleeps, but we do not account for that in interfaces which retrieve the remaining time.Helge observed that timerfd can return a remaining time larger than the relative timeout. That's not expected and breaks userland test programs.
Quoted 6 lines
Store the information that the timer was armed relative and provide functions to adjust the remaining time. To avoid bloating the hrtimer struct make state a u8, which as a bonus results in better code on x86 at least.
Reported-by Helge Deller <[email protected]>Signed-off-by Thomas Gleixner <[email protected]>
Great!
You can add for this series:
Any chance it can get backported to v4.4 ?
Thanks,
Helge
Quoted 195 lines
--- include/linux/hrtimer.h | 34 ++++++++++++++++++++++++++--- kernel/time/hrtimer.c | 55 +++++++++++++++++++++++++++++++---------------- kernel/time/timer_list.c | 2 - 3 files changed, 69 insertions(+), 22 deletions(-)include/linux/hrtimer.h +31
-3@@ -87,7 +87,8 @@ enum hrtimer_restart {* @function: timer expiry callback function * @base: pointer to the timer base (per cpu and per clock) * @state: state information (See bit values above) -* @start_pid: timer statistics field to store the pid of the task which +* @is_rel: Set if the timer was armed relative +* @start_pid: timer statistics field to store the pid of the task which * started the timer * @start_site: timer statistics field to store the site where the timer * was started @@ -101,7 +102,8 @@ struct hrtimer {ktime_t _softexpires;enum hrtimer_restart (*function)(struct hrtimer *);struct hrtimer_clock_base *base; -unsigned long state; +u8 state; +u8 is_rel;#ifdef CONFIG_TIMER_STATS int start_pid;void *start_site;@@ -321,6 +323,27 @@ static inline void clock_was_set_delayed#endif +static inline ktime_t +__hrtimer_expires_remaining_adjusted (const struct hrtimer *timer,ktime_t now) +{ +ktime_t rem =ktime_sub (timer->node.expires, now); + +/* +* Adjust relative timers for the extra we added in +* hrtimer_start_range_ns() to prevent short timeouts. +*/ +if (IS_ENABLED (CONFIG_TIME_LOW_RES ) && timer->is_rel) + rem.tv64 -= hrtimer_resolution; +return rem; +} + +static inline ktime_t +hrtimer_expires_remaining_adjusted (const struct hrtimer *timer) +{ +return __hrtimer_expires_remaining_adjusted (timer, + timer->base->get_time ()); +} +extern void clock_was_set (void );#ifdef CONFIG_TIMERFD extern void timerfd_clock_was_set (void );@@ -390,7 +413,12 @@ static inline void hrtimer_restart(struc }/* Query timers: */ -extern ktime_t hrtimer_get_remaining (const struct hrtimer *timer); +extern ktime_t __hrtimer_get_remaining (const struct hrtimer *timer,bool adjust); + +static inline ktime_t hrtimer_get_remaining (const struct hrtimer *timer) +{ +return __hrtimer_get_remaining (timer, false); +}extern u64 hrtimer_get_next_event (void );kernel/time/hrtimer.c +37
-18@@ -897,10 +897,10 @@ static int enqueue_hrtimer(struct hrtime*/ static void __remove_hrtimer (struct hrtimer *timer,struct hrtimer_clock_base *base, -unsigned long newstate,int reprogram) +u8 newstate,int reprogram) {struct hrtimer_cpu_base *cpu_base = base->cpu_base; -unsigned int state = timer->state; +u8 state = timer->state; timer->state = newstate;if (!(state &HRTIMER_STATE_ENQUEUED ))@@ -930,7 +930,7 @@ static inline int remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, bool restart) { if (hrtimer_is_queued(timer)) { - unsigned long state = timer->state; + u8 state = timer->state;int reprogram;/* @@ -954,6 +954,22 @@ remove_hrtimer(struct hrtimer *timer, streturn 0 ; } +static inline ktime_t hrtimer_update_lowres (struct hrtimer *timer,ktime_t tim, +const enum hrtimer_mode mode) +{ +#ifdef CONFIG_TIME_LOW_RES +/* +* CONFIG_TIME_LOW_RES indicates that the system has no way to return +* granular time values. For relative timers we add hrtimer_resolution +* (i.e. one jiffie) to prevent short timeouts. +*/ + timer->is_rel = mode &HRTIMER_MODE_REL ; +if (timer->is_rel) + tim =ktime_add_safe (tim,ktime_set (0 , hrtimer_resolution)); +#endif +return tim; +} +/** * hrtimer_start_range_ns - (re)start an hrtimer on the current CPU * @timer: the timer to be added @@ -974,19 +990,10 @@ void hrtimer_start_range_ns(struct hrtim/* Remove an active timer from the queue: */ remove_hrtimer (timer, base, true); -if (mode &HRTIMER_MODE_REL ) { +if (mode &HRTIMER_MODE_REL ) tim =ktime_add_safe (tim, base->get_time ()); -/* -* CONFIG_TIME_LOW_RES is a temporary way for architectures -* to signal that they simply return xtime in -* do_gettimeoffset(). In this case we want to round up by -* resolution when starting a relative timer, to avoid short -* timeouts. This will go away with the GTOD framework. -*/ -#ifdef CONFIG_TIME_LOW_RES - tim =ktime_add_safe (tim,ktime_set (0 , hrtimer_resolution)); -#endif - } + + tim =hrtimer_update_lowres (timer, tim, mode);hrtimer_set_expires_range_ns (timer, tim, delta_ns);@@ -1074,19 +1081,23 @@ EXPORT_SYMBOL_GPL(hrtimer_cancel);/** * hrtimer_get_remaining - get remaining time for the timer * @timer: the timer to read +* @adjust: adjust relative timers when CONFIG_TIME_LOW_RES=y */ -ktime_t hrtimer_get_remaining (const struct hrtimer *timer) +ktime_t __hrtimer_get_remaining (const struct hrtimer *timer,bool adjust) {unsigned long flags;ktime_t rem;lock_hrtimer_base (timer, &flags); - rem =hrtimer_expires_remaining (timer); +if (IS_ENABLED (CONFIG_TIME_LOW_RES ) && adjust) + rem =hrtimer_expires_remaining_adjusted (timer); +else + rem =hrtimer_expires_remaining (timer);unlock_hrtimer_base (timer, &flags);return rem; } -EXPORT_SYMBOL_GPL (hrtimer_get_remaining); +EXPORT_SYMBOL_GPL (__hrtimer_get_remaining);#ifdef CONFIG_NO_HZ_COMMON /** @@ -1220,6 +1231,14 @@ static void __run_hrtimer(struct hrtimer fn = timer->function;/* +* Clear the 'is relative' flag for the TIME_LOW_RES case. If the +* timer is restarted with a period then it becomes an absolute +* timer. If its not restarted it does not matter. +*/ +if (IS_ENABLED (CONFIG_TIME_LOW_RES )) + timer->is_rel = false; + +/* * Because we run timers from hardirq context, there is no chance * they get migrated to another cpu, therefore its safe to unlock * the timer base. kernel/time/timer_list.c +1
-1@@ -69,7 +69,7 @@ print_timer(struct seq_file *m, struct hprint_name_offset (m, taddr);SEQ_printf (m,", " );print_name_offset (m, timer->function); -SEQ_printf (m,", S:%02lx" , timer->state); +SEQ_printf (m,", S:%02x" , timer->state);#ifdef CONFIG_TIMER_STATS SEQ_printf (m,", " );print_name_offset (m, timer->start_site);
Re: [patch 1/4] hrtimer: Handle remaining time proper for TIME_LOW_RES
In reply to Thomas GleixnerHi Thomas,
* Thomas Gleixner <[email protected]>:
Quoted 7 lines
If
CONFIG_TIME_LOW_RESis enabled we add a jiffie to the relative timeout to prevent short sleeps, but we do not account for that in interfaces which retrieve the remaining time.Helge observed that timerfd can return a remaining time larger than the relative timeout. That's not expected and breaks userland test programs.
Quoted 6 lines
Store the information that the timer was armed relative and provide functions to adjust the remaining time. To avoid bloating the hrtimer struct make state a u8, which as a bonus results in better code on x86 at least.
Reported-by Helge Deller <[email protected]>Signed-off-by Thomas Gleixner <[email protected]>
Great!
You can add for this series:
Any chance it can get backported to v4.4 ?
Thanks,
Helge
Quoted 195 lines
--- include/linux/hrtimer.h | 34 ++++++++++++++++++++++++++--- kernel/time/hrtimer.c | 55 +++++++++++++++++++++++++++++++---------------- kernel/time/timer_list.c | 2 - 3 files changed, 69 insertions(+), 22 deletions(-)include/linux/hrtimer.h +31
-3@@ -87,7 +87,8 @@ enum hrtimer_restart {* @function: timer expiry callback function * @base: pointer to the timer base (per cpu and per clock) * @state: state information (See bit values above) -* @start_pid: timer statistics field to store the pid of the task which +* @is_rel: Set if the timer was armed relative +* @start_pid: timer statistics field to store the pid of the task which * started the timer * @start_site: timer statistics field to store the site where the timer * was started @@ -101,7 +102,8 @@ struct hrtimer {ktime_t _softexpires;enum hrtimer_restart (*function)(struct hrtimer *);struct hrtimer_clock_base *base; -unsigned long state; +u8 state; +u8 is_rel;#ifdef CONFIG_TIMER_STATS int start_pid;void *start_site;@@ -321,6 +323,27 @@ static inline void clock_was_set_delayed#endif +static inline ktime_t +__hrtimer_expires_remaining_adjusted (const struct hrtimer *timer,ktime_t now) +{ +ktime_t rem =ktime_sub (timer->node.expires, now); + +/* +* Adjust relative timers for the extra we added in +* hrtimer_start_range_ns() to prevent short timeouts. +*/ +if (IS_ENABLED (CONFIG_TIME_LOW_RES ) && timer->is_rel) + rem.tv64 -= hrtimer_resolution; +return rem; +} + +static inline ktime_t +hrtimer_expires_remaining_adjusted (const struct hrtimer *timer) +{ +return __hrtimer_expires_remaining_adjusted (timer, + timer->base->get_time ()); +} +extern void clock_was_set (void );#ifdef CONFIG_TIMERFD extern void timerfd_clock_was_set (void );@@ -390,7 +413,12 @@ static inline void hrtimer_restart(struc }/* Query timers: */ -extern ktime_t hrtimer_get_remaining (const struct hrtimer *timer); +extern ktime_t __hrtimer_get_remaining (const struct hrtimer *timer,bool adjust); + +static inline ktime_t hrtimer_get_remaining (const struct hrtimer *timer) +{ +return __hrtimer_get_remaining (timer, false); +}extern u64 hrtimer_get_next_event (void );kernel/time/hrtimer.c +37
-18@@ -897,10 +897,10 @@ static int enqueue_hrtimer(struct hrtime*/ static void __remove_hrtimer (struct hrtimer *timer,struct hrtimer_clock_base *base, -unsigned long newstate,int reprogram) +u8 newstate,int reprogram) {struct hrtimer_cpu_base *cpu_base = base->cpu_base; -unsigned int state = timer->state; +u8 state = timer->state; timer->state = newstate;if (!(state &HRTIMER_STATE_ENQUEUED ))@@ -930,7 +930,7 @@ static inline int remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, bool restart) { if (hrtimer_is_queued(timer)) { - unsigned long state = timer->state; + u8 state = timer->state;int reprogram;/* @@ -954,6 +954,22 @@ remove_hrtimer(struct hrtimer *timer, streturn 0 ; } +static inline ktime_t hrtimer_update_lowres (struct hrtimer *timer,ktime_t tim, +const enum hrtimer_mode mode) +{ +#ifdef CONFIG_TIME_LOW_RES +/* +* CONFIG_TIME_LOW_RES indicates that the system has no way to return +* granular time values. For relative timers we add hrtimer_resolution +* (i.e. one jiffie) to prevent short timeouts. +*/ + timer->is_rel = mode &HRTIMER_MODE_REL ; +if (timer->is_rel) + tim =ktime_add_safe (tim,ktime_set (0 , hrtimer_resolution)); +#endif +return tim; +} +/** * hrtimer_start_range_ns - (re)start an hrtimer on the current CPU * @timer: the timer to be added @@ -974,19 +990,10 @@ void hrtimer_start_range_ns(struct hrtim/* Remove an active timer from the queue: */ remove_hrtimer (timer, base, true); -if (mode &HRTIMER_MODE_REL ) { +if (mode &HRTIMER_MODE_REL ) tim =ktime_add_safe (tim, base->get_time ()); -/* -* CONFIG_TIME_LOW_RES is a temporary way for architectures -* to signal that they simply return xtime in -* do_gettimeoffset(). In this case we want to round up by -* resolution when starting a relative timer, to avoid short -* timeouts. This will go away with the GTOD framework. -*/ -#ifdef CONFIG_TIME_LOW_RES - tim =ktime_add_safe (tim,ktime_set (0 , hrtimer_resolution)); -#endif - } + + tim =hrtimer_update_lowres (timer, tim, mode);hrtimer_set_expires_range_ns (timer, tim, delta_ns);@@ -1074,19 +1081,23 @@ EXPORT_SYMBOL_GPL(hrtimer_cancel);/** * hrtimer_get_remaining - get remaining time for the timer * @timer: the timer to read +* @adjust: adjust relative timers when CONFIG_TIME_LOW_RES=y */ -ktime_t hrtimer_get_remaining (const struct hrtimer *timer) +ktime_t __hrtimer_get_remaining (const struct hrtimer *timer,bool adjust) {unsigned long flags;ktime_t rem;lock_hrtimer_base (timer, &flags); - rem =hrtimer_expires_remaining (timer); +if (IS_ENABLED (CONFIG_TIME_LOW_RES ) && adjust) + rem =hrtimer_expires_remaining_adjusted (timer); +else + rem =hrtimer_expires_remaining (timer);unlock_hrtimer_base (timer, &flags);return rem; } -EXPORT_SYMBOL_GPL (hrtimer_get_remaining); +EXPORT_SYMBOL_GPL (__hrtimer_get_remaining);#ifdef CONFIG_NO_HZ_COMMON /** @@ -1220,6 +1231,14 @@ static void __run_hrtimer(struct hrtimer fn = timer->function;/* +* Clear the 'is relative' flag for the TIME_LOW_RES case. If the +* timer is restarted with a period then it becomes an absolute +* timer. If its not restarted it does not matter. +*/ +if (IS_ENABLED (CONFIG_TIME_LOW_RES )) + timer->is_rel = false; + +/* * Because we run timers from hardirq context, there is no chance * they get migrated to another cpu, therefore its safe to unlock * the timer base. kernel/time/timer_list.c +1
-1@@ -69,7 +69,7 @@ print_timer(struct seq_file *m, struct hprint_name_offset (m, taddr);SEQ_printf (m,", " );print_name_offset (m, timer->function); -SEQ_printf (m,", S:%02lx" , timer->state); +SEQ_printf (m,", S:%02x" , timer->state);#ifdef CONFIG_TIMER_STATS SEQ_printf (m,", " );print_name_offset (m, timer->start_site);
tip-bot for Thomas Gleixner
merge bot[tip:timers/urgent] hrtimer: Handle remaining time proper for TIME_LOW_RES
In reply to Thomas Gleixnerhrtimer: Handle remaining time proper for TIME_LOW_RES
Commit-ID: 203cbf77de59fc8f13502dcfd11350c6d4a5c95f Gitweb: http://git.kernel.org/tip/203cbf77de59fc8f13502dcfd11350c6d4a5c95f Author: Thomas Gleixner <[email protected]> AuthorDate: Thu, 14 Jan 2016 16:54:46 +0000 Committer: Thomas Gleixner <[email protected]> CommitDate: Sun, 17 Jan 2016 11:13:55 +0100
hrtimer: Handle remaining time proper for TIME_LOW_RES
If CONFIG_TIME_LOW_RES is enabled we add a jiffie to the relative timeout to prevent short sleeps, but we do not account for that in interfaces which retrieve the remaining time.
Helge observed that timerfd can return a remaining time larger than the relative timeout. That's not expected and breaks userland test programs.
Store the information that the timer was armed relative and provide functions to adjust the remaining time. To avoid bloating the hrtimer struct make state a u8, which as a bonus results in better code on x86 at least.
--- include/linux/hrtimer.h | 34 +++++++++++++++++++++++++++--- kernel/time/hrtimer.c | 55 ++++++++++++++++++++++++++++++++---------------- kernel/time/timer_list.c | 2 +- 3 files changed, 69 insertions(+), 22 deletions(-)
include/linux/hrtimer.h +31 -3
@@ -87,7 +87,8 @@ enum hrtimer_restart {* @function: timer expiry callback function * @base: pointer to the timer base (per cpu and per clock) * @state: state information (See bit values above) -* @start_pid: timer statistics field to store the pid of the task which +* @is_rel: Set if the timer was armed relative +* @start_pid: timer statistics field to store the pid of the task which * started the timer * @start_site: timer statistics field to store the site where the timer * was started
@@ -101,7 +102,8 @@ struct hrtimer {ktime_t _softexpires;enum hrtimer_restart (*function)(struct hrtimer *);struct hrtimer_clock_base *base; -unsigned long state; +u8 state; +u8 is_rel;#ifdef CONFIG_TIMER_STATS int start_pid;void *start_site;
@@ -321,6 +323,27 @@ static inline void clock_was_set_delayed(void) { }#endif +static inline ktime_t +__hrtimer_expires_remaining_adjusted (const struct hrtimer *timer,ktime_t now) +{ +ktime_t rem =ktime_sub (timer->node.expires, now); + +/* +* Adjust relative timers for the extra we added in +* hrtimer_start_range_ns() to prevent short timeouts. +*/ +if (IS_ENABLED (CONFIG_TIME_LOW_RES ) && timer->is_rel) + rem.tv64 -= hrtimer_resolution; +return rem; +} + +static inline ktime_t +hrtimer_expires_remaining_adjusted (const struct hrtimer *timer) +{ +return __hrtimer_expires_remaining_adjusted (timer, + timer->base->get_time ()); +} +extern void clock_was_set (void );#ifdef CONFIG_TIMERFD extern void timerfd_clock_was_set (void );
@@ -390,7 +413,12 @@ static inline void hrtimer_restart(struct hrtimer *timer) }/* Query timers: */ -extern ktime_t hrtimer_get_remaining (const struct hrtimer *timer); +extern ktime_t __hrtimer_get_remaining (const struct hrtimer *timer,bool adjust); + +static inline ktime_t hrtimer_get_remaining (const struct hrtimer *timer) +{ +return __hrtimer_get_remaining (timer, false); +}extern u64 hrtimer_get_next_event (void );
kernel/time/hrtimer.c +37 -18
104 lines not on this page · raw message
kernel/time/timer_list.c +1 -1
@@ -69,7 +69,7 @@ print_timer(struct seq_file *m, struct hrtimer *taddr, struct hrtimer *timer,print_name_offset (m, taddr);SEQ_printf (m,", " );print_name_offset (m, timer->function); -SEQ_printf (m,", S:%02lx" , timer->state); +SEQ_printf (m,", S:%02x" , timer->state);#ifdef CONFIG_TIMER_STATS SEQ_printf (m,", " );print_name_offset (m, timer->start_site);
PATCH 2/4 timerfd: Handle relative timers with CONFIG_TIME_LOW_RES proper
In reply to Thomas GleixnerHelge reported that a relative timer can return a remaining time larger than the programmed relative time on parisc and other architectures which have CONFIG_TIME_LOW_RES set. This happens because we add a jiffie to the resulting expiry time to prevent short timeouts.
Use the new function hrtimer_expires_remaining_adjusted() to calculate the remaining time. It takes that extra added time into account for relative timers.
--- fs/timerfd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/timerfd.c +1 -1
@@ -153,7 +153,7 @@ static ktime_t timerfd_get_remaining(strif (isalarm (ctx)) remaining =alarm_expires_remaining (&ctx->t.alarm);else - remaining =hrtimer_expires_remaining (&ctx->t.tmr); + remaining =hrtimer_expires_remaining_adjusted (&ctx->t.tmr);return remaining.tv64 <0 ?ktime_set (0 ,0 ): remaining; }
PATCH 2/4 timerfd: Handle relative timers with CONFIG_TIME_LOW_RES proper
In reply to Thomas GleixnerHelge reported that a relative timer can return a remaining time larger than the programmed relative time on parisc and other architectures which have CONFIG_TIME_LOW_RES set. This happens because we add a jiffie to the resulting expiry time to prevent short timeouts.
Use the new function hrtimer_expires_remaining_adjusted() to calculate the remaining time. It takes that extra added time into account for relative timers.
--- fs/timerfd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/timerfd.c +1 -1
@@ -153,7 +153,7 @@ static ktime_t timerfd_get_remaining(strif (isalarm (ctx)) remaining =alarm_expires_remaining (&ctx->t.alarm);else - remaining =hrtimer_expires_remaining (&ctx->t.tmr); + remaining =hrtimer_expires_remaining_adjusted (&ctx->t.tmr);return remaining.tv64 <0 ?ktime_set (0 ,0 ): remaining; }
tip-bot for Thomas Gleixner
merge bot[tip:timers/urgent] timerfd: Handle relative timers with CONFIG_TIME_LOW_RES proper
timerfd: Handle relative timers with CONFIG_TIME_LOW_RES proper
Commit-ID: b62526ed11a1fe3861ab98d40b7fdab8981d788a Gitweb: http://git.kernel.org/tip/b62526ed11a1fe3861ab98d40b7fdab8981d788a Author: Thomas Gleixner <[email protected]> AuthorDate: Thu, 14 Jan 2016 16:54:46 +0000 Committer: Thomas Gleixner <[email protected]> CommitDate: Sun, 17 Jan 2016 11:13:55 +0100
timerfd: Handle relative timers with CONFIG_TIME_LOW_RES proper
Helge reported that a relative timer can return a remaining time larger than the programmed relative time on parisc and other architectures which have CONFIG_TIME_LOW_RES set. This happens because we add a jiffie to the resulting expiry time to prevent short timeouts.
Use the new function hrtimer_expires_remaining_adjusted() to calculate the remaining time. It takes that extra added time into account for relative timers.
--- fs/timerfd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/timerfd.c +1 -1
@@ -153,7 +153,7 @@ static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx)if (isalarm (ctx)) remaining =alarm_expires_remaining (&ctx->t.alarm);else - remaining =hrtimer_expires_remaining (&ctx->t.tmr); + remaining =hrtimer_expires_remaining_adjusted (&ctx->t.tmr);return remaining.tv64 <0 ?ktime_set (0 ,0 ): remaining; }
PATCH 3/4 posix-timers: Handle relative timers with CONFIG_TIME_LOW_RES proper
In reply to Thomas GleixnerAs Helge reported for timerfd we have the same issue in posix timers. We return remaining time larger than the programmed relative time to user space in case of CONFIG_TIME_LOW_RES=y. Use the proper function to adjust the extra time added in hrtimer_start_range_ns().
--- kernel/time/posix-timers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/posix-timers.c +1 -1
@@ -760,7 +760,7 @@ common_timer_get(struct k_itimer *timr, (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv); - remaining =ktime_sub (hrtimer_get_expires (timer), now); + remaining =__hrtimer_expires_remaining_adjusted (timer, now);/* Return 0 only, when the timer is expired and not pending */ if (remaining.tv64 <=0 ) {/*
tip-bot for Thomas Gleixner
merge bot[tip:timers/urgent] posix-timers: Handle relative timers with CONFIG_TIME_LOW_RES proper
posix-timers: Handle relative timers with CONFIG_TIME_LOW_RES proper
Commit-ID: 572c39172684c3711e4a03c9a7380067e2b0661c Gitweb: http://git.kernel.org/tip/572c39172684c3711e4a03c9a7380067e2b0661c Author: Thomas Gleixner <[email protected]> AuthorDate: Thu, 14 Jan 2016 16:54:47 +0000 Committer: Thomas Gleixner <[email protected]> CommitDate: Sun, 17 Jan 2016 11:13:55 +0100
posix-timers: Handle relative timers with CONFIG_TIME_LOW_RES proper
As Helge reported for timerfd we have the same issue in posix timers. We return remaining time larger than the programmed relative time to user space in case of CONFIG_TIME_LOW_RES=y. Use the proper function to adjust the extra time added in hrtimer_start_range_ns().
--- kernel/time/posix-timers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/posix-timers.c +1 -1
@@ -760,7 +760,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv); - remaining =ktime_sub (hrtimer_get_expires (timer), now); + remaining =__hrtimer_expires_remaining_adjusted (timer, now);/* Return 0 only, when the timer is expired and not pending */ if (remaining.tv64 <=0 ) {/*
PATCH 4/4 itimers: Handle relative timers with CONFIG_TIME_LOW_RES proper
In reply to Thomas GleixnerAs Helge reported for timerfd we have the same issue in itimers. We return remaining time larger than the programmed relative time to user space in case of CONFIG_TIME_LOW_RES=y. Use the proper function to adjust the extra time added in hrtimer_start_range_ns().
--- kernel/time/itimer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/itimer.c +1 -1
@@ -26,7 +26,7 @@*/ static struct timeval itimer_get_remtime (struct hrtimer *timer) { -ktime_t rem =hrtimer_get_remaining (timer); +ktime_t rem =__hrtimer_get_remaining (timer, true);/* * Racy but safe: if the itimer expires after the above
PATCH 4/4 itimers: Handle relative timers with CONFIG_TIME_LOW_RES proper
In reply to Thomas GleixnerAs Helge reported for timerfd we have the same issue in itimers. We return remaining time larger than the programmed relative time to user space in case of CONFIG_TIME_LOW_RES=y. Use the proper function to adjust the extra time added in hrtimer_start_range_ns().
--- kernel/time/itimer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/itimer.c +1 -1
@@ -26,7 +26,7 @@*/ static struct timeval itimer_get_remtime (struct hrtimer *timer) { -ktime_t rem =hrtimer_get_remaining (timer); +ktime_t rem =__hrtimer_get_remaining (timer, true);/* * Racy but safe: if the itimer expires after the above
tip-bot for Thomas Gleixner
merge bot[tip:timers/urgent] itimers: Handle relative timers with CONFIG_TIME_LOW_RES proper
itimers: Handle relative timers with CONFIG_TIME_LOW_RES proper
Commit-ID: 51cbb5242a41700a3f250ecfb48dcfb7e4375ea4 Gitweb: http://git.kernel.org/tip/51cbb5242a41700a3f250ecfb48dcfb7e4375ea4 Author: Thomas Gleixner <[email protected]> AuthorDate: Thu, 14 Jan 2016 16:54:48 +0000 Committer: Thomas Gleixner <[email protected]> CommitDate: Sun, 17 Jan 2016 11:13:55 +0100
itimers: Handle relative timers with CONFIG_TIME_LOW_RES proper
As Helge reported for timerfd we have the same issue in itimers. We return remaining time larger than the programmed relative time to user space in case of CONFIG_TIME_LOW_RES=y. Use the proper function to adjust the extra time added in hrtimer_start_range_ns().
--- kernel/time/itimer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/itimer.c +1 -1
@@ -26,7 +26,7 @@*/ static struct timeval itimer_get_remtime (struct hrtimer *timer) { -ktime_t rem =hrtimer_get_remaining (timer); +ktime_t rem =__hrtimer_get_remaining (timer, true);/* * Racy but safe: if the itimer expires after the above