[comp.sys.mac.programmer] Stashing A5

oster@dewey.soe.berkeley.edu (David Phillip Oster) (01/23/89)

In article <6347@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes:
_>However, this doesn't address the fact that you may need a different A5
_>from the one in CurrentA5, which was David's point.  This may happen in
_>interrupt driven code that is not switched by MultiFinder.  VBL tasks
_>only run when their application has the processor, but not so things
_>like socket listeners or custom interrupt handlers.  I still don't know
_>any way around this except for stashing a copy of your A5 in
_>code-relative space, which is explicitly forbidden (with good reason)
_>by Tech Note #2.

Be careful here. What is forbidden is modifying your code resources. There
is no problem creating a block of exectuable code at run time, that was
created with a nice constant built -in:

	MOVE.L	#Correct A5,-(sp)
	JSR	socketListener.
	RTS
you create this by saying:

typedef struct JumpBufA5{
	short	moveInstruction;
	long	a5Val;
	short	jsrInstruction;
	long	destination
	short	rtsInstrutcion;
}JumpBufA5, *JumpBufA5Ptr;

	listenerDispatcher = (JumpBufA5Ptr) NewPtr(sizeof(JmpBufA5));
	listenerDispatcher.moveInstruction = MOVEOPCODE;
	listenerDispatcher.a5Val = (long) CurrentA5;
	listenerDispatcher.jmpInstruction = JSROPCODE;
	listenerDispatcher.destination = (long) socketListerner;
	listenerDispatcher.rtsInsuction = RTSOPCODE;

and declare socket listener as:
/*
 */
pascal void socketListener(correctA5)Ptr correctA5;{
	Ptr oldA5;

	oldA5 = SetA5(coeectA5);
	...
	SetA5(oldA5);
}

You might think the above might lead you into trouble on a 68020 because
of the instruction cache. But, the instruction cache should never be
holding any address that NewPtr() is going to return, so the 68020 should
never get confused.  After all, the system reads code in from disk, and if
that isn't modifying memory that is about to be executed, I don't know
what is!

You might think you  could optimise the dispatcher's JSR, RTS to a JMP
instruction. Don't try it: you'll screw up the compiler's popping of
the arguments in socketListener.

The advantage of this trick is it lets you program the MMU to generate an
interrupt if anyone tries to write on one of your code segments.

--- David Phillip Oster            --"When we replace the mouse with a pen,
Arpa: oster@dewey.soe.berkeley.edu --3 button mouse fans will need saxophone
Uucp: {uwvax,decvax}!ucbvax!oster%dewey.soe.berkeley.edu --lessons." - Gasee

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

In article <27674@ucbvax.BERKELEY.EDU> oster@dewey.soe.berkeley.edu.UUCP
(David Phillip Oster) writes:
>Be careful here. What is forbidden is modifying your code resources. There
>is no problem creating a block of exectuable code at run time, that was
>created with a nice constant built -in:

That's not neccessarily true.  A memory manager typically has three kinds
of access checks, read, write, and execute.  In the hypothetical protected
mode OS, it's quite possible that the heap will be turned off for execute
mode access.  This protects against the old "jumping into data space" bug,
just as protecting against writing on executable code prevents against
the obverse "writing into code space" problem.  Still, you're probably
right, since Apple hasn't explicitly warned against putting code into
the heap.

>You might think the above might lead you into trouble on a 68020 because
>of the instruction cache. But, the instruction cache should never be
>holding any address that NewPtr() is going to return, so the 68020 should
>never get confused.  After all, the system reads code in from disk, and if
>that isn't modifying memory that is about to be executed, I don't know
>what is!

True.  I think the reason for this is that instructions aren't cached
until after they have been executed once.  Since this code never
changes except before it's executed the first time, there shouldn't be
a problem.  I believe this is the same reason the OS reads code from
disk without difficulty.

>You might think you  could optimise the dispatcher's JSR, RTS to a JMP
>instruction. Don't try it: you'll screw up the compiler's popping of
>the arguments in socketListener.

Well, except that you can't write a socket listener in anything but
assembler because everything is stored in registers.  I experimented
with a save/restore registers approach and writing a listener in C, but
pushing and popping the registers was too slow given the time
constraints of a listener.  If Apple had put all the information into a
data structure intead of into registers, there wouldn't be a problem.
But since ReadPacket requires the registers to be set up correctly....
-- 
Tim Maroney, Consultant, Eclectic Software, sun!hoptoad!tim
"The time is gone, the song is over.
 Thought I'd something more to say." - Roger Waters, Time