From: sandmann AT clio DOT rice DOT edu (Charles Sandmann) Message-Id: <10303100251.AA12110@clio.rice.edu> Subject: Example uclock() code To: djgpp-workers AT delorie DOT com (DJGPP developers) Date: Sun, 9 Mar 2003 20:51:55 -0600 (CST) X-Mailer: ELM [version 2.5 PL2] Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Reply-To: djgpp-workers AT delorie DOT com Example code. It doesn't protect calibration over midnight, doesn't protect _rdtsc() against 486 class machines running NT. But I've played with it and it seems to work. _rdtsc() protection will return _rdtsc() as zero - I'll try to add that this week as time permits. By the way, I disabled the version check and tested it on a P60 running W98 and it works as expected. Comments? The documentation for uclock() says it shouldn't be used over midnight, but we do correct for that in the current code, so I'll fix this to handle calibration over midnight. --- uclock.c Tue Dec 11 21:28:06 2001 +++ uclocktk.c Sun Mar 9 20:11:58 2003 @@ -10,6 +10,7 @@ #include #include #include +#include static int uclock_bss = -1; @@ -29,6 +30,25 @@ unsigned long tics, otics; uclock_t rv; + _farsetsel(_dos_ds); + + if(_os_trueversion == 0x532) { /* Windows NT, 2000, XP */ + #define CALIBRATION_TICS 5 /* Testing shows 1.7% std error */ + static long divider; + static unsigned long long otsc; + if (uclock_bss != __bss_count) { + otics = _farnspeekl(0x46c); + while ( (tics = _farnspeekl(0x46c)) == otics); + otsc = _rdtsc(); + otics = tics; + while ( (tics = _farnspeekl(0x46c)) <= otics+CALIBRATION_TICS); + divider = (_rdtsc() - otsc) / ((tics - otics)*65536); + if (divider) uclock_bss = __bss_count; + } + if (divider) /* On failure fall through */ + return (_rdtsc() - otsc) / divider; + } + if (uclock_bss != __bss_count) { int e = errno; @@ -51,7 +71,6 @@ first 55 msec after the timer was reprogrammed still look as if the timer worked in mode 3. So we simply wait for one clock tick when we run on Windows. */ - _farsetsel(_dos_ds); otics = _farnspeekl(0x46c); do { errno = 0; @@ -62,11 +81,11 @@ /* Make sure the numbers we get are consistent */ do { - otics = _farpeekl(_dos_ds, 0x46c); + otics = _farnspeekl(0x46c); outportb(0x43, 0x00); lsb = inportb(0x40); msb = inportb(0x40); - tics = _farpeekl(_dos_ds, 0x46c); + tics = _farnspeekl(0x46c); } while (otics != tics); /* calculate absolute time */