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