From: mauch AT unidui DOT uni-duisburg DOT de (Michael Mauch) To: Eli Zaretskii Cc: djgpp AT delorie DOT com Subject: Re: testing uclock() Date: Mon, 12 May 1997 13:22:03 +0200 Organization: Home, sweet home (via Gesamthochschule Duisburg) Message-Id: <337cfc42.2988017@unidui.uni-duisburg.de> References: In-Reply-To: Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="--=_3376fd5b326908407598619.MFSBCHJLHS" Precedence: bulk ----=_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 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 #include #include #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--