lkml.org 
[lkml]   [2016]   [Jan]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 1/2] kernel, timekeeping, add trylock option to ktime_get_with_offset()
    Date
    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@linaro.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Cc: Ingo Molnar <mingo@kernel.org>
    Cc: Xunlei Pang <pang.xunlei@linaro.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Baolin Wang <baolin.wang@linaro.org>
    Cc: Arnd Bergmann <arnd@arndb.de>
    Signed-off-by: Prarit Bhargava <prarit@redhat.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


    \
     
     \ /
      Last update: 2016-01-06 14:21    [W:4.010 / U:0.036 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site