Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!uunet!munnari!vuwcomp!cantuar!james From: james@cantuar.UUCP (J. Collier) Newsgroups: comp.sys.mac Subject: Re: turning off the stack sniffer (long) Message-ID: <135@cantuar.UUCP> Date: Thu, 2-Jul-87 02:49:26 EDT Article-I.D.: cantuar.135 Posted: Thu Jul 2 02:49:26 1987 Date-Received: Tue, 7-Jul-87 06:28:46 EDT References: <1289@briar.Philips.Com> Reply-To: james@cantuar.UUCP (J. Collier) Organization: University of Canterbury, Christchurch, New Zealand Lines: 90 Keywords: stack 60 Hz multitasking HeapEnd trap dispatcher dirty illegal Summary: There's another way, but problems aplenty Paul Rutter (per@philabs.Philips.Com) writes: >When playing with "multi-tasking", it is useful to be able to move the stack >pointer to one of several stack areas. The "stack sniffer" routine checks >whether the stack overlaps the heap during every tick, and bombs if it does. > >How do I disable the stack sniffer? Steve Munson (sbm@purdue.edu) suggested an alternative solution to this problem some weeks ago. I used a similar method in an experiment earlier this year - and found it effective to the extent that I tested it (not much). Hope I'm not deluding myself in thinking other people might be interested... NB - the suggestions which follow are most unlikely to work on anything newer than a 128k ROM, if at all. APPLE THOUGHT POLICE PLEASE HIT 'j' NOW...:-) Unfortunately, the 60Hz stack sniffer is not the only ROM routine which checks the stack. Disabling the stack sniffer (by setting StkLowPt to 0, if I remember correctly) also has some messy side-effects. Besides which, it's quite nice to have the sniffer look after the behaviour of ones own heap-resident stacks. The sniffing routines work by comparing the value of the stack pointer to the global HeapEnd. Somewhat surprisingly, changing the value of this global to the new stack limit at each context switch appears to achieve the desired effect. Of course, various other ROM routines will be using HeapEnd. However, after several cross-eyed hours searching a 128k ROM, I found only the following references to HeapEnd: 4008fc : Stack Sniffer (read) 409172 : GetFInfo - stack check (read) 40c218 : MapRgn - stack check (read) 40fed6 : SetApplBase (set) 4100b4 : SetApplLimit (set) 4108xx : MoreMasters (read & set) 4135a6 : InitResources (can't remember, but who cares?) So it seems that HeapEnd is normally used only to mark the limit of the stack area. SetApplBase, SetApplLimit and InitResources shouldn't be called after the application is under way. MoreMasters is trickier; I just allocated a large block of masters during initialisation and hoped for the best, but you will probably want to patch the trap. BTW, how are you initiating context switches? Doing it on the 60Hz interrupt I came across several problems: 1. I found I had to patch the interrupt vector and do the switch *after* the normal VBL tasks. 2. I had to disable switching during ROM routines (non-reentrant code :-(). This involved (don't barf) hooking the trap dispatcher. Tricky. Scott Knaster mentions (in "How to Write Macintosh Software") a particularly revolting system patch which relies on the value of the return address being from a certain ROM routine. The dispatcher therefore has to replace the stack frame if the routine was called from user code, but not if called from another ROM routine. Oh, what the ***, the bored will have stopped reading by now, so here goes.. It breaks every rule in the book: self modification, RTE, etc. etc. Do you want to run this on a 68020? %-Q ----------------------------------------------------------------------- /* set A-trap vector to "mytrdsp" */ #define CANTXFER APPLSCRATCH /* inhibit context switch if set */ #define XFERPEND APPLSCRATCH+1 /* c-s blocked during ROM call? */ /* (refer VBLtrap.c) */ #define SAVERA APPLSCRATCH+2 /* save return address here */ /*<4EA> <2SR> <-SP */ mytrdsp: tst.b CANTXFER /* set if called from ROM */ bne.s jtdisp /* if set, we can't mess with the stack */ addq.b #1, CANTXFER /* disable hook in ROM-ROM calls */ movem.l A0/A1, -(A7) /* <4EA> <2SR> <8SV>*/ movea.l 10(A7), A0 /* EA -> A0 */ lea trpcpy, A1 /* &(word after jmp) -> A1 */ move.w (A0), (A1) /* Axxx -> (word after jmp) */ addq.l #2, A0 /* skip trap word on rte */ move.l A0, SAVERA /* RA -> global */ move.l A1, 10(A7) /* <4MYEA><2SR><8SV> */ movem.l (A7)+, A0/A1 /* <4MYEA><2SR> */ jtdisp: jmp /* initialise on load */ trpcpy: dc.w 0xA000 /* dummy trap copied from code */ move.l SAVERA, -(A7) /* restore saved return address */ move.l SR, -(A7) /* push SR - cc's not needed */ /* assert : CANTXFER == 1 */ clr.b CANTXFER /* returning to user code - clear flag */ tst.b XFERPEND /* set if process xfer was blocked */ beq.s immrtn /* if not, return now */ jsr /* context switching routine */ immrtn: rte /* return & restore saved SR */ ------------------------------------------------------------------------------ Grubbiness rules, OK? Have fun. ------------------------- James Collier (james@cantuar.uucp / {watmath,munnari,mcvax}!cantuar!james Computer Science Dept., University of Canterbury, Christchurch, New Zealand. My supervisor doesn't know that I'm doing this.