www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2002/06/10/03:31:27

Message-ID: <004901c2104a$6d9e7240$0102a8c0@acceleron>
From: "Andrew Cottrell" <acottrel AT ihug DOT com DOT au>
To: <djgpp-workers AT delorie DOT com>, "Charles Sandmann" <sandmann AT clio DOT rice DOT edu>
References: <10206100445 DOT AA21243 AT clio DOT rice DOT edu>
Subject: Re: uclock() on Win2K
Date: Mon, 10 Jun 2002 16:45:05 +1000
MIME-Version: 1.0
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 6.00.2600.0000
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000
Reply-To: djgpp-workers AT delorie DOT com

> > On my Win95 box it doesn't work either - the timer seems to stay on
> > rate generator (so it's not continuous); there are jumps in the time.
>
> It now seems to be working on Win95.  Miracles never cease.  Sometimes
> the timer reprogram takes, sometimes it doesn't?
>
> It seems that the time between tics on Win2K isn't very even; I'm
> seeing anything from 280 msb per tic and 252 msb per tic.  When I let it
> run for a long time it seems to settle down to an average of around
> 256 msb per tic.  The first calibration tic always has much more than
> 256.  Maybe it reacts to the calibration and tries to bring an emulated
> timer in line?
>
> In any case, it would seem difficult to fix.

There may be a solution for W2k & XP. It may end up being a bit tricky to
ensure that it mimicks DOS.

Charles as you indicated in the first email Windows virtualised the TOD
tick, so why not use the virtualised TOD tick on Windows NT/2K/XP instead of
the timer registers? I don't know if this is the correct INT to use, but it
appears to work okay in the small test program I wrote. The uclock() code
would need to be modified to use int the bios tick counter instead of the
hardware registers on W2K/ XP (& I would also assume NT as well?) instead of
the existing code.

What do people think about this finding? Are there any better solutions? The
comments in the libc doc also need to be modified as they indicate that the
uclosk is very accurate, it may be on plain DOS, but not so on W2K/XP.

The  following is my test output. The ticks look okay on my XP box. I need
to run it for a longer test to see how it goes over a few minutes, but I
supect it will go okay.

Midnight flag = 0x00 TICKS = 0x 0010 8D9E , Time = 10Jun2002 16:33:04
Midnight flag = 0x00 TICKS = 0x 0010 8DB0 , Time = 10Jun2002 16:33:05
Midnight flag = 0x00 TICKS = 0x 0010 8DC2 , Time = 10Jun2002 16:33:06
Midnight flag = 0x00 TICKS = 0x 0010 8DD4 , Time = 10Jun2002 16:33:07
Midnight flag = 0x00 TICKS = 0x 0010 8DE7 , Time = 10Jun2002 16:33:08
Midnight flag = 0x00 TICKS = 0x 0010 8DF9 , Time = 10Jun2002 16:33:09
Midnight flag = 0x00 TICKS = 0x 0010 8E0C , Time = 10Jun2002 16:33:10
Midnight flag = 0x00 TICKS = 0x 0010 8E1E , Time = 10Jun2002 16:33:11
Midnight flag = 0x00 TICKS = 0x 0010 8E30 , Time = 10Jun2002 16:33:12
Midnight flag = 0x00 TICKS = 0x 0010 8E43 , Time = 10Jun2002 16:33:13
Midnight flag = 0x00 TICKS = 0x 0010 8E55 , Time = 10Jun2002 16:33:14

#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <dpmi.h>

/*
INT 1A - TIME - GET SYSTEM TIME
 AH = 00h
Return: CX:DX = number of clock ticks since midnight
 AL = midnight flag, nonzero if midnight passed since time last read
Notes: there are approximately 18.2 clock ticks per second, 1800B0h per 24
hrs
   (except on Tandy 2000, where the clock runs at 20 ticks per second)
 IBM and many clone BIOSes set the flag for AL rather than incrementing
   it, leading to loss of a day if two consecutive midnights pass
   without a request for the time (e.g. if the system is on but idle)
 since the midnight flag is cleared, if an application calls this
   function after midnight before DOS does, DOS will not receive the
   midnight flag and will fail to advance the date
 Modern releases of MS-DOS/PC DOS (5.0+???) assume that AL is a day
   rollover counter rather than a flag, as expected by older releases.
   DOS 5 - 7.10 (Windows 98 SE) provide an undocumented CONFIG.SYS
   SWITCHES=/T option to force the old behaviour of the day advancing
   code, that is using a flag instead of a counter.
 DR DOS 3.31 - DR-DOS 7.03 handle AL as a flag.
SeeAlso: AH=01h,AH=02h,INT 21/AH=2Ch,INT 55"Tandy 2000",INT 4E/AH=02h"TI"
SeeAlso: INT 62/AX=0099h,MEM 0040h:006Ch,MEM 0040h:0070h

*/

int main(int argc, char * argv[])
{
    int loop, timer;
    int a = 1;
    struct tm *time_now;
    time_t secs_now;
    char time_string[100];
    __dpmi_regs r;

    r.h.ah = 0x00;
    __dpmi_int(0x1A, &r);

    time(&secs_now);
    time_now = localtime(&secs_now);

    strftime(time_string, 90, "%d%b%Y %H:%M:%S", time_now);
    printf("Midnight flag = 0x%02X TICKS = 0x %04X %04X , Time = %s \n",
                     r.h.al, r.x.cx, r.x.dx, time_string);
    for( loop = 0; loop < 10; loop++)
    {
        for( timer = 1; timer < 99999999;timer++)
        {
        }
        r.h.ah = 0x00;
        __dpmi_int(0x1A, &r);
        time(&secs_now);
        time_now = localtime(&secs_now);
        strftime(time_string, 90, "%d%b%Y %H:%M:%S", time_now);
        printf("Midnight flag = 0x%02X TICKS = 0x %04X %04X , Time = %s \n",
                     r.h.al, r.x.cx, r.x.dx, time_string);
    }

  return (0);
}


- Raw text -


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