gstein@oracle.uucp (Gregory Stein) (02/02/90)
[ I posted this once before and received no response, so I'm trying
again... ]
Geez, it seems like StripAddress needs to be called *everywhere* if
you want to be 32-bit clean. If you maintain any kind of information
within a handle, it appears that you are required to call StripAddress
to access that information. Now, sure, I can dereference, strip it,
and store it so that I don't have to call StripAddress again (say, in
a sequence of stores), but as soon as I call a routine that moves
memory, I'll have to do it again.
I've been programming the Mac for almost six years now, but this whole
issue has me kind of stymied. Am I missing something here? For a
concrete example, let's define a structure like this:
struct foo {
int a, b, c;
} **bar;
bar = (struct foo **) NewHandle(sizeof(struct foo));
Now, when I say "(*bar)->a" is this 32-bit clean? For this example
and the current system software it is because the flag bits in the
handle represented by bar are zero, so there is no problem (the object
is not locked, purgable, or a resource). What happens if I do
something like:
HLock((Handle)bar);
(*bar)->a = f(); /* f() and g() move memory */
(*bar)->b = g();
HUnlock((Handle)bar);
Now, is this fragment still 32-bit clean? I would assume it isn't
because when the dereference (*bar) occurs, I pick up the flag bit in
the master pointer. The solution would be to add a StripAddress, but
what would happen if I did something like:
(*bar)->a = 50;
f();
(*bar)->b = 60;
g();
(*bar)->c = 70;
Do I have to add a strip address everywhere? Well, maybe. I might
have this code fragment in a routine that takes bar as a parameter.
The calling function may pass a normal handle or a resource handle.
Well, what should I do? Calling StripAddress everywhere seems like a
job for Mr. Anal Retentive Programmer. Should I ignore the issue when
dealing with handles? i.e. if I get a handle with flag bits in the
master pointer, then I'm in 24-bit mode and I don't care, but if it
has no flag bits then I'm in 32-bit mode and I still don't care? This
seems to be appropriate, but it also seems like the Mac can run in
32-bit mode but still use the current Memory Manager. Or is 32-bit
mode only supposed to be turned on by, say, a NuBus driver who uses
lots of StripAddress calls and then turns 32-bit mode off?
Thanx for any input.
--
Greg Stein -- This posting bears no relation to my employer
Arpa: gstein%oracle.uucp@apple.com
UUCP: ..!{uunet,apple}!oracle!gstein
keith@Apple.COM (Keith Rollin) (02/02/90)
In article <1990Feb2.010425.28126@oracle.com> gstein@oracle.uucp (Gregory Stein) writes: > >Geez, it seems like StripAddress needs to be called *everywhere* if >you want to be 32-bit clean. If you maintain any kind of information >within a handle, it appears that you are required to call StripAddress >to access that information. Now, sure, I can dereference, strip it, >and store it so that I don't have to call StripAddress again (say, in >a sequence of stores), but as soon as I call a routine that moves >memory, I'll have to do it again. > >I've been programming the Mac for almost six years now, but this whole >issue has me kind of stymied. Am I missing something here? For a >concrete example, let's define a structure like this: > > struct foo { > int a, b, c; > } **bar; > bar = (struct foo **) NewHandle(sizeof(struct foo)); > >Now, when I say "(*bar)->a" is this 32-bit clean? For this example >and the current system software it is because the flag bits in the >handle represented by bar are zero, so there is no problem (the object >is not locked, purgable, or a resource). What happens if I do >something like: > > HLock((Handle)bar); > (*bar)->a = f(); /* f() and g() move memory */ > (*bar)->b = g(); > HUnlock((Handle)bar); > >Now, is this fragment still 32-bit clean? I would assume it isn't >because when the dereference (*bar) occurs, I pick up the flag bit in >the master pointer. Of course it's 32-bit clean. In 24-bit mode, the hardware effectively ignores the high bits, so we used them for tag bits. In 32-bit mode, we naturally can't use the high byte for flags, or you would still be limited to a 24-bit address space. So when you are in 32-bit mode, the Memory Manager puts the bits elsewhere, freeing up the upper byte for address lines (there's actually a parallel 512 megabyte space in machines with the 32-bit Memory Manager, so that we can store the tag bits there :-) You only have to use StripAddress if you need to do master pointer comparisons or pointer arithmetic (e.g. subtract two pointers to find the size of data between them). -- ------------------------------------------------------------------------------ Keith Rollin --- Apple Computer, Inc. --- Developer Technical Support INTERNET: keith@apple.com UUCP: {decwrl, hoptoad, nsc, sun, amdahl}!apple!keith "Argue for your Apple, and sure enough, it's yours" - Keith Rollin, Contusions
am524@umd5.umd.edu (Matthew T. Russotto) (02/02/90)
In article <1990Feb2.010425.28126@oracle.com> gstein@oracle.uucp (Gregory Stein) writes:
+>[ I posted this once before and received no response, so I'm trying
+> again... ]
+>
+>
+> struct foo {
+> int a, b, c;
+> } **bar;
+> bar = (struct foo **) NewHandle(sizeof(struct foo));
+>
+>Now, when I say "(*bar)->a" is this 32-bit clean? For this example
+>and the current system software it is because the flag bits in the
+>handle represented by bar are zero, so there is no problem (the object
+>is not locked, purgable, or a resource).
Yes. The problem with the flag bits being in the upper 8 bits of the master
pointer is NOT YOUR PROBLEM. It is the MEMORY MANAGER itself which is NOT
32-bit clean (naturally, on 32-bit clean systems, the memory manager IS
32-bit clean, and the flags are stored elsewhere)
+> What happens if I do something like:
+>
+> HLock((Handle)bar);
+> (*bar)->a = f(); /* f() and g() move memory */
+> (*bar)->b = g();
+> HUnlock((Handle)bar);
+>
+>Now, is this fragment still 32-bit clean?
Yes.
+>Well, what should I do? Calling StripAddress everywhere seems like a
+>job for Mr. Anal Retentive Programmer. Should I ignore the issue when
+>dealing with handles? i.e. if I get a handle with flag bits in the
+>master pointer, then I'm in 24-bit mode and I don't care, but if it
+>has no flag bits then I'm in 32-bit mode and I still don't care? This
+>seems to be appropriate, but it also seems like the Mac can run in
+>32-bit mode but still use the current Memory Manager. Or is 32-bit
+>mode only supposed to be turned on by, say, a NuBus driver who uses
+>lots of StripAddress calls and then turns 32-bit mode off?
You just summarized the right answer-- I can think of only two reasons
to call StripAddress-- one is when comparing master pointers, so you
don't get the flags (why you would want to compare master pointers is
a different question). The other is when you have 32-bit mode on with
an UNCLEAN memory manager. Then, it will strip Memory manager generated
pointers so your routine can still get at them (instead of wrapping into
bus-errorville). Most programs will run with 24-bit mode always on.
On a 32-bit clean system, StripAddress returns its argument unchanged.
siegel@endor.harvard.edu (Rich Siegel) (02/02/90)
In article <1990Feb2.010425.28126@oracle.com> gstein@oracle.uucp (Gregory Stein) writes: >[ I posted this once before and received no response, so I'm trying > again... ] > >Geez, it seems like StripAddress needs to be called *everywhere* if >you want to be 32-bit clean. If you maintain any kind of information >within a handle, it appears that you are required to call StripAddress >to access that information. Now, sure, I can dereference, strip it, >and store it so that I don't have to call StripAddress again (say, in >a sequence of stores), but as soon as I call a routine that moves >memory, I'll have to do it again. Not quite. You should call StripAddress if you want to be sure that the address you get by dereferencing a handle is clear of any extra information such as flag bits. This is useful if you're planning to do any kind of address arithmetic. However, in the normal case, you can double-indirect a locked (or purgeable, or resource) handle and still get the right thing, because the system only uses the low-order 24 bits of whatever addresses you use. When the system runs in 32-bit mode, the flag bits will be kept in some place other than the high byte of the handle, since the system will use all 32 bits of the address. This means that you can still single-and double-indirect handles safely, but you should NOT use $00FFFFFF as a mask to get rid of the flag bits, since you'll smash the upper 8 bits of a 32-bit address and end up with a pointer to hell. :-) R. ~~~~~~~~~~~~~~~ Rich Siegel Staff Software Developer Symantec Corporation, Language Products Group Internet: siegel@endor.harvard.edu UUCP: ..harvard!endor!siegel "When someone who makes four hundred and fifty dollars an hour wants to tell you something for free, it's a good idea to listen." ~~~~~~~~~~~~~~~
paul@taniwha.UUCP (Paul Campbell) (02/04/90)
In article <1461@husc6.harvard.edu> siegel@endor.UUCP (Rich Siegel) writes: >In article <1990Feb2.010425.28126@oracle.com> gstein@oracle.uucp (Gregory Stein) writes: >> >>Geez, it seems like StripAddress needs to be called *everywhere* if >>you want to be 32-bit clean. If you maintain any kind of information > > Not quite. You should call StripAddress if you want to be sure >that the address you get by dereferencing a handle is clear of any >extra information such as flag bits. This is useful if you're planning to >do any kind of address arithmetic. However, in the normal case, you >can double-indirect a locked (or purgeable, or resource) handle and >still get the right thing, because the system only uses the low-order >24 bits of whatever addresses you use. It is also a problem if you are going to do a SwapMMUMode(1) call to get to 32-bit addressing on a 24-bit system in order to access a board with more than 1Mb of slot space and then want to work with any indirected handle, including the address of HLock()ed code - you have to load the address of code, Stripaddress it and jump to it ie: lea @1, a0 move.l a0, d0 _StripAddress move.l d0, a0 jmp (a0) @1: move.l #1, d0 _SwapMMUMode Paul -- Paul Campbell UUCP: ..!mtxinu!taniwha!paul AppleLink: CAMPBELL.P "Skifield": N, device to collect and refine assholes
dwb@archer.apple.com (David W. Berry) (02/06/90)
In article <1990Feb2.010425.28126@oracle.com> gstein@oracle.uucp (Gregory Stein) writes: >[ I posted this once before and received no response, so I'm trying > again... ] > > struct foo { > int a, b, c; > } **bar; > bar = (struct foo **) NewHandle(sizeof(struct foo)); > >Now, when I say "(*bar)->a" is this 32-bit clean? For this example Yes. If the flag bits are in the upper byte, the memory mapping hardware will be set to ignore the upper byte. If full 32 bit addresses are being used, the flags will be kept somewhere other than the upper byte. The primary things to remember to be 32 bit clean are: 1. Don't use bset/bclr to change or access flag bytes. Use HLock, HGetState, etc. 2. Don't fake handles. A handle and an &Pointer aren't the same thing. If you want to include your custom ?DEF in line in your program the following routine is real handy: ProcHandle ProcToHandle(ProcPtr proc) { struct ProcJmp { short jmp; ProcPtr addr; } **hand; hand = (struct ProcJmp **) NewHandle(sizeof(**hand)); (**hand).jmp = 0x4ef9; (**hand).addr = StripAddress(proc); /* excessive paranoia */ return (ProcHandle) hand; } 3. Don't try to walk the zone. The zone format is subject to change. If it changes you'll likely blow up. 4. Use GetWVariant and GetCVariant instead of using the upper byte of the definition routine. If you have to set the variant be real careful, remember to check for an auxilliary record and change the variant there if it exists. If not set it in the upper byte.
CXT105@psuvm.psu.edu (Christopher Tate) (11/19/90)
Do I need to call StripAddress() in the following situation? Here's the relevant code: Handle myHand; unsigned char *myPtr; myHand = NewHandle(AMOUNT); HLock(myHand); myPtr = StripAddress(*myHand); /* <-- do I need to do this? */ /* Now, put stuff into the block, using and incrementing myPtr */ Do I need to call StripAddress(*myHand) to make sure I get a valid pointer into the block? I *think* I do, because the master pointer might have strange stuff in it, but I'm not sure, and the tech note isn't too clear on this.... ------- Christopher Tate | etaT rehpotsirhC Bitnet: cxt105@psuvm | mvusp@501txc :tentiB Uucp: ...!psuvax1!psuvm.bitnet!cxt105 | 501txc!tentib.mvusp!1xavusp!... :pcuU Internet: cxt105@psuvm.psu.edu | ude.usp.mvusp@501txc :tenretnI
wilkins@jarthur.Claremont.EDU (Mark Wilkins) (11/20/90)
In article <90323.102417CXT105@psuvm.psu.edu> CXT105@psuvm.psu.edu (Christopher Tate) writes: >Do I need to call StripAddress() in the following situation? Here's the >relevant code: > >Handle myHand; >unsigned char *myPtr; > >myHand = NewHandle(AMOUNT); >HLock(myHand); >myPtr = StripAddress(*myHand); /* <-- do I need to do this? */ >/* Now, put stuff into the block, using and incrementing myPtr */ > >Do I need to call StripAddress(*myHand) to make sure I get a valid >pointer into the block? NO, you do not, and in a tight loop you shouldn't. Here's my logic: myHand points to a master pointer like this when running in 24-bit mode: xxxx xxxx 0000 0000 0000 0000 0000 0000 where the x's are mem. manager flags and the 0's are address data. In 32-bit mode the master pointer looks like this: 0000 0000 0000 0000 0000 0000 0000 0000 If you make a copy of the master pointer and increment it by two, you get the following: xxxx xxxx 0000 0000 0000 0000 0000 0010 (24-bit) 0000 0000 0000 0000 0000 0000 0000 0010 (32-bit) However, the 24-bit memory manager ignores the top 8 bits, whereas the 32-bit memory manager does not. So you get the right address when you access your incremented pointer. The case where StripAddress is needed is where you could be running in 24-bit mode and you call SwapMMUMode to set the addressing to 32-bit for a short time, as is necessary when accessing PixMap data directly. In that case, you need to make sure that the address is stripped before switching, because if it is not, the system will bus error when it tries to evaluate the flags as address bits. -- Mark Wilkins -- ******* "Freedom is a road seldom traveled by the multitude!" ********** *-----------------------------------------------------------------------------* * Mark R. Wilkins wilkins@jarthur.claremont.edu {uunet}!jarthur!wilkins * ****** MARK.WILKINS on AppleLink ****** MWilkins on America Online ******
stevec@Apple.COM (Steve Christensen) (11/20/90)
CXT105@psuvm.psu.edu (Christopher Tate) writes: >Do I need to call StripAddress() in the following situation? Here's the >relevant code: > >Handle myHand; >unsigned char *myPtr; > >myHand = NewHandle(AMOUNT); >HLock(myHand); >myPtr = StripAddress(*myHand); /* <-- do I need to do this? */ >/* Now, put stuff into the block, using and incrementing myPtr */ > >Do I need to call StripAddress(*myHand) to make sure I get a valid >pointer into the block? I *think* I do, because the master pointer >might have strange stuff in it, but I'm not sure, and the tech note >isn't too clear on this.... No, the pointer is valid without calling StripAddress(). In 24-bit addressing mode (non-A/UX, non-VM), the upper 8 bits of a pointer can contain some bits used by the Memory Manager, but they're ignored for address purposes. Generally you only need to call StripAddress if you need to compare two addresses, since then the full 32 bits is used... steve -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ whoami? Steve Christensen snail: Apple Computer, 20525 Mariani Ave, MS-81CS, Cupertino, CA 95035 internet: stevec@apple.com AppleLink: stevec CompuServe: 76174,1712
russotto@eng.umd.edu (Matthew T. Russotto) (11/20/90)
In article <90323.102417CXT105@psuvm.psu.edu> CXT105@psuvm.psu.edu (Christopher Tate) writes: >Do I need to call StripAddress() in the following situation? Here's the >relevant code: > >Handle myHand; >unsigned char *myPtr; > >myHand = NewHandle(AMOUNT); >HLock(myHand); >myPtr = StripAddress(*myHand); /* <-- do I need to do this? */ >/* Now, put stuff into the block, using and incrementing myPtr */ > >Do I need to call StripAddress(*myHand) to make sure I get a valid >pointer into the block? I *think* I do, because the master pointer >might have strange stuff in it, but I'm not sure, and the tech note >isn't too clear on this.... No. Not in this case. What will happen here is IF 32-bit memory manager is running THEN no garbage in master ptr ELSE (24 bit memory manager) garbage is ignored by MMU. You would need it if you put the MMU in 32 bit mode when under a 24-bit memory manager, i.e. Handle myHand; unsigned char *myPtr; extern Ptr hugebitmap /* 32-bit pointer into NuBus address space */ myHand = NewHandle(AMOUNT); HLock(myHand); myPtr = StripAddress(*myHand); oldmmumode = SwapMMUMode(32bitconstantwhateverthatis); BlockMove(hugebitmap, myHand, amount); SwapMMUMode(oldmmumode); -- Matthew T. Russotto russotto@eng.umd.edu russotto@wam.umd.edu .sig under construction, like the rest of this campus.
chewy@apple.com (Paul Snively) (11/20/90)
In article <46697@apple.Apple.COM> stevec@Apple.COM (Steve Christensen) writes: [Lead-in deleted for brevity's sake] > Generally you only need to call StripAddress if you need to compare two > addresses, since then the full 32 bits is used... This is almost correct. (It's obviously time to clarify my clarifications in the Tech Note.) ;-) If you are comparing two pointers that lie within the same block, you're guaranteed cool regardless, because whether you're doing signed or unsigned math, everything works because the high byte is consistent. The potential problems arise when you are comparing between pointers into _different_ blocks, particularly if: 1) the comparison is signed 2) one of the blocks is locked and 3) the other isn't (Note that I'm assuming 24-bit mode here). So the code in the original post is just fine. Seriously, I _do_ plan to revise the Tech Note yet again, and perhaps rewrite it wholesale in English that's closer to what I just wrote. Sorry 'bout the confusion, __________________________________________________________________________ Paul Snively Macintosh Developer Technical Support Apple Computer, Inc. chewy@apple.com Just because I work for Apple Computer, Inc. doesn't mean that I believe what they believe, or vice-versa. __________________________________________________________________________