Commit b9cbc585 authored by Christoph Lameter's avatar Christoph Lameter Committed by Linus Torvalds

[PATCH] gettimeofday nanoseconds patch

This issue was discussed on lkml and linux-ia64.  The patch introduces
"getnstimeofday" and removes all the code scaling gettimeofday to
nanoseoncs.  It makes it possible for the posix-timer functions to return
higher accuracy.
Signed-off-by: default avatarChristoph Lameter <clameter@sgi.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 346ed9c1
...@@ -348,6 +348,7 @@ extern long do_utimes(char __user * filename, struct timeval * times); ...@@ -348,6 +348,7 @@ extern long do_utimes(char __user * filename, struct timeval * times);
struct itimerval; struct itimerval;
extern int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue); extern int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue);
extern int do_getitimer(int which, struct itimerval *value); extern int do_getitimer(int which, struct itimerval *value);
extern void getnstimeofday (struct timespec *tv);
static inline void static inline void
set_normalized_timespec (struct timespec *ts, time_t sec, long nsec) set_normalized_timespec (struct timespec *ts, time_t sec, long nsec)
......
...@@ -1168,15 +1168,10 @@ void exit_itimers(struct signal_struct *sig) ...@@ -1168,15 +1168,10 @@ void exit_itimers(struct signal_struct *sig)
*/ */
static int do_posix_gettime(struct k_clock *clock, struct timespec *tp) static int do_posix_gettime(struct k_clock *clock, struct timespec *tp)
{ {
struct timeval tv;
if (clock->clock_get) if (clock->clock_get)
return clock->clock_get(tp); return clock->clock_get(tp);
do_gettimeofday(&tv); getnstimeofday(tp);
tp->tv_sec = tv.tv_sec;
tp->tv_nsec = tv.tv_usec * NSEC_PER_USEC;
return 0; return 0;
} }
...@@ -1192,24 +1187,16 @@ static u64 do_posix_clock_monotonic_gettime_parts( ...@@ -1192,24 +1187,16 @@ static u64 do_posix_clock_monotonic_gettime_parts(
struct timespec *tp, struct timespec *mo) struct timespec *tp, struct timespec *mo)
{ {
u64 jiff; u64 jiff;
struct timeval tpv;
unsigned int seq; unsigned int seq;
do { do {
seq = read_seqbegin(&xtime_lock); seq = read_seqbegin(&xtime_lock);
do_gettimeofday(&tpv); getnstimeofday(tp);
*mo = wall_to_monotonic; *mo = wall_to_monotonic;
jiff = jiffies_64; jiff = jiffies_64;
} while(read_seqretry(&xtime_lock, seq)); } while(read_seqretry(&xtime_lock, seq));
/*
* Love to get this before it is converted to usec.
* It would save a div AND a mpy.
*/
tp->tv_sec = tpv.tv_sec;
tp->tv_nsec = tpv.tv_usec * NSEC_PER_USEC;
return jiff; return jiff;
} }
......
...@@ -22,6 +22,9 @@ ...@@ -22,6 +22,9 @@
* "A Kernel Model for Precision Timekeeping" by Dave Mills * "A Kernel Model for Precision Timekeeping" by Dave Mills
* Allow time_constant larger than MAXTC(6) for NTP v4 (MAXTC == 10) * Allow time_constant larger than MAXTC(6) for NTP v4 (MAXTC == 10)
* (Even though the technical memorandum forbids it) * (Even though the technical memorandum forbids it)
* 2004-07-14 Christoph Lameter
* Added getnstimeofday to allow the posix timer functions to return
* with nanosecond accuracy
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -421,6 +424,41 @@ struct timespec current_kernel_time(void) ...@@ -421,6 +424,41 @@ struct timespec current_kernel_time(void)
EXPORT_SYMBOL(current_kernel_time); EXPORT_SYMBOL(current_kernel_time);
#ifdef CONFIG_TIME_INTERPOLATION
void getnstimeofday (struct timespec *tv)
{
unsigned long seq,sec,nsec;
do {
seq = read_seqbegin(&xtime_lock);
sec = xtime.tv_sec;
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;
}
tv->tv_sec = sec;
tv->tv_nsec = nsec;
}
#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;
}
#endif
EXPORT_SYMBOL(getnstimeofday);
#if (BITS_PER_LONG < 64) #if (BITS_PER_LONG < 64)
u64 get_jiffies_64(void) u64 get_jiffies_64(void)
{ {
......
...@@ -1241,8 +1241,7 @@ asmlinkage long sys_sysinfo(struct sysinfo __user *info) ...@@ -1241,8 +1241,7 @@ asmlinkage long sys_sysinfo(struct sysinfo __user *info)
* too. * too.
*/ */
do_gettimeofday((struct timeval *)&tp); getnstimeofday(&tp);
tp.tv_nsec *= NSEC_PER_USEC;
tp.tv_sec += wall_to_monotonic.tv_sec; tp.tv_sec += wall_to_monotonic.tv_sec;
tp.tv_nsec += wall_to_monotonic.tv_nsec; tp.tv_nsec += wall_to_monotonic.tv_nsec;
if (tp.tv_nsec - NSEC_PER_SEC >= 0) { if (tp.tv_nsec - NSEC_PER_SEC >= 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment