From dae373be9fec6f850159a05af3a1c36236a70d43 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 13 Sep 2012 19:12:16 -0400 Subject: alarmtimer: Use hrtimer per-alarm instead of per-base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Arve Hjønnevåg reported numerous crashes from the "BUG_ON(timer->state != HRTIMER_STATE_CALLBACK)" check in __run_hrtimer after it called alarmtimer_fired. It ends up the alarmtimer code was not properly handling possible failures of hrtimer_try_to_cancel, and because these faulres occur when the underlying base hrtimer is being run, this limits the ability to properly handle modifications to any alarmtimers on that base. Because much of the logic duplicates the hrtimer logic, it seems that we might as well have a per-alarmtimer hrtimer, and avoid the extra complextity of trying to multiplex many alarmtimers off of one hrtimer. Thus this patch moves the hrtimer to the alarm structure and simplifies the management logic. Changelog: v2: * Includes a fix for double alarm_start calls found by Arve Cc: Arve Hjønnevåg Cc: Colin Cross Cc: Thomas Gleixner Reported-by: Arve Hjønnevåg Tested-by: Arve Hjønnevåg Signed-off-by: John Stultz --- include/linux/alarmtimer.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/alarmtimer.h b/include/linux/alarmtimer.h index 96c5c249b086..f122c9fbf8c7 100644 --- a/include/linux/alarmtimer.h +++ b/include/linux/alarmtimer.h @@ -35,6 +35,7 @@ enum alarmtimer_restart { */ struct alarm { struct timerqueue_node node; + struct hrtimer timer; enum alarmtimer_restart (*function)(struct alarm *, ktime_t now); enum alarmtimer_type type; int state; @@ -43,7 +44,7 @@ struct alarm { void alarm_init(struct alarm *alarm, enum alarmtimer_type type, enum alarmtimer_restart (*function)(struct alarm *, ktime_t)); -void alarm_start(struct alarm *alarm, ktime_t start); +int alarm_start(struct alarm *alarm, ktime_t start); int alarm_try_to_cancel(struct alarm *alarm); int alarm_cancel(struct alarm *alarm); -- cgit v1.2.3 From a269eb50bd5793e43589270c2f326f4f7519ddda Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 13 Sep 2012 19:23:22 -0400 Subject: alarmtimer: Remove unused helpers & defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No one is using these alarmtimer state helpers, so yank them. Cc: Arve Hjønnevåg Cc: Colin Cross Cc: Thomas Gleixner Signed-off-by: John Stultz --- include/linux/alarmtimer.h | 28 ---------------------------- 1 file changed, 28 deletions(-) (limited to 'include') diff --git a/include/linux/alarmtimer.h b/include/linux/alarmtimer.h index f122c9fbf8c7..9069694e70eb 100644 --- a/include/linux/alarmtimer.h +++ b/include/linux/alarmtimer.h @@ -21,7 +21,6 @@ enum alarmtimer_restart { #define ALARMTIMER_STATE_INACTIVE 0x00 #define ALARMTIMER_STATE_ENQUEUED 0x01 -#define ALARMTIMER_STATE_CALLBACK 0x02 /** * struct alarm - Alarm timer structure @@ -50,33 +49,6 @@ int alarm_cancel(struct alarm *alarm); u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval); -/* - * A alarmtimer is active, when it is enqueued into timerqueue or the - * callback function is running. - */ -static inline int alarmtimer_active(const struct alarm *timer) -{ - return timer->state != ALARMTIMER_STATE_INACTIVE; -} - -/* - * Helper function to check, whether the timer is on one of the queues - */ -static inline int alarmtimer_is_queued(struct alarm *timer) -{ - return timer->state & ALARMTIMER_STATE_ENQUEUED; -} - -/* - * Helper function to check, whether the timer is running the callback - * function - */ -static inline int alarmtimer_callback_running(struct alarm *timer) -{ - return timer->state & ALARMTIMER_STATE_CALLBACK; -} - - /* Provide way to access the rtc device being used by alarmtimers */ struct rtc_device *alarmtimer_get_rtcdev(void); -- cgit v1.2.3 From 7916a1f14f06ac93e4cec81139fe4f7ec13b572c Mon Sep 17 00:00:00 2001 From: John Stultz Date: Wed, 5 Sep 2012 00:44:53 -0400 Subject: jiffies: Kill unused TICK_USEC_TO_NSEC No one is using TICK_USEC_TO_NSEC, so kill it. Cc: Catalin Marinas Cc: Arnd Bergmann Cc: Richard Cochran Cc: Prarit Bhargava Cc: Thomas Gleixner Signed-off-by: John Stultz --- include/linux/jiffies.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'include') diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 82680541576d..4a7e3864e80d 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -70,12 +70,6 @@ /* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */ #define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ) -/* - * TICK_USEC_TO_NSEC is the time between ticks in nsec assuming SHIFTED_HZ and - * a value TUSEC for TICK_USEC (can be set bij adjtimex) - */ -#define TICK_USEC_TO_NSEC(TUSEC) (SH_DIV(TUSEC * USER_HZ * 1000, SHIFTED_HZ, 8)) - /* some arch's have a small-data section that can be accessed register-relative * but that can only take up to, say, 4-byte variables. jiffies being part of * an 8-byte variable may not be correctly accessed unless we force the issue -- cgit v1.2.3 From b3c869d35b9b014f63ac0beacd31c57372084d01 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 4 Sep 2012 12:42:27 -0400 Subject: jiffies: Remove compile time assumptions about CLOCK_TICK_RATE CLOCK_TICK_RATE is used to accurately caclulate exactly how a tick will be at a given HZ. This is useful, because while we'd expect NSEC_PER_SEC/HZ, the underlying hardware will have some granularity limit, so we won't be able to have exactly HZ ticks per second. This slight error can cause timekeeping quality problems when using the jiffies or other jiffies driven clocksources. Thus we currently use compile time CLOCK_TICK_RATE value to generate SHIFTED_HZ and NSEC_PER_JIFFIES, which we then use to adjust the jiffies clocksource to correct this error. Unfortunately though, since CLOCK_TICK_RATE is a compile time value, and the jiffies clocksource is registered very early during boot, there are a number of cases where there are different possible hardware timers that have different tick rates. This causes problems in cases like ARM where there are numerous different types of hardware, each having their own compile-time CLOCK_TICK_RATE, making it hard to accurately support different hardware with a single kernel. For the most part, this doesn't matter all that much, as not too many systems actually utilize the jiffies or jiffies driven clocksource. Usually there are other highres clocksources who's granularity error is negligable. Even so, we have some complicated calcualtions that we do everywhere to handle these edge cases. This patch removes the compile time SHIFTED_HZ value, and introduces a register_refined_jiffies() function. This results in the default jiffies clock as being assumed a perfect HZ freq, and allows archtectures that care about jiffies accuracy to call register_refined_jiffies() with the tick rate, specified dynamically at boot. This allows us, where necessary, to not have a compile time CLOCK_TICK_RATE constant, simplifies the jiffies code, and still provides a way to have an accurate jiffies clock. NOTE: Since this patch does not add register_refinied_jiffies() calls for every arch, it may cause time quality regressions in some cases. Its likely these will not be noticable, but if they are an issue, adding the following to the end of setup_arch() should resolve the regression: register_refinied_jiffies(CLOCK_TICK_RATE) Cc: Catalin Marinas Cc: Arnd Bergmann Cc: Richard Cochran Cc: Prarit Bhargava Cc: Thomas Gleixner Signed-off-by: John Stultz --- include/linux/jiffies.h | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 4a7e3864e80d..388edb54bfb6 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -51,21 +51,10 @@ #define SH_DIV(NOM,DEN,LSH) ( (((NOM) / (DEN)) << (LSH)) \ + ((((NOM) % (DEN)) << (LSH)) + (DEN) / 2) / (DEN)) -#ifdef CLOCK_TICK_RATE -/* LATCH is used in the interval timer and ftape setup. */ -# define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ - -/* - * HZ is the requested value. However the CLOCK_TICK_RATE may not allow - * for exactly HZ. So SHIFTED_HZ is high res HZ ("<< 8" is for accuracy) - */ -# define SHIFTED_HZ (SH_DIV(CLOCK_TICK_RATE, LATCH, 8)) -#else -# define SHIFTED_HZ (HZ << 8) -#endif +extern int register_refined_jiffies(long clock_tick_rate); /* TICK_NSEC is the time between ticks in nsec assuming SHIFTED_HZ */ -#define TICK_NSEC (SH_DIV(1000000UL * 1000, SHIFTED_HZ, 8)) +#define TICK_NSEC ((NSEC_PER_SEC+HZ/2)/HZ) /* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */ #define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ) -- cgit v1.2.3 From d7b4202e0581683f1a14fe598633da0067f5241e Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 4 Sep 2012 15:12:07 -0400 Subject: time: Move timekeeper structure to timekeeper_internal.h for vsyscall changes We're going to need to access the timekeeper in update_vsyscall, so make the structure available for those who need it. Cc: Tony Luck Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Cc: Andy Lutomirski Cc: Martin Schwidefsky Cc: Paul Turner Cc: Steven Rostedt Cc: Richard Cochran Cc: Prarit Bhargava Cc: Thomas Gleixner Signed-off-by: John Stultz --- include/linux/timekeeper_internal.h | 68 +++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 include/linux/timekeeper_internal.h (limited to 'include') diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h new file mode 100644 index 000000000000..8ba43fa8c7e6 --- /dev/null +++ b/include/linux/timekeeper_internal.h @@ -0,0 +1,68 @@ +/* + * You SHOULD NOT be including this unless you're vsyscall + * handling code or timekeeping internal code! + */ + +#ifndef _LINUX_TIMEKEEPER_INTERNAL_H +#define _LINUX_TIMEKEEPER_INTERNAL_H + +#include +#include +#include + +/* Structure holding internal timekeeping values. */ +struct timekeeper { + /* Current clocksource used for timekeeping. */ + struct clocksource *clock; + /* NTP adjusted clock multiplier */ + u32 mult; + /* The shift value of the current clocksource. */ + u32 shift; + /* Number of clock cycles in one NTP interval. */ + cycle_t cycle_interval; + /* Number of clock shifted nano seconds in one NTP interval. */ + u64 xtime_interval; + /* shifted nano seconds left over when rounding cycle_interval */ + s64 xtime_remainder; + /* Raw nano seconds accumulated per NTP interval. */ + u32 raw_interval; + + /* Current CLOCK_REALTIME time in seconds */ + u64 xtime_sec; + /* Clock shifted nano seconds */ + u64 xtime_nsec; + + /* Difference between accumulated time and NTP time in ntp + * shifted nano seconds. */ + s64 ntp_error; + /* Shift conversion between clock shifted nano seconds and + * ntp shifted nano seconds. */ + u32 ntp_error_shift; + + /* + * wall_to_monotonic is what we need to add to xtime (or xtime corrected + * for sub jiffie times) to get to monotonic time. Monotonic is pegged + * at zero at system boot time, so wall_to_monotonic will be negative, + * however, we will ALWAYS keep the tv_nsec part positive so we can use + * the usual normalization. + * + * wall_to_monotonic is moved after resume from suspend for the + * monotonic time not to jump. We need to add total_sleep_time to + * wall_to_monotonic to get the real boot based time offset. + * + * - wall_to_monotonic is no longer the boot time, getboottime must be + * used instead. + */ + struct timespec wall_to_monotonic; + /* Offset clock monotonic -> clock realtime */ + ktime_t offs_real; + /* time spent in suspend */ + struct timespec total_sleep_time; + /* Offset clock monotonic -> clock boottime */ + ktime_t offs_boot; + /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */ + struct timespec raw_time; + /* Seqlock for all timekeeper values */ + seqlock_t lock; +}; +#endif /* _LINUX_TIMEKEEPER_INTERNAL_H */ -- cgit v1.2.3 From 189374aed657e2228ad6b39ece438c9cdafc8dae Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 4 Sep 2012 15:27:48 -0400 Subject: time: Move update_vsyscall definitions to timekeeper_internal.h Since users will need to include timekeeper_internal.h, move update_vsyscall definitions to timekeeper_internal.h. Cc: Tony Luck Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Cc: Andy Lutomirski Cc: Martin Schwidefsky Cc: Paul Turner Cc: Steven Rostedt Cc: Richard Cochran Cc: Prarit Bhargava Cc: Thomas Gleixner Signed-off-by: John Stultz --- include/linux/clocksource.h | 16 ---------------- include/linux/timekeeper_internal.h | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index fbe89e17124e..4dceaf8ae152 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -319,22 +319,6 @@ static inline void __clocksource_updatefreq_khz(struct clocksource *cs, u32 khz) __clocksource_updatefreq_scale(cs, 1000, khz); } -#ifdef CONFIG_GENERIC_TIME_VSYSCALL -extern void -update_vsyscall(struct timespec *ts, struct timespec *wtm, - struct clocksource *c, u32 mult); -extern void update_vsyscall_tz(void); -#else -static inline void -update_vsyscall(struct timespec *ts, struct timespec *wtm, - struct clocksource *c, u32 mult) -{ -} - -static inline void update_vsyscall_tz(void) -{ -} -#endif extern void timekeeping_notify(struct clocksource *clock); diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h index 8ba43fa8c7e6..9c1c2cf413a6 100644 --- a/include/linux/timekeeper_internal.h +++ b/include/linux/timekeeper_internal.h @@ -65,4 +65,21 @@ struct timekeeper { /* Seqlock for all timekeeper values */ seqlock_t lock; }; + + +#ifdef CONFIG_GENERIC_TIME_VSYSCALL +extern void +update_vsyscall(struct timespec *ts, struct timespec *wtm, + struct clocksource *c, u32 mult); +extern void update_vsyscall_tz(void); +#else +static inline void update_vsyscall(struct timespec *ts, struct timespec *wtm, + struct clocksource *c, u32 mult) +{ +} +static inline void update_vsyscall_tz(void) +{ +} +#endif + #endif /* _LINUX_TIMEKEEPER_INTERNAL_H */ -- cgit v1.2.3 From 706394211648117762edfaeffd6fc04bf3b1a75d Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 4 Sep 2012 15:34:21 -0400 Subject: time: Convert CONFIG_GENERIC_TIME_VSYSCALL to CONFIG_GENERIC_TIME_VSYSCALL_OLD To help migrate archtectures over to the new update_vsyscall method, redfine CONFIG_GENERIC_TIME_VSYSCALL as CONFIG_GENERIC_TIME_VSYSCALL_OLD Cc: Tony Luck Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Cc: Andy Lutomirski Cc: Martin Schwidefsky Cc: Paul Turner Cc: Steven Rostedt Cc: Richard Cochran Cc: Prarit Bhargava Cc: Thomas Gleixner Signed-off-by: John Stultz --- include/linux/timekeeper_internal.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h index 9c1c2cf413a6..a904d76a5faa 100644 --- a/include/linux/timekeeper_internal.h +++ b/include/linux/timekeeper_internal.h @@ -67,13 +67,14 @@ struct timekeeper { }; -#ifdef CONFIG_GENERIC_TIME_VSYSCALL +#ifdef CONFIG_GENERIC_TIME_VSYSCALL_OLD extern void -update_vsyscall(struct timespec *ts, struct timespec *wtm, +update_vsyscall_old(struct timespec *ts, struct timespec *wtm, struct clocksource *c, u32 mult); extern void update_vsyscall_tz(void); #else -static inline void update_vsyscall(struct timespec *ts, struct timespec *wtm, +static inline void +update_vsyscall_old(struct timespec *ts, struct timespec *wtm, struct clocksource *c, u32 mult) { } -- cgit v1.2.3 From 576094b7f0aaf41aadab9b7d4e5bd85faa432711 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 11 Sep 2012 19:58:13 -0400 Subject: time: Introduce new GENERIC_TIME_VSYSCALL Now that we moved everyone over to GENERIC_TIME_VSYSCALL_OLD, introduce the new declaration and config option for the new update_vsyscall method. Cc: Tony Luck Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Cc: Andy Lutomirski Cc: Martin Schwidefsky Cc: Paul Turner Cc: Steven Rostedt Cc: Richard Cochran Cc: Prarit Bhargava Cc: Thomas Gleixner Signed-off-by: John Stultz --- include/linux/timekeeper_internal.h | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h index a904d76a5faa..e1d558e237ec 100644 --- a/include/linux/timekeeper_internal.h +++ b/include/linux/timekeeper_internal.h @@ -66,16 +66,38 @@ struct timekeeper { seqlock_t lock; }; +static inline struct timespec tk_xtime(struct timekeeper *tk) +{ + struct timespec ts; + + ts.tv_sec = tk->xtime_sec; + ts.tv_nsec = (long)(tk->xtime_nsec >> tk->shift); + return ts; +} + + +#ifdef CONFIG_GENERIC_TIME_VSYSCALL + +extern void update_vsyscall(struct timekeeper *tk); +extern void update_vsyscall_tz(void); -#ifdef CONFIG_GENERIC_TIME_VSYSCALL_OLD -extern void -update_vsyscall_old(struct timespec *ts, struct timespec *wtm, - struct clocksource *c, u32 mult); +#elif defined(CONFIG_GENERIC_TIME_VSYSCALL_OLD) + +extern void update_vsyscall_old(struct timespec *ts, struct timespec *wtm, + struct clocksource *c, u32 mult); extern void update_vsyscall_tz(void); + +static inline void update_vsyscall(struct timekeeper *tk) +{ + struct timespec xt; + + xt = tk_xtime(tk); + update_vsyscall_old(&xt, &tk->wall_to_monotonic, tk->clock, tk->mult); +} + #else -static inline void -update_vsyscall_old(struct timespec *ts, struct timespec *wtm, - struct clocksource *c, u32 mult) + +static inline void update_vsyscall(struct timekeeper *tk) { } static inline void update_vsyscall_tz(void) -- cgit v1.2.3 From 015a830d44695adff8b52d2703608cec4a1041ba Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 28 Sep 2012 23:36:17 +0200 Subject: time/jiffies: bring back unconditional LATCH definition Patch a7ea3bbf5d "time/jiffies: Allow CLOCK_TICK_RATE to be undefined" breaks the compilation of targets that rely on the LATCH definition, because of recursive header file inclusion not defining CLOCK_TICK_RATE before it is checked here. This fixes the problem by moving LATCH back to where it was, but it seems that there are still cases where SHIFTED_HZ is defined incorrectly because of the same problem. Need to investigate further. Without this patch, building h7201_defconfig results in: arch/arm/mach-h720x/common.c: In function 'h720x_gettimeoffset': arch/arm/mach-h720x/common.c:50:73: error: 'LATCH' undeclared (first use in this function) arch/arm/mach-h720x/common.c:50:73: note: each undeclared identifier is reported only once for each function it appears in arch/arm/mach-h720x/common.c:51:1: warning: control reaches end of non-void function [-Wreturn-type] Signed-off-by: Arnd Bergmann Cc: Catalin Marinas Cc: Richard Cochran Cc: Prarit Bhargava Cc: Andrew Morton Cc: John Stultz Cc: Ingo Molnar Signed-off-by: John Stultz --- include/linux/jiffies.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 82680541576d..44e389d8e8fd 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -51,9 +51,10 @@ #define SH_DIV(NOM,DEN,LSH) ( (((NOM) / (DEN)) << (LSH)) \ + ((((NOM) % (DEN)) << (LSH)) + (DEN) / 2) / (DEN)) -#ifdef CLOCK_TICK_RATE /* LATCH is used in the interval timer and ftape setup. */ -# define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ +#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ + +#ifdef CLOCK_TICK_RATE /* * HZ is the requested value. However the CLOCK_TICK_RATE may not allow -- cgit v1.2.3