[comp.lang.pascal] Problems with interrupt handler for interrupt 08 or 1C in TP 6.0

ballerup@diku.dk (Per Goetterup) (01/04/91)

Hi everybody!

	I'm having some rather weird problems with a program of mine which
needs to get something updated on the screen no matter what else the program
might be doing.
	I'm using interrupt 1C (User Timer Tick) to call my procedure which
by the way DOESN'T call DOS (common error) - it only modifies the screen
memory.
	The problem is not to get it to work (it does) but what happens
next. I start it up by saving the old vector then re-assigning it to point
at my handler (procedure). This does indeed work and the screen get modified
as it should while my is running happily along. So far so good. Then
something might happen because sometimes the computer simply stops in the
middle of the program and lock up (refusing warm-boots), other times it runs
all the way to the end and then crashes when returning to either the DOS
prompt or Turbo's IDE (locks up again). At the end of my program I do
remember to reset the vector to the old value, and I even have an error
handler which does the same thing if an runtime error occurs. I also
remember to call the old interrupt handler at the end of my new one.
	I've then tried to use interrupt 08 (Hardware Timer) which btw calls
interrupt 1C during its processing. The result is the same. Crash on the way
or at the end. I've even had an error free run but at the next attempt it
crashed again. The conditions are always the same except the value of the
timer count (time passes!). This random behaviour really bugs me! - If it's
a programming error then it should occur at the same place every time - when
the conditions are the same, right? - And no, I'm not using anything random
inside the program WHAT SO EVER!
	Any ideas? - I feel I've tried it all, varying the compiler
directives (but always $F+ around the handler) and so on. I've tried to turn
interrupts on and off within the handler and sending an end-of-interrupt to
the CPU at the end of my handler - no change at all!. Naturally I've
checked both my program and the handler routine without using the interrupts
and they run perfectly!. No stack or range violations!

	Any hints or ideas would be most appreciated!

		Loads of thanks in advance!

			Per.

Reply by E-mail, but if it fails then please post your reply!

PS: I'm using Turbo Pascal 6.0 Professional as stated in the subject field.

-- 
| Per Gotterup                        | "The most merciful thing in the    |
| Student, DIKU (Dept. of Comp. Sci.) | world, I think, is the inability   |
| University of Copenhagen, Denmark   | of the human mind to correlate all |
| Internet: ballerup@freja.diku.dk    | its contents."  - H.P. Lovecraft - |

zhou@brazil.psych.purdue.edu (Albert Zhou) (01/05/91)

References: <1991Jan4.145541.17737@odin.diku.dk>
Sender: 
Reply-To: zhou@brazil.psych.purdue.edu (Albert Zhou)
Followup-To: 
Distribution: comp
Organization: Purdue University
Keywords: interrupt, timer, turbo pascal

If the program (say, WordPerfect) you are using happens to call Int 1C, when
your TSR is in the middle of running, you will get stuck. 

procedure yourintproc;
interrupt
begin
 set Int 1c to the old vector;
 (so that the interrupted program can do its own clock interrrupt) 
 do your things;

 set Int 1c back to @yourintproc;
end;


                                             

lukrw@vax1.cc.lehigh.edu (01/07/91)

In article <11648@j.cc.purdue.edu>, zhou@brazil.psych.purdue.edu (Albert Zhou) writes:

> If the program (say, WordPerfect) you are using happens to call Int 1C, when
> your TSR is in the middle of running, you will get stuck. 
> 
> procedure yourintproc;
> interrupt
> begin
>  set Int 1c to the old vector;
>  (so that the interrupted program can do its own clock interrrupt) 
>  do your things;
> 
>  set Int 1c back to @yourintproc;
> end;

Please, do not try this.  I don't know what he's getting at (sorry Albert),
but this will definitely not do anything healthy.

A more correct procedure for using int 1c is as follows:

  var
    saveint: pointer;

  procedure intproc; interrupt;
    begin
      {...Do interrupt processing}
      inline($9c/$ff/$1e/saveint);    {Chain to old interrupt}
    end;

  begin {main}
    getintvec($1c, saveint);          {Save old interrupt}
    setintvec($1c, @intproc);         {Install new interrupt handler}

    {....Do main processing}

    setintvec($1c, saveint);          {Restore old interrupt}
  end.

Note to Per:  If you are not using a similar inline call to chain to
the old interrupt, that may be part of the problem.  That simulates
an int by doing a pushf/call to the old routine.  The other thing to
be very careful of is the stack size at the time of the interrupt.  
It is very unpredictable, and you may be running out and not know it.
Be sure to turn off all runtime check to help keep your interrupt
from overflowing the stack, and keep the processing to an absolute
minimum (try not to use any procedures or local variables as well).
It is possible to switch to an alternate stack using an assembly 
routine, which would make things much safer.  Email me for the
procedure if you need it.  -- Kevin

dave@tygra.ddmi.com (David Conrad) (01/07/91)

In article <139.2787282f@vax1.cc.lehigh.edu> lukrw@vax1.cc.lehigh.edu writes:
>                                                The other thing to
>be very careful of is the stack size at the time of the interrupt.  
>It is very unpredictable, and you may be running out and not know it.
>Be sure to turn off all runtime check to help keep your interrupt
>from overflowing the stack, and keep the processing to an absolute
>minimum (try not to use any procedures or local variables as well).
>It is possible to switch to an alternate stack using an assembly 
>routine, which would make things much safer.  Email me for the
>procedure if you need it.  -- Kevin

That may not make things safer.  In fact, if not done extremely carefully,
it could be really, really dangerous.  The reason is that if you switch to
an alternate stack then your handler will most likely not be reentrant, and
if it does reenter it trashes its own stack.  I can think of ways to make
handlers which switch stacks reentrant, but they are ugly and complex (How
about storing the state of the stack in a global variable and have all
instructions which affect the stack execute in `critical' sections of code
with interrupts turned off and the global variable gets updated at the same
time.  Sound like fun?  No?  I didn't think so).
--
David Conrad		|	Computer: SYNTAX ERROR.
dave@tygra.ddmi.com	|	Me: No, a syntax error would be, `Me hit
uunet!tygra!dave	|	    computer in screen with big rock'.
------------------------|	Computer: APPROXIMATELY TWO BILLION DOLLARS.
"Why not just go mad?"	|			-- Dave Barry
-- 
=  CAT-TALK Conferencing Network, Computer Conferencing and File Archive  =
-  1-313-343-0800, 300/1200/2400/9600 baud, 8/N/1. New users use 'new'    - 
=  as a login id.  AVAILABLE VIA PC-PURSUIT!!! (City code "MIDET")        =
   E-MAIL Address: dave@DDMI.COM