Mail Archives: djgpp/1997/05/12/07:24:34
----=_3376fd5b326908407598619.MFSBCHJLHS
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
On Sun, 11 May 1997 12:21:41 +0300 (IDT), Eli Zaretskii wrote:
> On Fri, 9 May 1997, Michael Mauch wrote:
>
> > Thanks for your explanation of __bss_count. I guess this should be
> > changed in puclock, too. Shall I repost the whole thing?
>
> I think so, yes.
Ok. I declared wuclock() as a public symbol now, so a program can test
if the VTD API is available.
Regards...
Michael
----=_3376fd5b326908407598619.MFSBCHJLHS
Content-Type: text/plain; charset=us-ascii; name=Puclock.h
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=Puclock.h
#ifndef PUCLOCK_H
#define PUCLOCK_H
#include <time.h>
extern uclock_t (*puclock)(void);
uclock_t wuclock(void);
#endif
----=_3376fd5b326908407598619.MFSBCHJLHS
Content-Type: text/plain; charset=us-ascii; name=Puclock.c
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=Puclock.c
#include <string.h>
#include <dpmi.h>
#include <libc/bss.h>
#include "puclock.h"
static uclock_t wuclock_wrapper(void);
uclock_t (*puclock)(void) = wuclock_wrapper;
static int puclock_bss = -1;
/*
** wuclock() works just like uclock(), that is:
**
** "This function returns the number of uclock ticks since an arbitrary
** time, actually, since the first call to `uclock', which itself returns
** zero. The number of tics per second is UCLOCKS_PER_SEC."
** (quoted from libc.inf).
**
** wuclock() queries the Virtual Timer Device (VTD) of Windows 3.1 / Win95.
** Ralf Brown's Interrupt List says that the VTD returns the
** "clock tick time in 840ns units since Windows was started"
** - see Table 1969 in Intwin53.hlp, referenced by the topic
** "INT 2F 1684 - MS Windows - VTD - GET API ENTRY POINT".
**
** I hope that these "840ns units" are the same as 1 sec / UCLOCKS_PER_SEC,
** i.e. 838.1ns.
**
** Although we don't get this high resolution inside Windows, the granularity
** should still be better than the 55ms provided by other functions (e.g.
** rawclock()).
**
** Eli Zaretskii pointed out that we can't use uclock() on Windows 95,
** because Windows 95 reprograms the timer chip every now and then,
** spoiling the timer chip mode that uclock() relies on.
**
** wuclock() returns negative values if the VTD API is not available.
** The VTD API is supported in (the DOS window of) Win3.1, WfW3.11, Win95(a)
** and Win95b (OSR2), but not on plain DOS and WinNT4.0.
** I don't know about other varieties of Windows (NT3.51, OS/2, ...).
**
** The pointer puclock initially points to wuclock_wrapper(). This function
** calls wuclock() to test if the VTD API is available, if so, it sets
** puclock to wuclock(), else it sets it to the original uclock().
**
*/
uclock_t wuclock(void)
{
static struct
{
unsigned short lo,hi;
} VTD; /* address of the Virtual Timer Device API entry point */
static uclock_t base;
uclock_t rv;
__dpmi_regs regs; /* __dpmi_regs = _go32_dpmi_registers */
if (puclock_bss != __bss_count)
{
memset(®s,0,sizeof(regs));
regs.x.ax = 0x1684;
regs.x.bx = 0x0005;
regs.x.di = 0;
regs.x.es = 0;
if(__dpmi_simulate_real_mode_interrupt(0x2F,®s)) /* = _go32_dpmi_simulate_int */
return -1; /* error: VTD API not available */
VTD.lo = regs.x.di;
VTD.hi = regs.x.es;
if(!(VTD.lo | VTD.hi))
return -2; /* error: VTD API not available */
base = 0;
puclock_bss = __bss_count;
}
memset(®s,0,sizeof(regs));
regs.x.ax = 0x100;
regs.x.cs = VTD.hi;
regs.x.ip = VTD.lo;
if(__dpmi_simulate_real_mode_procedure_retf(®s))
return -3; /* error: VTD API call failed */
*((long*)&rv+0) = regs.d.eax;
*((long*)&rv+1) = regs.d.edx;
if(!base)
base = rv;
return rv - base;
}
static uclock_t wuclock_wrapper(void)
{
uclock_t r = wuclock(); /* test if VTD API is available */
if(r<0)
return puclock = uclock, uclock();
return puclock = wuclock, r;
}
----=_3376fd5b326908407598619.MFSBCHJLHS--
- Raw text -