[comp.sys.amiga] Interrupts

bart@amiga.UUCP (05/08/87)

[eat this line- please]

in article <1089@crash.CTS.COM>, mercurio@crash.CTS.COM (Phil Mercurio) says:
> I need help with a function being called by another function attached
> to the vertical blanking interval interrupt.  The purpose of the
> function is to scroll text onto the screen; it calls ScrollRaster()
> and BltBitMap().

Some (hopefully) helpful tips on writing interrupt servers:

according to the Rom Kernal Manual "certain system operations are not atomic
in nature and may be interrupted after only executing part of an important
instruction sequence.  Take the memeory allocation and deallocation functions
for example...[there is]... a finite possibility of interrupting a memory
related routine.  In such a case, a memory linked list may be inconsistent
when examined from the interrupt code itself.  To avoid serious problems,
the interrupt routine must not use any of the memory allocation or deallocation
functions."

this means (among other things) that attempting to call ANY routine that
indirectly allocated or deallocates memory is inherently dangerous from
interrupt code. this includes graphics routines, which may allocate/deallocate
temporary memory structures.

--------------------------------------------------------------------------------

one proper means of accomplishing the desired result is this then:

a) create a "slave" task which will accomplish your programming goal by calling
the desired function... have this task Wait() for a specific Signal.

b) install an interrupt handler on the desired interrupt chain whose sole
functions are to Signal() the task which you have set up, and return(0)
so that any following interrupts on the chain are serviced normally.

while simple in concept, there are numerous subtle system considerations to
be taken into account when implementing this approach:

1) while the interrupt handler will Signal() the "slave" task at interrupt time,
the "slave" task WILL ONLY BECOME ACTIVE when it is actually resheduled by exec.
if any higher priority task is ready to run, the "slave" task will NOT be the
next task scheduled to run.  thus, another interrupt may occur BEFORE the task
does whatever useful work you have designed it for.

2) if the "slave" task IS sheduled to run BEFORE the next interrupt occurs,
and if it takes too long, another interrupt may be posted before it completes.
this means that as soon as the "slave" task finishes, and Wait()s again, it
will immediately wake up because the Signal will already have been posted to
the task.  remember this, or your slave task may soak up all the system time,
and not allow other tasks their fair share of the processor.

3) don't ignore the possibility that because of priority level, your "slave"
task, EVEN THOUGH IT IS RECEIVING SIGNALS FROM THE INTERRUPT SERVER, conceivablymight not rescheduled until more than one interrupt has occurred. one solution
for this is to have the interrupt server both post a Signal AND increment a
counter variable.  When the slave task is rescheduled, a quick check of the
counter will tell the task how many interrupts have been posted since it last
completed its function; after the quick check, the "slave" task should clear
the counter to zero, so that the whole process can begin again.

--------------------------------------------------------------------------------

applied to the problem initially encountered by Phil Mercurio, this approach
allows the scrolling function to scroll N lines if 1 interrupt has occurred
since the last scroll, or COUNT*N lines if COUNT interrupts have been posted.
setting the "slave" task priority high enough to guarantee a "smooth" scroll
should be balance by a Delay(timeout) before the next Wait() to allow other
tasks to have their turn as well... the "count" implementation will provide a
limited "catch up" capability if other tasks are not good citizens as well.

amiga!bart