delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1997/04/29/10:54:50

From: mauch AT uni-duisburg DOT de (Michael Mauch)
Newsgroups: comp.os.msdos.djgpp
Subject: Re: testing uclock()
Date: Tue, 29 Apr 1997 15:41:55 +0200
Organization: Home, sweet home (via Gesamthochschule Duisburg)
Lines: 128
Distribution: world
Message-ID: <3364e262.1961163@news.uni-duisburg.de>
References: <Pine DOT SUN DOT 3 DOT 91 DOT 970427115144 DOT 17804G-100000 AT is>
NNTP-Posting-Host: ppp103.uni-duisburg.de
Mime-Version: 1.0
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp

On Sun, 27 Apr 1997 08:52:06 GMT, Eli Zaretskii <eliz AT is DOT elta DOT co DOT il> wrote:

> 
> On Sat, 26 Apr 1997, Michael Mauch wrote:
> 
> > Then the program works like it should - on plain MS-DOS 7 in virtual x86
> > mode. The first call to uclock() returns 0 and the other values are
> > always from 4 to 7 on my Pentium 75. 
> > 
> > However in a DOS window of Win95, I also get negative values sometimes
> > (i.e. not in each run, and only one of the hundred numbers).
> 
> That's because `uclock' reprograms the system timer chip, and
> Windows 95 has a nasty habit of resetting it to the default mode
> every now and then.  When the timer works in its default mode,
> you get negative values.

Oh, that's the problem then. Doesn't this mean that we can't use uclock() in a
Win95 DOS window, because we don't know what mode that default mode is?

On the other hand: isn't it possible that this default mode is just the same as
the one set by the first call to uclock()? The difference between two
consecutive calls to uclock() remains the same, even after that single negative
difference. I removed the first three outportb() calls from the uclock source
code, and now I don't get any negative differences anymore. So maybe Win95
resets the mode only when it feels that somebody else fiddled around with the
timer chip?

Looking through Ralf Brown's Interrupt List, I also found a DOS (16 bit mode in
DOS window) function that returns the "clock tick time in 840ns units since
Windows was started". It's a VxD API call to the Virtual Timer Device of
MS-Windows/Win95 - I don't know if this kind of functions work under NT. I
append a little test program that works under Win95 (hopefully it's not too long
for this newsgroup/list). It has to be compiled with a 16 bit compiler (I used
BC++ 4.52), because API call is a 16 bit function. I have no clue how to
translate this to DJGPP, maybe someone else is able to do that.

Regards...
		Michael


/* Compile with "bcc -v -3 -B vtd.c" */

#include <stdio.h>
#include <dos.h>

typedef unsigned long uclock_t;
/*
   Alas, Borland C has no 64-bit integers,
   so forget about the upper 32 bits for now.
*/

uclock_t wuclock(void)
{
  static struct
  {
    unsigned short lo,hi;
  } VTD;   /* address of the Virtual Timer Device API entry point */

  static int GotEntryPoint;
  static uclock_t rv,base;

  if(!GotEntryPoint)
  {
    asm{
         pushad
         mov ax,0x1684
         mov bx,0x0005
         xor di,di
         mov es,di
         int 0x2F
         mov word ptr VTD.lo,di
         mov word ptr VTD.hi,es
         popad
       }

    base = 0;
    GotEntryPoint = 1;
  }
  if(VTD.hi | VTD.lo)   /* if(NULL != *(void far*)VTD) */
  {
    static unsigned long TicksLow,TicksHigh;
    asm{
         /*
         0100h get current clock tick time
         Return: EDX:EAX = clock tick time in 840ns units since Windows
                   was started
         */
         push edx
         push eax

         mov ax,0x0100
         call dword ptr [VTD]
         mov dword ptr TicksLow,eax
         mov dword ptr TicksHigh,edx

         pop eax
         pop edx
       }
    rv = TicksLow; /* !!! throwing away the upper 32 bit for now */

    if(!base)
      base = rv;
    return rv - base;
  }
  return (uclock_t)(-1); /* error: VTD API not available */
}


#define MAXDT 10000

int main(int argc,char* argv[])
{
  uclock_t t0;
  static uclock_t dt[MAXDT];
  size_t i;

  printf( "%d\n", (int) (t0 = wuclock()) ); /* first call resets clock to 0 */

  for (i=0; i<MAXDT; i++) dt[i] = wuclock();

  for (i=1; i < MAXDT; i++) {
      printf( "%lu\t%lu\n", dt[i], dt[i] - dt[i-1] );
  }

  return 0;
}

- Raw text -


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