home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume2
/
turbo-C-timers
< prev
next >
Wrap
Internet Message Format
|
1991-08-07
|
18KB
From: asjoshi@phoenix.princeton.edu (Amit S. Joshi)
Newsgroups: comp.sources.misc
Subject: v02i069: Timer and CTRL BRK functions in Turbo C
Message-ID: <7472@ncoast.UUCP>
Date: 5 Mar 88 23:26:25 GMT
Approved: allbery@ncoast.UUCP
Comp.sources.misc: Volume 2, Issue 69
Submitted-By: "Amit S. Joshi" <asjoshi@phoenix.princeton.edu>
Archive-Name: turbo-C-timers
[*Another* ARCed source?! Egads! ++bsa]
Here are a set of four functions to handle timers and ^C breaks slightly
more easily from Turbo C. Includes a small 'manual' page to use the
functions. Could be ported to MSC (but I don't have that expensive
compiler ;-). For some reason the functions cause a stack overflow in
the small, tiny and medium models. There is a small test program to
excercise the timer functions included. Also included is the makefile
and the default rules file. I used NDMAKE.
UUdecode and then unarchive. Any old arc program (even tthe UNIX ones)
should be able to do it.
[Not any more; it's now a shar. ++bsa]
----- cut above this line -----
#! /bin/sh
#
# This is a shell archive. Save this into a file, edit it
# and delete all lines above this comment. Then give this
# file to sh by executing the command "sh file". The files
# will be extracted into the current directory owned by
# you with default permissions.
#
# The files contained herein are:
#
# -rw-r--r-- 1 allbery System 1622 Feb 27 00:55 MAKE.INI
# -rw-r--r-- 1 allbery System 1129 Mar 4 15:01 MAKEFILE
# -rw-r--r-- 1 allbery System 1574 Mar 4 15:37 TEST.C
# -rw-r--r-- 1 allbery System 5556 Feb 25 12:35 TICK.C
# -rw-r--r-- 1 allbery System 2511 Mar 4 14:56 TICK.DOC
# -rw-r--r-- 1 allbery System 1442 Feb 25 11:49 TICK.H
#
echo 'x - MAKE.INI'
if test -f MAKE.INI; then echo 'shar: not overwriting MAKE.INI'; else
sed 's/^X//' << '________This_Is_The_END________' > MAKE.INI
X# rules especially for the Turbo C package.
X
XCC=tcc
XAS=masm
XLB=lib
XCPP=cpp
XLINK=tlink
XMODEL=s
X
XLIB=c:\turboc\lib
XINCLUDE=c:\turboc\include
X
XLIBS=
XSTDLIBFILES=$(LIB)\math$(MODEL) $(LIB)\c$(MODEL) $(LIB)\fp87
XSTDOBJFILES=$(LIB)\c0$(MODEL)
X
X
XTCFLAGS=-DTURBOC -m$(MODEL)
XASFLAGS=/E
XLFLAGS=/d
XCFLAGS=
X
X.SUFFIXES: .i .com .exe .obj .asm .c .for .pas
X
X# create response files for tlink too.
X.RESPONSE_LINK: tlink
X
X# ASM -> EXE using masm and tlink
X.asm.exe:
X $(AS) $<;
X $(LINK) $(STDOBJFILES) $*,$*,,$(STDLIBFILES) $(LFLAGS)
X @rm -f $*.obj
X
X# ASM -> OBJ using MASM
X.asm.obj:
X $(AS) $<;
X
X# C -> ASM using tcc -S option
X.c.asm:
X $(CC) $(TCFLAGS) -S $(CFLAGS) -I$(INCLUDE) -L$(LIB) $(LIBS) $<
X @tcod $*
X @mv $*.cod $*.asm
X
X# C -> COM using tcc and then exe2bin
X.c.com:
X $(CC) $(TCFLAGS) $(CFLAGS) -I$(INCLUDE) -L$(LIB) $(LIBS) $<
X -(@exe2bin $*.exe $*.com)
X @rm -f $*.obj $*.exe
X
X# C -> EXE using tcc ; use this since it is faster than C -> OBJ -> EXE
X.c.exe:
X $(CC) $(TCFLAGS) $(CFLAGS) -I$(INCLUDE) -L$(LIB) $(LIBS) $<
X @rm -fi- $*.obj
X
X# C -> OBJ using tcc -c option
X.c.obj:
X $(CC) $(TCFLAGS) -c $(CFLAGS) -I$(INCLUDE) -L$(LIB) $(LIBS) $<
X
X# OBJ -> EXE using tcc
X.obj.exe:
X $(CC) $(TCFLAGS) $(CFLAGS) -I$(INCLUDE) -L$(LIB) $(LIBS) $<
X
X# EXE -> COM using exe2bin
X.exe.com:
X exe2bin $< $*.com
X @rm -f $*.exe
X
X# C -> I run preprocessor only
X.c.i:
X $(CPP) $(TCFLAGS) -P $(CFLAGS) -I$(INCLUDE) -L$(LIB) $(LIBS) $<
X
X# cleans the current directory - always needed
Xclean:; @rm -f *.bak *.map *.lst
X
X# make makefile using mkmf interactively
________This_Is_The_END________
if test `wc -l < MAKE.INI` -ne 75; then
echo 'shar: MAKE.INI was damaged during transit (should have been 75 bytes)'
fi
fi ; : end of overwriting check
echo 'x - MAKEFILE'
if test -f MAKEFILE; then echo 'shar: not overwriting MAKEFILE'; else
sed 's/^X//' << '________This_Is_The_END________' > MAKEFILE
X
XMODEL = ml
X# turn optimization on by default
XCFLAGS = -O
X
XDEST = .
X
XEXTHDRS = /turboc/include/dos.h \
X /turboc/include/stdarg.h \
X /turboc/include/stdio.h \
X /turboc/include/stdlib.h
X
XHDRS = TICK.H
X
XLIBS =
X
XMAKEFILE = makefile
X
XOBJS = TEST.OBJ \
X TICK.OBJ
X
X# Print over the ethernet
XPRINT = eprint
X
XPROGRAM = test.exe
X
XSRCS = TEST.C \
X TICK.C
X
Xall: $(PROGRAM)
X
X$(PROGRAM): $(OBJS) $(LIBS)
X $(LINK) $(STDOBJFILES) $(OBJS),$@,,$(LIBS) $(STDLIBFILES)
X
Xclean:; rm -f *.bak *.lst *.map $(OBJS)
X
Xdepend:; @mkmf -f $(MAKEFILE) PROGRAM=$(PROGRAM) DEST=$(DEST)
X
Xinstall: $(PROGRAM)
X @mv $(PROGRAM) $(DEST)
X
Xprint:; $(PRINT) $(HDRS) $(SRCS)
X
Xprogram: $(PROGRAM)
X
Xupdate: $(DEST)/$(PROGRAM)
X
X$(DEST)/$(PROGRAM): $(SRCS) $(LIBS) $(HDRS) $(EXTHDRS)
X @make -f $(MAKEFILE) DEST=$(DEST) install
X###
XTEST.OBJ: /turboc/include/stdio.h /turboc/include/stdarg.h tick.h \
X /turboc/include/dos.h
XTICK.OBJ: /turboc/include/stdlib.h /turboc/include/stdio.h \
X /turboc/include/stdarg.h tick.h /turboc/include/dos.h
________This_Is_The_END________
if test `wc -l < MAKEFILE` -ne 54; then
echo 'shar: MAKEFILE was damaged during transit (should have been 54 bytes)'
fi
fi ; : end of overwriting check
echo 'x - TEST.C'
if test -f TEST.C; then echo 'shar: not overwriting TEST.C'; else
sed 's/^X//' << '________This_Is_The_END________' > TEST.C
X/* test.c - gently excersise the tick.c functions */
X
X#include <stdio.h>
X#include "tick.h"
X
X#define NT 300
X#define ND 5
X
Xvoid test1(void) {
X printf("1");
X}
X
Xvoid test2(void) {
X putc('a',stderr);
X}
X
Xmain() {
X int i;
X void test1(), test2();
X
X for (i = NT; i > 0; i--) {
X test1(); test2();
X delay(ND);
X }
X
X if ((i = install_timer(test1)) != 0) {
X printf("Install_timer failed: %d\n",i);
X exit(1);
X }
X
X printf("\nInstalled timer 1\n");
X
X for (i = NT; i > 0; i--) delay(ND);
X
X if ((i = install_timer(test2)) != 0) {
X printf("Install_timer failed: %d\n",i);
X exit(1);
X }
X
X printf("\nInstalled timer 2\n");
X
X for (i = NT; i > 0; i--) delay(ND);
X
X if ((i = remove_timer(test2)) != 0) {
X printf("Remove timer failed: %d\n",i);
X exit(1);
X }
X printf("\nRemoved timer 2\n");
X for (i = NT; i > 0; i--) delay(ND);
X if ((i = install_timer(test2)) != 0) {
X printf("Install_timer failed: %d\n",i);
X exit(1);
X }
X
X printf("\nInstalled timer 2\n");
X
X for (i = NT; i > 0; i--) delay(ND);
X if ((i = remove_timer(test1)) != 0) {
X printf("Remove timer failed: %d\n",i);
X exit(1);
X }
X printf("\nRemoved timer 1\n");
X for (i = NT; i > 0; i--) delay(ND);
X
X if ((i = install_timer(test1)) != 0) {
X printf("Install_timer failed: %d\n",i);
X exit(1);
X }
X
X printf("\nInstalled timer 1\n");
X for (i = NT; i > 0; i--) delay(ND);
X
X if ((i = remove_timer(NULLVFP)) != 0) {
X printf("Remove timer failed: %d\n",i);
X exit(1);
X }
X printf("\nRemoved all timers\n");
X for (i = NT; i < 0; i--) delay(ND);
X}
X
________This_Is_The_END________
if test `wc -l < TEST.C` -ne 80; then
echo 'shar: TEST.C was damaged during transit (should have been 80 bytes)'
fi
fi ; : end of overwriting check
echo 'x - TICK.C'
if test -f TICK.C; then echo 'shar: not overwriting TICK.C'; else
sed 's/^X//' << '________This_Is_The_END________' > TICK.C
X/* tick.c - installs a function which is called every clock tick */
X/* (c) - Amit Joshi, Princeton University
X
X This code may be used freely for any noncommercial use. It may NOT
X be used in any commercial package without written permission from
X the author. This clause is to protect me from legal hassles with
X the university about code developed here. This code is supplied
X "AS IS" i.e. with no warranty. Do not remove this notice. Any
X modifications should be clearly noted before redistribution.
X**/
X
X/** Amit Joshi
X MAE Dept., Engg. Quad.
X Princeton University
X December 1987
X**/
X
X/**
X The __tick__() and dosbusy() functions have been stolen from the
X "rdir.c" code by Dean D. McCrory. The __tick__() has been
X rewritten (and renamed from timer_handler()) to be more general.
X Amit Joshi
X January 1988
X**/
X
X#include <stdlib.h>
X#include <stdio.h>
X#include "tick.h"
X
X/* Stuff for to handle the ctrl break functions */
Xstatic int __nc_brks = 0;
Xstatic char __abort = 1;
Xstatic void (* __c_brks[NCBRKS])();
X
X/* Stuff to run timers */
Xstatic void interrupt (* __otimer)() = NULLIVFP;
Xstatic int __ntimers = 0;
Xstatic void (* __timers[NTIMERS])();
Xstatic char far * dosbusy_fl; /* dos maintains this */
X
X/* The functions used in this file */
Xstatic int __cbrk(void);
Xstatic void __clean_timer(void);
Xstatic void interrupt __tick__(void);
Xstatic char far * getdosbusy(void);
X
Xstatic int
X__cbrk(void) {
X int nf;
X
X if (!abort) {
X for (nf = 0; nf < __nc_brks; ++nf)
X (* __c_brks[nf])();
X exit(1);
X } else return 1;
X}
X
Xstatic void
X__clean_timer(void) {
X if (__otimer == NULLIVFP) return; /* nothing set yet */
X setvect(TIMER_INT,__otimer);
X}
X
X/* __tick__ ()
X *
X * This function intercepts the hardware timer interrupt. It checks the
X * dosbusy flag and runs through a list of timer driven functions if safe
X * to do so.
X */
X
Xstatic void interrupt
X__tick__(void)
X{
X static int in_fl = 0;
X int timer;
X
X /* if the following statement is NOT coded, the 8259 blocks all hardware
X interrupts including the keyboard interrupt. Since we wait for a key
X in list_directory (), this causes the PC to lock up. This one took
X a while to figure out */
X outportb (0x20, 0x20); /* send eoi to 8259 */
X (*__otimer) (); /* chain to previous timer handler */
X
X if (! in_fl)
X {
X in_fl = 1; /* we are in our ISR */
X if (! *dosbusy_fl )
X /* run through the list of timers */
X for (timer = 0; timer < __ntimers; ++timer)
X if (__timers[timer] != NULLVFP)
X (* __timers[timer])();
X in_fl = 0;
X }
X return; /* return from ISR */
X}
X
X/* getdosbusy ()
X *
X * Gets the Dos busy flag through interrupt 34h. This Dos function returnes
X * the busy flag address in es:bx. This is an UNDOCUMENTED feature of Dos,
X * however it has worked in Dos versions 2.11 - 3.30 for me - Dean McCrory.
X */
Xstatic char far *
Xgetdosbusy (void)
X{
X struct SREGS sregs; /* segment registers */
X union REGS regs; /* normal registers */
X
X regs.h.ah = 0x34; /* get dos busy flag address (UNDOCUMENTED) */
X intdosx (®s, ®s, &sregs);
X return (MK_FP (sregs.es, regs.x.bx));
X}
X
Xint
Xinstall_timer(void (*func)(void))
X{
X int i = 0;
X void __clean_timer();
X void interrupt __tick__();
X
X /* check if the function is already installed */
X
X if (!__ntimers) {
X __otimer = getvect(TIMER_INT);
X /* Get address of DOS busy flag. */
X dosbusy_fl = getdosbusy();
X if (atexit(__clean_timer)) return 2;
X install_cbrk(NULLVFP);
X setvect(TIMER_INT,__tick__);
X }
X /* are we already installed ? */
X for (i=0; i < __ntimers; i++)
X if (__timers[i] == func) return 0;
X /* enough space for another function ? */
X if (__ntimers >= NTIMERS) return 1;
X __timers[__ntimers++] = func;
X return 0;
X}
X
Xint
Xremove_timer(void (*func)(void))
X{
X int i = 0;
X
X if (func == NULLVFP) {
X __clean_timer();
X __ntimers = 0;
X return 0;
X }
X
X if (!__ntimers) return 1; /* No timers return func not there */
X
X do {
X /* have we found the function ? */
X if (__timers[i] == func) {
X /* is it the last one in the chain ? */
X if (i++ == __ntimers) {
X __timers[i-1] = NULLVFP;
X } else {
X /* move the chain backwards */
X do {
X __timers[i-1] = __timers[i]; i++;
X } while(i <= __ntimers);
X }
X __ntimers--;
X return 0;
X } else i++;
X } while (i < __ntimers);
X return 1;
X}
X
Xint
Xinstall_cbrk (void (* func)(void))
X{
X int i = 0;
X
X
X
X if (!__nc_brks) {
X setcbrk(1); /* ensure that ctrl break is enabled */
X ctrlbrk(__cbrk);
X __abort = 1;
X }
X
X if (func == NULLVFP) __abort = 1;
X
X for (i = 0; i < __nc_brks; i++)
X if (__c_brks[i] == func) return 0;
X /* enough space for another function ? */
X if (__nc_brks >= NCBRKS) return 1;
X __c_brks[__nc_brks++] = func;
X return 0;
X}
X
Xint
Xremove_cbrk (void (* func)(void))
X{
X int i = 0;
X
X if (func == NULLVFP) __abort = 0;
X
X if (!__nc_brks) return 1; /* No timers return func not there */
X
X do {
X /* have we found the function ? */
X if (__c_brks[i] == func) {
X /* is it the last one in the chain ? */
X if (i++ == __nc_brks) {
X __c_brks[i-1] = NULLVFP;
X } else {
X /* move the chain backwards */
X do {
X __c_brks[i-1] = __c_brks[i]; i++;
X } while(i <= __nc_brks);
X }
X __nc_brks--;
X return 0;
X } else i++;
X } while (i < __nc_brks);
X return 1;
________This_Is_The_END________
if test `wc -l < TICK.C` -ne 220; then
echo 'shar: TICK.C was damaged during transit (should have been 220 bytes)'
fi
fi ; : end of overwriting check
echo 'x - TICK.DOC'
if test -f TICK.DOC; then echo 'shar: not overwriting TICK.DOC'; else
sed 's/^X//' << '________This_Is_The_END________' > TICK.DOC
XAll the functions in this file make heavy use of TurboC and PCDOS
Xfacilities and are not portable.
X
XWARNING:
X DO NOT compile with tiny, small or medium models. Stack overflow
X occurs and if the stack checking option of the compiler is used
X then the timers are not unloaded and the system crashes - in fact
X you have to setup the entire system from scratch.
X
XUSAGE:
X #include "tick.h"
X
X int install_timer(vod (*func());
X Installs the function "func()" to be called EVERY tick.
X Removes the function on exit from the program - both if
X ^C or normal. You MUST NOT use the Turbo C supplied
X ctrlbrk() function if you use this one. Use
X "install_cbrk()" instead.
X
X int install_cbrk(void (*func)());
X Installs the function "func()" to be called when ^C is hit.
X You can chain a series of functions. If you use this DO NOT
X use the Turbo C supplied ctrlbrk(). If argument is NULLVFP
X ^C exits from the program.
X
X int remove_timer(void (*func)());
X Removes "func()" from timer list. If NULLVFP is given as an
X argument all timers are cleaned.
X
X int remove_cbrk(void (*func)());
X Removes "func()" from ctrlbrk list. If argument is NULLVFP
X ^C has no action.
XRETURN VALUES:
X 0 => function was successfully installed or removed.
X 1 => Install failed because of lack of space. Compile again with a
X larger NTIMER or NCBRK in "tick.h"
X Remove failed because function not found.
X 2 => Install timer failed because we could not hook timer cleaner
X onto atexit(). Try again with fewer atexit() functions.
X
XNOTES:
X * DO NOT use the Turbo C ctrlbrk() function if using these functions
X - it can have quite disasterous effects. Use install_cbrk() - it
X is more general in any case !.
X * Both the install functions try to check if the function is already
X present and do not duplicate installations.
X * Define HARDTIMER in "tick.h" if you want to use the hardware
X interrupt rather than the DOS 'soft' interrupt. This is at your own
X peril. I have not used this.
X
XBUGS:
X Notify all bugs to :
X Q3696@PUCC.BITNET or
X {seismo, rutgers}\!princeton\!phoenix\!asjoshi
X
XACKNOWLEDGEMENTS:
X Dean D. McCrory for two functions which really form the heart of the
X timer portion : timer_handler, and dosbusy. The first has been
X modified and made more general. It is also renamed to __tick__().
X The rest of the code was written using Turbo C v1.5 entirely by me
X Thanks to Borland for the wonderful (and inexpensive) C compiler.
X
________This_Is_The_END________
if test `wc -l < TICK.DOC` -ne 62; then
echo 'shar: TICK.DOC was damaged during transit (should have been 62 bytes)'
fi
fi ; : end of overwriting check
echo 'x - TICK.H'
if test -f TICK.H; then echo 'shar: not overwriting TICK.H'; else
sed 's/^X//' << '________This_Is_The_END________' > TICK.H
X/* tick.h - the include file for timer and c_brk function installation */
X/* (c) - Amit Joshi, Princeton University
X
X This code may be used freely for any noncommercial use. It may NOT
X be used in any commercial package without written permission from
X the author. This clause is to protect me from legal hassles with
X the university about code developed here. This code is supplied
X "AS IS" i.e. with no warranty. Do not remove this notice. Any
X modifications should be clearly noted before redistribution.
X**/
X
X/** Amit Joshi
X MAE Dept., Engg. Quad.
X Princeton University
X December 1987
X**/
X
X/**
X Change the values defined for NTIMERS and NCBRKS to increase
X number of timer and cbrk functions installed.
X
X Amit Joshi
X January 1988
X**/
X
X#ifndef __TICK_H__
X#define __TICK_H__
X
X#include <dos.h>
X
X/* Change the following definitions to increase number of timers and cbrks */
X#define NTIMERS 2 /* number of timers installable */
X#define NCBRKS 2 /* number of cbrks installable */
X
X#define NULLIVFP (void interrupt (*)())NULL
X#define NULLVFP (void (*)())NULL
X#define NULLFP (int (*)())NULL
X
X#ifdef HARDTIMER
X#define TIMER_INT 0x08
X#else
X#define TIMER_INT 0x1C
X#endif
X
X/* user callable functions */
Xint _Cdecl install_timer(void (*func)());
Xint _Cdecl install_cbrk(void (*func)());
Xint _Cdecl remove_timer(void (*func)());
Xint _Cdecl remove_cbrk(void (*func)());
X
X#endif __TICK_H__
________This_Is_The_END________
if test `wc -l < TICK.H` -ne 51; then
echo 'shar: TICK.H was damaged during transit (should have been 51 bytes)'
fi
fi ; : end of overwriting check
exit 0
---- cut below this line -----
Amit Joshi BITNET | Q3696@PUCC.BITNET
USENET | {seismo, rutgers}\!princeton\!phoenix\!asjoshi
"There's a pleasure in being mad... which none but madmen know!" - St.Dryden
--
Amit Joshi BITNET | Q3696@PUCC.BITNET
USENET | {seismo, rutgers}\!princeton\!phoenix\!asjoshi
"There's a pleasure in being mad... which none but madmen know!" - St.Dryden