Commit d4f558bc authored by Jeff Dike's avatar Jeff Dike Committed by Linus Torvalds

[PATCH] uml: convert the real-time clock to gettimeofday from rdtsc

There are a whole bunch of reasons to use gettimeofday rather than rdtsc,
so this patch does just that.
Signed-off-by: default avatarJeff Dike <jdike@addtoit.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 58b08935
...@@ -166,6 +166,7 @@ extern int os_protect_memory(void *addr, unsigned long len, ...@@ -166,6 +166,7 @@ extern int os_protect_memory(void *addr, unsigned long len,
int r, int w, int x); int r, int w, int x);
extern int os_unmap_memory(void *addr, int len); extern int os_unmap_memory(void *addr, int len);
extern void os_flush_stdout(void); extern void os_flush_stdout(void);
extern unsigned long long os_usecs(void);
#endif #endif
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include <sys/time.h> #include <sys/time.h>
#include <signal.h> #include <signal.h>
#include <errno.h> #include <errno.h>
#include <string.h>
#include "user_util.h" #include "user_util.h"
#include "kern_util.h" #include "kern_util.h"
#include "user.h" #include "user.h"
...@@ -95,49 +94,12 @@ void uml_idle_timer(void) ...@@ -95,49 +94,12 @@ void uml_idle_timer(void)
set_interval(ITIMER_REAL); set_interval(ITIMER_REAL);
} }
static unsigned long long get_host_hz(void)
{
char mhzline[16], *end;
unsigned long long mhz;
int ret, mult, rest, len;
ret = cpu_feature("cpu MHz", mhzline,
sizeof(mhzline) / sizeof(mhzline[0]));
if(!ret)
panic ("Could not get host MHZ");
mhz = strtoul(mhzline, &end, 10);
/* This business is to parse a floating point number without using
* floating types.
*/
rest = 0;
mult = 0;
if(*end == '.'){
end++;
len = strlen(end);
if(len < 6)
mult = 6 - len;
else if(len > 6)
end[6] = '\0';
rest = strtoul(end, NULL, 10);
while(mult-- > 0)
rest *= 10;
}
return(1000000 * mhz + rest);
}
unsigned long long host_hz = 0;
extern int do_posix_clock_monotonic_gettime(struct timespec *tp); extern int do_posix_clock_monotonic_gettime(struct timespec *tp);
void time_init(void) void time_init(void)
{ {
struct timespec now; struct timespec now;
host_hz = get_host_hz();
if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR) if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR)
panic("Couldn't set SIGVTALRM handler"); panic("Couldn't set SIGVTALRM handler");
set_interval(ITIMER_VIRTUAL); set_interval(ITIMER_VIRTUAL);
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "user_util.h" #include "user_util.h"
#include "time_user.h" #include "time_user.h"
#include "mode.h" #include "mode.h"
#include "os.h"
u64 jiffies_64; u64 jiffies_64;
...@@ -42,12 +43,10 @@ unsigned long long sched_clock(void) ...@@ -42,12 +43,10 @@ unsigned long long sched_clock(void)
int timer_irq_inited = 0; int timer_irq_inited = 0;
static int first_tick; static int first_tick;
static unsigned long long prev_tsc; static unsigned long long prev_usecs;
#ifdef CONFIG_UML_REAL_TIME_CLOCK
static long long delta; /* Deviation per interval */ static long long delta; /* Deviation per interval */
#endif
extern unsigned long long host_hz; #define MILLION 1000000
void timer_irq(union uml_pt_regs *regs) void timer_irq(union uml_pt_regs *regs)
{ {
...@@ -61,22 +60,25 @@ void timer_irq(union uml_pt_regs *regs) ...@@ -61,22 +60,25 @@ void timer_irq(union uml_pt_regs *regs)
} }
if(first_tick){ if(first_tick){
#ifdef CONFIG_UML_REAL_TIME_CLOCK #if defined(CONFIG_UML_REAL_TIME_CLOCK)
unsigned long long tsc;
/* We've had 1 tick */ /* We've had 1 tick */
tsc = time_stamp(); unsigned long long usecs = os_usecs();
delta += usecs - prev_usecs;
prev_usecs = usecs;
delta += tsc - prev_tsc; /* Protect against the host clock being set backwards */
prev_tsc = tsc; if(delta < 0)
delta = 0;
ticks += (delta * HZ) / host_hz; ticks += (delta * HZ) / MILLION;
delta -= (ticks * host_hz) / HZ; delta -= (ticks * MILLION) / HZ;
#else #else
ticks = 1; ticks = 1;
#endif #endif
} }
else { else {
prev_tsc = time_stamp(); prev_usecs = os_usecs();
first_tick = 1; first_tick = 1;
} }
...@@ -151,7 +153,7 @@ void __udelay(um_udelay_t usecs) ...@@ -151,7 +153,7 @@ void __udelay(um_udelay_t usecs)
{ {
int i, n; int i, n;
n = (loops_per_jiffy * HZ * usecs) / 1000000; n = (loops_per_jiffy * HZ * usecs) / MILLION;
for(i=0;i<n;i++) ; for(i=0;i<n;i++) ;
} }
...@@ -159,7 +161,7 @@ void __const_udelay(um_udelay_t usecs) ...@@ -159,7 +161,7 @@ void __const_udelay(um_udelay_t usecs)
{ {
int i, n; int i, n;
n = (loops_per_jiffy * HZ * usecs) / 1000000; n = (loops_per_jiffy * HZ * usecs) / MILLION;
for(i=0;i<n;i++) ; for(i=0;i<n;i++) ;
} }
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
# Licensed under the GPL # Licensed under the GPL
# #
obj-y = file.o process.o tty.o user_syms.o drivers/ obj-y = file.o process.o time.o tty.o user_syms.o drivers/
USER_OBJS := $(foreach file,file.o process.o tty.o,$(obj)/$(file)) USER_OBJS := $(foreach file,file.o process.o time.o tty.o,$(obj)/$(file))
$(USER_OBJS) : %.o: %.c $(USER_OBJS) : %.o: %.c
$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
/* #include <stdlib.h>
* sys-i386/time.c #include <sys/time.h>
* Created 25.9.2002 Sapan Bhatia
*
*/
unsigned long long time_stamp(void) unsigned long long os_usecs(void)
{ {
unsigned long low, high; struct timeval tv;
asm("rdtsc" : "=a" (low), "=d" (high)); gettimeofday(&tv, NULL);
return((((unsigned long long) high) << 32) + low); return((unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec);
} }
/* /*
......
obj-y = bitops.o bugs.o checksum.o fault.o ksyms.o ldt.o ptrace.o \ obj-y = bitops.o bugs.o checksum.o fault.o ksyms.o ldt.o ptrace.o \
ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o time.o ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o
obj-$(CONFIG_HIGHMEM) += highmem.o obj-$(CONFIG_HIGHMEM) += highmem.o
obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_MODULES) += module.o
......
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