Date: Tue, 18 Feb 1997 15:57:10 +0200 (IST) From: Eli Zaretskii To: Ian Miller cc: DJGPP workers Subject: Re: Exact timming II In-Reply-To: <33097AB8.41C67EA6@dra.hmg.gb> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII 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 #include #include 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, ®s); 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, ®s); } return 1; } #include #include 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; }