[PATCH] Add getnstimestamp function
authorMatt Helsley <matthltc@us.ibm.com>
Mon, 12 Dec 2005 08:37:09 +0000 (00:37 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 12 Dec 2005 16:57:42 +0000 (08:57 -0800)
There are several functions that might seem appropriate for a timestamp:

get_cycles()
current_kernel_time()
do_gettimeofday()
<read jiffies/jiffies_64>

Each has problems with combinations of SMP-safety, low resolution, and
monotonicity. This patch adds a new function that returns a monotonic SMP-safe
timestamp with nanosecond resolution where available.

Changes:
Split timestamp into separate patch
Moved to kernel/time.c
Renamed to getnstimestamp
Fixed unintended-pointer-arithmetic bug

Signed-off-by: Matt Helsley <matthltc@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
include/linux/time.h
kernel/time.c

index bfbe92d0767c62a61f09db17b5b59cb8e4a080a6..797ccd813bb004a1f02e52651f0c49260617254d 100644 (file)
@@ -95,6 +95,7 @@ struct itimerval;
 extern int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue);
 extern int do_getitimer(int which, struct itimerval *value);
 extern void getnstimeofday (struct timespec *tv);
+extern void getnstimestamp(struct timespec *ts);
 
 extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
 
index 245d595a13cb9f566f67c2ac6ab6dfb8c0af1143..b94bfa8c03e0ce045c02195942dcdfc16172bdab 100644 (file)
@@ -561,6 +561,28 @@ void getnstimeofday(struct timespec *tv)
 EXPORT_SYMBOL_GPL(getnstimeofday);
 #endif
 
+void getnstimestamp(struct timespec *ts)
+{
+       unsigned int seq;
+       struct timespec wall2mono;
+
+       /* synchronize with settimeofday() changes */
+       do {
+               seq = read_seqbegin(&xtime_lock);
+               getnstimeofday(ts);
+               wall2mono = wall_to_monotonic;
+       } while(unlikely(read_seqretry(&xtime_lock, seq)));
+
+       /* adjust to monotonicaly-increasing values */
+       ts->tv_sec += wall2mono.tv_sec;
+       ts->tv_nsec += wall2mono.tv_nsec;
+       while (unlikely(ts->tv_nsec >= NSEC_PER_SEC)) {
+               ts->tv_nsec -= NSEC_PER_SEC;
+               ts->tv_sec++;
+       }
+}
+EXPORT_SYMBOL_GPL(getnstimestamp);
+
 #if (BITS_PER_LONG < 64)
 u64 get_jiffies_64(void)
 {