delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2003/03/09/22:02:19

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
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 <go32.h>
 #include <dpmi.h>
 #include <libc/bss.h>
+#include <dos.h>
 
 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 */

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019