LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [2.6.24.x] UML select()/poll() oversleeping reproducibly (was Re: [uml-devel] g_timeout_add)
       [not found]         ` <20080215184650.GA8810@c2.user-mode-linux.org>
@ 2008-03-14 23:01           ` Nix
  2008-03-17 16:27             ` Jeff Dike
                               ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Nix @ 2008-03-14 23:01 UTC (permalink / raw)
  To: Jeff Dike
  Cc: clowncoder, user-mode-linux-devel, linux-kernel Mailing List,
	Thomas Gleixner

On 15 Feb 2008, Jeff Dike told this:
> The smoking gun - a poll that should have timed out in .5 sec slept
> for 12.

FWIW this breaks all sorts of things, as one might expect: obviously it
breaks select() as well as poll(). For me the symptoms were a failure of
DHCP and spontaneous dropping off the net because lease renewal wasn't
happening in time (with 2.6.24.3, not with 2.6.24.2 that I can see).

The precise degree of oversleeping seems to depend on the clocksource in
use on the host (all hosts here are lightly loaded, running on 2.6.24.2
throughout these tests: select() does not wait for way too long
here). On a 1.4GHz Athlon IV using the tsc clocksource, I see consistent
oversleeps, but not enormous ones:

bash-3.2# ./select-sleep 1
Slept for 1 seconds.
bash-3.2# ./select-sleep 5
Slept for 7 seconds.
bash-3.2# ./select-sleep 5
Slept for 7 seconds.
bash-3.2# ./select-sleep 10
Slept for 13 seconds.
bash-3.2# ./select-sleep 30
Slept for 39 seconds.
bash-3.2# ./select-sleep 30
Slept for 39 seconds.
bash-3.2# ./select-sleep 60
Slept for 78 seconds.

On a 900MHz PIII using the pit clocksource (ick, why the hell isn't it
using tsc? oh, tsc unstable, how helpful) I see huge discrepancies,
still consistent, and interestingly all exactly four times as long as we
asked to sleep:

bash-3.2# ./select-sleep 1
Slept for 4 seconds.
bash-3.2# ./select-sleep 5
Slept for 20 seconds.
bash-3.2# ./select-sleep 5
Slept for 20 seconds.
bash-3.2# ./select-sleep 30
Slept for 120 seconds.
bash-3.2# ./select-sleep 30
Slept for 120 seconds.
bash-3.2# ./select-sleep 60
Slept for 240 seconds.


I'll do the -ttt UML tracing you requested next.


I'm testing using a little filesystem image containing a shell, glibc, and
this trivial obvious five-minute hack:

#define _POSIX_C_SOURCE 200112L

#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
#include <sys/time.h>

int main (int argc, char *argv[])
 {
  long interval;
  struct timeval now;
  struct timeval timeout;
  struct timeval then;
  char *converr;
  fd_set foo;

  if (argc != 2)
   {
    fprintf (stderr, "Syntax: select-sleep INTERVAL\n");
    return 1;
   }

  interval = strtol (argv[1], &converr, 10);

  if (*converr != '\0')
   {
    fprintf (stderr, "Cannot convert %s to an integer\n", argv[1]);
    return 2;
   }

  gettimeofday (&then, NULL);
  timeout.tv_sec = interval;
  timeout.tv_usec = 0;

  FD_ZERO(&foo);
  select (0, NULL, NULL, NULL, &timeout);

  /* Watch me not care about not EINTR, I'm interested in *overlong* sleeps */

  gettimeofday (&now, NULL);

  fprintf (stderr, "Slept for %li seconds.\n", now.tv_sec - then.tv_sec);

  return 0;
 }

The UML's .config:

CONFIG_DEFCONFIG_LIST="arch/$ARCH/defconfig"
CONFIG_GENERIC_HARDIRQS=y
CONFIG_UML=y
CONFIG_MMU=y
CONFIG_NO_IOMEM=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_IRQ_RELEASE_METHOD=y
CONFIG_MPENTIUMIII=y
CONFIG_X86_CMPXCHG=y
CONFIG_X86_L1_CACHE_SHIFT=5
CONFIG_X86_XADD=y
CONFIG_X86_WP_WORKS_OK=y
CONFIG_X86_INVLPG=y
CONFIG_X86_BSWAP=y
CONFIG_X86_POPAD_OK=y
CONFIG_X86_GOOD_APIC=y
CONFIG_X86_INTEL_USERCOPY=y
CONFIG_X86_USE_PPRO_CHECKSUM=y
CONFIG_X86_TSC=y
CONFIG_X86_CMOV=y
CONFIG_X86_MINIMUM_CPU_FAMILY=4
CONFIG_UML_X86=y
CONFIG_X86_32=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_HOST_VMSPLIT_3G=y
CONFIG_TOP_ADDR=0xC0000000
CONFIG_ARCH_HAS_SC_SIGNALS=y
CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_ZONE_DMA_FLAG=0
CONFIG_VIRT_TO_BUS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_LD_SCRIPT_DYN=y
CONFIG_NET=y
CONFIG_BINFMT_ELF=y
CONFIG_MCONSOLE=y
CONFIG_NEST_LEVEL=0
CONFIG_KERNEL_STACK_ORDER=2
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=128
CONFIG_LOCALVERSION=""
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_FAIR_USER_SCHED=y
CONFIG_RELAY=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_BASE_SMALL=0
CONFIG_BLOCK=y
CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_DEFAULT_DEADLINE=y
CONFIG_DEFAULT_IOSCHED="deadline"
CONFIG_BLK_DEV=y
CONFIG_BLK_DEV_UBD=y
CONFIG_BLK_DEV_COW_COMMON=y
CONFIG_STDERR_CONSOLE=y
CONFIG_STDIO_CONSOLE=y
CONFIG_SSL=y
CONFIG_NULL_CHAN=y
CONFIG_PORT_CHAN=y
CONFIG_PTY_CHAN=y
CONFIG_TTY_CHAN=y
CONFIG_XTERM_CHAN=y
CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
CONFIG_CON_CHAN="tty"
CONFIG_SSL_CHAN="pty"
CONFIG_UNIX98_PTYS=y
CONFIG_UML_RANDOM=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_ASK_IP_FIB_HASH=y
CONFIG_IP_FIB_HASH=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_SYN_COOKIES=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
CONFIG_TCP_CONG_ADVANCED=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK_ENABLED=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CT_ACCT=y
CONFIG_NF_CONNTRACK_MARK=y
CONFIG_NF_CT_PROTO_UDPLITE=y
CONFIG_NF_CONNTRACK_FTP=y
CONFIG_NF_CONNTRACK_IRC=y
CONFIG_NF_CONNTRACK_SIP=y
CONFIG_NETFILTER_XTABLES=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
CONFIG_NETFILTER_XT_MATCH_HELPER=y
CONFIG_NETFILTER_XT_MATCH_LIMIT=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
CONFIG_NF_CONNTRACK_IPV4=y
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_MATCH_IPRANGE=y
CONFIG_IP_NF_MATCH_TOS=y
CONFIG_IP_NF_MATCH_RECENT=y
CONFIG_IP_NF_MATCH_OWNER=y
CONFIG_IP_NF_MATCH_ADDRTYPE=y
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_TARGET_REJECT=y
CONFIG_IP_NF_TARGET_LOG=y
CONFIG_NF_NAT=y
CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_NF_NAT_FTP=y
CONFIG_NF_NAT_IRC=y
CONFIG_NF_NAT_SIP=y
CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_TARGET_TOS=y
CONFIG_IP_NF_TARGET_ECN=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CBQ=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_HFSC=y
CONFIG_NET_SCH_PRIO=y
CONFIG_NET_SCH_RED=y
CONFIG_NET_SCH_SFQ=y
CONFIG_NET_SCH_TEQL=y
CONFIG_NET_SCH_TBF=y
CONFIG_NET_SCH_GRED=y
CONFIG_NET_SCH_DSMARK=y
CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS=y
CONFIG_NET_CLS_BASIC=y
CONFIG_NET_CLS_TCINDEX=y
CONFIG_NET_CLS_ROUTE4=y
CONFIG_NET_CLS_ROUTE=y
CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
CONFIG_CLS_U32_PERF=y
CONFIG_CLS_U32_MARK=y
CONFIG_NET_CLS_RSVP=y
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_STACK=32
CONFIG_NET_EMATCH_CMP=y
CONFIG_NET_EMATCH_NBYTE=y
CONFIG_NET_EMATCH_U32=y
CONFIG_NET_EMATCH_META=y
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=y
CONFIG_NET_ACT_GACT=y
CONFIG_NET_ACT_PEDIT=y
CONFIG_NET_SCH_FIFO=y
CONFIG_FIB_RULES=y
CONFIG_UML_NET=y
CONFIG_UML_NET_TUNTAP=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_TUN=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT2_FS_SECURITY=y
CONFIG_FS_MBCACHE=y
CONFIG_FS_POSIX_ACL=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
CONFIG_PRINT_QUOTA_WARNING=y
CONFIG_QUOTACTL=y
CONFIG_DNOTIFY=y
CONFIG_GENERIC_ACL=y
CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_CONFIGFS_FS=y
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_NFS_V3_ACL=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_ACL_SUPPORT=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_MSDOS_PARTITION=y
CONFIG_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITY_CAPABILITIES=y
CONFIG_SECURITY_FILE_CAPABILITIES=y
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_SHA1=y
CONFIG_BITREVERSE=y
CONFIG_CRC32=y
CONFIG_PLIST=y
CONFIG_HAS_DMA=y
CONFIG_INSTRUMENTATION=y
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_BUGVERBOSE=y

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [2.6.24.x] UML select()/poll() oversleeping reproducibly (was Re: [uml-devel] g_timeout_add)
  2008-03-14 23:01           ` [2.6.24.x] UML select()/poll() oversleeping reproducibly (was Re: [uml-devel] g_timeout_add) Nix
@ 2008-03-17 16:27             ` Jeff Dike
  2008-03-17 17:03             ` Jeff Dike
  2008-03-17 19:34             ` Jeff Dike
  2 siblings, 0 replies; 8+ messages in thread
From: Jeff Dike @ 2008-03-17 16:27 UTC (permalink / raw)
  To: Nix
  Cc: clowncoder, user-mode-linux-devel, linux-kernel Mailing List,
	Thomas Gleixner

On Fri, Mar 14, 2008 at 11:01:35PM +0000, Nix wrote:
> On a 1.4GHz Athlon IV using the tsc clocksource, I see consistent
> oversleeps, but not enormous ones:

> bash-3.2# ./select-sleep 10
> Slept for 13 seconds.

I'm seeing the same thing with tickless disabled on current UML - stay
tuned...

				Jeff

-- 
Work email - jdike at linux dot intel dot com

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [2.6.24.x] UML select()/poll() oversleeping reproducibly (was Re: [uml-devel] g_timeout_add)
  2008-03-14 23:01           ` [2.6.24.x] UML select()/poll() oversleeping reproducibly (was Re: [uml-devel] g_timeout_add) Nix
  2008-03-17 16:27             ` Jeff Dike
@ 2008-03-17 17:03             ` Jeff Dike
  2008-03-17 19:34             ` Jeff Dike
  2 siblings, 0 replies; 8+ messages in thread
From: Jeff Dike @ 2008-03-17 17:03 UTC (permalink / raw)
  To: Nix
  Cc: clowncoder, user-mode-linux-devel, linux-kernel Mailing List,
	Thomas Gleixner

On Fri, Mar 14, 2008 at 11:01:35PM +0000, Nix wrote:
> bash-3.2# ./select-sleep 10
> Slept for 13 seconds.

See what kind of difference the patch below makes - it reduces the 30%
oversleeping down to 10% for me.  That's still way too much, but it's
better.

The problem being fixed here is that setitimer consistently returns a
remaining time greater than what was originally requested, by ~20%:

1205773032.413780 setitimer(ITIMER_VIRTUAL, {it_interval={0, 10000}, it_value={0, 10000}}, NULL) = 0
1205773032.413814 setitimer(ITIMER_VIRTUAL, {it_interval={0, 0},
it_value={0, 0}}, {it_interval={0, 10998}, it_value={0, 11998}}) = 0

This is setting a 100 HZ timer, immediately followed by a cancellation
which also requests the amount left on the timer.  The interval is
rounded up by 10%, and the first tick by 20%.

	       	       	    Jeff

-- 
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-02-18 11:53:51.000000000 -0500
+++ linux-2.6.22/arch/um/os-Linux/time.c	2008-03-17 12:55:41.000000000 -0400
@@ -58,12 +58,17 @@ static inline long long timeval_to_ns(co
 long long disable_timer(void)
 {
 	struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } });
+	int remain, max = UM_NSEC_PER_SEC / UM_HZ;
 
 	if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0)
 		printk(UM_KERN_ERR "disable_timer - setitimer failed, "
 		       "errno = %d\n", errno);
 
-	return timeval_to_ns(&time.it_value);
+	remain = timeval_to_ns(&time.it_value);
+	if (remain > max)
+		remain = max;
+
+	return remain;
 }
 
 long long os_nsecs(void)

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [2.6.24.x] UML select()/poll() oversleeping reproducibly (was Re: [uml-devel] g_timeout_add)
  2008-03-14 23:01           ` [2.6.24.x] UML select()/poll() oversleeping reproducibly (was Re: [uml-devel] g_timeout_add) Nix
  2008-03-17 16:27             ` Jeff Dike
  2008-03-17 17:03             ` Jeff Dike
@ 2008-03-17 19:34             ` Jeff Dike
  2008-03-17 21:08               ` [2.6.24.x] UML select()/poll() oversleeping reproducibly Nix
  2 siblings, 1 reply; 8+ messages in thread
From: Jeff Dike @ 2008-03-17 19:34 UTC (permalink / raw)
  To: Nix
  Cc: clowncoder, user-mode-linux-devel, linux-kernel Mailing List,
	Thomas Gleixner

Below is the same patch with another kluge, which cuts down the
requested sleep by 10% in hopes of getting the actual sleep closer to
what's wanted.

This is unusable in anything resembling mainline, but I'd like to see
how your various systems react to it.  I'm getting very close to the
sleeps I asked for (with slight undersleeping, which is a bug).

       	       	   Jeff

-- 
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-02-18 11:53:51.000000000 -0500
+++ linux-2.6.22/arch/um/os-Linux/time.c	2008-03-17 15:11:51.000000000 -0400
@@ -58,12 +58,17 @@ static inline long long timeval_to_ns(co
 long long disable_timer(void)
 {
 	struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } });
+	int remain, max = UM_NSEC_PER_SEC / UM_HZ;
 
 	if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0)
 		printk(UM_KERN_ERR "disable_timer - setitimer failed, "
 		       "errno = %d\n", errno);
 
-	return timeval_to_ns(&time.it_value);
+	remain = timeval_to_ns(&time.it_value);
+	if (remain > max)
+		remain = max;
+
+	return remain;
 }
 
 long long os_nsecs(void)
@@ -126,6 +131,8 @@ void idle_sleep(unsigned long long nsecs
 	 */
 	if (nsecs == 0)
 		nsecs = UM_NSEC_PER_SEC / UM_HZ;
+
+	nsecs = nsecs * 9 / 10;
 	ts = ((struct timespec) { .tv_sec	= nsecs / UM_NSEC_PER_SEC,
 				  .tv_nsec	= nsecs % UM_NSEC_PER_SEC });
 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [2.6.24.x] UML select()/poll() oversleeping reproducibly
  2008-03-17 19:34             ` Jeff Dike
@ 2008-03-17 21:08               ` Nix
  2008-03-18 17:00                 ` Jeff Dike
  0 siblings, 1 reply; 8+ messages in thread
From: Nix @ 2008-03-17 21:08 UTC (permalink / raw)
  To: Jeff Dike
  Cc: clowncoder, user-mode-linux-devel, linux-kernel Mailing List,
	Thomas Gleixner

On 17 Mar 2008, Jeff Dike verbalised:

> Below is the same patch with another kluge, which cuts down the
> requested sleep by 10% in hopes of getting the actual sleep closer to
> what's wanted.

Eeuuuuw. :)

> This is unusable in anything resembling mainline, but I'd like to see
> how your various systems react to it.  I'm getting very close to the
> sleeps I asked for (with slight undersleeping, which is a bug).

OK.

Tests on host with clocksource pit:

bash-3.2# bin/select-sleep 5
Slept for 5 seconds.
bash-3.2# bin/select-sleep 10
Slept for 11 seconds.
bash-3.2# bin/select-sleep 30
Slept for 31 seconds.
bash-3.2# bin/select-sleep 60
Slept for 61 seconds.

... so much better than the 4x error without this patch.

Tests on host with clocksource tsc:

bash-3.2# bin/select-sleep 5
Slept for 5 seconds.
bash-3.2# bin/select-sleep 10
Slept for 10 seconds.
bash-3.2# bin/select-sleep 30
Slept for 30 seconds.
bash-3.2# bin/select-sleep 60
Slept for 61 seconds.

Distinctly better than without this patch.

(Am I the only person who finds it strange that (some) clocksource
hackers are arguing about accuracy problems in the ppm range while we're
glad to get an error of `only' single seconds per minute out of it? 
Maybe next year we can invent the `pendulum' clocksource :) )

-- 
`The rest is a tale of post and counter-post.' --- Ian Rawlings
                                                   describes USENET

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [2.6.24.x] UML select()/poll() oversleeping reproducibly
  2008-03-17 21:08               ` [2.6.24.x] UML select()/poll() oversleeping reproducibly Nix
@ 2008-03-18 17:00                 ` Jeff Dike
  2008-03-18 19:39                   ` Nix
  2008-03-19 22:14                   ` Nix
  0 siblings, 2 replies; 8+ messages in thread
From: Jeff Dike @ 2008-03-18 17:00 UTC (permalink / raw)
  To: Nix
  Cc: clowncoder, user-mode-linux-devel, linux-kernel Mailing List,
	Thomas Gleixner

Below is another patch.

I was hurt and disappointed by your
> Eeuuuuw. :)
so I got rid of the 9/10 thing.

This version keeps track of the time between ticks (as reported by the
host's gettimeofday) and adjusts its sleeping and reporting ticks
accordingly.

It's still undersleeping a little - your little test once reported 19
seconds for a 20 second sleep.  Otherwise, it's reporting sleep times
that are right on the money.

				Jeff

-- 
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-03-18 12:32:19.000000000 -0400
+++ linux-2.6.22/arch/um/os-Linux/time.c	2008-03-18 12:45:50.000000000 -0400
@@ -11,6 +11,7 @@
 #include "kern_constants.h"
 #include "os.h"
 #include "user.h"
+#include "kern_util.h"
 
 int set_interval(void)
 {
@@ -58,12 +59,17 @@ static inline long long timeval_to_ns(co
 long long disable_timer(void)
 {
 	struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } });
+	int remain, max = UM_NSEC_PER_SEC / UM_HZ;
 
 	if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0)
 		printk(UM_KERN_ERR "disable_timer - setitimer failed, "
 		       "errno = %d\n", errno);
 
-	return timeval_to_ns(&time.it_value);
+	remain = timeval_to_ns(&time.it_value);
+	if (remain > max)
+		remain = max;
+
+	return remain;
 }
 
 long long os_nsecs(void)
@@ -79,7 +85,47 @@ static int after_sleep_interval(struct t
 {
 	return 0;
 }
+
+
+static void deliver_alarm(void)
+{
+	alarm_handler(SIGVTALRM, NULL);
+}
+
+static unsigned long long sleep_time(unsigned long long nsecs)
+{
+	return nsecs;
+}
+
 #else
+unsigned long long last_tick;
+unsigned long long skew;
+
+extern void alarm_handler(int sig, struct sigcontext *sc);
+
+static void deliver_alarm(void)
+{
+	unsigned long long this_tick = os_nsecs();
+	int one_tick = UM_NSEC_PER_SEC / UM_HZ;
+
+	if (last_tick == 0)
+		last_tick = this_tick - one_tick;
+
+	skew += this_tick - last_tick;
+
+	while (skew >= one_tick) {
+		alarm_handler(SIGVTALRM, NULL);
+		skew -= one_tick;
+	}
+
+	last_tick = this_tick;
+}
+
+static unsigned long long sleep_time(unsigned long long nsecs)
+{
+	return nsecs > skew ? nsecs - skew : 0;
+}
+
 static inline long long timespec_to_us(const struct timespec *ts)
 {
 	return ((long long) ts->tv_sec * UM_USEC_PER_SEC) +
@@ -102,6 +148,8 @@ static int after_sleep_interval(struct t
 	 */
 	if (start_usecs > usec)
 		start_usecs = usec;
+
+	start_usecs -= skew / UM_NSEC_PER_USEC;
 	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 });
@@ -113,8 +161,6 @@ static int after_sleep_interval(struct t
 }
 #endif
 
-extern void alarm_handler(int sig, struct sigcontext *sc);
-
 void idle_sleep(unsigned long long nsecs)
 {
 	struct timespec ts;
@@ -126,10 +172,12 @@ void idle_sleep(unsigned long long nsecs
 	 */
 	if (nsecs == 0)
 		nsecs = UM_NSEC_PER_SEC / UM_HZ;
+
+	nsecs = sleep_time(nsecs);
 	ts = ((struct timespec) { .tv_sec	= nsecs / UM_NSEC_PER_SEC,
 				  .tv_nsec	= nsecs % UM_NSEC_PER_SEC });
 
 	if (nanosleep(&ts, &ts) == 0)
-		alarm_handler(SIGVTALRM, NULL);
+		deliver_alarm();
 	after_sleep_interval(&ts);
 }

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [2.6.24.x] UML select()/poll() oversleeping reproducibly
  2008-03-18 17:00                 ` Jeff Dike
@ 2008-03-18 19:39                   ` Nix
  2008-03-19 22:14                   ` Nix
  1 sibling, 0 replies; 8+ messages in thread
From: Nix @ 2008-03-18 19:39 UTC (permalink / raw)
  To: Jeff Dike
  Cc: clowncoder, user-mode-linux-devel, linux-kernel Mailing List,
	Thomas Gleixner

On 18 Mar 2008, Jeff Dike outgrape:

> Below is another patch.
>
> I was hurt and disappointed by your
>> Eeuuuuw. :)
> so I got rid of the 9/10 thing.

Yay! That's much less dependent on the exact nature of whatever the
underlying bug is :) a random 9/10, well, it just makes my skin itch
even if it does work (unless there turned out to be a fundamental reason
why 9/10 was the right value, that is).

> This version keeps track of the time between ticks (as reported by the
> host's gettimeofday) and adjusts its sleeping and reporting ticks
> accordingly.
>
> It's still undersleeping a little - your little test once reported 19
> seconds for a 20 second sleep.  Otherwise, it's reporting sleep times
> that are right on the money.

I think we can live with that. Expecting perfect accuracy, even in a
sleep, is hopeless unless we're niced to realtime priority in any case,
and this looks like it should automatically adapt to varying load on
the host as well, which is really quite neat.

I'll give it an acid test (does ISC dhclient work now?) in a few hours,
when I can afford to drop offline.

-- 
`The rest is a tale of post and counter-post.' --- Ian Rawlings
                                                   describes USENET

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [2.6.24.x] UML select()/poll() oversleeping reproducibly
  2008-03-18 17:00                 ` Jeff Dike
  2008-03-18 19:39                   ` Nix
@ 2008-03-19 22:14                   ` Nix
  1 sibling, 0 replies; 8+ messages in thread
From: Nix @ 2008-03-19 22:14 UTC (permalink / raw)
  To: Jeff Dike
  Cc: user-mode-linux-devel, linux-kernel Mailing List, Thomas Gleixner

On 18 Mar 2008, Jeff Dike told this:
> This version keeps track of the time between ticks (as reported by the
> host's gettimeofday) and adjusts its sleeping and reporting ticks
> accordingly.

I can confirm that, as expected, this patch works well enough that
timing problems don't break dhclient anymore (which requires a 2x
oversleep, which you're a long way from now).

At last I can upgrade my firewall :)

-- 
`The rest is a tale of post and counter-post.' --- Ian Rawlings
                                                   describes USENET

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2008-03-19 23:47 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <47B34BA0.30006@club-internet.fr>
     [not found] ` <20080214003853.GA15952@c2.user-mode-linux.org>
     [not found]   ` <47B4BDCD.4080605@club-internet.fr>
     [not found]     ` <20080215160205.GA6082@c2.user-mode-linux.org>
     [not found]       ` <47B5CE40.9000005@club-internet.fr>
     [not found]         ` <20080215184650.GA8810@c2.user-mode-linux.org>
2008-03-14 23:01           ` [2.6.24.x] UML select()/poll() oversleeping reproducibly (was Re: [uml-devel] g_timeout_add) Nix
2008-03-17 16:27             ` Jeff Dike
2008-03-17 17:03             ` Jeff Dike
2008-03-17 19:34             ` Jeff Dike
2008-03-17 21:08               ` [2.6.24.x] UML select()/poll() oversleeping reproducibly Nix
2008-03-18 17:00                 ` Jeff Dike
2008-03-18 19:39                   ` Nix
2008-03-19 22:14                   ` Nix

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).