From: Jeff E Mandel <mandel@tmc.tulane.edu>
Subject: Re: Memory Manager-safe Deferred Tasks - A Proposal
X-Xxmessage-Id: <A70194E107013009@mandel.anes.tulane.edu>
Nntp-Posting-Host-[nntpd-8982]: mandel.anes.tulane.edu
X-Xxdate: Wed, 14 Oct 92 15:12:01 GMT
Organization: Tulane University School of Medicine
X-Useragent: Nuntius v1.1.1d12
Date: Wed, 14 Oct 1992 14:11:51 GMT

In article <Bw3H6x.IAo@news.cso.uiuc.edu> Pete Resnick,
resnick@cogsci.uiuc.edu writes:
>I like this idea very much, and this would actually be pretty easy to
>implement: You could write a device driver that would simply call the
>routine you specified. You could call the device driver asynchronously,
>which can be done at interrupt time; the call will remain in the queue
>until interrupt time is over and the system gets to call the driver.
>Then the driver would call your task, which would be free to move
>memory. This should happen at least somewhat quicker than having to
>wait for your event loop to come around for the next time.

Well, I have done stuff like this in a driver, and you still have the
same problem - someone has to call SystemTask for the driver to get
called, and you can't always depend on it happening as often as you want.

>
>I do see one problem with the scheme:
>
>>Something like:
>
>>FUNCTION DTHzInstall (dtTaskPtr: QElemPtr, dtHeapZone: THz) : OSErr;
>
>Note that the dtTaskPtr, or the parameter block in the case of my
>device driver idea, would have to be preallocated. You would still run
>into the same problem you have in your internal queue, that you may
>run out of space; in this case, you might run out of the queue
>elements you have allocated. But other than this, it would be no
>problem.

There is no problem with preallocating enough dtTaskPtrs if you are
guaranteed that the time that the dtTask is pending is small. When it is
unbounded, then you need to make it BIG, which is why I strongly advocate
the private queue. If you use a standard system queue, such as the event
queue, you need to enlarge this queue's allocation at boot time, and it
is memory permanently committed to this function.

Since people don't seem to be jumping in on this, here's my thinking on
how to implement DTHzInstall.  It seems to me that the two problems to
avoid are reentering a Memory Manager call that is non-reentrant, and
attempting to move memory in a heap that is not "quiet". I'm pretty sure
that satisfying the first criterion also satisfies the second, but if it
doesn't, we can always solve that as well (why would you ever exit the
Memory Manager with an inconsistent heap?)

The problem is that of a critical section. Unless there is some secret,
undocumented semaphore for the Memory Manager, we create one of our own
by a head/tail patch for every Memory Manager routine. Basically, the
patch increments the semaphore on entry and decrements it on exit. Now,
when our dtTask is delivered, and the semaphore is nonzero, the task is
moved to a private queue, and the tail patch examines this queue, and
when the semaphore decrements to zero, it executes every task there. This
allows for the fact that one Memory Manager trap can invoke another. I'd
probably set the current heap to the one passed in the dtHeapZone
parameter and restore the previous one on exit.

The advantage of this approach is that you aren't messing with the memory
manager to try to make it reentrant, you're just getting your task
executed when the memory Manager isn't involved in managing memory. Sort
of the difference between "Sh*t or get off the pot!" and "Please let me
know when you're done, and if it's not too much trouble, leave me some
paper" :-).

OK, having spread the kerosene on the floor, let me retreat to my bunker
and wait for the flames to rise...

Jeff
Newsgroups: comp.sys.mac.programmer