[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1452085234-10667-2-git-send-email-prarit@redhat.com>
Date: Wed, 6 Jan 2016 08:00:33 -0500
From: Prarit Bhargava <prarit@...hat.com>
To: linux-kernel@...r.kernel.org
Cc: Prarit Bhargava <prarit@...hat.com>,
John Stultz <john.stultz@...aro.org>,
Thomas Gleixner <tglx@...utronix.de>,
Ingo Molnar <mingo@...nel.org>,
Xunlei Pang <pang.xunlei@...aro.org>,
Peter Zijlstra <peterz@...radead.org>,
Baolin Wang <baolin.wang@...aro.org>,
Arnd Bergmann <arnd@...db.de>
Subject: [PATCH 1/2] kernel, timekeeping, add trylock option to ktime_get_with_offset()
This is a timekeeping staging patch for the printk() timestamp
functionality that adds a trylock option for the timekeeping_lock() to
ktime_get_with_offset(). When trylock is 1, calls to
ktime_get_with_offset() will return return a ktime of 0 if the
timekeeping_lock is locked.
This patch adds ktime_try_real(), ktime_try_boot(), and ktime_try_tai() as
wrapper functions around ktime_get_with_offset() with trylock = 1, and
modifies other callers to call ktime_get_with_offset() with trylock = 0.
Cc: John Stultz <john.stultz@...aro.org>
Cc: Thomas Gleixner <tglx@...utronix.de>
Cc: Ingo Molnar <mingo@...nel.org>
Cc: Xunlei Pang <pang.xunlei@...aro.org>
Cc: Peter Zijlstra <peterz@...radead.org>
Cc: Baolin Wang <baolin.wang@...aro.org>
Cc: Arnd Bergmann <arnd@...db.de>
Signed-off-by: Prarit Bhargava <prarit@...hat.com>
---
include/linux/timekeeping.h | 50 +++++++++++++++++++++++++++++++++++++++----
kernel/time/timekeeping.c | 15 ++++++++++++-
2 files changed, 60 insertions(+), 5 deletions(-)
diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h
index ec89d84..4f47352 100644
--- a/include/linux/timekeeping.h
+++ b/include/linux/timekeeping.h
@@ -166,7 +166,7 @@ enum tk_offsets {
};
extern ktime_t ktime_get(void);
-extern ktime_t ktime_get_with_offset(enum tk_offsets offs);
+extern ktime_t ktime_get_with_offset(enum tk_offsets offs, int trylock);
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);
@@ -176,7 +176,16 @@ extern u32 ktime_get_resolution_ns(void);
*/
static inline ktime_t ktime_get_real(void)
{
- return ktime_get_with_offset(TK_OFFS_REAL);
+ return ktime_get_with_offset(TK_OFFS_REAL, 0);
+}
+
+/**
+ * ktime_try_real - same as ktime_get_real, except return 0 if timekeeping is
+ * locked.
+ */
+static inline ktime_t ktime_try_real(void)
+{
+ return ktime_get_with_offset(TK_OFFS_REAL, 1);
}
/**
@@ -187,7 +196,16 @@ static inline ktime_t ktime_get_real(void)
*/
static inline ktime_t ktime_get_boottime(void)
{
- return ktime_get_with_offset(TK_OFFS_BOOT);
+ return ktime_get_with_offset(TK_OFFS_BOOT, 0);
+}
+
+/**
+ * ktime_try_boottime - same as ktime_get_bootime, except return 0 if
+ * timekeeping is locked.
+ */
+static inline ktime_t ktime_try_boottime(void)
+{
+ return ktime_get_with_offset(TK_OFFS_BOOT, 1);
}
/**
@@ -195,7 +213,16 @@ static inline ktime_t ktime_get_boottime(void)
*/
static inline ktime_t ktime_get_clocktai(void)
{
- return ktime_get_with_offset(TK_OFFS_TAI);
+ return ktime_get_with_offset(TK_OFFS_TAI, 0);
+}
+
+/**
+ * ktime_try_clocktai - same as ktime_get_clocktai, except return 0 if
+ * timekeeping is locked.
+ */
+static inline ktime_t ktime_try_clocktai(void)
+{
+ return ktime_get_with_offset(TK_OFFS_TAI, 1);
}
/**
@@ -216,16 +243,31 @@ static inline u64 ktime_get_real_ns(void)
return ktime_to_ns(ktime_get_real());
}
+static inline u64 ktime_try_real_ns(void)
+{
+ return ktime_to_ns(ktime_try_real());
+}
+
static inline u64 ktime_get_boot_ns(void)
{
return ktime_to_ns(ktime_get_boottime());
}
+static inline u64 ktime_try_boot_ns(void)
+{
+ return ktime_to_ns(ktime_try_boottime());
+}
+
static inline u64 ktime_get_tai_ns(void)
{
return ktime_to_ns(ktime_get_clocktai());
}
+static inline u64 ktime_try_tai_ns(void)
+{
+ return ktime_to_ns(ktime_try_clocktai());
+}
+
static inline u64 ktime_get_raw_ns(void)
{
return ktime_to_ns(ktime_get_raw());
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index d563c19..6e2cbeb 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -44,6 +44,8 @@ static struct {
static DEFINE_RAW_SPINLOCK(timekeeper_lock);
static struct timekeeper shadow_timekeeper;
+/* printk may call ktime_get_with_offset() before timekeeping is initialized. */
+static int timekeeping_initialized;
/**
* struct tk_fast - NMI safe timekeeper
* @seq: Sequence counter for protecting updates. The lowest bit
@@ -705,15 +707,22 @@ static ktime_t *offsets[TK_OFFS_MAX] = {
[TK_OFFS_TAI] = &tk_core.timekeeper.offs_tai,
};
-ktime_t ktime_get_with_offset(enum tk_offsets offs)
+ktime_t ktime_get_with_offset(enum tk_offsets offs, int trylock)
{
struct timekeeper *tk = &tk_core.timekeeper;
unsigned int seq;
ktime_t base, *offset = offsets[offs];
s64 nsecs;
+ unsigned long flags = 0;
+
+ if (unlikely(!timekeeping_initialized))
+ return ktime_set(0, 0);
WARN_ON(timekeeping_suspended);
+ if (trylock && !raw_spin_trylock_irqsave(&timekeeper_lock, flags))
+ return ktime_set(KTIME_MAX, 0);
+
do {
seq = read_seqcount_begin(&tk_core.seq);
base = ktime_add(tk->tkr_mono.base, *offset);
@@ -721,6 +730,9 @@ ktime_t ktime_get_with_offset(enum tk_offsets offs)
} while (read_seqcount_retry(&tk_core.seq, seq));
+ if (trylock)
+ raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
+
return ktime_add_ns(base, nsecs);
}
@@ -1255,6 +1267,7 @@ void __init timekeeping_init(void)
write_seqcount_end(&tk_core.seq);
raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
+ timekeeping_initialized = 1;
}
/* time in seconds when suspend began for persistent clock */
--
1.7.9.3
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists