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 -- Peter Jeremy Please excuse any delays as the result of my ISP's inability to implement an MTA that is either RFC2821-compliant or matches their claimed behaviour. -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 195 bytes Desc: not available Url : http://lists.freebsd.org/pipermail/freebsd-stable/attachments/20090101/9a2aa1b0/attachment.pgp
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 59998858On a whim, hack kern_tc.c to only use 2 or 3 timehands structures instead of 64. -- John Baldwin