[comp.sys.apple] interrupt handling--careful!

AWCTTYPA@UIAMVS.BITNET.UUCP (07/01/88)

>Date:         Sun, 26 Jun 88 22:03:34 GMT
>From:         Sean Kamath <tektronix!reed!kamath@ucbvax.berkeley.edu>

Sean Kamath writes, in response to Bob Church:
>[...]  I don't know what machine you are running
>on, but it's got to be a GS if you have interrupts on the keyboard, or else
>it's someting like the //c's built in interrupt handly, which get's a 60 Hz
>interrupt and polls the keyboard.

Ah...now that's what any reasonable person would think from reading some
of the GS documentation.  "Keyboard interrupts" are indeed mentioned--they
are provided for with some MiscTool calls.  But they don't actually exist.
The closest the IIgs comes to having Keyboard Interrupts is that the Event
Manager installs a HeartBeat Interrupt task (gets called every 1/60 sec) that
polls the keyboard, doing a PostEvent for every key found (stuffing a KeyDown
or AutoKey [repeating key] event into the event queue, along with all the
modifier bits, the TickCount, and the mouse position).

>interrupt service routine: (assuming you aren't using ProDOS to direct them
>to the right place)
>
>    sei     ;no interrupts
     [...]
>    cli
>    rti
     [...]

DON'T RE-ENABLE INTERRUPTS FROM INSIDE AN INTERRUPT HANDLER UNLESS YOU
ARE *SURE* IT WON'T CAUSE A PROBLEM.  A ProDOS interrupt handler should
never do it--and even if you bypass ProDOS and install your own routine
at $3FE/$3FF, I still strongly recommend not doing it.

When a 6502, 65C02, or 65816 in 6502 mode gets an interrupt, the interrupt-
disable flag is automatically set AFTER the flags and return address are
pushed onto the stack.  This means interrupts are ALREADY disabled when
your handler is called, and that they will be AUTOMATICALLY re-enabled
when the RTI restores the old flag byte (the P register) from the stack.

By putting a CLI into your routine, you risk getting another interrupt
BEFORE the RTI occurs, and in a really high-interrupt situation, you
could keep getting interrupts so fast that the pending RTIs (3 bytes
each) would eat up all your stack space and start overwriting important
stuff, leading to a crash when the interrupts finally slow down a bit,
if not sooner.

Even if the above doesn't happen, ProDOS's interrupt handling routines
are NOT designed to be re-entrant (meaning they will not work correctly
if they are called AGAIN before they are finished with the previous
interrupt).  To see this, take a look at what ProDOS does when an IRQ
occurs (start at $3FE/$3FF, which point to ProDOS's interrupt entry on
the $BFxx page).  It stores the CPU registers, as well as lots of
important info about the state of the language card and the active $C800
ROM, in FIXED LOCATIONS.  This info is used to restore the state of the
machine when the interrupt handling is complete.  If a SECOND interrupt
is allowed to occur before ProDOS returns from the first, then new info
will be "preserved" in the locations; the second one will return fine,
but when the FIRST one finally returns, the wrong info will be used to
restore the A/X/Y registers, etc., and a crash will result sooner or
later.

>Sean Kamath
>UUCP:  {decvax allegra ucbcad ucbvax hplabs ihnp4}!tektronix!reed!kamath
>CSNET: reed!kamath@Tektronix.CSNET  ||  BITNET: reed!kamath@PSUVAX1.BITNET
>ARPA:  reed!kamath@PSUVAX1.CS.PSU.EDU
>US Snail: 3934 SE Boise, Portland, OR  97202-3126 (I hate 4 line .sigs!)

--David A. Lyons  a.k.a.  DAL Systems    |  If a B-tree is corrupted
  PO Box 287 | North Liberty, IA 52317   |  in a forest and no error
  BITNET: AWCTTYPA@UIAMVS                |  checking is done, will
  CompuServe: 72177,3233                 |  anyone notice whether its
  GEnie mail: D.LYONS2                   |  stoarge gets deallocated?