delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1997/02/18/12:26:32

Message-Id: <m0vwtBG-000UCfC@londen.tip.nl>
Date: Tue, 18 Feb 97 18:18 MET
Mime-Version: 1.0
To: sjoerd DOT s DOT bakker AT tip DOT nl
From: LS Bakker <sjoerd DOT s DOT bakker AT tip DOT nl>
Subject: Re: Exact timming II
Cc: DJGPP workers <djgpp-workers AT delorie DOT com>

On Tue, 18 Feb 1997, Ian Miller wrote:

> 24023
> +40
> +16
> +18
> +16
> +16
> +18
> 36
> +20
> +8
> +8
> +8
> +8
> +8
> 
> 
> It looks to me like the timer mode is changed in all three cases.
> Does this get me anywhere?

I think your on-chip cache is playing cat-and-mouse with your timing.  In 
general, it is a good idea to invalidate the cache if you need stable 
(if slow) performance from tight loops.

However, the program below, which uses the BIOS event wait service, seems 
to be a better vehicle for testing this.  On my machine in prints values 
around 22000 both in plain DOS and in Windows 3.1 DOS box.  This value 
seems about right for mode 2, where the counter changes by 1 every 838 
nanoseconds, and the program waits for 20*976 microseconds.  What does it 
print for you?

(In case it matters: I compiled it with -O2 -g.)

----------------------------- uclktest.c -------------------------------
/* Set-up a flag in which the 7th bit will automagically be set when
   an amount of time specified by TIMEOUT (in milliseconds) has passed.
   Call with non-zero SETUP value to start the timer which will
   set the flag; call with zero SETUP to cancel the timer before
   the time-out occurs, so this service will be available again.
   This function returns 1 if the call succeeds, 0 otherwise (which
   means somebody else uses this service, or the linear address of the
   flag variable is invalid).
*/

#include <dpmi.h>
#include <go32.h>
#include <sys/farptr.h>

int
wait_interval(int setup, unsigned long msec, unsigned long laddr)
{
  unsigned long usecs = 976L * msec;
  __dpmi_regs regs;

  if (setup)
    {
      unsigned char flag;

      /* It's in conventional memory, so must be at most 20 bits.  */
      if (laddr > 0xfffff)
        return 0;

      flag = _farpeekb (_dos_ds, laddr);
      flag &= 0x7f;    /* clear the 7th bit */
      _farpokeb (_dos_ds, laddr, flag);

      /* To set the event wait, call BIOS Interrupt 15h, function 8300h.  */
      regs.x.ax = 0x8300;
      regs.x.dx = (unsigned short)(usecs & 0xffff);
      regs.x.cx = (unsigned short)(usecs >> 16);
      regs.x.es  = laddr >> 4;
      regs.x.bx = laddr & 0xf;
      __dpmi_int(0x15, &regs);

      if (regs.x.flags & 1)
        /* Somebody uses this service already, so we can't.  Give up. */
        return 0;
    }
  else
    {
      /* To cancel the event wait, call BIOS Interrupt 15h, function 8301h.  */
      regs.x.ax = 0x8301;
      __dpmi_int(0x15, &regs);
    }

  return 1;
}

#include <stdio.h>
#include <time.h>

int
main (void)
{
  uclock_t t0, t1;

  unsigned long flag_offset =
    _go32_info_block.linear_address_of_transfer_buffer;

  t0 = uclock ();

  /* Set wait interval for 20 milliseconds.  */
  if (!wait_interval (1, 20, flag_offset))
    {
      printf ("BIOS wait service not available\n");
      return 1;
    }

  for (_farsetsel (_dos_ds); (_farnspeekb (flag_offset) & 0x80) == 0; )
    ;

  t1 = uclock ();
  wait_interval (0, 0, 0);
  printf ("Timer counter was incremented by %ld units\n", (long)(t1 - t0));

  return 0;
}



- Raw text -


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