aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/timekeeping.c
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@citrix.com>2013-06-27 06:35:46 -0400
committerThomas Gleixner <tglx@linutronix.de>2013-06-28 17:15:06 -0400
commit780427f0e113b4c77dfff4d258c05a902cdb0eb9 (patch)
tree778bc50cbd83b67bdd6ae580a192c4c65e9711bd /kernel/time/timekeeping.c
parent04397fe94ad65289884b9862b6a0c722ececaadf (diff)
timekeeping: Indicate that clock was set in the pvclock gtod notifier
If the clock was set (stepped), set the action parameter to functions in the pvclock gtod notifier chain to non-zero. This allows the callee to only do work if the clock was stepped. This will be used on Xen as the synchronization of the Xen wallclock to the control domain's (dom0) system time will be done with this notifier and updating on every timer tick is unnecessary and too expensive. Signed-off-by: David Vrabel <david.vrabel@citrix.com> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Cc: John Stultz <john.stultz@linaro.org> Cc: <xen-devel@lists.xen.org> Link: http://lkml.kernel.org/r/1372329348-20841-4-git-send-email-david.vrabel@citrix.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/time/timekeeping.c')
-rw-r--r--kernel/time/timekeeping.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index d8b23a929e66..846d0a1f235e 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -29,6 +29,7 @@
29 29
30#define TK_CLEAR_NTP (1 << 0) 30#define TK_CLEAR_NTP (1 << 0)
31#define TK_MIRROR (1 << 1) 31#define TK_MIRROR (1 << 1)
32#define TK_CLOCK_WAS_SET (1 << 2)
32 33
33static struct timekeeper timekeeper; 34static struct timekeeper timekeeper;
34static DEFINE_RAW_SPINLOCK(timekeeper_lock); 35static DEFINE_RAW_SPINLOCK(timekeeper_lock);
@@ -204,9 +205,9 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
204 205
205static RAW_NOTIFIER_HEAD(pvclock_gtod_chain); 206static RAW_NOTIFIER_HEAD(pvclock_gtod_chain);
206 207
207static void update_pvclock_gtod(struct timekeeper *tk) 208static void update_pvclock_gtod(struct timekeeper *tk, bool was_set)
208{ 209{
209 raw_notifier_call_chain(&pvclock_gtod_chain, 0, tk); 210 raw_notifier_call_chain(&pvclock_gtod_chain, was_set, tk);
210} 211}
211 212
212/** 213/**
@@ -220,7 +221,7 @@ int pvclock_gtod_register_notifier(struct notifier_block *nb)
220 221
221 raw_spin_lock_irqsave(&timekeeper_lock, flags); 222 raw_spin_lock_irqsave(&timekeeper_lock, flags);
222 ret = raw_notifier_chain_register(&pvclock_gtod_chain, nb); 223 ret = raw_notifier_chain_register(&pvclock_gtod_chain, nb);
223 update_pvclock_gtod(tk); 224 update_pvclock_gtod(tk, true);
224 raw_spin_unlock_irqrestore(&timekeeper_lock, flags); 225 raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
225 226
226 return ret; 227 return ret;
@@ -252,7 +253,7 @@ static void timekeeping_update(struct timekeeper *tk, unsigned int action)
252 ntp_clear(); 253 ntp_clear();
253 } 254 }
254 update_vsyscall(tk); 255 update_vsyscall(tk);
255 update_pvclock_gtod(tk); 256 update_pvclock_gtod(tk, action & TK_CLOCK_WAS_SET);
256 257
257 if (action & TK_MIRROR) 258 if (action & TK_MIRROR)
258 memcpy(&shadow_timekeeper, &timekeeper, sizeof(timekeeper)); 259 memcpy(&shadow_timekeeper, &timekeeper, sizeof(timekeeper));
@@ -512,7 +513,7 @@ int do_settimeofday(const struct timespec *tv)
512 513
513 tk_set_xtime(tk, tv); 514 tk_set_xtime(tk, tv);
514 515
515 timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR); 516 timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
516 517
517 write_seqcount_end(&timekeeper_seq); 518 write_seqcount_end(&timekeeper_seq);
518 raw_spin_unlock_irqrestore(&timekeeper_lock, flags); 519 raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
@@ -556,7 +557,7 @@ int timekeeping_inject_offset(struct timespec *ts)
556 tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, *ts)); 557 tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, *ts));
557 558
558error: /* even if we error out, we forwarded the time, so call update */ 559error: /* even if we error out, we forwarded the time, so call update */
559 timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR); 560 timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
560 561
561 write_seqcount_end(&timekeeper_seq); 562 write_seqcount_end(&timekeeper_seq);
562 raw_spin_unlock_irqrestore(&timekeeper_lock, flags); 563 raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
@@ -646,7 +647,7 @@ static int change_clocksource(void *data)
646 module_put(new->owner); 647 module_put(new->owner);
647 } 648 }
648 } 649 }
649 timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR); 650 timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
650 651
651 write_seqcount_end(&timekeeper_seq); 652 write_seqcount_end(&timekeeper_seq);
652 raw_spin_unlock_irqrestore(&timekeeper_lock, flags); 653 raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
@@ -887,7 +888,7 @@ void timekeeping_inject_sleeptime(struct timespec *delta)
887 888
888 __timekeeping_inject_sleeptime(tk, delta); 889 __timekeeping_inject_sleeptime(tk, delta);
889 890
890 timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR); 891 timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
891 892
892 write_seqcount_end(&timekeeper_seq); 893 write_seqcount_end(&timekeeper_seq);
893 raw_spin_unlock_irqrestore(&timekeeper_lock, flags); 894 raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
@@ -969,7 +970,7 @@ static void timekeeping_resume(void)
969 tk->cycle_last = clock->cycle_last = cycle_now; 970 tk->cycle_last = clock->cycle_last = cycle_now;
970 tk->ntp_error = 0; 971 tk->ntp_error = 0;
971 timekeeping_suspended = 0; 972 timekeeping_suspended = 0;
972 timekeeping_update(tk, TK_MIRROR); 973 timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET);
973 write_seqcount_end(&timekeeper_seq); 974 write_seqcount_end(&timekeeper_seq);
974 raw_spin_unlock_irqrestore(&timekeeper_lock, flags); 975 raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
975 976
@@ -1243,9 +1244,10 @@ out_adjust:
1243 * It also calls into the NTP code to handle leapsecond processing. 1244 * It also calls into the NTP code to handle leapsecond processing.
1244 * 1245 *
1245 */ 1246 */
1246static inline void accumulate_nsecs_to_secs(struct timekeeper *tk) 1247static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk)
1247{ 1248{
1248 u64 nsecps = (u64)NSEC_PER_SEC << tk->shift; 1249 u64 nsecps = (u64)NSEC_PER_SEC << tk->shift;
1250 unsigned int action = 0;
1249 1251
1250 while (tk->xtime_nsec >= nsecps) { 1252 while (tk->xtime_nsec >= nsecps) {
1251 int leap; 1253 int leap;
@@ -1268,8 +1270,10 @@ static inline void accumulate_nsecs_to_secs(struct timekeeper *tk)
1268 __timekeeping_set_tai_offset(tk, tk->tai_offset - leap); 1270 __timekeeping_set_tai_offset(tk, tk->tai_offset - leap);
1269 1271
1270 clock_was_set_delayed(); 1272 clock_was_set_delayed();
1273 action = TK_CLOCK_WAS_SET;
1271 } 1274 }
1272 } 1275 }
1276 return action;
1273} 1277}
1274 1278
1275/** 1279/**
@@ -1354,6 +1358,7 @@ static void update_wall_time(void)
1354 struct timekeeper *tk = &shadow_timekeeper; 1358 struct timekeeper *tk = &shadow_timekeeper;
1355 cycle_t offset; 1359 cycle_t offset;
1356 int shift = 0, maxshift; 1360 int shift = 0, maxshift;
1361 unsigned int action;
1357 unsigned long flags; 1362 unsigned long flags;
1358 1363
1359 raw_spin_lock_irqsave(&timekeeper_lock, flags); 1364 raw_spin_lock_irqsave(&timekeeper_lock, flags);
@@ -1406,7 +1411,7 @@ static void update_wall_time(void)
1406 * Finally, make sure that after the rounding 1411 * Finally, make sure that after the rounding
1407 * xtime_nsec isn't larger than NSEC_PER_SEC 1412 * xtime_nsec isn't larger than NSEC_PER_SEC
1408 */ 1413 */
1409 accumulate_nsecs_to_secs(tk); 1414 action = accumulate_nsecs_to_secs(tk);
1410 1415
1411 write_seqcount_begin(&timekeeper_seq); 1416 write_seqcount_begin(&timekeeper_seq);
1412 /* Update clock->cycle_last with the new value */ 1417 /* Update clock->cycle_last with the new value */
@@ -1422,7 +1427,7 @@ static void update_wall_time(void)
1422 * updating. 1427 * updating.
1423 */ 1428 */
1424 memcpy(real_tk, tk, sizeof(*tk)); 1429 memcpy(real_tk, tk, sizeof(*tk));
1425 timekeeping_update(real_tk, 0); 1430 timekeeping_update(real_tk, action);
1426 write_seqcount_end(&timekeeper_seq); 1431 write_seqcount_end(&timekeeper_seq);
1427out: 1432out:
1428 raw_spin_unlock_irqrestore(&timekeeper_lock, flags); 1433 raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
@@ -1684,6 +1689,7 @@ int do_adjtimex(struct timex *txc)
1684 1689
1685 if (tai != orig_tai) { 1690 if (tai != orig_tai) {
1686 __timekeeping_set_tai_offset(tk, tai); 1691 __timekeeping_set_tai_offset(tk, tai);
1692 update_pvclock_gtod(tk, true);
1687 clock_was_set_delayed(); 1693 clock_was_set_delayed();
1688 } 1694 }
1689 write_seqcount_end(&timekeeper_seq); 1695 write_seqcount_end(&timekeeper_seq);