From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752292AbcAFNBB (ORCPT ); Wed, 6 Jan 2016 08:01:01 -0500 Received: from mx1.redhat.com ([209.132.183.28]:50649 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752026AbcAFNAv (ORCPT ); Wed, 6 Jan 2016 08:00:51 -0500 From: Prarit Bhargava To: linux-kernel@vger.kernel.org Cc: Prarit Bhargava , John Stultz , Thomas Gleixner , Ingo Molnar , Xunlei Pang , Peter Zijlstra , Baolin Wang , Arnd Bergmann Subject: [PATCH 1/2] kernel, timekeeping, add trylock option to ktime_get_with_offset() Date: Wed, 6 Jan 2016 08:00:33 -0500 Message-Id: <1452085234-10667-2-git-send-email-prarit@redhat.com> In-Reply-To: <1452085234-10667-1-git-send-email-prarit@redhat.com> References: <1452085234-10667-1-git-send-email-prarit@redhat.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Xunlei Pang Cc: Peter Zijlstra Cc: Baolin Wang Cc: Arnd Bergmann Signed-off-by: Prarit Bhargava --- 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