Skip to content

Commit 810fb07

Browse files
committed
Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer fixes from Thomas Gleixner: "Two fixes from the timer departement: - Fix a long standing issue in the NOHZ tick code which causes RB tree corruption, delayed timers and other malfunctions. The cause for this is code which modifies the expiry time of an enqueued hrtimer. - Revert the CLOCK_MONOTONIC/CLOCK_BOOTTIME unification due to regression reports. Seems userspace _is_ relying on the documented behaviour despite our hope that it wont" * 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: Revert: Unify CLOCK_MONOTONIC and CLOCK_BOOTTIME tick/sched: Do not mess with an enqueued hrtimer
2 parents 7d9e55f + a3ed0e4 commit 810fb07

File tree

15 files changed

+119
-109
lines changed

15 files changed

+119
-109
lines changed

Documentation/trace/ftrace.rst

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -461,9 +461,17 @@ of ftrace. Here is a list of some of the key files:
461461
and ticks at the same rate as the hardware clocksource.
462462

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

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

drivers/input/evdev.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
enum evdev_clock_type {
3232
EV_CLK_REAL = 0,
3333
EV_CLK_MONO,
34+
EV_CLK_BOOT,
3435
EV_CLK_MAX
3536
};
3637

@@ -197,10 +198,12 @@ static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid)
197198
case CLOCK_REALTIME:
198199
clk_type = EV_CLK_REAL;
199200
break;
200-
case CLOCK_BOOTTIME:
201201
case CLOCK_MONOTONIC:
202202
clk_type = EV_CLK_MONO;
203203
break;
204+
case CLOCK_BOOTTIME:
205+
clk_type = EV_CLK_BOOT;
206+
break;
204207
default:
205208
return -EINVAL;
206209
}
@@ -311,6 +314,8 @@ static void evdev_events(struct input_handle *handle,
311314

312315
ev_time[EV_CLK_MONO] = ktime_get();
313316
ev_time[EV_CLK_REAL] = ktime_mono_to_real(ev_time[EV_CLK_MONO]);
317+
ev_time[EV_CLK_BOOT] = ktime_mono_to_any(ev_time[EV_CLK_MONO],
318+
TK_OFFS_BOOT);
314319

315320
rcu_read_lock();
316321

include/linux/hrtimer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,11 @@ struct hrtimer_clock_base {
161161
enum hrtimer_base_type {
162162
HRTIMER_BASE_MONOTONIC,
163163
HRTIMER_BASE_REALTIME,
164+
HRTIMER_BASE_BOOTTIME,
164165
HRTIMER_BASE_TAI,
165166
HRTIMER_BASE_MONOTONIC_SOFT,
166167
HRTIMER_BASE_REALTIME_SOFT,
168+
HRTIMER_BASE_BOOTTIME_SOFT,
167169
HRTIMER_BASE_TAI_SOFT,
168170
HRTIMER_MAX_CLOCK_BASES,
169171
};

include/linux/timekeeper_internal.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ struct tk_read_base {
5252
* @offs_real: Offset clock monotonic -> clock realtime
5353
* @offs_boot: Offset clock monotonic -> clock boottime
5454
* @offs_tai: Offset clock monotonic -> clock tai
55-
* @time_suspended: Accumulated suspend time
5655
* @tai_offset: The current UTC to TAI offset in seconds
5756
* @clock_was_set_seq: The sequence number of clock was set events
5857
* @cs_was_changed_seq: The sequence number of clocksource change events
@@ -95,7 +94,6 @@ struct timekeeper {
9594
ktime_t offs_real;
9695
ktime_t offs_boot;
9796
ktime_t offs_tai;
98-
ktime_t time_suspended;
9997
s32 tai_offset;
10098
unsigned int clock_was_set_seq;
10199
u8 cs_was_changed_seq;

include/linux/timekeeping.h

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,20 @@ extern void ktime_get_ts64(struct timespec64 *ts);
3333
extern time64_t ktime_get_seconds(void);
3434
extern time64_t __ktime_get_real_seconds(void);
3535
extern time64_t ktime_get_real_seconds(void);
36-
extern void ktime_get_active_ts64(struct timespec64 *ts);
3736

3837
extern int __getnstimeofday64(struct timespec64 *tv);
3938
extern void getnstimeofday64(struct timespec64 *tv);
4039
extern void getboottime64(struct timespec64 *ts);
4140

42-
#define ktime_get_real_ts64(ts) getnstimeofday64(ts)
43-
44-
/* Clock BOOTTIME compatibility wrappers */
45-
static inline void get_monotonic_boottime64(struct timespec64 *ts)
46-
{
47-
ktime_get_ts64(ts);
48-
}
41+
#define ktime_get_real_ts64(ts) getnstimeofday64(ts)
4942

5043
/*
5144
* ktime_t based interfaces
5245
*/
46+
5347
enum tk_offsets {
5448
TK_OFFS_REAL,
49+
TK_OFFS_BOOT,
5550
TK_OFFS_TAI,
5651
TK_OFFS_MAX,
5752
};
@@ -62,10 +57,6 @@ extern ktime_t ktime_mono_to_any(ktime_t tmono, enum tk_offsets offs);
6257
extern ktime_t ktime_get_raw(void);
6358
extern u32 ktime_get_resolution_ns(void);
6459

65-
/* Clock BOOTTIME compatibility wrappers */
66-
static inline ktime_t ktime_get_boottime(void) { return ktime_get(); }
67-
static inline u64 ktime_get_boot_ns(void) { return ktime_get(); }
68-
6960
/**
7061
* ktime_get_real - get the real (wall-) time in ktime_t format
7162
*/
@@ -74,6 +65,17 @@ static inline ktime_t ktime_get_real(void)
7465
return ktime_get_with_offset(TK_OFFS_REAL);
7566
}
7667

68+
/**
69+
* ktime_get_boottime - Returns monotonic time since boot in ktime_t format
70+
*
71+
* This is similar to CLOCK_MONTONIC/ktime_get, but also includes the
72+
* time spent in suspend.
73+
*/
74+
static inline ktime_t ktime_get_boottime(void)
75+
{
76+
return ktime_get_with_offset(TK_OFFS_BOOT);
77+
}
78+
7779
/**
7880
* ktime_get_clocktai - Returns the TAI time of day in ktime_t format
7981
*/
@@ -100,6 +102,11 @@ static inline u64 ktime_get_real_ns(void)
100102
return ktime_to_ns(ktime_get_real());
101103
}
102104

105+
static inline u64 ktime_get_boot_ns(void)
106+
{
107+
return ktime_to_ns(ktime_get_boottime());
108+
}
109+
103110
static inline u64 ktime_get_tai_ns(void)
104111
{
105112
return ktime_to_ns(ktime_get_clocktai());
@@ -112,11 +119,17 @@ static inline u64 ktime_get_raw_ns(void)
112119

113120
extern u64 ktime_get_mono_fast_ns(void);
114121
extern u64 ktime_get_raw_fast_ns(void);
122+
extern u64 ktime_get_boot_fast_ns(void);
115123
extern u64 ktime_get_real_fast_ns(void);
116124

117125
/*
118126
* timespec64 interfaces utilizing the ktime based ones
119127
*/
128+
static inline void get_monotonic_boottime64(struct timespec64 *ts)
129+
{
130+
*ts = ktime_to_timespec64(ktime_get_boottime());
131+
}
132+
120133
static inline void timekeeping_clocktai64(struct timespec64 *ts)
121134
{
122135
*ts = ktime_to_timespec64(ktime_get_clocktai());

include/uapi/linux/time.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ struct __kernel_old_timeval {
7373
*/
7474
#define CLOCK_SGI_CYCLE 10
7575
#define CLOCK_TAI 11
76-
#define CLOCK_MONOTONIC_ACTIVE 12
7776

7877
#define MAX_CLOCKS 16
7978
#define CLOCKS_MASK (CLOCK_REALTIME | CLOCK_MONOTONIC)

kernel/time/hrtimer.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
9090
.clockid = CLOCK_REALTIME,
9191
.get_time = &ktime_get_real,
9292
},
93+
{
94+
.index = HRTIMER_BASE_BOOTTIME,
95+
.clockid = CLOCK_BOOTTIME,
96+
.get_time = &ktime_get_boottime,
97+
},
9398
{
9499
.index = HRTIMER_BASE_TAI,
95100
.clockid = CLOCK_TAI,
@@ -105,6 +110,11 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
105110
.clockid = CLOCK_REALTIME,
106111
.get_time = &ktime_get_real,
107112
},
113+
{
114+
.index = HRTIMER_BASE_BOOTTIME_SOFT,
115+
.clockid = CLOCK_BOOTTIME,
116+
.get_time = &ktime_get_boottime,
117+
},
108118
{
109119
.index = HRTIMER_BASE_TAI_SOFT,
110120
.clockid = CLOCK_TAI,
@@ -119,7 +129,7 @@ static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = {
119129

120130
[CLOCK_REALTIME] = HRTIMER_BASE_REALTIME,
121131
[CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC,
122-
[CLOCK_BOOTTIME] = HRTIMER_BASE_MONOTONIC,
132+
[CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME,
123133
[CLOCK_TAI] = HRTIMER_BASE_TAI,
124134
};
125135

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

576587
ktime_t now = ktime_get_update_offsets_now(&base->clock_was_set_seq,
577-
offs_real, offs_tai);
588+
offs_real, offs_boot, offs_tai);
578589

579590
base->clock_base[HRTIMER_BASE_REALTIME_SOFT].offset = *offs_real;
591+
base->clock_base[HRTIMER_BASE_BOOTTIME_SOFT].offset = *offs_boot;
580592
base->clock_base[HRTIMER_BASE_TAI_SOFT].offset = *offs_tai;
581593

582594
return now;

kernel/time/posix-stubs.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,6 @@ int do_clock_gettime(clockid_t which_clock, struct timespec64 *tp)
8383
case CLOCK_BOOTTIME:
8484
get_monotonic_boottime64(tp);
8585
break;
86-
case CLOCK_MONOTONIC_ACTIVE:
87-
ktime_get_active_ts64(tp);
8886
default:
8987
return -EINVAL;
9088
}

kernel/time/posix-timers.c

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -252,16 +252,15 @@ static int posix_get_coarse_res(const clockid_t which_clock, struct timespec64 *
252252
return 0;
253253
}
254254

255-
static int posix_get_tai(clockid_t which_clock, struct timespec64 *tp)
255+
static int posix_get_boottime(const clockid_t which_clock, struct timespec64 *tp)
256256
{
257-
timekeeping_clocktai64(tp);
257+
get_monotonic_boottime64(tp);
258258
return 0;
259259
}
260260

261-
static int posix_get_monotonic_active(clockid_t which_clock,
262-
struct timespec64 *tp)
261+
static int posix_get_tai(clockid_t which_clock, struct timespec64 *tp)
263262
{
264-
ktime_get_active_ts64(tp);
263+
timekeeping_clocktai64(tp);
265264
return 0;
266265
}
267266

@@ -1317,9 +1316,19 @@ static const struct k_clock clock_tai = {
13171316
.timer_arm = common_hrtimer_arm,
13181317
};
13191318

1320-
static const struct k_clock clock_monotonic_active = {
1319+
static const struct k_clock clock_boottime = {
13211320
.clock_getres = posix_get_hrtimer_res,
1322-
.clock_get = posix_get_monotonic_active,
1321+
.clock_get = posix_get_boottime,
1322+
.nsleep = common_nsleep,
1323+
.timer_create = common_timer_create,
1324+
.timer_set = common_timer_set,
1325+
.timer_get = common_timer_get,
1326+
.timer_del = common_timer_del,
1327+
.timer_rearm = common_hrtimer_rearm,
1328+
.timer_forward = common_hrtimer_forward,
1329+
.timer_remaining = common_hrtimer_remaining,
1330+
.timer_try_to_cancel = common_hrtimer_try_to_cancel,
1331+
.timer_arm = common_hrtimer_arm,
13231332
};
13241333

13251334
static const struct k_clock * const posix_clocks[] = {
@@ -1330,11 +1339,10 @@ static const struct k_clock * const posix_clocks[] = {
13301339
[CLOCK_MONOTONIC_RAW] = &clock_monotonic_raw,
13311340
[CLOCK_REALTIME_COARSE] = &clock_realtime_coarse,
13321341
[CLOCK_MONOTONIC_COARSE] = &clock_monotonic_coarse,
1333-
[CLOCK_BOOTTIME] = &clock_monotonic,
1342+
[CLOCK_BOOTTIME] = &clock_boottime,
13341343
[CLOCK_REALTIME_ALARM] = &alarm_clock,
13351344
[CLOCK_BOOTTIME_ALARM] = &alarm_clock,
13361345
[CLOCK_TAI] = &clock_tai,
1337-
[CLOCK_MONOTONIC_ACTIVE] = &clock_monotonic_active,
13381346
};
13391347

13401348
static const struct k_clock *clockid_to_kclock(const clockid_t id)

kernel/time/tick-common.c

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -419,19 +419,6 @@ void tick_suspend_local(void)
419419
clockevents_shutdown(td->evtdev);
420420
}
421421

422-
static void tick_forward_next_period(void)
423-
{
424-
ktime_t delta, now = ktime_get();
425-
u64 n;
426-
427-
delta = ktime_sub(now, tick_next_period);
428-
n = ktime_divns(delta, tick_period);
429-
tick_next_period += n * tick_period;
430-
if (tick_next_period < now)
431-
tick_next_period += tick_period;
432-
tick_sched_forward_next_period();
433-
}
434-
435422
/**
436423
* tick_resume_local - Resume the local tick device
437424
*
@@ -444,8 +431,6 @@ void tick_resume_local(void)
444431
struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
445432
bool broadcast = tick_resume_check_broadcast();
446433

447-
tick_forward_next_period();
448-
449434
clockevents_tick_resume(td->evtdev);
450435
if (!broadcast) {
451436
if (td->mode == TICKDEV_MODE_PERIODIC)

kernel/time/tick-internal.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,6 @@ static inline void tick_check_oneshot_broadcast_this_cpu(void) { }
141141
static inline bool tick_broadcast_oneshot_available(void) { return tick_oneshot_possible(); }
142142
#endif /* !(BROADCAST && ONESHOT) */
143143

144-
#if defined(CONFIG_NO_HZ_COMMON) || defined(CONFIG_HIGH_RES_TIMERS)
145-
extern void tick_sched_forward_next_period(void);
146-
#else
147-
static inline void tick_sched_forward_next_period(void) { }
148-
#endif
149-
150144
/* NO_HZ_FULL internal */
151145
#ifdef CONFIG_NO_HZ_FULL
152146
extern void tick_nohz_init(void);

kernel/time/tick-sched.c

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,6 @@ struct tick_sched *tick_get_tick_sched(int cpu)
5151
*/
5252
static ktime_t last_jiffies_update;
5353

54-
/*
55-
* Called after resume. Make sure that jiffies are not fast forwarded due to
56-
* clock monotonic being forwarded by the suspended time.
57-
*/
58-
void tick_sched_forward_next_period(void)
59-
{
60-
last_jiffies_update = tick_next_period;
61-
}
62-
6354
/*
6455
* Must be called with interrupts disabled !
6556
*/
@@ -804,12 +795,12 @@ static void tick_nohz_stop_tick(struct tick_sched *ts, int cpu)
804795
return;
805796
}
806797

807-
hrtimer_set_expires(&ts->sched_timer, tick);
808-
809-
if (ts->nohz_mode == NOHZ_MODE_HIGHRES)
810-
hrtimer_start_expires(&ts->sched_timer, HRTIMER_MODE_ABS_PINNED);
811-
else
798+
if (ts->nohz_mode == NOHZ_MODE_HIGHRES) {
799+
hrtimer_start(&ts->sched_timer, tick, HRTIMER_MODE_ABS_PINNED);
800+
} else {
801+
hrtimer_set_expires(&ts->sched_timer, tick);
812802
tick_program_event(tick, 1);
803+
}
813804
}
814805

815806
static void tick_nohz_retain_tick(struct tick_sched *ts)

0 commit comments

Comments
 (0)