Mail Archives: djgpp/2001/03/29/04:31:49
Frank Heckenbach wrote:
> This should make it possible to fix/work-around the problem in
> CRT...
>
> What I'm wondering is, if DJGPP's libc contains a delay() function
> which does handle short delays well (and even seems to use
> microseconds internally AFAICS), why doesn't its usleep() function
> do the same thing?
>
> Are there any issues with the interrupt call used in delay() (that I
> probably should be aware of when using it in CRT), or what is the
> reason? Anyone knows?
From the libc sources (in djlsr203.zip) usleep() uses the 55ms
timer ticks while delay() uses the 0x1586 BIOS interrupt described as
Category: BIOS
INT 15 - BIOS - WAIT (AT,PS) AH = 86h
CX:DX = interval in microseconds
Return: CF clear if successful (wait interval elapsed)
CF set on error or AH=83h wait already in progress
AH = status (see #00496)
Note:
the resolution of the wait period is 977 microseconds on many systems
because many BIOSes use the 1/1024 second fast interrupt from the AT
real-time clock chip which is available on INT 70; because newer
BIOSes may have much more precise timers available, it is not
possible to use this function accurately for very short delays unless
the precise behavior of the BIOS is known (or found through testing)
SeeAlso: AH=41h,AH=83h,INT 1A/AX=FF01h,INT 70
Duno why the difference.
I send a copy of this message to c.o.m.djgpp: somebody should know there.
For reference:
The code in usleep.c is
#include <unistd.h>
#include <time.h>
#include <dpmi.h>
unsigned int
usleep(unsigned int _useconds)
{
clock_t cl_time;
clock_t start_time = clock();
/* 977 * 1024 is about 1e6. The funny logic keeps the math from
overflowing for large _useconds */
_useconds >>= 10;
cl_time = _useconds * CLOCKS_PER_SEC / 977;
while (1)
{
clock_t elapsed = clock() - start_time;
if (elapsed >= cl_time)
break;
__dpmi_yield();
}
return 0;
}
The code in delay.c is
#include <dos.h>
#include <dpmi.h>
void delay(unsigned msec)
{
__dpmi_regs r;
while (msec)
{
unsigned usec;
unsigned msec_this = msec;
if (msec_this > 4000)
msec_this = 4000;
usec = msec_this * 1000;
r.h.ah = 0x86;
r.x.cx = usec>>16;
r.x.dx = usec & 0xffff;
__dpmi_int(0x15, &r);
msec -= msec_this;
}
}
Hope this helps
Maurice
--
Maurice Lombardi
Laboratoire de Spectrometrie Physique,
Universite Joseph Fourier de Grenoble, BP87
38402 Saint Martin d'Heres Cedex FRANCE
Tel: 33 (0)4 76 51 47 51
Fax: 33 (0)4 76 51 45 44
mailto:Maurice DOT Lombardi AT ujf-grenoble DOT fr
- Raw text -