home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------*/
- /* s s l e e p . c */
- /* */
- /* Smart sleep routines for UUPC/extended */
- /* */
- /* Written by Dave Watts, modified by Drew Derbyshire */
- /* */
- /* Generates DOS specific code with Windows support by default, */
- /* generates call to OS/2 family API if FAMILYAPI is defined */
- /*--------------------------------------------------------------------*/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <dos.h>
-
- #include "lib.h"
- #include "ssleep.h"
-
- #ifdef FAMILYAPI
- #define INCL_NOPM
- #define INCL_BASE
- #include <os2.h>
- #include <assert.h>
- #else
- #include <sys/timeb.h>
- #define MULTIPLEX 0x2F
-
- static void GiveUpTimeSlice(void);
- static int RunningUnderWindowsWith386(void);
-
- /*--------------------------------------------------------------------*/
- /* Use this first to see if the rest are OK */
- /* */
- /* MOV AX,1600h ; Check for win386/win3.0 */
- /* present */
- /* INT 2Fh */
- /* Return AL = 0 -> No Windows, AL = 80 -> No WIn386 mode */
- /* AL = 1 or AL = FFh -> Win386 2.xx running */
- /* else AL = Major version (3), AH = Minor version */
- /*--------------------------------------------------------------------*/
- /* --------------- Release time slice */
- /* MOV AX,1680h ; **** Release time slice */
- /* INT 2Fh ; Let someone else run */
- /* Return code is AL = 80H -> service not installed, AL = 0 -> all */
- /* OK */
- /*--------------------------------------------------------------------*/
- /* --------------- Enter critical section (disable task switch) */
- /* MOV AX,1681H ; Don't tread on me! */
- /* INT 2Fh */
- /*--------------------------------------------------------------------*/
- /* --------------- End critical section (Permit task switching) */
- /* MOV AX,1682h */
- /* INT 2Fh */
- /*--------------------------------------------------------------------*/
-
- /*--------------------------------------------------------------------*/
- /* R u n n i n g U n d e r W i n d o w s W i t h 3 8 6 */
- /* */
- /* Easily the longest function name in UUPC/extended. */
- /* */
- /* Determines if we are running under MS-Windows 386 or */
- /* MS-Windows 3. We save the result, to avoid excessively */
- /* disabling interrupts when in a spin loop. */
- /*--------------------------------------------------------------------*/
-
- static int RunningUnderWindowsWith386(void)
- {
- static int result = 2;
- union REGS inregs, outregs;
- int irq;
-
- if (result != 2) /* First call? */
- return result; /* No --> Return saved result */
-
- irq = MULTIPLEX;
- inregs.x.ax = 0x1600;
- int86(irq, &inregs, &outregs);
- if ( (outregs.h.al & 0x7f) == 0)
- result = 0;
- else
- result = 1;
- return result;
- } /* RunningUnderWindowsWith386 */
-
- /*--------------------------------------------------------------------*/
- /* G i v e U p T i m e S l i c e */
- /* */
- /* Surrender our time slice when executing under Windows/386 */
- /* or Windows release 3. */
- /*--------------------------------------------------------------------*/
-
- static void GiveUpTimeSlice(void)
- {
- union REGS inregs, outregs;
- int irq = MULTIPLEX;
-
- inregs.x.ax = 0x1680;
- int86(irq, &inregs, &outregs);
- if (outregs.h.al != 0) {
- printf("Problem giving up timeslice: %u\n", outregs.h.al);
- abort();
- }
- } /* GiveUpTimeSlice */
- #endif
-
-
- /*--------------------------------------------------------------------*/
- /* ssleep() - wait n seconds */
- /* */
- /* Simply delay until n seconds have passed. */
- /*--------------------------------------------------------------------*/
-
- void ssleep(time_t interval)
- {
- time_t start;
-
- start = time((time_t *)NULL);
- while ((time((time_t *)NULL) - start) < interval)
- ddelay(1000);
- } /*ssleep*/
-
- /*--------------------------------------------------------------------*/
- /* d d e l a y */
- /* */
- /* Delay for an interval of milliseconds */
- /*--------------------------------------------------------------------*/
-
- void ddelay (int milliseconds)
- {
-
- #ifdef FAMILYAPI
- USHORT result = DosSleep(milliseconds);
- assert(result == 0);
- #else
- struct timeb t;
- time_t seconds;
- unsigned last;
-
- /*--------------------------------------------------------------------*/
- /* Handle the special case of 0 delay, which is simply a */
- /* request to give up our timeslice */
- /*--------------------------------------------------------------------*/
-
- if (milliseconds == 0) /* Make it compatible with DosSleep */
- {
- if (RunningUnderWindowsWith386())
- GiveUpTimeSlice();
- return;
- } /* if */
-
- ftime(&t); /* Get a starting time */
- last = t.millitm; /* Save milliseconds portion */
- seconds = t.time; /* Save seconds as well */
-
- while( milliseconds > 0) /* Begin the spin loop */
- {
- int volatile count; /* Don't let compiler optimize this */
- if (RunningUnderWindowsWith386())
- GiveUpTimeSlice();
- else
- for ( count = 0; count < 2400; count ++);
- /* We spin so that interrupts are
- enabled for most of the loop */
- ftime(&t); /* Take a new time check */
- if (t.time == seconds) /* Same second as last pass? */
- milliseconds -= (t.millitm - last); /* Yes --> mSecond delta*/
- else
- milliseconds -= 1000 * (int) (t.time - seconds)
- - (last - t.millitm);
- /* No --> Handle wrap of mSeconds */
- last = t.millitm; /* Update last tick indicator */
- seconds = t.time; /* Update this as well; only needed if
- it changed (see above), but it
- kills time (which is our job) */
- } /* while */
-
- #endif /* FAMILYAPI */
-
- } /* ddelay */
-