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

Re: non-monotonic do_gettimeofday?



right, though out of curiosity, here's a couple of questions: 

-from an execution time point of view it doesnt make a difference, right?
(or will the compiler possibly inline do_gettimeoffset in case it is
shorter?)

-how long is the timer interrupt (and in general, any level
triggered interrupt) signalled? Just curious to know how long we would
have to do a cli() to miss an interrupt... 

thanks, 
akshay



On Fri, 6 Sep 2002, Johan Adolfsson wrote:

> 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;
> > > > }
>