mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* Linux time routines
@ 2006-02-15  8:15 Ulrich Windl
  2006-02-15 21:20 ` George Anzinger
  0 siblings, 1 reply; 2+ messages in thread
From: Ulrich Windl @ 2006-02-15  8:15 UTC (permalink / raw)
  To: linux-kernel; +Cc: johnstul

(Please CC: replies to me, not subscribed)
Hi,

first of all I must conferss that I was wrong when presenting
1) a patch for getnstimeofday()
2) measurements based on 1)

My patch, even when looking right at the first glance, it was ignoring the tick-
interpolation when no time interpolator was defined. It clearly indicates that the 
the variety on non-coherent time routines is a mess. A revised fix would look like 
this (other junks unaffected):

-#ifdef CONFIG_TIME_INTERPOLATION
+/* get system time with nanosecond accuracy */
 void getnstimeofday (struct timespec *tv)
 {
-	unsigned long seq,sec,nsec;
-
+	unsigned long seq, nsec, sec;
+#ifdef CONFIG_TIME_INTERPOLATION
 	do {
 		seq = read_seqbegin(&xtime_lock);
 		sec = xtime.tv_sec;
-		nsec = xtime.tv_nsec+time_interpolator_get_offset();
+		nsec = xtime.tv_nsec + time_interpolator_get_offset();
 	} while (unlikely(read_seqretry(&xtime_lock, seq)));
 
 	while (unlikely(nsec >= NSEC_PER_SEC)) {
 		nsec -= NSEC_PER_SEC;
 		++sec;
 	}
+#else
+	{	/*FIXME: Try not to loose nanoseconds */
+		struct timeval tv;
+
+		do_gettimeofday(&tv);
+		sec = tv.tv_sec;
+		nsec = tv.tv_usec * 1000 + xtime.tv_nsec % 1000;
+	}
+#endif
 	tv->tv_sec = sec;
 	tv->tv_nsec = nsec;
 }


--

Another important issue is this:
do_gettimeofday() (and related routines) currently does not return anything. 
However occasionally one needs the "raw" (more or less) value of the tick 
interpolation (e.g. for PPS frequency calibration). To get the current time and 
the interpolation value in a coherent way, it seems easiest to make 
do_gettimeofday() (and related) routines to return the interpolation value (they 
have it anyway).

(Explanation: NTP offset correction plus frequency correction do already add to 
the kernel clock. So when trying to estimate the absolute frequency error, you 
must measure the timing without such corrections.)

Thus something like:
unsigned long do_gettimeofday (struct timeval *tv)
{
        unsigned long seq, nsec, usec, sec, offset;
        do {
                seq = read_seqbegin(&xtime_lock);
                offset = time_interpolator_get_offset();
                sec = xtime.tv_sec;
                nsec = xtime.tv_nsec;
        } while (unlikely(read_seqretry(&xtime_lock, seq)));

        usec = (nsec + offset) / 1000;

        while (unlikely(usec >= USEC_PER_SEC)) {
                usec -= USEC_PER_SEC;
                ++sec;
        }

        tv->tv_sec = sec;
        tv->tv_usec = usec;
        return offset / 1000;
}

or

unsigned long do_gettimeofday(struct timeval *tv)
{
        unsigned long seq;
        unsigned long result, usec, sec;
        unsigned long max_ntp_tick;

        do {
                unsigned long lost;

                seq = read_seqbegin(&xtime_lock);

                result = usec = cur_timer->get_offset();
                lost = jiffies - wall_jiffies;

                /*
                 * If time_adjust is negative then NTP is slowing the clock
                 * so make sure not to go into next possible interval.
                 * Better to lose some accuracy than have time go backwards..
                 */
                if (unlikely(time_adjust < 0)) {
                        max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj;
                        usec = min(usec, max_ntp_tick);

                        if (lost)
                                usec += lost * max_ntp_tick;
                }
                else if (unlikely(lost))
                        usec += lost * (USEC_PER_SEC / HZ);

                sec = xtime.tv_sec;
                usec += (xtime.tv_nsec / 1000);
        } while (read_seqretry(&xtime_lock, seq));

        while (usec >= 1000000) {
                usec -= 1000000;
                sec++;
        }

        tv->tv_sec = sec;
        tv->tv_usec = usec;
        return result;
}

Similarly

static int do_posix_gettime(struct k_clock *clock, struct timespec *tp)
{
        if (clock->clock_get)
                return clock->clock_get(tp);

        return getnstimeofday(tp);
}

with

int do_posix_clock_monotonic_gettime(struct timespec *tp) returning the proper 
interpolation offset, etc.

Would such a change in the interface be acceptable?

Regards,
Ulrich


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Linux time routines
  2006-02-15  8:15 Linux time routines Ulrich Windl
@ 2006-02-15 21:20 ` George Anzinger
  0 siblings, 0 replies; 2+ messages in thread
From: George Anzinger @ 2006-02-15 21:20 UTC (permalink / raw)
  To: Ulrich Windl; +Cc: linux-kernel, johnstul

Ulrich Windl wrote:
> (Please CC: replies to me, not subscribed)
> Hi,
> 
> first of all I must conferss that I was wrong when presenting
> 1) a patch for getnstimeofday()
> 2) measurements based on 1)
> 
> My patch, even when looking right at the first glance, it was ignoring the tick-
> interpolation when no time interpolator was defined. It clearly indicates that the 
> the variety on non-coherent time routines is a mess. A revised fix would look like 
> this (other junks unaffected):
> 
> -#ifdef CONFIG_TIME_INTERPOLATION
> +/* get system time with nanosecond accuracy */
>  void getnstimeofday (struct timespec *tv)
>  {
> -	unsigned long seq,sec,nsec;
> -
> +	unsigned long seq, nsec, sec;
> +#ifdef CONFIG_TIME_INTERPOLATION
>  	do {
>  		seq = read_seqbegin(&xtime_lock);
>  		sec = xtime.tv_sec;
> -		nsec = xtime.tv_nsec+time_interpolator_get_offset();
> +		nsec = xtime.tv_nsec + time_interpolator_get_offset();
>  	} while (unlikely(read_seqretry(&xtime_lock, seq)));
>  
>  	while (unlikely(nsec >= NSEC_PER_SEC)) {
>  		nsec -= NSEC_PER_SEC;
>  		++sec;
>  	}
> +#else
> +	{	/*FIXME: Try not to loose nanoseconds */
> +		struct timeval tv;
> +
> +		do_gettimeofday(&tv);
> +		sec = tv.tv_sec;
> +		nsec = tv.tv_usec * 1000 + xtime.tv_nsec % 1000;
> +	}
> +#endif
>  	tv->tv_sec = sec;
>  	tv->tv_nsec = nsec;
>  }
> 
> 
> --
> 
> Another important issue is this:
> do_gettimeofday() (and related routines) currently does not return anything. 
> However occasionally one needs the "raw" (more or less) value of the tick 
> interpolation (e.g. for PPS frequency calibration). To get the current time and 
> the interpolation value in a coherent way, it seems easiest to make 
> do_gettimeofday() (and related) routines to return the interpolation value (they 
> have it anyway).
> 
> (Explanation: NTP offset correction plus frequency correction do already add to 
> the kernel clock. So when trying to estimate the absolute frequency error, you 
> must measure the timing without such corrections.)
> 
> Thus something like:
> unsigned long do_gettimeofday (struct timeval *tv)
> {
>         unsigned long seq, nsec, usec, sec, offset;
>         do {
>                 seq = read_seqbegin(&xtime_lock);
>                 offset = time_interpolator_get_offset();
>                 sec = xtime.tv_sec;
>                 nsec = xtime.tv_nsec;
>         } while (unlikely(read_seqretry(&xtime_lock, seq)));
> 
>         usec = (nsec + offset) / 1000;
> 
>         while (unlikely(usec >= USEC_PER_SEC)) {
>                 usec -= USEC_PER_SEC;
>                 ++sec;
>         }
> 
>         tv->tv_sec = sec;
>         tv->tv_usec = usec;
>         return offset / 1000;
> }
> 
> or
> 
> unsigned long do_gettimeofday(struct timeval *tv)
> {
>         unsigned long seq;
>         unsigned long result, usec, sec;
>         unsigned long max_ntp_tick;
> 
>         do {
>                 unsigned long lost;
> 
>                 seq = read_seqbegin(&xtime_lock);
> 
>                 result = usec = cur_timer->get_offset();
>                 lost = jiffies - wall_jiffies;
> 
>                 /*
>                  * If time_adjust is negative then NTP is slowing the clock
>                  * so make sure not to go into next possible interval.
>                  * Better to lose some accuracy than have time go backwards..
>                  */
>                 if (unlikely(time_adjust < 0)) {
>                         max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj;
>                         usec = min(usec, max_ntp_tick);
> 
>                         if (lost)
>                                 usec += lost * max_ntp_tick;
>                 }
>                 else if (unlikely(lost))
>                         usec += lost * (USEC_PER_SEC / HZ);
> 
>                 sec = xtime.tv_sec;
>                 usec += (xtime.tv_nsec / 1000);
>         } while (read_seqretry(&xtime_lock, seq));
> 
>         while (usec >= 1000000) {
>                 usec -= 1000000;
>                 sec++;
>         }
> 
>         tv->tv_sec = sec;
>         tv->tv_usec = usec;
>         return result;
> }
> 
> Similarly
> 
> static int do_posix_gettime(struct k_clock *clock, struct timespec *tp)
> {
>         if (clock->clock_get)
>                 return clock->clock_get(tp);
> 
>         return getnstimeofday(tp);
> }
> 
> with
> 
> int do_posix_clock_monotonic_gettime(struct timespec *tp) returning the proper 
> interpolation offset, etc.
> 
> Would such a change in the interface be acceptable?

The problem with this is that it leaves time_phase and the limit imposed by 
FINENSEC out.  What I did for a customer, a bit ago, was to change 
update_wall_time_one_tick() to calculate delta_nsec for NEXT time.  Then I 
used this pre-calculated delta_nsec to adjust do_gettimeofday().
> 

-- 
George Anzinger   george@wildturkeyranch.net
HRT (High-res-timers):  http://sourceforge.net/projects/high-res-timers/


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2006-02-15 21:21 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-02-15  8:15 Linux time routines Ulrich Windl
2006-02-15 21:20 ` George Anzinger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®