Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 Feb 2009 16:37:03 -0500
From:      John Baldwin <jhb@freebsd.org>
To:        freebsd-stable@freebsd.org
Cc:        Peter Jeremy <peterjeremy@optushome.com.au>
Subject:   Re: Interval timers firing early
Message-ID:  <200902111637.04229.jhb@freebsd.org>
In-Reply-To: <20090101024228.GF87057@server.vk2pj.dyndns.org>
References:  <20090101024228.GF87057@server.vk2pj.dyndns.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wednesday 31 December 2008 9:42:28 pm Peter Jeremy wrote:
> I have some code that uses setitimer() to generate one-shot timers of
> ~60s (the intent is to fire ~10msec before the minute boundary).
> 
> On my amd64 laptop running 7.0-stable from mid-March the SIGALRM
> arrives at the expected time.  On a system running a recent amd64
> -current, the SIGALRM arrives about 10msec late (which I'm not too
> fussed about).
> 
> On two i386 systems running 7.1-PRE (from mid-Oct) and a fresh 7.1-RC2
> install, the SIGALRM arrives early - ~11msec for the 7.1-PRE system and
> ~5msec for the 7.1-RC2 system.
> 
> All systems are running HZ=1000.  Two of the systems (the one running
> 7.1-PRE and the one running -current) are running BOINC.  All systems
> are otherwise unloaded.  I've looked at the timer code and can't
> quickly see anything that would explain this.  Does anyone have any
> ideas?
> 
> The relevant code looks like the following:
>     while (1) {
> 	struct timeval		now;
> 	struct itimerval	it;
> 	int			usecs;
> 
> 	if (gettimeofday(&now, NULL) < 0) {
> 	    syslog(LOG_ERR, "gettimeofday: %m");
> 	    exit(1);
> 	}
> 	/* Set timer for just before next minute */
> 	it.it_interval.tv_sec = 0;
> 	it.it_interval.tv_usec = 0;
> 	usecs = 59990000 - ((now.tv_sec % 60) * 1000000 + now.tv_usec);
> 	if (usecs < 10000)	/* allow 10msec slop */
> 	    usecs += 60000000;
> 	it.it_value.tv_sec = usecs / 1000000;
> 	it.it_value.tv_usec = usecs % 1000000;
> 	if (setitimer(ITIMER_REAL, &it, NULL) < 0) {
> 	    syslog(LOG_ERR, "setitimer: %m");
> 	    exit(1);
> 	}
> 	printf("%d.%06ld %2d.%06ld %d\n", now.tv_sec, now.tv_usec,
> 	       it.it_value.tv_sec, it.it_value.tv_usec, usecs);
> 	/* do stuff here which is interrupted by SIGALRM */
>     }
> 
> On the 7.1-PRE system, I get output like:
> 1230776939.991464 59.998536 59998536
> 1230776999.978991  0.011009 11009
> 1230776999.991996 59.998004 59998004
> 1230777059.979532  0.010468 10468
> 1230777059.991538 59.998462 59998462
> 1230777119.979058  0.010942 10942
> 1230777119.991065 59.998935 59998935
> 1230777179.978597  0.011403 11403
> 1230777179.991610 59.998390 59998390
> 1230777239.979139  0.010861 10861
> 1230777239.991142 59.998858 59998858

On a whim, hack kern_tc.c to only use 2 or 3 timehands structures instead of 
64.

-- 
John Baldwin



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902111637.04229.jhb>