[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: non-monotonic do_gettimeofday?



On Friday 06 September 2002 16.15, Akshay Adhikari wrote:
> Right, changed it, and it works... thanks!
> akshay

Great, but perhaps we should handle that in do_gettimeofday()
as they do it on i386 instead?

void do_gettimeofday(struct timeval *tv)
{
        unsigned long flags;

        save_flags(flags);
        cli();
        *tv = xtime;
        tv->tv_usec += do_gettimeoffset();
+        {
+                unsigned long lost = jiffies - wall_jiffies;
+                if (lost)
+                        usec += lost * (1000000 / HZ);
+        }
        restore_flags(flags);
        while (tv->tv_usec >= 1000000) {
                tv->tv_usec -= 1000000;
                tv->tv_sec++;
        }
}

/Johan

> On Fri, 6 Sep 2002, Johan Adolfsson wrote:
> > On Friday 06 September 2002 15.17, Akshay Adhikari wrote:
> > > here is a modified version of do_gettimeoffset and do_gettimeofday in
> > > time.c v.1.11, which seems to have drastically reduced the number of
> > > time warps, possibly because it accounts for unexcecuted timer bottom
> > > halves...
> >
> > Yes, you're right - we didn't handle that, but you missed one case I
> > think,
> >
> > see below:
> > > (assumption is that HZ is 100, but that can be changed easily..)
> >
> > To be clear you can write (1000000/HZ), the compiler will optimise it
> > so no division will take place at runtime anyway.
> >
> > > static unsigned long do_slow_gettimeoffset(void)
> > > {
> > >         unsigned long count;
> > >         unsigned long usec_count = 0;
> > >
> > >         static unsigned long count_p = LATCH;    /* for the first call
> > > after boot */
> > >         static unsigned long jiffies_p = 0;
> > >
> > >         unsigned long jiffies_t;
> > >
> > >         count = *R_TIMER0_DATA;
> > >         jiffies_t = jiffies;
> > >
> > >         usec_count = cris_timer0_value_us[count];
> > >         if( jiffies_t == jiffies_p ) {
> > >                 if( count > count_p ) {
> > >                         /*printk(KERN_WARNING "warp %ld to %ld\n",
> > > count_p, count);*/
> > >                         usec_count += (jiffies_t-wall_jiffies+1)*10000;
> > >                 }
> >
> > Here you misses one case were wall_jiffies isn't handled.
> >
> > >         }
> > >
> > >         else
> > >                 usec_count+= (jiffies_t-wall_jiffies)*10000;
> >
> > I suggest changing the intire if statement to the following and
> > allways take care of the wall_jiffies:
> >
> >          if( jiffies_t == jiffies_p ) {
> >                  if( count > count_p ) {
> >                          /*printk(KERN_WARNING "warp %ld to %ld\n",
> > 		 count_p, count);*/
> >                          usec_count += (1000000/HZ);
> >                  }
> >          }
> >
> >          usec_count+= (jiffies_t-wall_jiffies)*(1000000/HZ);
> >
> > >         jiffies_p = jiffies_t;
> > >         count_p = count;
> > >         return usec_count;
> > > }