lkml.org 
[lkml]   [2006]   [Aug]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC][PATCH -mm 1/2] i386: Detect clock skew during suspend
    Date
    Detect the situations in which the time after a resume from disk would
    be earlier than the time before the suspend and prevent them from
    happening on i386.

    Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
    ---
    arch/i386/kernel/time.c | 24 ++++++++++++++++++------
    1 files changed, 18 insertions(+), 6 deletions(-)

    Index: linux-2.6.18-rc4-mm1/arch/i386/kernel/time.c
    ===================================================================
    --- linux-2.6.18-rc4-mm1.orig/arch/i386/kernel/time.c
    +++ linux-2.6.18-rc4-mm1/arch/i386/kernel/time.c
    @@ -285,16 +285,19 @@ void notify_arch_cmos_timer(void)
    mod_timer(&sync_cmos_timer, jiffies + 1);
    }

    -static long clock_cmos_diff, sleep_start;
    +static long clock_cmos_diff;
    +static unsigned long sleep_start;

    static int timer_suspend(struct sys_device *dev, pm_message_t state)
    {
    /*
    * Estimate time zone so that set_time can update the clock
    */
    - clock_cmos_diff = -get_cmos_time();
    + unsigned long ctime = get_cmos_time();
    +
    + clock_cmos_diff = -ctime;
    clock_cmos_diff += get_seconds();
    - sleep_start = get_cmos_time();
    + sleep_start = ctime;
    return 0;
    }

    @@ -302,16 +305,25 @@ static int timer_resume(struct sys_devic
    {
    unsigned long flags;
    unsigned long sec;
    - unsigned long sleep_length;
    + unsigned long ctime = get_cmos_time();
    + long sleep_length = (ctime - sleep_start) * HZ;
    struct timespec ts;
    +
    + if (sleep_length < 0) {
    + printk(KERN_WARNING "Time skew detected in timer resume!\n");
    + /* The time after the resume must not be earlier than the time
    + * before the suspend or some nasty things will happen
    + */
    + sleep_length = 0;
    + ctime = sleep_start;
    + }
    #ifdef CONFIG_HPET_TIMER
    if (is_hpet_enabled())
    hpet_reenable();
    #endif
    setup_pit_timer();
    - sec = get_cmos_time() + clock_cmos_diff;
    - sleep_length = (get_cmos_time() - sleep_start) * HZ;

    + sec = ctime + clock_cmos_diff;
    ts.tv_sec = sec;
    ts.tv_nsec = 0;
    do_settimeofday(&ts);
    -
    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: 2006-08-13 23:13    [W:4.087 / U:0.500 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site