#Code Segment Mgmt …
Hi y'all,
The following code is used to manage code segment traffic in a large THINK C
with objects application. We use the TCL and the Prepare() class libraries. I
would like anyone's comments on this code. Anything appreciated. Your payment
in full is the code itself. Please maintain the copyright notice.
The usage is to make a call like this …
void main()
…
InitSegmentMgr();
…
) // end main()
and then else where when the mood hits …
UnloadSegment( Routine_In_Segment_Name );
Thanks,
// joe
/*
* SegmentMgr.c – routines for managing code segments
*
* Copyright ~ 1991 Christopher R. Wysocki. All rights reserved.
*
*/
// #include "SegmentMgr.h"
#define __DEBUG__
static long gOrigA6;
/*
* InitSegmentMgr
*
* Initialize our segment manager.
* This routine should be called as the first function in main().
*/
void InitSegmentMgr(void);
void InitSegmentMgr(void)
{
asm {
move.l a6,gOrigA6 ; save initial value of a6
}
}
/*
* UnloadSegment
*
* Call this routine instead of the Toolbox routine _UnloadSeg to unload
* a segment. This routine walks through the A6 chain to ensure that no
* routine in the segment to be unloaded is in the current calling chain.
*
*/
void UnloadSegment(void *routineAddr);
void UnloadSegment(void *routineAddr)
{
asm {
movem.l a3-a4,-(a7) ; save registers on stack
movea.l routineAddr,a0 ; get pointer to jump table entry
cmpi.w #0xA9F0,4(a0) ; is the segment loaded?
beq @4 ; go return if not
subq.w #4,a7 ; space for result
pea 'CODE' ; push resource type
move.w -2(a0),-(a7) ; push segment number (resource ID)
_GetResource ; get the appropriate CODE resource
move.l (a7)+,a0 ; pop the resource handle
#ifdef __DEBUG__
cmpa.l #0,a0 ; is the handle nil?
bne.s @0 ; branch if not
pea @cantLoadCODERsrc ; push pointer to message
_DebugStr ; drop into Macsbug
bra.s @4 ; and go return
@cantLoadCODERsrc:
dc.b "\pUnloadSegment: can't load CODE resource!"
@0
#endif
move.l (a0),d0 ; get master pointer
_StripAddress ; strip off high byte if in 24-bit mode
movea.l d0,a3 ; save ptr to start of block in a3
_GetHandleSize ; get size of CODE resource handle
movea.l a3,a4 ; keep block ptr in a4
adda.l d0,a4 ; add length to get ptr to byte after block
movea.l a6,a1 ; a1 walks through the a6 calling chain
@1 cmpa.l gOrigA6,a1 ; are we at the end of the calling chain?
beq.s @3 ; exit loop if so
move.l 4(a1),d0 ; get return address
_StripAddress ; strip off high byte if in 24-bit mode
cmp.l a3,d0 ; check if this address is in the segment
blo.s @2 ; that we want to unload — if it is,
cmp.l a4,d0 ; exit the loop without unloading the
blo.s @4 ; segment
@2 movea.l (a1),a1 ; the return address isn't in the segment,
bra.s @1 ; so get previous contents of a6 and loop
@3 move.l routineAddr,-(a7) ; push pointer to routine
_UnloadSeg ; unload the segment
@4 movem.l (a7)+,a3-a4 ; restore registers from stack
}
}