lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
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

Powered by Openwall GNU/*/Linux Powered by OpenVZ