From: grobbins@Apple.COM (Grobbins)
Newsgroups: comp.sys.mac.programmer
Subject: Re: Deferred Tasks - What can I do?
Date: 7 Oct 92 23:59:07 GMT
Organization: Apple Computer Inc., Cupertino, CA

In article <Bvq666.MHH@news.cso.uiuc.edu> resnick@cogsci.uiuc.edu (Pete Resnick) writes:
>Can I move memory (e.g. call NewPtr) in a deferred task, i.e. one I
>installed with DTInstall?

No, since deferred tasks must adhere to interrupt-time restrictions.
This is discussed in Jim Luther's DTM tech note (#320, for those
who still believe in numbers.)  I'll paste the relevant portion
below.

Grobbins            grobbins@apple.com

Usual disclaimers apply.

---

from Tech Note 320, "Deferred Task Traps, Truths, and Tips":

How and when the Deferred Task Manager calls deferred tasks

Since understanding how something works usually answers most questions about
it, this note gives a complete explanation of how deferred tasks get called.
 I'll start with the occurrence of an interrupt.

When an interrupt occurs, the processor stops executing the current program
and control is passed to the Macintosh's primary interrupt handler.  The
primary interrupt handler saves registers A0-A3/D0-D3 and then decides what
secondary interrupt handler to dispatch to.  If the system has an MMU, was
booted 24-bit mode but is presently in 32-bit mode, then the MMU state is
saved and the MMU is switched to 24-bit mode.  If the system has power
management (i.e., is a portable Macintosh) and is in slow speed, the speed
is saved and is then switched to full speed.  Control is then passed to the
secondary interrupt handler which handles the interrupt.

When control returns to the primary interrupt handler from the secondary
interrupt handler, the primary interrupt handler checks to see if there are
any deferred tasks in the deferred task queue and checks to see if upon exit
of this interrupt, the processor priority level will be returned to 0.  If
both conditions are true, control is passed to the Deferred Task Manager to
execute those tasks.

The Deferred Task Manager checks to see if a deferred task is already
active; if so, the Deferred Task Manager exits.  Otherwise, one by one, each
deferred task in the deferred task queue is dequeued, and then called with
register A1 containing dtParm from the DeferredTask record and the processor
priority level is set to 0 (i.e., all interrupts are enabled).  When all
deferred tasks have been dequeued and called, control is returned to the
primary interrupt handler.

When control returns to primary interrupt handler from the Deferred Task
Manager, the primary interrupt handler restores the MMU state and speed if
necessary and then restores registers A0-A3/D0-D3.  Then the primary
interrupt handler returns control to the program executing before the
interrupt occurred.

With that explanation out of the way, here are a few things that may or may
not be obvious.

Deferred tasks are interrupt time code

That is, deferred tasks are run as a result of an interrupt.  A deferred
task must follow many of the same rules as a interrupt handler.  Here's a
warning to go along with the material in the Deferred Task Manager chapter
of Inside Macintosh Volume V.

Warning:	Deferred tasks are executed at the interrupt level and must
preserve all registers other than A0-A3 and D0-D3.  Your deferred task must
not make any calls to the Memory Manager, directly or indirectly, and can't
depend on handles to unlocked blocks being valid.  If it uses application
globals, it must also ensure that register A5 contains the address of the
boundary between the application globals and the application parameters; for
details, see Setting and Restoring the A5 Register in the Memory Management
chapter of Inside Macintosh Volume VI.  Your deferred task should avoid
accessing a low-memory variables or calling a trap that would access one
because while MultiFinder@ or System 7 is running, application low-memory
global variables are being swapped in and out. 

Deferred tasks can be interrupted

That's the purpose of using deferred tasks - to let interrupt driven
processes keep running while your deferred task completes a lengthy task. 
This means that your deferred task must be interruptible-that is, you should
not have to do anything such as timing-critical hardware access that can get
screwed up with interrupts on.

If the interrupt handler that installs the deferred task can be called again
while that deferred task is executing, then you also need to make sure the
way the interrupt handler and the deferred task code work together is
reentrant.  For example, the interrupt code should not modify a data buffer
that the deferred task is processing.

Deferred tasks are not prioritized

Deferred tasks are executed in the order they were added to the deferred
task queue no matter what interrupt level the code installing the task may
have been running at.

Deferred task latency

There may be significant latency incurred between installing a deferred task
with DTInstall and when that task is performed.  This time is not
deterministic and cannot be controlled.  Real-time response cannot be
guaranteed on Macintosh computers with or without the use of deferred tasks.

Newsgroups: comp.sys.mac.programmer