mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-20 05:31:15 +00:00
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. Reported-and-tested-by: Helge Deller <deller@gmx.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: John Stultz <john.stultz@linaro.org> Cc: linux-m68k@lists.linux-m68k.org Cc: dhowells@redhat.com Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/20160114164159.273328486@linutronix.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
f02b4b72d1
commit
203cbf77de
3 changed files with 69 additions and 22 deletions
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue