diff options
-rw-r--r-- | include/linux/clocksource.h | 3 | ||||
-rw-r--r-- | include/linux/time.h | 2 | ||||
-rw-r--r-- | kernel/posix-timers.c | 15 | ||||
-rw-r--r-- | kernel/time/timekeeping.c | 44 |
4 files changed, 64 insertions, 0 deletions
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index f0a7fb984413..f88d32f8ff7c 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h | |||
@@ -79,6 +79,7 @@ struct clocksource { | |||
79 | /* timekeeping specific data, ignore */ | 79 | /* timekeeping specific data, ignore */ |
80 | cycle_t cycle_interval; | 80 | cycle_t cycle_interval; |
81 | u64 xtime_interval; | 81 | u64 xtime_interval; |
82 | u32 raw_interval; | ||
82 | /* | 83 | /* |
83 | * Second part is written at each timer interrupt | 84 | * Second part is written at each timer interrupt |
84 | * Keep it in a different cache line to dirty no | 85 | * Keep it in a different cache line to dirty no |
@@ -87,6 +88,7 @@ struct clocksource { | |||
87 | cycle_t cycle_last ____cacheline_aligned_in_smp; | 88 | cycle_t cycle_last ____cacheline_aligned_in_smp; |
88 | u64 xtime_nsec; | 89 | u64 xtime_nsec; |
89 | s64 error; | 90 | s64 error; |
91 | struct timespec raw_time; | ||
90 | 92 | ||
91 | #ifdef CONFIG_CLOCKSOURCE_WATCHDOG | 93 | #ifdef CONFIG_CLOCKSOURCE_WATCHDOG |
92 | /* Watchdog related data, used by the framework */ | 94 | /* Watchdog related data, used by the framework */ |
@@ -215,6 +217,7 @@ static inline void clocksource_calculate_interval(struct clocksource *c, | |||
215 | 217 | ||
216 | /* Go back from cycles -> shifted ns, this time use ntp adjused mult */ | 218 | /* Go back from cycles -> shifted ns, this time use ntp adjused mult */ |
217 | c->xtime_interval = (u64)c->cycle_interval * c->mult; | 219 | c->xtime_interval = (u64)c->cycle_interval * c->mult; |
220 | c->raw_interval = ((u64)c->cycle_interval * c->mult_orig) >> c->shift; | ||
218 | } | 221 | } |
219 | 222 | ||
220 | 223 | ||
diff --git a/include/linux/time.h b/include/linux/time.h index e15206a7e82e..205f974b9ebf 100644 --- a/include/linux/time.h +++ b/include/linux/time.h | |||
@@ -117,6 +117,7 @@ extern int do_setitimer(int which, struct itimerval *value, | |||
117 | extern unsigned int alarm_setitimer(unsigned int seconds); | 117 | extern unsigned int alarm_setitimer(unsigned int seconds); |
118 | extern int do_getitimer(int which, struct itimerval *value); | 118 | extern int do_getitimer(int which, struct itimerval *value); |
119 | extern void getnstimeofday(struct timespec *tv); | 119 | extern void getnstimeofday(struct timespec *tv); |
120 | extern void getrawmonotonic(struct timespec *ts); | ||
120 | extern void getboottime(struct timespec *ts); | 121 | extern void getboottime(struct timespec *ts); |
121 | extern void monotonic_to_bootbased(struct timespec *ts); | 122 | extern void monotonic_to_bootbased(struct timespec *ts); |
122 | 123 | ||
@@ -214,6 +215,7 @@ struct itimerval { | |||
214 | #define CLOCK_MONOTONIC 1 | 215 | #define CLOCK_MONOTONIC 1 |
215 | #define CLOCK_PROCESS_CPUTIME_ID 2 | 216 | #define CLOCK_PROCESS_CPUTIME_ID 2 |
216 | #define CLOCK_THREAD_CPUTIME_ID 3 | 217 | #define CLOCK_THREAD_CPUTIME_ID 3 |
218 | #define CLOCK_MONOTONIC_RAW 4 | ||
217 | 219 | ||
218 | /* | 220 | /* |
219 | * The IDs of various hardware clocks: | 221 | * The IDs of various hardware clocks: |
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index e36d5798cbff..d3c66b53dff6 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c | |||
@@ -223,6 +223,15 @@ static int posix_ktime_get_ts(clockid_t which_clock, struct timespec *tp) | |||
223 | } | 223 | } |
224 | 224 | ||
225 | /* | 225 | /* |
226 | * Get monotonic time for posix timers | ||
227 | */ | ||
228 | static int posix_get_monotonic_raw(clockid_t which_clock, struct timespec *tp) | ||
229 | { | ||
230 | getrawmonotonic(tp); | ||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | /* | ||
226 | * Initialize everything, well, just everything in Posix clocks/timers ;) | 235 | * Initialize everything, well, just everything in Posix clocks/timers ;) |
227 | */ | 236 | */ |
228 | static __init int init_posix_timers(void) | 237 | static __init int init_posix_timers(void) |
@@ -235,9 +244,15 @@ static __init int init_posix_timers(void) | |||
235 | .clock_get = posix_ktime_get_ts, | 244 | .clock_get = posix_ktime_get_ts, |
236 | .clock_set = do_posix_clock_nosettime, | 245 | .clock_set = do_posix_clock_nosettime, |
237 | }; | 246 | }; |
247 | struct k_clock clock_monotonic_raw = { | ||
248 | .clock_getres = hrtimer_get_res, | ||
249 | .clock_get = posix_get_monotonic_raw, | ||
250 | .clock_set = do_posix_clock_nosettime, | ||
251 | }; | ||
238 | 252 | ||
239 | register_posix_clock(CLOCK_REALTIME, &clock_realtime); | 253 | register_posix_clock(CLOCK_REALTIME, &clock_realtime); |
240 | register_posix_clock(CLOCK_MONOTONIC, &clock_monotonic); | 254 | register_posix_clock(CLOCK_MONOTONIC, &clock_monotonic); |
255 | register_posix_clock(CLOCK_MONOTONIC_RAW, &clock_monotonic_raw); | ||
241 | 256 | ||
242 | posix_timers_cache = kmem_cache_create("posix_timers_cache", | 257 | posix_timers_cache = kmem_cache_create("posix_timers_cache", |
243 | sizeof (struct k_itimer), 0, SLAB_PANIC, | 258 | sizeof (struct k_itimer), 0, SLAB_PANIC, |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 83d3555a6998..5099c95b8aa2 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -75,6 +75,9 @@ static void clocksource_forward_now(void) | |||
75 | 75 | ||
76 | nsec = cyc2ns(clock, cycle_delta); | 76 | nsec = cyc2ns(clock, cycle_delta); |
77 | timespec_add_ns(&xtime, nsec); | 77 | timespec_add_ns(&xtime, nsec); |
78 | |||
79 | nsec = ((s64)cycle_delta * clock->mult_orig) >> clock->shift; | ||
80 | clock->raw_time.tv_nsec += nsec; | ||
78 | } | 81 | } |
79 | 82 | ||
80 | /** | 83 | /** |
@@ -183,6 +186,8 @@ static void change_clocksource(void) | |||
183 | 186 | ||
184 | clocksource_forward_now(); | 187 | clocksource_forward_now(); |
185 | 188 | ||
189 | new->raw_time = clock->raw_time; | ||
190 | |||
186 | clock = new; | 191 | clock = new; |
187 | clock->cycle_last = 0; | 192 | clock->cycle_last = 0; |
188 | clock->cycle_last = clocksource_read(new); | 193 | clock->cycle_last = clocksource_read(new); |
@@ -205,6 +210,39 @@ static inline void change_clocksource(void) { } | |||
205 | #endif | 210 | #endif |
206 | 211 | ||
207 | /** | 212 | /** |
213 | * getrawmonotonic - Returns the raw monotonic time in a timespec | ||
214 | * @ts: pointer to the timespec to be set | ||
215 | * | ||
216 | * Returns the raw monotonic time (completely un-modified by ntp) | ||
217 | */ | ||
218 | void getrawmonotonic(struct timespec *ts) | ||
219 | { | ||
220 | unsigned long seq; | ||
221 | s64 nsecs; | ||
222 | cycle_t cycle_now, cycle_delta; | ||
223 | |||
224 | do { | ||
225 | seq = read_seqbegin(&xtime_lock); | ||
226 | |||
227 | /* read clocksource: */ | ||
228 | cycle_now = clocksource_read(clock); | ||
229 | |||
230 | /* calculate the delta since the last update_wall_time: */ | ||
231 | cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; | ||
232 | |||
233 | /* convert to nanoseconds: */ | ||
234 | nsecs = ((s64)cycle_delta * clock->mult_orig) >> clock->shift; | ||
235 | |||
236 | *ts = clock->raw_time; | ||
237 | |||
238 | } while (read_seqretry(&xtime_lock, seq)); | ||
239 | |||
240 | timespec_add_ns(ts, nsecs); | ||
241 | } | ||
242 | EXPORT_SYMBOL(getrawmonotonic); | ||
243 | |||
244 | |||
245 | /** | ||
208 | * timekeeping_valid_for_hres - Check if timekeeping is suitable for hres | 246 | * timekeeping_valid_for_hres - Check if timekeeping is suitable for hres |
209 | */ | 247 | */ |
210 | int timekeeping_valid_for_hres(void) | 248 | int timekeeping_valid_for_hres(void) |
@@ -466,6 +504,12 @@ void update_wall_time(void) | |||
466 | second_overflow(); | 504 | second_overflow(); |
467 | } | 505 | } |
468 | 506 | ||
507 | clock->raw_time.tv_nsec += clock->raw_interval; | ||
508 | if (clock->raw_time.tv_nsec >= NSEC_PER_SEC) { | ||
509 | clock->raw_time.tv_nsec -= NSEC_PER_SEC; | ||
510 | clock->raw_time.tv_sec++; | ||
511 | } | ||
512 | |||
469 | /* accumulate error between NTP and clock interval */ | 513 | /* accumulate error between NTP and clock interval */ |
470 | clock->error += tick_length; | 514 | clock->error += tick_length; |
471 | clock->error -= clock->xtime_interval << (NTP_SCALE_SHIFT - clock->shift); | 515 | clock->error -= clock->xtime_interval << (NTP_SCALE_SHIFT - clock->shift); |