lkml.org 
[lkml]   [2005]   [Aug]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH 3/3] Updated dynamic tick patches - Recover walltime upon wakeup
    On Wed, Aug 31, 2005 at 10:28:43PM +0530, Srivatsa Vaddagiri wrote:
    > Following patches related to dynamic tick are posted in separate mails,
    > for convenience of review. The first patch probably applies w/o dynamic
    > tick consideration also.
    >
    > Patch 3/3 -> Use lost tick information in dyn-tick time recovery

    This patch uses the lost tick information returned by mark_offset()
    function in dyn-tick, to recover time.


    ---

    arch/i386/Kconfig | 0
    linux-2.6.13-rc6-mm2-root/arch/i386/kernel/dyn-tick.c | 11 ++++++--
    linux-2.6.13-rc6-mm2-root/arch/i386/kernel/time.c | 13 ++++++----
    linux-2.6.13-rc6-mm2-root/arch/i386/kernel/timers/timer_cyclone.c | 4 ++-
    linux-2.6.13-rc6-mm2-root/arch/i386/kernel/timers/timer_hpet.c | 4 ++-
    linux-2.6.13-rc6-mm2-root/arch/i386/kernel/timers/timer_none.c | 3 +-
    linux-2.6.13-rc6-mm2-root/arch/i386/kernel/timers/timer_pit.c | 3 +-
    linux-2.6.13-rc6-mm2-root/arch/i386/kernel/timers/timer_pm.c | 6 +++-
    linux-2.6.13-rc6-mm2-root/arch/i386/kernel/timers/timer_tsc.c | 12 ++++++---
    linux-2.6.13-rc6-mm2-root/include/asm-i386/timer.h | 2 -
    10 files changed, 40 insertions(+), 18 deletions(-)

    diff -puN include/asm-i386/timer.h~drift_fix include/asm-i386/timer.h
    --- linux-2.6.13-rc6-mm2/include/asm-i386/timer.h~drift_fix 2005-08-31 16:36:17.000000000 +0530
    +++ linux-2.6.13-rc6-mm2-root/include/asm-i386/timer.h 2005-08-31 16:36:30.000000000 +0530
    @@ -19,7 +19,7 @@
    */
    struct timer_opts {
    char* name;
    - void (*mark_offset)(void);
    + int (*mark_offset)(void);
    unsigned long (*get_offset)(void);
    unsigned long long (*monotonic_clock)(void);
    void (*delay)(unsigned long);
    diff -puN arch/i386/kernel/time.c~drift_fix arch/i386/kernel/time.c
    --- linux-2.6.13-rc6-mm2/arch/i386/kernel/time.c~drift_fix 2005-08-31 16:36:17.000000000 +0530
    +++ linux-2.6.13-rc6-mm2-root/arch/i386/kernel/time.c 2005-08-31 16:36:30.000000000 +0530
    @@ -253,7 +253,7 @@ EXPORT_SYMBOL(profile_pc);
    * timer_interrupt() needs to keep up the real-time clock,
    * as well as call the "do_timer()" routine every clocktick
    */
    -static inline void do_timer_interrupt(int irq, struct pt_regs *regs)
    +static inline void do_timer_interrupt(int irq, struct pt_regs *regs, int lost)
    {
    #ifdef CONFIG_X86_IO_APIC
    if (timer_ack) {
    @@ -271,7 +271,8 @@ static inline void do_timer_interrupt(in
    }
    #endif

    - do_timer_interrupt_hook(regs);
    + if (!dyn_tick_enabled() || lost)
    + do_timer_interrupt_hook(regs);


    if (MCA_bus) {
    @@ -296,6 +297,8 @@ static inline void do_timer_interrupt(in
    */
    irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
    {
    + int lost;
    +
    /*
    * Here we are in the timer irq handler. We just have irqs locally
    * disabled but we don't know if the timer_bh is running on the other
    @@ -305,9 +308,9 @@ irqreturn_t timer_interrupt(int irq, voi
    */
    write_seqlock(&xtime_lock);

    - cur_timer->mark_offset();
    -
    - do_timer_interrupt(irq, regs);
    + lost = cur_timer->mark_offset();
    +
    + do_timer_interrupt(irq, regs, lost);

    write_sequnlock(&xtime_lock);
    return IRQ_HANDLED;
    diff -puN arch/i386/kernel/dyn-tick.c~drift_fix arch/i386/kernel/dyn-tick.c
    --- linux-2.6.13-rc6-mm2/arch/i386/kernel/dyn-tick.c~drift_fix 2005-08-31 16:36:17.000000000 +0530
    +++ linux-2.6.13-rc6-mm2-root/arch/i386/kernel/dyn-tick.c 2005-08-31 16:36:30.000000000 +0530
    @@ -92,7 +92,13 @@ void dyn_tick_interrupt(int irq, struct

    if (all_were_sleeping) {
    /* Recover jiffies */
    - cur_timer->mark_offset();
    + if (irq) {
    + int lost;
    +
    + lost = cur_timer->mark_offset();
    + if (lost)
    + do_timer(regs);
    + }
    if (cpu_has_local_apic())
    enable_pit_timer();
    }
    @@ -116,8 +122,7 @@ void dyn_tick_time_init(struct timer_opt
    {
    spin_lock_init(&dyn_tick_lock);

    - if (strncmp(cur_timer->name, "tsc", 3) == 0 ||
    - strncmp(cur_timer->name, "pmtmr", 3) == 0) {
    + if (strncmp(cur_timer->name, "pmtmr", 3) == 0) {
    dyn_tick->state |= DYN_TICK_SUITABLE;
    printk(KERN_INFO "dyn-tick: Found suitable timer: %s\n",
    cur_timer->name);
    diff -puN arch/i386/kernel/timers/timer_cyclone.c~drift_fix arch/i386/kernel/timers/timer_cyclone.c
    --- linux-2.6.13-rc6-mm2/arch/i386/kernel/timers/timer_cyclone.c~drift_fix 2005-08-31 16:36:17.000000000 +0530
    +++ linux-2.6.13-rc6-mm2-root/arch/i386/kernel/timers/timer_cyclone.c 2005-08-31 16:36:30.000000000 +0530
    @@ -45,7 +45,7 @@ static seqlock_t monotonic_lock = SEQLOC
    } while (high != cyclone_timer[1]);


    -static void mark_offset_cyclone(void)
    +static int mark_offset_cyclone(void)
    {
    unsigned long lost, delay;
    unsigned long delta = last_cyclone_low;
    @@ -101,6 +101,8 @@ static void mark_offset_cyclone(void)
    */
    if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ))
    jiffies_64++;
    +
    + return 1;
    }

    static unsigned long get_offset_cyclone(void)
    diff -puN arch/i386/kernel/timers/timer_hpet.c~drift_fix arch/i386/kernel/timers/timer_hpet.c
    --- linux-2.6.13-rc6-mm2/arch/i386/kernel/timers/timer_hpet.c~drift_fix 2005-08-31 16:36:17.000000000 +0530
    +++ linux-2.6.13-rc6-mm2-root/arch/i386/kernel/timers/timer_hpet.c 2005-08-31 16:36:30.000000000 +0530
    @@ -96,7 +96,7 @@ static unsigned long get_offset_hpet(voi
    return edx;
    }

    -static void mark_offset_hpet(void)
    +static int mark_offset_hpet(void)
    {
    unsigned long long this_offset, last_offset;
    unsigned long offset;
    @@ -119,6 +119,8 @@ static void mark_offset_hpet(void)
    this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
    monotonic_base += cycles_2_ns(this_offset - last_offset);
    write_sequnlock(&monotonic_lock);
    +
    + return 1;
    }

    static void delay_hpet(unsigned long loops)
    diff -puN arch/i386/kernel/timers/timer_none.c~drift_fix arch/i386/kernel/timers/timer_none.c
    --- linux-2.6.13-rc6-mm2/arch/i386/kernel/timers/timer_none.c~drift_fix 2005-08-31 16:36:17.000000000 +0530
    +++ linux-2.6.13-rc6-mm2-root/arch/i386/kernel/timers/timer_none.c 2005-08-31 16:36:30.000000000 +0530
    @@ -1,9 +1,10 @@
    #include <linux/init.h>
    #include <asm/timer.h>

    -static void mark_offset_none(void)
    +static int mark_offset_none(void)
    {
    /* nothing needed */
    + return 1;
    }

    static unsigned long get_offset_none(void)
    diff -puN arch/i386/kernel/timers/timer_pit.c~drift_fix arch/i386/kernel/timers/timer_pit.c
    --- linux-2.6.13-rc6-mm2/arch/i386/kernel/timers/timer_pit.c~drift_fix 2005-08-31 16:36:17.000000000 +0530
    +++ linux-2.6.13-rc6-mm2-root/arch/i386/kernel/timers/timer_pit.c 2005-08-31 16:36:30.000000000 +0530
    @@ -32,9 +32,10 @@ static int __init init_pit(char* overrid
    return 0;
    }

    -static void mark_offset_pit(void)
    +static int mark_offset_pit(void)
    {
    /* nothing needed */
    + return 1;
    }

    static unsigned long long monotonic_clock_pit(void)
    diff -puN arch/i386/kernel/timers/timer_pm.c~drift_fix arch/i386/kernel/timers/timer_pm.c
    --- linux-2.6.13-rc6-mm2/arch/i386/kernel/timers/timer_pm.c~drift_fix 2005-08-31 16:36:17.000000000 +0530
    +++ linux-2.6.13-rc6-mm2-root/arch/i386/kernel/timers/timer_pm.c 2005-08-31 16:36:30.000000000 +0530
    @@ -135,7 +135,7 @@ pm_good:
    setup_pit_timer();

    init_cpu_khz();
    - set_dyn_tick_max_skip( (0xFFFFFF / (286 * 1000000)) * 1024 * HZ );
    + set_dyn_tick_max_skip(((0xFFFFFF / 1000000) * 286 * HZ) >> 10);
    return 0;
    }

    @@ -156,7 +156,7 @@ static inline u32 cyc2us(u32 cycles)
    * this gets called during each timer interrupt
    * - Called while holding the writer xtime_lock
    */
    -static void mark_offset_pmtmr(void)
    +static int mark_offset_pmtmr(void)
    {
    u32 lost, delta, deltaus, offset_now;

    @@ -182,6 +182,8 @@ static void mark_offset_pmtmr(void)
    /* compensate for lost ticks */
    if (lost >= 2)
    jiffies_64 += lost - 1;
    +
    + return lost;
    }

    static int pmtmr_resume(void)
    diff -puN arch/i386/kernel/timers/timer_tsc.c~drift_fix arch/i386/kernel/timers/timer_tsc.c
    --- linux-2.6.13-rc6-mm2/arch/i386/kernel/timers/timer_tsc.c~drift_fix 2005-08-31 16:36:17.000000000 +0530
    +++ linux-2.6.13-rc6-mm2-root/arch/i386/kernel/timers/timer_tsc.c 2005-08-31 16:36:30.000000000 +0530
    @@ -177,7 +177,7 @@ static inline void update_monotonic_base
    }

    #ifdef CONFIG_HPET_TIMER
    -static void mark_offset_tsc_hpet(void)
    +static int mark_offset_tsc_hpet(void)
    {
    unsigned long long last_offset;
    unsigned long offset, temp, hpet_current;
    @@ -221,6 +221,8 @@ static void mark_offset_tsc_hpet(void)
    delay_at_last_interrupt = hpet_current - offset;
    ASM_MUL64_REG(temp, delay_at_last_interrupt,
    hpet_usec_quotient, delay_at_last_interrupt);
    +
    + return 1;
    }
    #endif

    @@ -347,7 +349,7 @@ int recalibrate_cpu_khz(void)
    }
    EXPORT_SYMBOL(recalibrate_cpu_khz);

    -static void mark_offset_tsc(void)
    +static int mark_offset_tsc(void)
    {
    unsigned long lost,delay;
    unsigned long delta = last_tsc_low;
    @@ -456,8 +458,12 @@ static void mark_offset_tsc(void)
    * between tsc and pit reads (as noted when
    * usec delta is > 90% # of usecs/tick)
    */
    - if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ))
    + if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ)) {
    jiffies_64++;
    + lost++;
    + }
    +
    + return 1;
    }

    static int __init init_tsc(char* override)
    diff -puN arch/i386/Kconfig~drift_fix arch/i386/Kconfig
    _



    --


    Thanks and Regards,
    Srivatsa Vaddagiri,
    Linux Technology Center,
    IBM Software Labs,
    Bangalore, INDIA - 560017
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-08-31 19:29    [W:2.299 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site