Skip to contentSkip to conversation

UML - Deal with host time going backwards

PATCH In review Jeff Dike 6 participants 18 messages Jun 3, 2008 – Jun 5, 2008 User-mode Linux (UML)

lore
Share & tools
lore

Jeff Dike

author
#0 lore raw

PATCH 1/6 UML - Deal with host time going backwards

Protection against the host's time going backwards - keep track of the time at the last tick and if it's greater than the current time, keep time stopped until the host catches up.

---
 arch/um/os-Linux/time.c |    7 +++++++
 1 file changed, 7 insertions(+)
arch/um/os-Linux/time.c +7 -0
Index: linux-2.6-git/arch/um/os-Linux/time.c
===================================================================
@@ -106,6 +106,10 @@ static void deliver_alarm(void)
 	unsigned long long this_tick = os_nsecs();
 	int one_tick = UM_NSEC_PER_SEC / UM_HZ;
 
+	/* Protection against the host's time going backwards */
+	if ((last_tick != 0) && (this_tick < last_tick))
+		this_tick = last_tick;
+
 	if (last_tick == 0)
 		last_tick = this_tick - one_tick;
 
@@ -148,6 +152,9 @@ static int after_sleep_interval(struct t
 		start_usecs = usec;
 
 	start_usecs -= skew / UM_NSEC_PER_USEC;
+	if (start_usecs < 0)
+		start_usecs = 0;
+
 	tv = ((struct timeval) { .tv_sec  = start_usecs / UM_USEC_PER_SEC,
 				 .tv_usec = start_usecs % UM_USEC_PER_SEC });
 	interval = ((struct itimerval) { { 0, usec }, tv });

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
User-mode-linux-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel

#1 lore raw
Quoted 3 lines · On Tue, 3 Jun 2008 15:02:35 -0400 Jeff Dike <[email protected]> wrote:

Protection against the host's time going backwards - keep track of the time at the last tick and if it's greater than the current time, keep time stopped until the host catches up.

Strange. What would cause the host's time (or at least UML's perception of it) to go backwards?

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
User-mode-linux-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel

#2 lore raw
Quoted 9 lines · Andrew Morton

On Tue, 3 Jun 2008 15:02:35 -0400

Quoted 3 lines · Jeff Dike

Protection against the host's time going backwards - keep track of the time at the last tick and if it's greater than the current time, keep time stopped until the host catches up.

Strange. What would cause the host's time (or at least UML's perception of it) to go backwards?

A wild guess would be that the UML process is running "fast" at some point and its expectation of the host's time is skewed forward because of that.

Another possibility is that the hosts clock got reset between the times UML has checked it and the correction was a negative one.

DRH

Signature · 1 line
Dialup is like pissing through a pipette. Slow and excruciatingly painful.
#3 lore raw
Quoted 8 lines · Daniel Hazelton
Quoted 7 lines · Andrew Morton

On Tue, 3 Jun 2008 15:02:35 -0400

Quoted 3 lines · Jeff Dike

Protection against the host's time going backwards - keep track of the time at the last tick and if it's greater than the current time, keep time stopped until the host catches up.

Quoted 5 lines
Quoted 2 lines

Strange. What would cause the host's time (or at least UML's perception of it) to go backwards?

A wild guess would be that the UML process is running "fast" at some point and its expectation of the host's time is skewed forward because of that.

Quite so. Simply running ntp on the host (in slew-only mode, no less!) can cause this.

Quoted 2 lines

Another possibility is that the hosts clock got reset between the times UML has checked it and the correction was a negative one.

That too.

Signature · 3 lines
`If you are having a "ua luea luea le ua le" kind of day, I can only
 assume that you are doing no work due [to] incapacitating nausea caused 
 by numerous lazy demons.' --- Frossie
#4 lore raw
Quoted 16 lines · On Tue, 03 Jun 2008 20:52:18 +0100 Nix <[email protected]> wrote:
Quoted 8 lines · Daniel Hazelton
Quoted 7 lines · Andrew Morton

On Tue, 3 Jun 2008 15:02:35 -0400

Quoted 3 lines · Jeff Dike

Protection against the host's time going backwards - keep track of the time at the last tick and if it's greater than the current time, keep time stopped until the host catches up.

Quoted 5 lines
Quoted 2 lines

Strange. What would cause the host's time (or at least UML's perception of it) to go backwards?

A wild guess would be that the UML process is running "fast" at some point and its expectation of the host's time is skewed forward because of that.

Quoted 8 lines

Quite so. Simply running ntp on the host (in slew-only mode, no less!) can cause this.

Quoted 2 lines

Another possibility is that the hosts clock got reset between the times UML has checked it and the correction was a negative one.

That too.

So if I change the host's time by an hour, the time will not advance at all on the guest for the next hour? Sounds suboptimal :)

I suppose the guest should be running an ntp client synced to something sane anyway?

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
User-mode-linux-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel

#5 lore raw
Quoted 22 lines · Andrew Morton

On Tue, 03 Jun 2008 20:52:18 +0100

Quoted 19 lines · Nix
Quoted 8 lines · Daniel Hazelton
Quoted 7 lines · Andrew Morton

On Tue, 3 Jun 2008 15:02:35 -0400

Quoted 3 lines · Jeff Dike

Protection against the host's time going backwards - keep track of the time at the last tick and if it's greater than the current time, keep time stopped until the host catches up.

Quoted 6 lines
Quoted 2 lines

Strange. What would cause the host's time (or at least UML's perception of it) to go backwards?

A wild guess would be that the UML process is running "fast" at some point and its expectation of the host's time is skewed forward because of that.

Quite so. Simply running ntp on the host (in slew-only mode, no less!) can cause this.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

Another possibility is that the hosts clock got reset between the times UML has checked it and the correction was a negative one.

That too.

So if I change the host's time by an hour, the time will not advance at all on the guest for the next hour? Sounds suboptimal :)

I agree. But like I said originally - it's a wild guess. I don't even know how accurate it is.

Quoted 2 lines

I suppose the guest should be running an ntp client synced to something sane anyway?

That might be helpful :)

DRH

Signature · 11 lines
Dialup is like pissing through a pipette. Slow and excruciatingly painful.

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
User-mode-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
author
#6 lore raw
In reply to Andrew Morton
Quoted 2 lines · Andrew Morton

So if I change the host's time by an hour, the time will not advance at all on the guest for the next hour? Sounds suboptimal :)

It is, but if the host is whacked, the guest just has to do the best that it can...

Jeff

Signature · 1 line
Work email - jdike at linux dot intel dot com
#7 lore raw
Quoted 6 lines · Jeff Dike
Quoted 2 lines · Andrew Morton

So if I change the host's time by an hour, the time will not advance at all on the guest for the next hour? Sounds suboptimal :)

It is, but if the host is whacked, the guest just has to do the best that it can...

Could using a CLOCK_MONOTONIC time source fix this? Those timers do not change when we change the time on the host.

Eric

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
User-mode-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel

author
#8 lore raw
Quoted 2 lines · Eric W. Biederman

Could using a CLOCK_MONOTONIC time source fix this? Those timers do not change when we change the time on the host.

Hmmm, maybe. The man page looks promising...

Jeff

Signature · 11 lines
Work email - jdike at linux dot intel dot com

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
User-mode-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
#9 lore raw
In reply to Eric W. Biederman
Quoted 5 lines · Eric W. Biederman
Quoted 4 lines · Jeff Dike
Quoted 2 lines · Andrew Morton

So if I change the host's time by an hour, the time will not advance at all on the guest for the next hour? Sounds suboptimal :)

Quoted 7 lines
Quoted 2 lines

It is, but if the host is whacked, the guest just has to do the best that it can...

Could using a CLOCK_MONOTONIC time source fix this? Those timers do not change when we change the time on the host.

Eric

I'm not all that familiar with the specifics of the code - my original statements about possible causes were barely more than wild guesses - but this does sound like it would work.

DRH

Signature · 11 lines
Dialup is like pissing through a pipette. Slow and excruciatingly painful.

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
User-mode-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
#10 lore raw
In reply to Jeff Dike
Quoted 9 lines · Jeff Dike
Quoted 3 lines · Andrew Morton

So if I change the host's time by an hour, the time will not advance at all on the guest for the next hour? Sounds suboptimal :)

It is, but if the host is whacked, the guest just has to do the best that it can...

Shouldn't UML use a monotonic host clock for guest timekeeping?

J

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
User-mode-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel

author
#11 lore raw
Quoted 1 line · Jeremy Fitzhardinge

Shouldn't UML use a monotonic host clock for guest timekeeping?

Indeed, Eric pointed out the posix timers, which I had forgotten about. On the face of it, a monotonic timer should do the trick, but it's not obvious how to get it to behave like a monotonic gettimeofday...

Jeff

Signature · 11 lines
Work email - jdike at linux dot intel dot com

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
User-mode-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
#12 lore raw
Quoted 9 lines · Jeff Dike
Quoted 2 lines · Jeremy Fitzhardinge

Shouldn't UML use a monotonic host clock for guest timekeeping?

Indeed, Eric pointed out the posix timers, which I had forgotten about. On the face of it, a monotonic timer should do the trick, but it's not obvious how to get it to behave like a monotonic gettimeofday...

You can either read the monotonic clock directly, or use it as a time source for a monotonic timer. clock_gettime(CLOCK_MONOTONIC, &ts) will return the time in ns, and you can just feed that directly into the guest as a clocksource.

J

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
User-mode-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel

author
#13 lore raw
Quoted 4 lines · Jeremy Fitzhardinge

You can either read the monotonic clock directly, or use it as a time source for a monotonic timer. clock_gettime(CLOCK_MONOTONIC, &ts) will return the time in ns, and you can just feed that directly into the guest as a clocksource.

Aha, I was looking at timer_* and not getting reasonable-looking results. The one questionable aspect of this is that I need to pull in a new library (librt) and I wonder how many people don't have it installed...

Anyway, the patch below seems to make the guest behave reasonably in the face of the host time doing funky things...

Give it a spin and let me know how it does. If there aren't any problems, I'll get it into mainline.

Jeff

Signature · 150 lines
Work email - jdike at linux dot intel dot com

Index: linux-2.6.22/arch/um/os-Linux/time.c
===================================================================
--- linux-2.6.22.orig/arch/um/os-Linux/time.c	2008-06-02 15:38:34.000000000 -0400
+++ linux-2.6.22/arch/um/os-Linux/time.c	2008-06-04 19:49:16.000000000 -0400
@@ -56,6 +56,11 @@ static inline long long timeval_to_ns(co
 		tv->tv_usec * UM_NSEC_PER_USEC;
 }
 
+static inline long long timespec_to_ns(const struct timespec *ts)
+{
+	return ((long long) ts->tv_sec * UM_NSEC_PER_SEC) + ts->tv_nsec;
+}
+
 long long disable_timer(void)
 {
 	struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } });
@@ -72,12 +77,22 @@ long long disable_timer(void)
 	return remain;
 }
 
-long long os_nsecs(void)
+static inline long long nsecs(int clock)
 {
-	struct timeval tv;
+	struct timespec ts;
+
+	clock_gettime(clock, &ts);
+	return timespec_to_ns(&ts);
+}
+
+long long os_wall_nsecs(void)
+{
+	return nsecs(CLOCK_REALTIME);
+}
 
-	gettimeofday(&tv, NULL);
-	return timeval_to_ns(&tv);
+long long os_mono_nsecs(void)
+{
+	return nsecs(CLOCK_MONOTONIC);
 }
 
 extern void alarm_handler(int sig, struct sigcontext *sc);
@@ -104,13 +119,9 @@ unsigned long long skew;
 
 static void deliver_alarm(void)
 {
-	unsigned long long this_tick = os_nsecs();
+	unsigned long long this_tick = os_mono_nsecs();
 	int one_tick = UM_NSEC_PER_SEC / UM_HZ;
 
-	/* Protection against the host's time going backwards */
-	if ((last_tick != 0) && (this_tick < last_tick))
-		this_tick = last_tick;
-
 	if (last_tick == 0)
 		last_tick = this_tick - one_tick;
 
Index: linux-2.6.22/arch/um/Makefile
===================================================================
--- linux-2.6.22.orig/arch/um/Makefile	2008-05-29 11:21:25.000000000 -0400
+++ linux-2.6.22/arch/um/Makefile	2008-06-04 19:42:09.000000000 -0400
@@ -126,7 +126,7 @@ define cmd_vmlinux__
 	$(CC) $(CFLAGS_vmlinux) -o $@ \
 	-Wl,-T,$(vmlinux-lds) $(vmlinux-init) \
 	-Wl,--start-group $(vmlinux-main) -Wl,--end-group \
-	-lutil \
+	-lutil -lrt \
 	$(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o \
 	FORCE ,$^) ; rm -f linux
 endef
Index: linux-2.6.22/arch/um/include/os.h
===================================================================
--- linux-2.6.22.orig/arch/um/include/os.h	2008-06-02 15:38:34.000000000 -0400
+++ linux-2.6.22/arch/um/include/os.h	2008-06-04 19:51:55.000000000 -0400
@@ -244,7 +244,8 @@ extern int set_interval(void);
 extern int timer_one_shot(int ticks);
 extern long long disable_timer(void);
 extern void uml_idle_timer(void);
-extern long long os_nsecs(void);
+extern long long os_wall_nsecs(void);
+extern long long os_mono_nsecs(void);
 
 /* skas/mem.c */
 extern long run_syscall_stub(struct mm_id * mm_idp,
Index: linux-2.6.22/arch/um/kernel/time.c
===================================================================
--- linux-2.6.22.orig/arch/um/kernel/time.c	2008-06-02 15:38:33.000000000 -0400
+++ linux-2.6.22/arch/um/kernel/time.c	2008-06-04 19:51:59.000000000 -0400
@@ -74,7 +74,7 @@ static irqreturn_t um_timer(int irq, voi
 
 static cycle_t itimer_read(void)
 {
-	return os_nsecs() / 1000;
+	return os_mono_nsecs() / 1000;
 }
 
 static struct clocksource itimer_clocksource = {
@@ -117,7 +117,7 @@ void __init time_init(void)
 
 	timer_init();
 
-	nsecs = os_nsecs();
+	nsecs = os_wall_nsecs();
 	set_normalized_timespec(&wall_to_monotonic, -nsecs / NSEC_PER_SEC,
 				-nsecs % NSEC_PER_SEC);
 	set_normalized_timespec(&xtime, nsecs / NSEC_PER_SEC,
Index: linux-2.6.22/arch/um/os-Linux/skas/process.c
===================================================================
--- linux-2.6.22.orig/arch/um/os-Linux/skas/process.c	2008-06-04 19:51:05.000000000 -0400
+++ linux-2.6.22/arch/um/os-Linux/skas/process.c	2008-06-04 19:51:59.000000000 -0400
@@ -359,7 +359,7 @@ void userspace(struct uml_pt_regs *regs)
 		printk(UM_KERN_ERR "Failed to get itimer, errno = %d\n", errno);
 	nsecs = timer.it_value.tv_sec * UM_NSEC_PER_SEC +
 		timer.it_value.tv_usec * UM_NSEC_PER_USEC;
-	nsecs += os_nsecs();
+	nsecs += os_mono_nsecs();
 
 	while (1) {
 		/*
@@ -420,7 +420,7 @@ void userspace(struct uml_pt_regs *regs)
 				relay_signal(SIGTRAP, regs);
 				break;
 			case SIGVTALRM:
-				now = os_nsecs();
+				now = os_mono_nsecs();
 				if (now < nsecs)
 					break;
 				block_signals();
@@ -430,7 +430,7 @@ void userspace(struct uml_pt_regs *regs)
 					UM_NSEC_PER_SEC +
 					timer.it_value.tv_usec *
 					UM_NSEC_PER_USEC;
-				nsecs += os_nsecs();
+				nsecs += os_mono_nsecs();
 				break;
 			case SIGIO:
 			case SIGILL:

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
User-mode-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
#14 lore raw

On 5 Jun 2008, Jeff Dike verbalised:

Quoted 4 lines

Aha, I was looking at timer_* and not getting reasonable-looking results. The one questionable aspect of this is that I need to pull in a new library (librt) and I wonder how many people don't have it installed...

It comes with glibc, and even ls uses it (for clock_gettime(), to determine what format to use for date display).

I'd say using it is about as safe as can be.

Quoted 5 lines

Anyway, the patch below seems to make the guest behave reasonably in the face of the host time doing funky things...

Give it a spin and let me know how it does. If there aren't any problems, I'll get it into mainline.

Rebuilding for a test now.

Signature · 13 lines
`If you are having a "ua luea luea le ua le" kind of day, I can only
 assume that you are doing no work due [to] incapacitating nausea caused 
 by numerous lazy demons.' --- Frossie

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
User-mode-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
author
#15 lore raw
Quoted 4 lines · Nix

It comes with glibc, and even ls uses it (for clock_gettime(), to determine what format to use for date display).

I'd say using it is about as safe as can be.

Without adding -lrt to the link line here (F7), I get

arch/um/os-Linux/built-in.o: In function `nsecs':
/home/jdike/linux/2.6/linux-2.6.22/arch/um/os-Linux/time.c:84: undefined reference to `clock_gettime'
collect2: ld returned 1 exit status

A little odd for a system call...

Quoted 2 lines

Does this really only apply on top of 2.6.22? Which of the bewildering blizzard of time-fixup patches we've been exchanging do I need? :)

I have it on top of 2.6.26-rc2-mm1, plus all the other patches I've sent to Andrew. The patch which started this discussion is the one you really need though, since this backs it out.

Jeff

Signature · 11 lines
Work email - jdike at linux dot intel dot com

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
User-mode-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
#16 lore raw

On 5 Jun 2008, Jeff Dike uttered the following:

Quoted 7 lines · Nix
Quoted 4 lines

It comes with glibc, and even ls uses it (for clock_gettime(), to determine what format to use for date display).

I'd say using it is about as safe as can be.

Without adding -lrt to the link line here (F7), I get

Yes, you'll definitely *need* -lrt for clock_*().

Quoted 5 lines

arch/um/os-Linux/built-in.o: In function `nsecs':
/home/jdike/linux/2.6/linux-2.6.22/arch/um/os-Linux/time.c:84: undefined reference to `clock_gettime'
collect2: ld returned 1 exit status

A little odd for a system call...

I think it's in there because it's part of the POSIX realtime extensions, so you should have to, as it were, assent to using something that's not as portable as just using libc. It makes more sense than libm, anyway.

(It's completely moot for UML of course :) )

Signature · 13 lines
`If you are having a "ua luea luea le ua le" kind of day, I can only
 assume that you are doing no work due [to] incapacitating nausea caused 
 by numerous lazy demons.' --- Frossie

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
User-mode-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
#17 lore raw
In reply to Jeff Dike

On 5 Jun 2008, Jeff Dike uttered the following:

Quoted 1 line

Index: linux-2.6.22/arch/um/os-Linux/time.c

Does this really only apply on top of 2.6.22? Which of the bewildering blizzard of time-fixup patches we've been exchanging do I need? :)

Signature · 13 lines
`If you are having a "ua luea luea le ua le" kind of day, I can only
 assume that you are doing no work due [to] incapacitating nausea caused 
 by numerous lazy demons.' --- Frossie

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
User-mode-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel