Skip to content

Commit 7c3f1a5

Browse files
Tomas JanousekLinus Torvalds
authored andcommitted
Introduce boot based time
The commits 411187f (GTOD: persistent clock support) c1d370e (i386: use GTOD persistent clock support) changed the monotonic time so that it no longer jumps after resume, but it's not possible to use it for boot time and process start time calculations then. Also, the uptime no longer increases during suspend. I add a variable to track the wall_to_monotonic changes, a function to get the real boot time and a function to get the boot based time from the monotonic one. [[email protected]: remove exports, add comment] Signed-off-by: Tomas Janousek <[email protected]> Cc: Tomas Smetana <[email protected]> Cc: John Stultz <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Ingo Molnar <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 35ef63f commit 7c3f1a5

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

include/linux/time.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ extern int do_setitimer(int which, struct itimerval *value,
116116
extern unsigned int alarm_setitimer(unsigned int seconds);
117117
extern int do_getitimer(int which, struct itimerval *value);
118118
extern void getnstimeofday(struct timespec *tv);
119+
extern void getboottime(struct timespec *ts);
120+
extern void monotonic_to_bootbased(struct timespec *ts);
119121

120122
extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
121123
extern int timekeeping_is_continuous(void);

kernel/time/timekeeping.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,17 @@ EXPORT_SYMBOL(xtime_lock);
3636
* at zero at system boot time, so wall_to_monotonic will be negative,
3737
* however, we will ALWAYS keep the tv_nsec part positive so we can use
3838
* the usual normalization.
39+
*
40+
* wall_to_monotonic is moved after resume from suspend for the monotonic
41+
* time not to jump. We need to add total_sleep_time to wall_to_monotonic
42+
* to get the real boot based time offset.
43+
*
44+
* - wall_to_monotonic is no longer the boot time, getboottime must be
45+
* used instead.
3946
*/
4047
struct timespec xtime __attribute__ ((aligned (16)));
4148
struct timespec wall_to_monotonic __attribute__ ((aligned (16)));
49+
static unsigned long total_sleep_time; /* seconds */
4250

4351
EXPORT_SYMBOL(xtime);
4452

@@ -251,6 +259,7 @@ void __init timekeeping_init(void)
251259
xtime.tv_nsec = 0;
252260
set_normalized_timespec(&wall_to_monotonic,
253261
-xtime.tv_sec, -xtime.tv_nsec);
262+
total_sleep_time = 0;
254263

255264
write_sequnlock_irqrestore(&xtime_lock, flags);
256265
}
@@ -282,6 +291,7 @@ static int timekeeping_resume(struct sys_device *dev)
282291

283292
xtime.tv_sec += sleep_length;
284293
wall_to_monotonic.tv_sec -= sleep_length;
294+
total_sleep_time += sleep_length;
285295
}
286296
/* re-base the last cycle value */
287297
clock->cycle_last = clocksource_read(clock);
@@ -476,3 +486,30 @@ void update_wall_time(void)
476486
change_clocksource();
477487
update_vsyscall(&xtime, clock);
478488
}
489+
490+
/**
491+
* getboottime - Return the real time of system boot.
492+
* @ts: pointer to the timespec to be set
493+
*
494+
* Returns the time of day in a timespec.
495+
*
496+
* This is based on the wall_to_monotonic offset and the total suspend
497+
* time. Calls to settimeofday will affect the value returned (which
498+
* basically means that however wrong your real time clock is at boot time,
499+
* you get the right time here).
500+
*/
501+
void getboottime(struct timespec *ts)
502+
{
503+
set_normalized_timespec(ts,
504+
- (wall_to_monotonic.tv_sec + total_sleep_time),
505+
- wall_to_monotonic.tv_nsec);
506+
}
507+
508+
/**
509+
* monotonic_to_bootbased - Convert the monotonic time to boot based.
510+
* @ts: pointer to the timespec to be converted
511+
*/
512+
void monotonic_to_bootbased(struct timespec *ts)
513+
{
514+
ts->tv_sec += total_sleep_time;
515+
}

0 commit comments

Comments
 (0)