Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 321334
b: refs/heads/master
c: 6d0ef90
h: refs/heads/master
v: v3
  • Loading branch information
John Stultz authored and Ingo Molnar committed Jul 31, 2012
1 parent aa69ca6 commit 8bd9f7e
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 37 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d4e3ab384b2343c7074f713ac330f839c38c52ee
refs/heads/master: 6d0ef903e2bda70da124c10d8ad89f2382c87991
90 changes: 54 additions & 36 deletions trunk/kernel/time/timekeeping.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ struct timekeeper {
* used instead.
*/
struct timespec wall_to_monotonic;
/* time spent in suspend */
struct timespec total_sleep_time;
/* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */
struct timespec raw_time;
/* 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;
};
Expand Down Expand Up @@ -117,6 +117,31 @@ static void tk_xtime_add(struct timekeeper *tk, const struct timespec *ts)
tk->xtime_nsec += (u64)ts->tv_nsec << tk->shift;
}

static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec wtm)
{
struct timespec tmp;

/*
* Verify consistency of: offset_real = -wall_to_monotonic
* before modifying anything
*/
set_normalized_timespec(&tmp, -tk->wall_to_monotonic.tv_sec,
-tk->wall_to_monotonic.tv_nsec);
WARN_ON_ONCE(tk->offs_real.tv64 != timespec_to_ktime(tmp).tv64);
tk->wall_to_monotonic = wtm;
set_normalized_timespec(&tmp, -wtm.tv_sec, -wtm.tv_nsec);
tk->offs_real = timespec_to_ktime(tmp);
}

static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t)
{
/* Verify consistency before modifying */
WARN_ON_ONCE(tk->offs_boot.tv64 != timespec_to_ktime(tk->total_sleep_time).tv64);

tk->total_sleep_time = t;
tk->offs_boot = timespec_to_ktime(t);
}

/**
* timekeeper_setup_internals - Set up internals to use clocksource clock.
*
Expand Down Expand Up @@ -217,14 +242,6 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
return nsec + arch_gettimeoffset();
}

static void update_rt_offset(struct timekeeper *tk)
{
struct timespec tmp, *wtm = &tk->wall_to_monotonic;

set_normalized_timespec(&tmp, -wtm->tv_sec, -wtm->tv_nsec);
tk->offs_real = timespec_to_ktime(tmp);
}

/* must hold write on timekeeper.lock */
static void timekeeping_update(struct timekeeper *tk, bool clearntp)
{
Expand All @@ -234,7 +251,6 @@ static void timekeeping_update(struct timekeeper *tk, bool clearntp)
tk->ntp_error = 0;
ntp_clear();
}
update_rt_offset(tk);
xt = tk_xtime(tk);
update_vsyscall(&xt, &tk->wall_to_monotonic, tk->clock, tk->mult);
}
Expand Down Expand Up @@ -419,8 +435,8 @@ int do_settimeofday(const struct timespec *tv)
ts_delta.tv_sec = tv->tv_sec - xt.tv_sec;
ts_delta.tv_nsec = tv->tv_nsec - xt.tv_nsec;

timekeeper.wall_to_monotonic =
timespec_sub(timekeeper.wall_to_monotonic, ts_delta);
tk_set_wall_to_mono(&timekeeper,
timespec_sub(timekeeper.wall_to_monotonic, ts_delta));

tk_set_xtime(&timekeeper, tv);

Expand Down Expand Up @@ -454,8 +470,8 @@ int timekeeping_inject_offset(struct timespec *ts)


tk_xtime_add(&timekeeper, ts);
timekeeper.wall_to_monotonic =
timespec_sub(timekeeper.wall_to_monotonic, *ts);
tk_set_wall_to_mono(&timekeeper,
timespec_sub(timekeeper.wall_to_monotonic, *ts));

timekeeping_update(&timekeeper, true);

Expand Down Expand Up @@ -621,7 +637,7 @@ void __init timekeeping_init(void)
{
struct clocksource *clock;
unsigned long flags;
struct timespec now, boot;
struct timespec now, boot, tmp;

read_persistent_clock(&now);
read_boot_clock(&boot);
Expand All @@ -642,23 +658,19 @@ void __init timekeeping_init(void)
if (boot.tv_sec == 0 && boot.tv_nsec == 0)
boot = tk_xtime(&timekeeper);

set_normalized_timespec(&timekeeper.wall_to_monotonic,
-boot.tv_sec, -boot.tv_nsec);
update_rt_offset(&timekeeper);
timekeeper.total_sleep_time.tv_sec = 0;
timekeeper.total_sleep_time.tv_nsec = 0;
set_normalized_timespec(&tmp, -boot.tv_sec, -boot.tv_nsec);
tk_set_wall_to_mono(&timekeeper, tmp);

tmp.tv_sec = 0;
tmp.tv_nsec = 0;
tk_set_sleep_time(&timekeeper, tmp);

write_sequnlock_irqrestore(&timekeeper.lock, flags);
}

/* time in seconds when suspend began */
static struct timespec timekeeping_suspend_time;

static void update_sleep_time(struct timespec t)
{
timekeeper.total_sleep_time = t;
timekeeper.offs_boot = timespec_to_ktime(t);
}

/**
* __timekeeping_inject_sleeptime - Internal function to add sleep interval
* @delta: pointer to a timespec delta value
Expand All @@ -674,10 +686,9 @@ static void __timekeeping_inject_sleeptime(struct timekeeper *tk,
"sleep delta value!\n");
return;
}

tk_xtime_add(tk, delta);
tk->wall_to_monotonic = timespec_sub(tk->wall_to_monotonic, *delta);
update_sleep_time(timespec_add(tk->total_sleep_time, *delta));
tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, *delta));
tk_set_sleep_time(tk, timespec_add(tk->total_sleep_time, *delta));
}

/**
Expand Down Expand Up @@ -1018,11 +1029,18 @@ static inline void accumulate_nsecs_to_secs(struct timekeeper *tk)

/* Figure out if its a leap sec and apply if needed */
leap = second_overflow(tk->xtime_sec);
tk->xtime_sec += leap;
tk->wall_to_monotonic.tv_sec -= leap;
if (leap)
clock_was_set_delayed();
if (unlikely(leap)) {
struct timespec ts;

tk->xtime_sec += leap;

ts.tv_sec = leap;
ts.tv_nsec = 0;
tk_set_wall_to_mono(tk,
timespec_sub(tk->wall_to_monotonic, ts));

clock_was_set_delayed();
}
}
}

Expand Down

0 comments on commit 8bd9f7e

Please sign in to comment.