2.6.15:kernel/time.c: The Nanosecond and code duplication

From: Ulrich Windl
Date: Mon Feb 13 2006 - 03:26:58 EST


Hi!

I'm working on an integration of current NTP kernel algorithms for Linux 2.6.
xtime now has nanosecond resolution, but there's no POSIX like syscall interface
(clock_getres, clock_gettime, clock_settime) yet.

There's a hacked-on getnstimeofday() which, what I discovered doesn't actually
pass along the nanosecond resolution of xtime. It does:

void getnstimeofday(struct timespec *tv)
{
struct timeval x;

do_gettimeofday(&x);
tv->tv_sec = x.tv_sec;
tv->tv_nsec = x.tv_usec * NSEC_PER_USEC;
}

The proper solution most likely is to define POSIX compatible routines with
nanosecond resolution, and then define the microsecond-resolution from those, and
not the other way round.

Also there are severe religious wars on how a clock interface should look like for
a particular architecture. Besides the time interpolator there are architecture-
specific get_offset() calls. While making some people happy, it causes a code
explosion considering amount and complexity of code. I'd strongly prefer one time
variable (xtime) and an interpolator for the time elapsed since xtime was updates,
combinded with a method how to get consistent time. That's bad IMHO.

To make a long story short, here's a patch (just for inspiring you) I made to get
the nanoseconds available to other modules and to user land (via new methods
outside this patch):

Index: kernel/time.c
===================================================================
RCS file: /root/LinuxCVS/Kernel/kernel/time.c,v
retrieving revision 1.1.1.6.2.1
diff -u -r1.1.1.6.2.1 time.c
--- kernel/time.c 11 Feb 2006 18:16:28 -0000 1.1.1.6.2.1
+++ kernel/time.c 12 Feb 2006 17:30:51 -0000
@@ -1405,26 +1407,36 @@
}
EXPORT_SYMBOL(timespec_trunc);

-#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, offset;
do {
seq = read_seqbegin(&xtime_lock);
+#ifdef CONFIG_TIME_INTERPOLATION
+ offset = time_interpolator_get_offset();
+#else
+ offset = 0;
+#endif
sec = xtime.tv_sec;
- nsec = xtime.tv_nsec+time_interpolator_get_offset();
+ nsec = xtime.tv_nsec + offset;
} while (unlikely(read_seqretry(&xtime_lock, seq)));

+#ifdef CONFIG_TIME_INTERPOLATION
while (unlikely(nsec >= NSEC_PER_SEC)) {
nsec -= NSEC_PER_SEC;
++sec;
}
+#endif
tv->tv_sec = sec;
tv->tv_nsec = nsec;
}
EXPORT_SYMBOL_GPL(getnstimeofday);

+#ifdef CONFIG_TIME_INTERPOLATION
+/* this is a mess: there are also architecture-dependent ``do_gettimeofday()''
+ * and ``do_settimeofday()''
+ */
int do_settimeofday (struct timespec *tv)
{
time_t wtm_sec, sec = tv->tv_sec;
@@ -1451,42 +1463,14 @@

void 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)));
+ struct timespec ts;

- usec = (nsec + offset) / 1000;
-
- while (unlikely(usec >= USEC_PER_SEC)) {
- usec -= USEC_PER_SEC;
- ++sec;
- }
-
- tv->tv_sec = sec;
- tv->tv_usec = usec;
+ getnstimeofday(&ts);
+ tv->tv_sec = ts.tv_sec;
+ tv->tv_usec = (ts.tv_nsec + 500) / 1000;
}

EXPORT_SYMBOL(do_gettimeofday);
-
-
-#else
-/*
- * Simulate gettimeofday using do_gettimeofday which only allows a timeval
- * and therefore only yields usec accuracy
- */
-void getnstimeofday(struct timespec *tv)
-{
- struct timeval x;
-
- do_gettimeofday(&x);
- tv->tv_sec = x.tv_sec;
- tv->tv_nsec = x.tv_usec * NSEC_PER_USEC;
-}
-EXPORT_SYMBOL_GPL(getnstimeofday);
#endif

void getnstimestamp(struct timespec *ts)


Regards,
Ulrich

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/