Mail Archives: djgpp-workers/1997/02/18/09:00:59
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, ®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 <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 -