summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Helsley <matthltc@us.ibm.com>2005-12-12 00:37:09 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2005-12-12 08:57:42 -0800
commit64123fd42c7a1e4ebf6acd2399c98caddc7e0c26 (patch)
treed6b1794fa33287d145a44ab55bc2e2ef65ebf248
parent894ec8707ced240b96dc45944790fb35d9a6b03c (diff)
[PATCH] Add getnstimestamp function
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>
-rw-r--r--include/linux/time.h1
-rw-r--r--kernel/time.c22
2 files changed, 23 insertions, 0 deletions
diff --git a/include/linux/time.h b/include/linux/time.h
index bfbe92d0767c..797ccd813bb0 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -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);
diff --git a/kernel/time.c b/kernel/time.c
index 245d595a13cb..b94bfa8c03e0 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -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)
{