Skip to content

Commit

Permalink
Revert: Unify CLOCK_MONOTONIC and CLOCK_BOOTTIME
Browse files Browse the repository at this point in the history
Revert commits

92af4dc ("tracing: Unify the "boot" and "mono" tracing clocks")
127bfa5 ("hrtimer: Unify MONOTONIC and BOOTTIME clock behavior")
7250a40 ("posix-timers: Unify MONOTONIC and BOOTTIME clock behavior")
d6c7270 ("timekeeping: Remove boot time specific code")
f2d6fdb ("Input: Evdev - unify MONOTONIC and BOOTTIME clock behavior")
d6ed449 ("timekeeping: Make the MONOTONIC clock behave like the BOOTTIME clock")
7219932 ("timekeeping: Add the new CLOCK_MONOTONIC_ACTIVE clock")

As stated in the pull request for the unification of CLOCK_MONOTONIC and
CLOCK_BOOTTIME, it was clear that we might have to revert the change.

As reported by several folks systemd and other applications rely on the
documented behaviour of CLOCK_MONOTONIC on Linux and break with the above
changes. After resume daemons time out and other timeout related issues are
observed. Rafael compiled this list:

* systemd kills daemons on resume, after >WatchdogSec seconds
  of suspending (Genki Sky).  [Verified that that's because systemd uses
  CLOCK_MONOTONIC and expects it to not include the suspend time.]

* systemd-journald misbehaves after resume:
  systemd-journald[7266]: File /var/log/journal/016627c3c4784cd4812d4b7e96a34226/system.journal
corrupted or uncleanly shut down, renaming and replacing.
  (Mike Galbraith).

* NetworkManager reports "networking disabled" and networking is broken
  after resume 50% of the time (Pavel).  [May be because of systemd.]

* MATE desktop dims the display and starts the screensaver right after
  system resume (Pavel).

* Full system hang during resume (me).  [May be due to systemd or NM or both.]

That happens on debian and open suse systems.

It's sad, that these problems were neither catched in -next nor by those
folks who expressed interest in this change.

Reported-by: Rafael J. Wysocki <[email protected]>
Reported-by: Genki Sky <[email protected]>,
Reported-by: Pavel Machek <[email protected]>
Signed-off-by: Thomas Gleixner <[email protected]>
Cc: Dmitry Torokhov <[email protected]>
Cc: John Stultz <[email protected]>
Cc: Jonathan Corbet <[email protected]>
Cc: Kevin Easton <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Mark Salyzyn <[email protected]>
Cc: Michael Kerrisk <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Petr Mladek <[email protected]>
Cc: Prarit Bhargava <[email protected]>
Cc: Sergey Senozhatsky <[email protected]>
Cc: Steven Rostedt <[email protected]>
  • Loading branch information
KAGA-KOKO committed Apr 26, 2018
1 parent 1f71add commit a3ed0e4
Show file tree
Hide file tree
Showing 15 changed files with 114 additions and 104 deletions.
14 changes: 11 additions & 3 deletions Documentation/trace/ftrace.rst
Original file line number Diff line number Diff line change
Expand Up @@ -461,9 +461,17 @@ of ftrace. Here is a list of some of the key files:
and ticks at the same rate as the hardware clocksource.

boot:
Same as mono. Used to be a separate clock which accounted
for the time spent in suspend while CLOCK_MONOTONIC did
not.
This is the boot clock (CLOCK_BOOTTIME) and is based on the
fast monotonic clock, but also accounts for time spent in
suspend. Since the clock access is designed for use in
tracing in the suspend path, some side effects are possible
if clock is accessed after the suspend time is accounted before
the fast mono clock is updated. In this case, the clock update
appears to happen slightly sooner than it normally would have.
Also on 32-bit systems, it's possible that the 64-bit boot offset
sees a partial update. These effects are rare and post
processing should be able to handle them. See comments in the
ktime_get_boot_fast_ns() function for more information.

To set a clock, simply echo the clock name into this file::

Expand Down
7 changes: 6 additions & 1 deletion drivers/input/evdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
enum evdev_clock_type {
EV_CLK_REAL = 0,
EV_CLK_MONO,
EV_CLK_BOOT,
EV_CLK_MAX
};

Expand Down Expand Up @@ -197,10 +198,12 @@ static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid)
case CLOCK_REALTIME:
clk_type = EV_CLK_REAL;
break;
case CLOCK_BOOTTIME:
case CLOCK_MONOTONIC:
clk_type = EV_CLK_MONO;
break;
case CLOCK_BOOTTIME:
clk_type = EV_CLK_BOOT;
break;
default:
return -EINVAL;
}
Expand Down Expand Up @@ -311,6 +314,8 @@ static void evdev_events(struct input_handle *handle,

ev_time[EV_CLK_MONO] = ktime_get();
ev_time[EV_CLK_REAL] = ktime_mono_to_real(ev_time[EV_CLK_MONO]);
ev_time[EV_CLK_BOOT] = ktime_mono_to_any(ev_time[EV_CLK_MONO],
TK_OFFS_BOOT);

rcu_read_lock();

Expand Down
2 changes: 2 additions & 0 deletions include/linux/hrtimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,11 @@ struct hrtimer_clock_base {
enum hrtimer_base_type {
HRTIMER_BASE_MONOTONIC,
HRTIMER_BASE_REALTIME,
HRTIMER_BASE_BOOTTIME,
HRTIMER_BASE_TAI,
HRTIMER_BASE_MONOTONIC_SOFT,
HRTIMER_BASE_REALTIME_SOFT,
HRTIMER_BASE_BOOTTIME_SOFT,
HRTIMER_BASE_TAI_SOFT,
HRTIMER_MAX_CLOCK_BASES,
};
Expand Down
2 changes: 0 additions & 2 deletions include/linux/timekeeper_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ struct tk_read_base {
* @offs_real: Offset clock monotonic -> clock realtime
* @offs_boot: Offset clock monotonic -> clock boottime
* @offs_tai: Offset clock monotonic -> clock tai
* @time_suspended: Accumulated suspend time
* @tai_offset: The current UTC to TAI offset in seconds
* @clock_was_set_seq: The sequence number of clock was set events
* @cs_was_changed_seq: The sequence number of clocksource change events
Expand Down Expand Up @@ -95,7 +94,6 @@ struct timekeeper {
ktime_t offs_real;
ktime_t offs_boot;
ktime_t offs_tai;
ktime_t time_suspended;
s32 tai_offset;
unsigned int clock_was_set_seq;
u8 cs_was_changed_seq;
Expand Down
37 changes: 25 additions & 12 deletions include/linux/timekeeping.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,20 @@ extern void ktime_get_ts64(struct timespec64 *ts);
extern time64_t ktime_get_seconds(void);
extern time64_t __ktime_get_real_seconds(void);
extern time64_t ktime_get_real_seconds(void);
extern void ktime_get_active_ts64(struct timespec64 *ts);

extern int __getnstimeofday64(struct timespec64 *tv);
extern void getnstimeofday64(struct timespec64 *tv);
extern void getboottime64(struct timespec64 *ts);

#define ktime_get_real_ts64(ts) getnstimeofday64(ts)

/* Clock BOOTTIME compatibility wrappers */
static inline void get_monotonic_boottime64(struct timespec64 *ts)
{
ktime_get_ts64(ts);
}
#define ktime_get_real_ts64(ts) getnstimeofday64(ts)

/*
* ktime_t based interfaces
*/

enum tk_offsets {
TK_OFFS_REAL,
TK_OFFS_BOOT,
TK_OFFS_TAI,
TK_OFFS_MAX,
};
Expand All @@ -62,10 +57,6 @@ extern ktime_t ktime_mono_to_any(ktime_t tmono, enum tk_offsets offs);
extern ktime_t ktime_get_raw(void);
extern u32 ktime_get_resolution_ns(void);

/* Clock BOOTTIME compatibility wrappers */
static inline ktime_t ktime_get_boottime(void) { return ktime_get(); }
static inline u64 ktime_get_boot_ns(void) { return ktime_get(); }

/**
* ktime_get_real - get the real (wall-) time in ktime_t format
*/
Expand All @@ -74,6 +65,17 @@ static inline ktime_t ktime_get_real(void)
return ktime_get_with_offset(TK_OFFS_REAL);
}

/**
* ktime_get_boottime - Returns monotonic time since boot in ktime_t format
*
* This is similar to CLOCK_MONTONIC/ktime_get, but also includes the
* time spent in suspend.
*/
static inline ktime_t ktime_get_boottime(void)
{
return ktime_get_with_offset(TK_OFFS_BOOT);
}

/**
* ktime_get_clocktai - Returns the TAI time of day in ktime_t format
*/
Expand All @@ -100,6 +102,11 @@ static inline u64 ktime_get_real_ns(void)
return ktime_to_ns(ktime_get_real());
}

static inline u64 ktime_get_boot_ns(void)
{
return ktime_to_ns(ktime_get_boottime());
}

static inline u64 ktime_get_tai_ns(void)
{
return ktime_to_ns(ktime_get_clocktai());
Expand All @@ -112,11 +119,17 @@ static inline u64 ktime_get_raw_ns(void)

extern u64 ktime_get_mono_fast_ns(void);
extern u64 ktime_get_raw_fast_ns(void);
extern u64 ktime_get_boot_fast_ns(void);
extern u64 ktime_get_real_fast_ns(void);

/*
* timespec64 interfaces utilizing the ktime based ones
*/
static inline void get_monotonic_boottime64(struct timespec64 *ts)
{
*ts = ktime_to_timespec64(ktime_get_boottime());
}

static inline void timekeeping_clocktai64(struct timespec64 *ts)
{
*ts = ktime_to_timespec64(ktime_get_clocktai());
Expand Down
1 change: 0 additions & 1 deletion include/uapi/linux/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ struct __kernel_old_timeval {
*/
#define CLOCK_SGI_CYCLE 10
#define CLOCK_TAI 11
#define CLOCK_MONOTONIC_ACTIVE 12

#define MAX_CLOCKS 16
#define CLOCKS_MASK (CLOCK_REALTIME | CLOCK_MONOTONIC)
Expand Down
16 changes: 14 additions & 2 deletions kernel/time/hrtimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
.clockid = CLOCK_REALTIME,
.get_time = &ktime_get_real,
},
{
.index = HRTIMER_BASE_BOOTTIME,
.clockid = CLOCK_BOOTTIME,
.get_time = &ktime_get_boottime,
},
{
.index = HRTIMER_BASE_TAI,
.clockid = CLOCK_TAI,
Expand All @@ -105,6 +110,11 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
.clockid = CLOCK_REALTIME,
.get_time = &ktime_get_real,
},
{
.index = HRTIMER_BASE_BOOTTIME_SOFT,
.clockid = CLOCK_BOOTTIME,
.get_time = &ktime_get_boottime,
},
{
.index = HRTIMER_BASE_TAI_SOFT,
.clockid = CLOCK_TAI,
Expand All @@ -119,7 +129,7 @@ static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = {

[CLOCK_REALTIME] = HRTIMER_BASE_REALTIME,
[CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC,
[CLOCK_BOOTTIME] = HRTIMER_BASE_MONOTONIC,
[CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME,
[CLOCK_TAI] = HRTIMER_BASE_TAI,
};

Expand Down Expand Up @@ -571,12 +581,14 @@ __hrtimer_get_next_event(struct hrtimer_cpu_base *cpu_base, unsigned int active_
static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base)
{
ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME].offset;
ktime_t *offs_boot = &base->clock_base[HRTIMER_BASE_BOOTTIME].offset;
ktime_t *offs_tai = &base->clock_base[HRTIMER_BASE_TAI].offset;

ktime_t now = ktime_get_update_offsets_now(&base->clock_was_set_seq,
offs_real, offs_tai);
offs_real, offs_boot, offs_tai);

base->clock_base[HRTIMER_BASE_REALTIME_SOFT].offset = *offs_real;
base->clock_base[HRTIMER_BASE_BOOTTIME_SOFT].offset = *offs_boot;
base->clock_base[HRTIMER_BASE_TAI_SOFT].offset = *offs_tai;

return now;
Expand Down
2 changes: 0 additions & 2 deletions kernel/time/posix-stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ int do_clock_gettime(clockid_t which_clock, struct timespec64 *tp)
case CLOCK_BOOTTIME:
get_monotonic_boottime64(tp);
break;
case CLOCK_MONOTONIC_ACTIVE:
ktime_get_active_ts64(tp);
default:
return -EINVAL;
}
Expand Down
26 changes: 17 additions & 9 deletions kernel/time/posix-timers.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,16 +252,15 @@ static int posix_get_coarse_res(const clockid_t which_clock, struct timespec64 *
return 0;
}

static int posix_get_tai(clockid_t which_clock, struct timespec64 *tp)
static int posix_get_boottime(const clockid_t which_clock, struct timespec64 *tp)
{
timekeeping_clocktai64(tp);
get_monotonic_boottime64(tp);
return 0;
}

static int posix_get_monotonic_active(clockid_t which_clock,
struct timespec64 *tp)
static int posix_get_tai(clockid_t which_clock, struct timespec64 *tp)
{
ktime_get_active_ts64(tp);
timekeeping_clocktai64(tp);
return 0;
}

Expand Down Expand Up @@ -1317,9 +1316,19 @@ static const struct k_clock clock_tai = {
.timer_arm = common_hrtimer_arm,
};

static const struct k_clock clock_monotonic_active = {
static const struct k_clock clock_boottime = {
.clock_getres = posix_get_hrtimer_res,
.clock_get = posix_get_monotonic_active,
.clock_get = posix_get_boottime,
.nsleep = common_nsleep,
.timer_create = common_timer_create,
.timer_set = common_timer_set,
.timer_get = common_timer_get,
.timer_del = common_timer_del,
.timer_rearm = common_hrtimer_rearm,
.timer_forward = common_hrtimer_forward,
.timer_remaining = common_hrtimer_remaining,
.timer_try_to_cancel = common_hrtimer_try_to_cancel,
.timer_arm = common_hrtimer_arm,
};

static const struct k_clock * const posix_clocks[] = {
Expand All @@ -1330,11 +1339,10 @@ static const struct k_clock * const posix_clocks[] = {
[CLOCK_MONOTONIC_RAW] = &clock_monotonic_raw,
[CLOCK_REALTIME_COARSE] = &clock_realtime_coarse,
[CLOCK_MONOTONIC_COARSE] = &clock_monotonic_coarse,
[CLOCK_BOOTTIME] = &clock_monotonic,
[CLOCK_BOOTTIME] = &clock_boottime,
[CLOCK_REALTIME_ALARM] = &alarm_clock,
[CLOCK_BOOTTIME_ALARM] = &alarm_clock,
[CLOCK_TAI] = &clock_tai,
[CLOCK_MONOTONIC_ACTIVE] = &clock_monotonic_active,
};

static const struct k_clock *clockid_to_kclock(const clockid_t id)
Expand Down
15 changes: 0 additions & 15 deletions kernel/time/tick-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -419,19 +419,6 @@ void tick_suspend_local(void)
clockevents_shutdown(td->evtdev);
}

static void tick_forward_next_period(void)
{
ktime_t delta, now = ktime_get();
u64 n;

delta = ktime_sub(now, tick_next_period);
n = ktime_divns(delta, tick_period);
tick_next_period += n * tick_period;
if (tick_next_period < now)
tick_next_period += tick_period;
tick_sched_forward_next_period();
}

/**
* tick_resume_local - Resume the local tick device
*
Expand All @@ -444,8 +431,6 @@ void tick_resume_local(void)
struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
bool broadcast = tick_resume_check_broadcast();

tick_forward_next_period();

clockevents_tick_resume(td->evtdev);
if (!broadcast) {
if (td->mode == TICKDEV_MODE_PERIODIC)
Expand Down
6 changes: 0 additions & 6 deletions kernel/time/tick-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,6 @@ static inline void tick_check_oneshot_broadcast_this_cpu(void) { }
static inline bool tick_broadcast_oneshot_available(void) { return tick_oneshot_possible(); }
#endif /* !(BROADCAST && ONESHOT) */

#if defined(CONFIG_NO_HZ_COMMON) || defined(CONFIG_HIGH_RES_TIMERS)
extern void tick_sched_forward_next_period(void);
#else
static inline void tick_sched_forward_next_period(void) { }
#endif

/* NO_HZ_FULL internal */
#ifdef CONFIG_NO_HZ_FULL
extern void tick_nohz_init(void);
Expand Down
9 changes: 0 additions & 9 deletions kernel/time/tick-sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,6 @@ struct tick_sched *tick_get_tick_sched(int cpu)
*/
static ktime_t last_jiffies_update;

/*
* Called after resume. Make sure that jiffies are not fast forwarded due to
* clock monotonic being forwarded by the suspended time.
*/
void tick_sched_forward_next_period(void)
{
last_jiffies_update = tick_next_period;
}

/*
* Must be called with interrupts disabled !
*/
Expand Down
Loading

0 comments on commit a3ed0e4

Please sign in to comment.