diff options
author | Matt Helsley <matthltc@us.ibm.com> | 2005-12-12 00:37:09 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-12-12 08:57:42 -0800 |
commit | 64123fd42c7a1e4ebf6acd2399c98caddc7e0c26 (patch) | |
tree | d6b1794fa33287d145a44ab55bc2e2ef65ebf248 | |
parent | 894ec8707ced240b96dc45944790fb35d9a6b03c (diff) | |
download | op-kernel-dev-64123fd42c7a1e4ebf6acd2399c98caddc7e0c26.zip op-kernel-dev-64123fd42c7a1e4ebf6acd2399c98caddc7e0c26.tar.gz |
[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.h | 1 | ||||
-rw-r--r-- | kernel/time.c | 22 |
2 files changed, 23 insertions, 0 deletions
diff --git a/include/linux/time.h b/include/linux/time.h index bfbe92d..797ccd8 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 245d595..b94bfa8 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) { |