ia64/xen-unstable

changeset 856:cb5916bb9685

bitkeeper revision 1.533 (3f9e6a73y_so5j_vqiY6UPUJof-DFQ)

time.c:
Fix up interpolation of time so that, under normal use, we will never see time go backwards.
author kaf24@scramble.cl.cam.ac.uk
date Tue Oct 28 13:09:07 2003 +0000 (2003-10-28)
parents 21376a12e008
children 4a6a4b1ae475
files xen/arch/i386/time.c xenolinux-2.4.22-sparse/arch/xeno/kernel/time.c
line diff
     1.1 --- a/xen/arch/i386/time.c	Tue Oct 28 11:29:39 2003 +0000
     1.2 +++ b/xen/arch/i386/time.c	Tue Oct 28 13:09:07 2003 +0000
     1.3 @@ -258,9 +258,21 @@ s_time_t get_s_time(void)
     1.4  {
     1.5      s_time_t now;
     1.6      unsigned long flags;
     1.7 +
     1.8      read_lock_irqsave(&xtime_lock, flags);
     1.9 +
    1.10      now = stime_irq + get_time_delta();
    1.11 +
    1.12 +    /* Ensure that the returned system time is monotonically increasing. */
    1.13 +    {
    1.14 +        static s_time_t prev_now = 0;
    1.15 +        if ( unlikely(now < prev_now) )
    1.16 +            now = prev_now;
    1.17 +        prev_now = now;
    1.18 +    }
    1.19 +
    1.20      read_unlock_irqrestore(&xtime_lock, flags);
    1.21 +
    1.22      return now; 
    1.23  }
    1.24  
    1.25 @@ -335,16 +347,6 @@ int __init init_xeno_time()
    1.26      for ( rdtsc_bitshift = 0; cpu_ghz != 0; rdtsc_bitshift++, cpu_ghz >>= 1 )
    1.27          continue;
    1.28  
    1.29 -    /*
    1.30 -     * We actually adjust cpu_freq to be 0.001% slower than the real
    1.31 -     * frequenecy. This makes time run a little bit slower when interpolating
    1.32 -     * the passage of time between periodic interrupts, so we expect a little
    1.33 -     * jump in time whenever an interrupt comes in (roughly 100ns every 10ms).
    1.34 -     * However, this should avoid us considtently running too fast and jumping
    1.35 -     * _backwards_ on each interrupt, which would be much worse!
    1.36 -     */
    1.37 -    cpu_freq = cpu_freq - (cpu_freq / 100000ULL);
    1.38 -
    1.39      scale  = 1000000000LL << (32 + rdtsc_bitshift);
    1.40      scale /= cpu_freq;
    1.41      st_scale_f = scale & 0xffffffff;
     2.1 --- a/xenolinux-2.4.22-sparse/arch/xeno/kernel/time.c	Tue Oct 28 11:29:39 2003 +0000
     2.2 +++ b/xenolinux-2.4.22-sparse/arch/xeno/kernel/time.c	Tue Oct 28 13:09:07 2003 +0000
     2.3 @@ -79,11 +79,20 @@ static s64 shadow_system_time;
     2.4  static u32 shadow_time_version;
     2.5  static struct timeval shadow_tv;
     2.6  
     2.7 +/*
     2.8 + * We use this to ensure that gettimeofday() is monotonically increasing. We
     2.9 + * only break this guarantee if the wall clock jumps backwards "a long way".
    2.10 + */
    2.11 +static struct timeval last_seen_tv = {0,0};
    2.12 +
    2.13  #ifdef CONFIG_XENO_PRIV
    2.14 -/* Periodically propagate synchronised time to the RTC and to Xen. */
    2.15 -static long last_rtc_update, last_xen_update;
    2.16 +/* Periodically propagate synchronised time base to the RTC and to Xen. */
    2.17 +static long last_update_to_rtc, last_update_to_xen;
    2.18  #endif
    2.19  
    2.20 +/* Periodically take synchronised time base from Xen, if we need it. */
    2.21 +static long last_update_from_xen;
    2.22 +
    2.23  static u64 processed_system_time;
    2.24  
    2.25  #define HANDLE_USEC_UNDERFLOW(_tv)         \
    2.26 @@ -232,11 +241,13 @@ void do_gettimeofday(struct timeval *tv)
    2.27  
    2.28   again:
    2.29      read_lock_irqsave(&xtime_lock, flags);
    2.30 +
    2.31      _tv.tv_usec = get_time_delta_usecs();
    2.32      if ( (lost = (jiffies - wall_jiffies)) != 0 )
    2.33          _tv.tv_usec += lost * (1000000 / HZ);
    2.34      _tv.tv_sec   = xtime.tv_sec;
    2.35      _tv.tv_usec += xtime.tv_usec;
    2.36 +
    2.37      if ( unlikely(!TIME_VALUES_UP_TO_DATE) )
    2.38      {
    2.39          /*
    2.40 @@ -250,10 +261,18 @@ void do_gettimeofday(struct timeval *tv)
    2.41          write_unlock_irqrestore(&xtime_lock, flags);
    2.42          goto again;
    2.43      }
    2.44 -    read_unlock_irqrestore(&xtime_lock, flags);
    2.45  
    2.46      HANDLE_USEC_OVERFLOW(_tv);
    2.47  
    2.48 +    /* Ensure that time-of-day is monotonically increasing. */
    2.49 +    if ( (_tv.tv_sec < last_seen_tv.tv_sec) ||
    2.50 +         ((_tv.tv_sec == last_seen_tv.tv_sec) &&
    2.51 +          (_tv.tv_usec < last_seen_tv.tv_usec)) )
    2.52 +        _tv = last_seen_tv;
    2.53 +    last_seen_tv = _tv;
    2.54 +
    2.55 +    read_unlock_irqrestore(&xtime_lock, flags);
    2.56 +
    2.57      *tv = _tv;
    2.58  }
    2.59  
    2.60 @@ -292,11 +311,15 @@ void do_settimeofday(struct timeval *tv)
    2.61      time_maxerror = NTP_PHASE_LIMIT;
    2.62      time_esterror = NTP_PHASE_LIMIT;
    2.63  
    2.64 +    /* Reset all our running time counts. They make no sense now. */
    2.65 +    last_seen_tv.tv_sec = 0;
    2.66 +    last_update_from_xen = 0;
    2.67 +
    2.68  #ifdef CONFIG_XENO_PRIV
    2.69      if ( start_info.dom_id == 0 )
    2.70      {
    2.71          dom0_op_t op;
    2.72 -        last_rtc_update = last_xen_update = 0;
    2.73 +        last_update_to_rtc = last_update_to_xen = 0;
    2.74          op.cmd = DOM0_SETTIME;
    2.75          op.u.settime.secs        = newtv.tv_sec;
    2.76          op.u.settime.usecs       = newtv.tv_usec;
    2.77 @@ -335,6 +358,7 @@ static inline void do_timer_interrupt(in
    2.78                                        struct pt_regs *regs)
    2.79  {
    2.80      s64 delta;
    2.81 +    long sec_diff;
    2.82  
    2.83      get_time_values_from_xen();
    2.84  
    2.85 @@ -351,21 +375,43 @@ static inline void do_timer_interrupt(in
    2.86          processed_system_time += NS_PER_TICK;
    2.87      }
    2.88      
    2.89 -    if ( !independent_wallclock && ((time_status & STA_UNSYNC) != 0) )
    2.90 +    /*
    2.91 +     * Take synchronised time from Xen once a minute if we're not
    2.92 +     * synchronised ourselves, and we haven't chosen to keep an independent
    2.93 +     * time base.
    2.94 +     */
    2.95 +    if ( !independent_wallclock && 
    2.96 +         ((time_status & STA_UNSYNC) != 0) &&
    2.97 +         (xtime.tv_sec > (last_update_from_xen + 60)) )
    2.98      {
    2.99          /* Adjust shadow timeval for jiffies that haven't updated xtime yet. */
   2.100          shadow_tv.tv_usec -= (jiffies - wall_jiffies) * (1000000/HZ);
   2.101          HANDLE_USEC_UNDERFLOW(shadow_tv);
   2.102  
   2.103 +        /*
   2.104 +         * Reset our running time counts if they are invalidated by a warp
   2.105 +         * backwards of more than 500ms.
   2.106 +         */
   2.107 +        sec_diff = xtime.tv_sec - shadow_tv.tv_sec;
   2.108 +        if ( unlikely(abs(sec_diff) > 1) ||
   2.109 +             unlikely(((sec_diff * 1000000) + 
   2.110 +                       xtime.tv_usec - shadow_tv.tv_usec) > 500000) )
   2.111 +        {
   2.112 +            last_update_to_rtc = last_update_to_xen = 0;
   2.113 +            last_seen_tv.tv_sec = 0;
   2.114 +        }
   2.115 +
   2.116          /* Update our unsynchronised xtime appropriately. */
   2.117          xtime = shadow_tv;
   2.118 +
   2.119 +        last_update_from_xen = xtime.tv_sec;
   2.120      }
   2.121  
   2.122  #ifdef CONFIG_XENO_PRIV
   2.123  	if ( (start_info.dom_id == 0) && ((time_status & STA_UNSYNC) == 0) )
   2.124      {
   2.125          /* Send synchronised time to Xen approximately every minute. */
   2.126 -        if ( xtime.tv_sec > (last_xen_update + 60) )
   2.127 +        if ( xtime.tv_sec > (last_update_to_xen + 60) )
   2.128          {
   2.129              dom0_op_t op;
   2.130              struct timeval tv = xtime;
   2.131 @@ -379,7 +425,7 @@ static inline void do_timer_interrupt(in
   2.132              op.u.settime.system_time = shadow_system_time;
   2.133              HYPERVISOR_dom0_op(&op);
   2.134  
   2.135 -            last_xen_update = xtime.tv_sec;
   2.136 +            last_update_to_xen = xtime.tv_sec;
   2.137          }
   2.138  
   2.139          /*
   2.140 @@ -387,14 +433,14 @@ static inline void do_timer_interrupt(in
   2.141           * clock accordingly every ~11 minutes. Set_rtc_mmss() has to be called
   2.142           * as close as possible to 500 ms before the new second starts.
   2.143           */
   2.144 -        if ( (xtime.tv_sec > (last_rtc_update + 660)) &&
   2.145 +        if ( (xtime.tv_sec > (last_update_to_rtc + 660)) &&
   2.146               (xtime.tv_usec >= (500000 - ((unsigned) tick) / 2)) &&
   2.147               (xtime.tv_usec <= (500000 + ((unsigned) tick) / 2)) )
   2.148          {
   2.149              if ( set_rtc_mmss(xtime.tv_sec) == 0 )
   2.150 -                last_rtc_update = xtime.tv_sec;
   2.151 +                last_update_to_rtc = xtime.tv_sec;
   2.152              else
   2.153 -                last_rtc_update = xtime.tv_sec - 600;
   2.154 +                last_update_to_rtc = xtime.tv_sec - 600;
   2.155          }
   2.156      }
   2.157  #endif