From: Joel Fernandes <joelaf@google.com>
To: linux-kernel@vger.kernel.org
Cc: Joel Fernandes <joelaf@google.com>,
John Stultz <john.stultz@linaro.org>,
Thomas Gleixner <tglx@linutronix.de>,
Steven Rostedt <rostedt@goodmis.org>,
"Rafael J . Wysocki" <rafael.j.wysocki@intel.com>
Subject: [RFC] timekeeping: Use cached readouts for monotonic and raw clocks in suspend
Date: Sat, 19 Nov 2016 13:41:11 -0800 [thread overview]
Message-ID: <1479591671-13397-1-git-send-email-joelaf@google.com> (raw)
I am planning to add boot clock as a trace clock that can account suspend time
during tracing, however ktime_get_with_offset throws a warning as the
clocksource is attempted to be accessed in suspend.
Currently only fast monotonic and raw timekeepers are halted and the cached
readout and cycles are used to make them return time during suspend. However,
ktime APIs such as ktime_get_with_offset to get the bootclock throw a warning.
Instead of warning, lets use the cached readouts and the last cycles at suspend
to return the time.
Cc: John Stultz <john.stultz@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Joel Fernandes <joelaf@google.com>
---
kernel/time/timekeeping.c | 72 ++++++++++++++++++++++++++++-------------------
1 file changed, 43 insertions(+), 29 deletions(-)
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 37dec7e..8ed43ce 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -434,29 +434,37 @@ static cycle_t dummy_clock_read(struct clocksource *cs)
}
/**
- * halt_fast_timekeeper - Prevent fast timekeeper from accessing clocksource.
- * @tk: Timekeeper to snapshot.
+ * halt_timekeepers - Prevent timekeepers from accessing clocksource.
*
* It generally is unsafe to access the clocksource after timekeeping has been
* suspended, so take a snapshot of the readout base of @tk and use it as the
* fast timekeeper's readout base while suspended. It will return the same
* number of cycles every time until timekeeping is resumed at which time the
- * proper readout base for the fast timekeeper will be restored automatically.
+ * proper readout base for the timekeeper will be restored automatically.
*/
-static void halt_fast_timekeeper(struct timekeeper *tk)
+
+static struct tk_read_base tkr_dummy_mono;
+static struct tk_read_base tkr_dummy_raw;
+
+static void halt_timekeepers(void)
{
- static struct tk_read_base tkr_dummy;
- struct tk_read_base *tkr = &tk->tkr_mono;
+ struct timekeeper *tk = &tk_core.timekeeper;
- memcpy(&tkr_dummy, tkr, sizeof(tkr_dummy));
- cycles_at_suspend = tkr->read(tkr->clock);
- tkr_dummy.read = dummy_clock_read;
- update_fast_timekeeper(&tkr_dummy, &tk_fast_mono);
+ /*
+ * Save the last readouts of mono and raw and replace their
+ * read functions to return the last cycles at suspend.
+ */
+ cycles_at_suspend = tk->tkr_mono.cycle_last;
+ memcpy(&tkr_dummy_mono, &tk->tkr_mono, sizeof(tkr_dummy_mono));
+ memcpy(&tkr_dummy_raw, &tk->tkr_raw, sizeof(tkr_dummy_mono));
+ tkr_dummy_mono.read = dummy_clock_read;
+ tkr_dummy_raw.read = dummy_clock_read;
- tkr = &tk->tkr_raw;
- memcpy(&tkr_dummy, tkr, sizeof(tkr_dummy));
- tkr_dummy.read = dummy_clock_read;
- update_fast_timekeeper(&tkr_dummy, &tk_fast_raw);
+ /*
+ * Halt the fast and slow timekeepers and use the cached readouts
+ */
+ update_fast_timekeeper(&tkr_dummy_mono, &tk_fast_mono);
+ update_fast_timekeeper(&tkr_dummy_raw, &tk_fast_raw);
}
#ifdef CONFIG_GENERIC_TIME_VSYSCALL_OLD
@@ -689,17 +697,18 @@ EXPORT_SYMBOL(getnstimeofday64);
ktime_t ktime_get(void)
{
- struct timekeeper *tk = &tk_core.timekeeper;
+ struct tk_read_base *tkr;
unsigned int seq;
ktime_t base;
s64 nsecs;
- WARN_ON(timekeeping_suspended);
+ tkr = timekeeping_suspended ?
+ &tkr_dummy_mono : &tk_core.timekeeper.tkr_mono;
do {
seq = read_seqcount_begin(&tk_core.seq);
- base = tk->tkr_mono.base;
- nsecs = timekeeping_get_ns(&tk->tkr_mono);
+ base = tkr->base;
+ nsecs = timekeeping_get_ns(tkr);
} while (read_seqcount_retry(&tk_core.seq, seq));
@@ -709,15 +718,16 @@ EXPORT_SYMBOL_GPL(ktime_get);
u32 ktime_get_resolution_ns(void)
{
- struct timekeeper *tk = &tk_core.timekeeper;
+ struct tk_read_base *tkr;
unsigned int seq;
u32 nsecs;
- WARN_ON(timekeeping_suspended);
+ tkr = timekeeping_suspended ?
+ &tkr_dummy_mono : &tk_core.timekeeper.tkr_mono;
do {
seq = read_seqcount_begin(&tk_core.seq);
- nsecs = tk->tkr_mono.mult >> tk->tkr_mono.shift;
+ nsecs = tkr->mult >> tkr->shift;
} while (read_seqcount_retry(&tk_core.seq, seq));
return nsecs;
@@ -732,17 +742,18 @@ static ktime_t *offsets[TK_OFFS_MAX] = {
ktime_t ktime_get_with_offset(enum tk_offsets offs)
{
- struct timekeeper *tk = &tk_core.timekeeper;
+ struct tk_read_base *tkr;
unsigned int seq;
ktime_t base, *offset = offsets[offs];
s64 nsecs;
- WARN_ON(timekeeping_suspended);
+ tkr = timekeeping_suspended ?
+ &tkr_dummy_mono : &tk_core.timekeeper.tkr_mono;
do {
seq = read_seqcount_begin(&tk_core.seq);
- base = ktime_add(tk->tkr_mono.base, *offset);
- nsecs = timekeeping_get_ns(&tk->tkr_mono);
+ base = ktime_add(tkr->base, *offset);
+ nsecs = timekeeping_get_ns(tkr);
} while (read_seqcount_retry(&tk_core.seq, seq));
@@ -776,15 +787,18 @@ EXPORT_SYMBOL_GPL(ktime_mono_to_any);
*/
ktime_t ktime_get_raw(void)
{
- struct timekeeper *tk = &tk_core.timekeeper;
+ struct tk_read_base *tkr;
unsigned int seq;
ktime_t base;
s64 nsecs;
+ tkr = timekeeping_suspended ?
+ &tkr_dummy_raw : &tk_core.timekeeper.tkr_raw;
+
do {
seq = read_seqcount_begin(&tk_core.seq);
- base = tk->tkr_raw.base;
- nsecs = timekeeping_get_ns(&tk->tkr_raw);
+ base = tkr->base;
+ nsecs = timekeeping_get_ns(tkr);
} while (read_seqcount_retry(&tk_core.seq, seq));
@@ -1734,7 +1748,7 @@ int timekeeping_suspend(void)
}
timekeeping_update(tk, TK_MIRROR);
- halt_fast_timekeeper(tk);
+ halt_timekeepers();
write_seqcount_end(&tk_core.seq);
raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
--
2.8.0.rc3.226.g39d4020
next reply other threads:[~2016-11-19 21:49 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-11-19 21:41 Joel Fernandes [this message]
2016-11-20 13:24 ` Thomas Gleixner
2016-11-21 3:09 ` joelaf
2016-11-21 11:46 ` Thomas Gleixner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1479591671-13397-1-git-send-email-joelaf@google.com \
--to=joelaf@google.com \
--cc=john.stultz@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=rafael.j.wysocki@intel.com \
--cc=rostedt@goodmis.org \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®