#Code Segment Mgmt …
5 messages in this thread
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
}
}
Joe,
Well, one comment I'd like to make is the idea of "defered segment unloading".
We use this to clean out the heap at a later time when it is safe to do so. We
use a combination of your approach (checking to see if it's in the call chain)
and queueing segments until the main event loop is reached before it is
de-queued.
Works great, and keeps the "UnloadSegs" dependencies out of code. That is,
each module unloads itself.
Cheers,
Rob
Rob:
>>>
We use a combination of your approach (checking to see if it's in the call
chain) and queueing segments until the main event loop is reached before it is
de-queued.
<<<
Do you queue without allocating memory (so that it can be called at GrowZone
time)?
Steve
===>
Do you queue without allocating memory (so that it can be called at GrowZone
time)?
<===
Yeah, we use a statically allocated queue for just that reason. It really
doesn't take too much space. We actually cue up segment ID's and not function
pointers. You can convert back and forth from function pointers to segment
ID's fairly easily.
Cheers,
Rob
Joe:
Is the A6 chain still valid during GrowZone? I know that the Think C Debugger
loses track of the call chain during the GrowZoneProc, but I haven't actually
studied it in TMON to determine whether or not it's the Memory Mgr that's using
A6 for something other than a standard frame pointer.
This is worth knowing, because "else where when the mood hits" most
conveniently would be when you *know* you are pressed for memory.
Steve