ia64/xen-unstable

changeset 654:4d7f44227ecf

bitkeeper revision 1.369 (3f1bc567VPb_t9DjpccNKurPwExgnA)

time.c:
Fixed more timing problems in Xen. Got rid of wctime_lock and use stime_lock instead, which ensures that both wallclock timebase and system timebase are always in sync. Also update cpu_freq variable only when tiembase is updated to avoid a backwards time warp.
author kaf24@scramble.cl.cam.ac.uk
date Mon Jul 21 10:50:15 2003 +0000 (2003-07-21)
parents a7bfe57ca27f
children 3c7d3bff01da
files xen/arch/i386/time.c
line diff
     1.1 --- a/xen/arch/i386/time.c	Mon Jul 21 10:17:01 2003 +0000
     1.2 +++ b/xen/arch/i386/time.c	Mon Jul 21 10:50:15 2003 +0000
     1.3 @@ -322,7 +322,6 @@ s_time_t get_s_time(void)
     1.4  
     1.5  
     1.6  /* Wall Clock time */
     1.7 -static spinlock_t wctime_lock;
     1.8  struct timeval    wall_clock_time; /* wall clock time at last update */
     1.9  s_time_t          wctime_st;       /* system time at last update */
    1.10  
    1.11 @@ -331,11 +330,11 @@ void do_gettimeofday(struct timeval *tv)
    1.12      unsigned long flags;
    1.13      unsigned long usec, sec;
    1.14  
    1.15 -    spin_lock_irqsave(&wctime_lock, flags);
    1.16 -    usec = ((unsigned long)(NOW() - wctime_st))/1000;
    1.17 +    spin_lock_irqsave(&stime_lock, flags);
    1.18 +    usec = ((unsigned long)(__get_s_time() - wctime_st))/1000;
    1.19      sec = wall_clock_time.tv_sec;
    1.20      usec += wall_clock_time.tv_usec;
    1.21 -    spin_unlock_irqrestore(&wctime_lock, flags);
    1.22 +    spin_unlock_irqrestore(&stime_lock, flags);
    1.23  
    1.24      while (usec >= 1000000) {
    1.25          usec -= 1000000;
    1.26 @@ -362,59 +361,16 @@ void update_dom_time(shared_info_t *si)
    1.27      spin_lock_irqsave(&stime_lock, flags);
    1.28      si->system_time  = stime_now;
    1.29      si->st_timestamp = stime_pcc;
    1.30 -    spin_unlock_irqrestore(&stime_lock, flags);
    1.31 -
    1.32 -    spin_lock_irqsave(&wctime_lock, flags);
    1.33      si->tv_sec       = wall_clock_time.tv_sec;
    1.34      si->tv_usec      = wall_clock_time.tv_usec;
    1.35      si->wc_timestamp = wctime_st;
    1.36      si->wc_version++;
    1.37 -    spin_unlock_irqrestore(&wctime_lock, flags);    
    1.38 +    spin_unlock_irqrestore(&stime_lock, flags);
    1.39  
    1.40      TRC(printk(" 0x%08X%08X\n", (u32)(wctime_st>>32), (u32)wctime_st));
    1.41  }
    1.42  
    1.43  /*
    1.44 - * Update hypervisors notion of time
    1.45 - * This is done periodically of it's own timer
    1.46 - */
    1.47 -static struct ac_timer update_timer;
    1.48 -static void update_time(unsigned long foo)
    1.49 -{
    1.50 -    unsigned long  flags;
    1.51 -    s_time_t       new_st;
    1.52 -    unsigned long  usec;
    1.53 -
    1.54 -    /* Update system time. */
    1.55 -    spin_lock_irqsave(&stime_lock, flags);
    1.56 -    stime_now = new_st = __get_s_time();
    1.57 -    rdtscl(stime_pcc);
    1.58 -    /* Don't reeenable IRQs until we release wctime_lock. */
    1.59 -    spin_unlock(&stime_lock);
    1.60 -
    1.61 -    /* Update wall clock time. */
    1.62 -    spin_lock(&wctime_lock);
    1.63 -    usec = ((unsigned long)(new_st - wctime_st))/1000;
    1.64 -    usec += wall_clock_time.tv_usec;
    1.65 -    while (usec >= 1000000) {
    1.66 -        usec -= 1000000;
    1.67 -        wall_clock_time.tv_sec++;
    1.68 -    }
    1.69 -    wall_clock_time.tv_usec = usec;
    1.70 -    wctime_st = new_st;
    1.71 -    spin_unlock_irqrestore(&wctime_lock, flags);
    1.72 -
    1.73 -    TRC(printk("TIME[%02d] update time: stime_now=%lld now=%lld,wct=%ld:%ld\n",
    1.74 -               smp_processor_id(), stime_now, new_st, wall_clock_time.tv_sec,
    1.75 -               wall_clock_time.tv_usec));
    1.76 -
    1.77 -    /* Reload the timer. */
    1.78 -    update_timer.expires = new_st + MILLISECS(200);
    1.79 -    add_ac_timer(&update_timer);
    1.80 -}
    1.81 -
    1.82 -
    1.83 -/*
    1.84   * VERY crude way to keep system time from drfiting.
    1.85   * Update the scaling factor using the RTC
    1.86   * This is done periodically of it's own timer
    1.87 @@ -428,15 +384,18 @@ static void update_time(unsigned long fo
    1.88   * being in sync with the CMOS update-in-progress flag, which causes this
    1.89   * routine to bail.
    1.90   */
    1.91 -#define UPDATE_PERIOD   MILLISECS(50200)
    1.92 -static struct ac_timer scale_timer;
    1.93 +/*
    1.94 + * NB2. Note that update_scale is called from update_time with the stime_lock
    1.95 + * still held. This is because we must only slow down cpu_freq at a timebase
    1.96 + * change. If we did it in the middle of an update period then time would
    1.97 + * seem to jump backwards since BASE+OLD_FREQ*DIFF > BASE+NEW_FREQ*DIFF.
    1.98 + */
    1.99 +#define SCALE_UPDATE_PERIOD   MILLISECS(50200)
   1.100  static unsigned long   init_cmos_time;
   1.101  static u64             cpu_freqs[3];
   1.102 -static void update_scale(unsigned long foo)
   1.103 +static void update_scale(void)
   1.104  {
   1.105 -    unsigned long  flags;
   1.106      unsigned long  cmos_time;
   1.107 -    s_time_t       now;
   1.108      u32            st, ct;
   1.109      s32            dt;
   1.110      u64            scale;
   1.111 @@ -445,11 +404,8 @@ static void update_scale(unsigned long f
   1.112      if ( (cmos_time = maybe_get_cmos_time()) == 0 )
   1.113          return;
   1.114  
   1.115 -    spin_lock_irqsave(&stime_lock, flags);
   1.116 -    now  = __get_s_time();
   1.117 -
   1.118      ct = (u32)(cmos_time - init_cmos_time);
   1.119 -    st = (u32)(now/SECONDS(1));
   1.120 +    st = (u32)(stime_now/SECONDS(1));
   1.121      dt = (s32)(ct - st);
   1.122  
   1.123      /* work out adjustment to scaling factor. allow +/- 1s drift */
   1.124 @@ -468,13 +424,58 @@ static void update_scale(unsigned long f
   1.125      scale /= cpu_freq;
   1.126      st_scale_f = scale & 0xffffffff;
   1.127      st_scale_i = scale >> 32;
   1.128 +}
   1.129 +
   1.130 +
   1.131 +/*
   1.132 + * Update hypervisors notion of time
   1.133 + * This is done periodically of it's own timer
   1.134 + */
   1.135 +#define TIME_UPDATE_PERIOD    MILLISECS(200)
   1.136 +static struct ac_timer update_timer;
   1.137 +static void update_time(unsigned long foo)
   1.138 +{
   1.139 +    unsigned long  flags;
   1.140 +    s_time_t       new_st;
   1.141 +    unsigned long  usec;
   1.142 +    static int calls_since_scale_update = 0;
   1.143 +
   1.144 +    spin_lock_irqsave(&stime_lock, flags);
   1.145 +
   1.146 +    /* Update system time. */
   1.147 +    stime_now = new_st = __get_s_time();
   1.148 +    rdtscl(stime_pcc);
   1.149 +
   1.150 +    /* Maybe update our rate to be in sync with the RTC. */
   1.151 +    if ( ++calls_since_scale_update >= 
   1.152 +         (SCALE_UPDATE_PERIOD/TIME_UPDATE_PERIOD) )
   1.153 +    {
   1.154 +        update_scale();
   1.155 +        calls_since_scale_update = 0;
   1.156 +    }
   1.157 +
   1.158 +    /* Update wall clock time. */
   1.159 +    usec = ((unsigned long)(new_st - wctime_st))/1000;
   1.160 +    usec += wall_clock_time.tv_usec;
   1.161 +    while (usec >= 1000000) {
   1.162 +        usec -= 1000000;
   1.163 +        wall_clock_time.tv_sec++;
   1.164 +    }
   1.165 +    wall_clock_time.tv_usec = usec;
   1.166 +    wctime_st = new_st;
   1.167  
   1.168      spin_unlock_irqrestore(&stime_lock, flags);
   1.169 -    scale_timer.expires  = now + UPDATE_PERIOD;
   1.170 -    add_ac_timer(&scale_timer);
   1.171 -    TRC(printk(" %ds[%d] ", dt, freq_index));
   1.172 +
   1.173 +    TRC(printk("TIME[%02d] update time: stime_now=%lld now=%lld,wct=%ld:%ld\n",
   1.174 +               smp_processor_id(), stime_now, new_st, wall_clock_time.tv_sec,
   1.175 +               wall_clock_time.tv_usec));
   1.176 +
   1.177 +    /* Reload the timer. */
   1.178 +    update_timer.expires = new_st + TIME_UPDATE_PERIOD;
   1.179 +    add_ac_timer(&update_timer);
   1.180  }
   1.181  
   1.182 +
   1.183  /***************************************************************************
   1.184   * Init Xeno Time
   1.185   * This has to be done after all CPUs have been booted
   1.186 @@ -487,7 +488,6 @@ int __init init_xeno_time()
   1.187      s64      freq_off;
   1.188  
   1.189      spin_lock_init(&stime_lock);
   1.190 -    spin_lock_init(&wctime_lock);
   1.191  
   1.192      printk("Init Time[%02d]:\n", cpu);
   1.193  
   1.194 @@ -523,11 +523,6 @@ int __init init_xeno_time()
   1.195      update_timer.function = &update_time;
   1.196      update_time(0);
   1.197   
   1.198 -    init_ac_timer(&scale_timer, 0);
   1.199 -    scale_timer.data = 4;
   1.200 -    scale_timer.function = &update_scale;
   1.201 -    update_scale(0);
   1.202 -
   1.203      printk(".... System Time: %lldns\n",   NOW());
   1.204      printk(".....cpu_freq:    %08X%08X\n", (u32)(cpu_freq>>32), (u32)cpu_freq);
   1.205      printk(".....cpu_cycle:   %u ps\n",    cpu_cycle);