[comp.sys.mac.programmer] Stack manipulation problems

bob@xanadu.COM (Bob Schumaker) (01/06/89)

We are in the process of implementing a multi-tasking executive and we are
running into a problem when we move the stack.  The premise is that we
can allocate some storage in the heap, make the stack pointer point
to this storage (after setting up A6 and then copying the stack frame)
and restarting execution with the new values (using setjmp/longjmp under
LSC 3.01p3).  (This clever hack was suggested to us by Michael McClary.  It
is known to work just fine on various onther systems, so the principle is
sound if not particularly pleasing to purists).  By the way, the stack
sniffer *is* disabled during the process.

As soon as the stack pointer and A6 contain the new values, the Mac
environment behaves strangely -- the menus highlight with a black
rectangle (no highlighted text shows) and/or the text disappears from
the menus.  Things get progressively weirder from there.

As a check, we just copied the stack frame (using the same method) several K
below the stack pointer (unused memory between the heap and the stack) and
set up all the appropriate registers in an identical fashion -- and
everything worked just fine!

Does anyone out there have any idea what's going on?  The only thing that
we can figure is that somewhere in the Mac system software, some routine
cares where the stack is -- someone that is, besides the stack sniffer,
which *should* be disabled at this point...

Thanks in advance.

tim@hoptoad.uucp (Tim Maroney) (01/06/89)

In article <ebmyn#1CMsZI=bob@xanadu.COM> bob@xanadu.COM (Bob Schumaker) writes:
>We are in the process of implementing a multi-tasking executive and we are
>running into a problem when we move the stack.  The premise is that we
>can allocate some storage in the heap, make the stack pointer point
>to this storage (after setting up A6 and then copying the stack frame)
>and restarting execution with the new values (using setjmp/longjmp under
>LSC 3.01p3).
>
>As soon as the stack pointer and A6 contain the new values, the Mac
>environment behaves strangely -- the menus highlight with a black
>rectangle (no highlighted text shows) and/or the text disappears from
>the menus.  Things get progressively weirder from there.

Clearly data in the heap are getting overwritten, therefore you are not
leaving enough space for the stack.  Bear in mind that the Mac OS has
only one stack -- OS interrupt-driven code will run on whatever the
current SP is set to, as will desk accessories if you give them time.
Make sure you have left at least 8K of stack space.

Check this by using MacsBug's heap check function.  If you are overwriting
heap data belonging to other blocks, the heap checker will almost surely
give an error.

I assume you have remembered that 68K stacks grow downwards, so you
need to set the SP to the *end* of the block you've allocated, that is,
the highest address, not the lowest address.  (Actually it should be
set to the highest address minus four bytes.)

>As a check, we just copied the stack frame (using the same method) several K
>below the stack pointer (unused memory between the heap and the stack) and
>set up all the appropriate registers in an identical fashion -- and
>everything worked just fine!

Move the stack away from the heap and you're pretty darned unlikely to
overwrite other data in the heap.

>Does anyone out there have any idea what's going on?  The only thing that
>we can figure is that somewhere in the Mac system software, some routine
>cares where the stack is -- someone that is, besides the stack sniffer,
>which *should* be disabled at this point...

"Looking for bugs in all the wrong places...."  The menu manager problems
indicate that the menu manager heap data structures are getting trashed.
-- 
Tim Maroney, Consultant, Eclectic Software, sun!hoptoad!tim
"Please help support the moratorium on meaningless quotes in .signatures."
  -- Doug Asherman on rec.music.cd

grg@berlin.acss.umn.edu (George Gonzalez) (01/07/89)

I ran into exactly the same problems when implementing multi-tasking
within a program I was writing.  I did a lot of head scratching until
I peeked at the stack, and some of the ROM trap code.

What's happening is that many of the ROM traps assume that they can
use the space above the op of the appl heap up to the bottom of the stack
for temporary storage.  I think UnionRgn is one of the worst offenders,
dividing up that space into 3-5 equal sized chunks and putting temporary
QuicDraw regions in each chunk.  This is OK under normal stack usage, but
bad if you have several stacks in the stack area.  Some of them will get
creamed by the temporary vars.
  There's also a problem if you created the stacks in the appl heap.  Now
UnionRgn sees that there's no room below the stack and above the heap, as
the stack is *inside* the heap.  So it just quietly does nothing.  This
explains why screen redraws get garbled, as QuickDraw can't do its job.

When I asked Apple how to solve the problem, they suggested doing all
QuickDraw calls from the bottommost stack (the one that has clear space below
it down to the top of the appl heap).  So allocate your screen update task
*last*, and don't draw from any other task.   Ugly, but that's the way it is.

It would be nice if Apple cleaned up their stack usage.  But this would require
new ROM's, so its not likely to happen to fix this problem.

jmunkki@kampi.hut.fi (Juri Munkki) (01/07/89)

In article <275@berlin.acss.umn.edu> grg@berlin.acss.umn.edu (George Gonzalez) writes:
>What's happening is that many of the ROM traps assume that they can
>use the space above the op of the appl heap up to the bottom of the stack
>for temporary storage.  I think UnionRgn is one of the worst offenders,
>dividing up that space into 3-5 equal sized chunks and putting temporary
>QuicDraw regions in each chunk.  This is OK under normal stack usage, but
>bad if you have several stacks in the stack area.  Some of them will get
>creamed by the temporary vars.

Makes me wonder what happens if an exception happens when quickdraw is
using the space below the stack. If this exception uses a lot of stack
space, isn't it likely that it will overwrite some of the temporary
storage?

_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
|     Juri Munkki jmunkki@hut.fi  jmunkki@fingate.bitnet        I Want   Ne   |
|     Helsinki University of Technology Computing Centre        My Own   XT   |
~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~

ts@cup.portal.com (Tim W Smith) (01/08/89)

Is the stack sniffer still around?  I was developing a simple multitasking
system to be downloaded to a stand-alone 68k system, and was using my
Mac II to test the code ( TMON and LightspeedC make a great 68k
development system ).  There were several stacks in my heap area.
Since my system did no Mac system calls, I didn't get any of the
problems with screen manipulation or anything like that.

But I definitely forgot about the stack sniffer.  I did not disable it.
Yet, I got no bombs.  What's going on?

						Tim Smith

parent@Apple.COM (Sean Parent) (01/10/89)

In article <18694@santra.UUCP>, jmunkki@kampi.hut.fi (Juri Munkki) writes:
> In article <275@berlin.acss.umn.edu> grg@berlin.acss.umn.edu (George Gonzalez) writes:
> >What's happening is that many of the ROM traps assume that they can
> >use the space above the op of the appl heap up to the bottom of the stack
> >for temporary storage.  I think UnionRgn is one of the worst offenders,
> Makes me wonder what happens if an exception happens when quickdraw is
> using the space below the stack. If this exception uses a lot of stack

I believe that QD just moves A7 to gobble up a good sized piece of the stack.
The worst problem is that it uses a couple different methods to determine where
the bottom of the stack is (I believe they are all based on low memory globals).
Using multible stacks with QD is very tricky and certinly not recomended.

Sean

parent@Apple.COM (Sean Parent) (01/10/89)

In article <13322@cup.portal.com>, ts@cup.portal.com (Tim W Smith) writes:
> Is the stack sniffer still around?  I was developing a simple multitasking

> development system ).  There were several stacks in my heap area.

> But I definitely forgot about the stack sniffer.  I did not disable it.
> Yet, I got no bombs.  What's going on?

I am not sure but a believe that that stack sniffer looks for the top of the
heap to be overwritten when the SP is out of range. I do know that you do not
need to worry about the stack sniffer if you are using A7 to manage your own
stacks. Lot's of software uses A7 as just another address register for things
like fast blitters.

Note - You should not try to use QD while you are operating with an alternate
stack there are major problems with doing so. (see other articles for more info)

Sean

shebanow@Apple.COM (Andrew Shebanow) (01/15/89)

What you are experiencing is a common problem encountered
by people trying to implement multiple threads of execution
within a single Mac application.

The problem is that QuickDraw (and certain Memory Manager calls)
use the stack to store temporary data. They determine how much
space is available by subtracting the top of the application heap
from the current stack pointer. Since your stack pointer is INSIDE
of your heap, you get a very large negative number for stack size.
QuickDraw then proceeds to wipe some amount of memory doing its
drawing. Depending on where your stack is, and how much stack
QuickDraw thinks it has, all sorts of bad things can happen.

The workaround is to switch to the main stack BEFORE calling
any Mac traps. You can do this by a) patching the A-TRAP dispatcher
or b) using glue for all traps.

Andrew Shebanow
Macintosh Developer Technical Support
Apple Computer