Skip to content

Commit 7219932

Browse files
KAGA-KOKOIngo Molnar
authored andcommitted
timekeeping: Add the new CLOCK_MONOTONIC_ACTIVE clock
The planned change to unify the behaviour of the MONOTONIC and BOOTTIME clocks vs. suspend removes the ability to retrieve the active non-suspended time of a system. Provide a new CLOCK_MONOTONIC_ACTIVE clock which returns the active non-suspended time of the system via clock_gettime(). This preserves the old behaviour of CLOCK_MONOTONIC before the BOOTTIME/MONOTONIC unification. This new clock also allows applications to detect programmatically that the MONOTONIC and BOOTTIME clocks are identical. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com> Cc: John Stultz <john.stultz@linaro.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Kevin Easton <kevin@guarana.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mark Salyzyn <salyzyn@android.com> Cc: Michael Kerrisk <mtk.manpages@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Petr Mladek <pmladek@suse.com> Cc: Prarit Bhargava <prarit@redhat.com> Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Cc: Steven Rostedt <rostedt@goodmis.org> Link: http://lkml.kernel.org/r/20180301165149.965235774@linutronix.de Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 78b98e3 commit 7219932

File tree

6 files changed

+55
-0
lines changed

6 files changed

+55
-0
lines changed

include/linux/timekeeper_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ 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
5556
* @tai_offset: The current UTC to TAI offset in seconds
5657
* @clock_was_set_seq: The sequence number of clock was set events
5758
* @cs_was_changed_seq: The sequence number of clocksource change events
@@ -94,6 +95,7 @@ struct timekeeper {
9495
ktime_t offs_real;
9596
ktime_t offs_boot;
9697
ktime_t offs_tai;
98+
ktime_t time_suspended;
9799
s32 tai_offset;
98100
unsigned int clock_was_set_seq;
99101
u8 cs_was_changed_seq;

include/linux/timekeeping.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ extern void getrawmonotonic64(struct timespec64 *ts);
3232
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);
35+
extern void ktime_get_active_ts64(struct timespec64 *ts);
3536

3637
extern int __getnstimeofday64(struct timespec64 *tv);
3738
extern void getnstimeofday64(struct timespec64 *tv);

include/uapi/linux/time.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ struct itimerval {
6161
*/
6262
#define CLOCK_SGI_CYCLE 10
6363
#define CLOCK_TAI 11
64+
#define CLOCK_MONOTONIC_ACTIVE 12
6465

6566
#define MAX_CLOCKS 16
6667
#define CLOCKS_MASK (CLOCK_REALTIME | CLOCK_MONOTONIC)

kernel/time/posix-stubs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ int do_clock_gettime(clockid_t which_clock, struct timespec64 *tp)
7373
case CLOCK_BOOTTIME:
7474
get_monotonic_boottime64(tp);
7575
break;
76+
case CLOCK_MONOTONIC_ACTIVE:
77+
ktime_get_active_ts64(tp);
7678
default:
7779
return -EINVAL;
7880
}

kernel/time/posix-timers.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,13 @@ static int posix_get_tai(clockid_t which_clock, struct timespec64 *tp)
263263
return 0;
264264
}
265265

266+
static int posix_get_monotonic_active(clockid_t which_clock,
267+
struct timespec64 *tp)
268+
{
269+
ktime_get_active_ts64(tp);
270+
return 0;
271+
}
272+
266273
static int posix_get_hrtimer_res(clockid_t which_clock, struct timespec64 *tp)
267274
{
268275
tp->tv_sec = 0;
@@ -1330,6 +1337,11 @@ static const struct k_clock clock_boottime = {
13301337
.timer_arm = common_hrtimer_arm,
13311338
};
13321339

1340+
static const struct k_clock clock_monotonic_active = {
1341+
.clock_getres = posix_get_hrtimer_res,
1342+
.clock_get = posix_get_monotonic_active,
1343+
};
1344+
13331345
static const struct k_clock * const posix_clocks[] = {
13341346
[CLOCK_REALTIME] = &clock_realtime,
13351347
[CLOCK_MONOTONIC] = &clock_monotonic,
@@ -1342,6 +1354,7 @@ static const struct k_clock * const posix_clocks[] = {
13421354
[CLOCK_REALTIME_ALARM] = &alarm_clock,
13431355
[CLOCK_BOOTTIME_ALARM] = &alarm_clock,
13441356
[CLOCK_TAI] = &clock_tai,
1357+
[CLOCK_MONOTONIC_ACTIVE] = &clock_monotonic_active,
13451358
};
13461359

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

kernel/time/timekeeping.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec64 wtm)
139139
static inline void tk_update_sleep_time(struct timekeeper *tk, ktime_t delta)
140140
{
141141
tk->offs_boot = ktime_add(tk->offs_boot, delta);
142+
143+
/* Accumulate time spent in suspend */
144+
tk->time_suspended += delta;
142145
}
143146

144147
/*
@@ -886,6 +889,39 @@ void ktime_get_ts64(struct timespec64 *ts)
886889
}
887890
EXPORT_SYMBOL_GPL(ktime_get_ts64);
888891

892+
/**
893+
* ktime_get_active_ts64 - Get the active non-suspended monotonic clock
894+
* @ts: pointer to timespec variable
895+
*
896+
* The function calculates the monotonic clock from the realtime clock and
897+
* the wall_to_monotonic offset, subtracts the accumulated suspend time and
898+
* stores the result in normalized timespec64 format in the variable
899+
* pointed to by @ts.
900+
*/
901+
void ktime_get_active_ts64(struct timespec64 *ts)
902+
{
903+
struct timekeeper *tk = &tk_core.timekeeper;
904+
struct timespec64 tomono, tsusp;
905+
u64 nsec, nssusp;
906+
unsigned int seq;
907+
908+
WARN_ON(timekeeping_suspended);
909+
910+
do {
911+
seq = read_seqcount_begin(&tk_core.seq);
912+
ts->tv_sec = tk->xtime_sec;
913+
nsec = timekeeping_get_ns(&tk->tkr_mono);
914+
tomono = tk->wall_to_monotonic;
915+
nssusp = tk->time_suspended;
916+
} while (read_seqcount_retry(&tk_core.seq, seq));
917+
918+
ts->tv_sec += tomono.tv_sec;
919+
ts->tv_nsec = 0;
920+
timespec64_add_ns(ts, nsec + tomono.tv_nsec);
921+
tsusp = ns_to_timespec64(nssusp);
922+
*ts = timespec64_sub(*ts, tsusp);
923+
}
924+
889925
/**
890926
* ktime_get_seconds - Get the seconds portion of CLOCK_MONOTONIC
891927
*

0 commit comments

Comments
 (0)