ge@phoibos.cs.kun.nl (Ge Weijers) (12/19/90)
I'm about to begin writing a largish programming language implementation to run under Windows-3 in standard and 386 enhanced mode. The language, Scheme, needs a garbage-collected heap. My problem is: Do selector numbers refering to blocks of memory change through the lifetime of a program? If they do I have to address all memory through a special table, which would slow down the implementation severely. Does the alternative, keeping the heap blocks locked for all time, give major problems? The documentation (SDK) is not very specific on this. Any info appreciated. Ge' Weijers Ge' Weijers Internet/UUCP: ge@cs.kun.nl Faculty of Mathematics and Computer Science, (uunet.uu.net!cs.kun.nl!ge) University of Nijmegen, Toernooiveld 1 tel. +3180612483 (UTC+1, 6525 ED Nijmegen, the Netherlands UTC+2 march/september
nickel@cs.utexas.edu (Jody P. Nickel) (12/19/90)
If you are only going to run in 386 enhanced mode the this will simplify your task immensely. After a GlobalAlloc, you can lock this memory and leave it locked until it is no longer needed. The far pointer you receive is a selector:0 pointer. The selector is valid as long as the memory stays allocted. i.e. Don't free the memory and expect the pointer to be valid. The indirection from the selector to the physical address is handled by the 386. This indirection is very fast, but the loading of a new selector into a segment register is expensive, minimize the number of times you load a segment register and your performance should be acceptable.
mojo@netcom.UUCP (Morris Jones) (12/20/90)
ge@cs.kun.nl writes: >Do selector numbers refering to blocks of memory change through the lifetime of >a program? If they do I have to address all memory through a special table, >which would slow down the implementation severely. Does the alternative, >keeping the heap blocks locked for all time, give major problems? In enhanced mode, memory selectors don't change. If you really must, you can keep the memory locked without serious effect, because the 386 can still swap memory out to the swapfile. But don't PageLock all your memory. Mojo -- mojo@netcom.UUCP Site Coordinating Instructor, San Jose South Morris "Mojo" Jones Skilled Motorcycling And Rider Training (S.M.A.R.T.) Campbell, CA 800-675-5559 ... 800-CC-RIDER ... 408-423-2212 AA4KB @ N6LDL.#NOCAL.CA.USA.NA / aa4kb.ampr.org / netcom!mojo@apple.com
billf@progress.COM (Bill Ferro) (12/20/90)
nickel@cs.utexas.edu (Jody P. Nickel) writes: >If you are only going to run in 386 enhanced mode the this will simplify >your task immensely. After a GlobalAlloc, you can lock this memory and >leave it locked until it is no longer needed. The far pointer you receive >is a selector:0 pointer. This is also true for standard mode. Malloc and Free code examples follow: char *malloc(nbytes) WORD nbytes; { HANDLE h; if ((h=GlobalAlloc(GMEM_MOVEABLE,DWORD(nbytes))) == NULL) return ((char *)0); else return ((char *)GlobalLock(h)); } void free(ptr) char *ptr; { HANDLE h; h = LOWORD(GlobalHandle(HIWORD(ptr))); GlobalUnlock(h); GlobalFree(h); return; } -bf -- Bill Ferro UUCP: mit-eddie!progress!billf Progress Software Corp. Internet: billf@progress.com 5 Oak Park Bedford, MA 01730
jason@media-lab.MEDIA.MIT.EDU (Jason A. Kinchen) (12/20/90)
In article <1990Dec19.194631.22880@progress.com> billf@progress.COM (Bill Ferro) writes: >nickel@cs.utexas.edu (Jody P. Nickel) writes: > >>If you are only going to run in 386 enhanced mode the this will simplify >>your task immensely. After a GlobalAlloc, you can lock this memory and >>leave it locked until it is no longer needed. The far pointer you receive >>is a selector:0 pointer. > > This is also true for standard mode. Malloc and Free code >examples follow: > [here was the most often written Windows code in the world.} Okay, now here's one for you. GlobalAlloc can take a long or DWORD (32 bit) and therefore has a 4 Gigabyte address space. However, they warn you in the Guide to Programming that if you allocate more than 64K the returned pointer must be cast and saved as a huge pointer so the proper segment arithmetic is done. Has anyone solved the problem of dynamically, globally alloc'ing an arbitrarily long block of memory when you don't know in advance if it's longer than 64K? Do you have to compile huge model or something nasty like that? Thanks in advance. -- Jason Kinchen jason@media-lab.MIT.EDU
nadkarni@ashok.dec.com (Ashok P. Nadkarni) (12/20/90)
In article <588@rodan.cs.utexas.edu>, nickel@cs.utexas.edu (Jody P. Nickel) writes... >If you are only going to run in 386 enhanced mode the this will simplify >your task immensely. After a GlobalAlloc, you can lock this memory and >leave it locked until it is no longer needed. As far as I know, this is also true in standard mode. It's only real mode that you need to worry about being a good citizen in terms of unlocking global memory. /Ashok Nadkarni
mojo@netcom.UUCP (Morris Jones) (12/21/90)
jason@media-lab.media.mit.edu (Jason A. Kinchen) writes: > Has anyone solved the problem >of dynamically, globally alloc'ing an arbitrarily long block of memory >when you don't know in advance if it's longer than 64K? Do you have >to compile huge model or something nasty like that? Here's one option if you're on a 386: See Appendix E of the SDK manual. Use the function Global32Alloc. The selector you get back well be a USE32 selector, thus requiring a 32-bit offset. Now the problem comes in referencing all that memory from a 16-bit program. You can get 16-bit pointers into the memory using Global16PointerAlloc, but each pointer will be limited to a 64K segment of space. If you write some assembler, you can reference the memory using the 32-bit registers, or other bits of 386-specific code. Just some food for thought ... Mojo -- mojo@netcom.UUCP Site Coordinating Instructor, San Jose South Morris "Mojo" Jones Skilled Motorcycling And Rider Training (S.M.A.R.T.) Campbell, CA 800-675-5559 ... 800-CC-RIDER ... 408-423-2212 AA4KB @ N6LDL.#NOCAL.CA.USA.NA / aa4kb.ampr.org / netcom!mojo@apple.com
nickel@cs.utexas.edu (Jody P. Nickel) (12/22/90)
This isn't pretty but... And I'm sure Microsoft won't condone it. The pointer returned will always be an XXXX:0000, where XXXX is the selector for the first 64K of the memory. To get to the next 64K you need to increment the selector by (I'm not %100 of the value) 8. The easiest way to do this is using the _based keyword and a far *; Something like the following. _segment BigSeg; char _based(BigSeg) *pBigSeg; void far *x; x=GlobalLock(...); BigSeg=FP_SEG(x); pBigSeg = NULL; Now pBigSeg is pointing at the first 64 K and can move through it with ease. To get at the next 64K, increment BigSeg by 8, reset pBigSeg to 0 and now you have the next 64K. This by no means is any easier than using a huge model pointer but if you don't want to use the huge memory model this, or something like it is the only alternative. Disclaimer.. Use at your own risk, if Microsoft choses to change the way these huge blocks are mapped into the LDT this code won't work. (But neither will the programs
goodearl@world.std.com (Robert Goodearl) (12/22/90)
In article <600@rodan.cs.utexas.edu> nickel@cs.utexas.edu (Jody P. Nickel) writes: >This isn't pretty but... And I'm sure Microsoft won't condone it. The pointer >returned will always be an XXXX:0000, where XXXX is the selector for the >first 64K of the memory. To get to the next 64K you need to increment the >selector by (I'm not %100 of the value) 8. The easiest way to do this is >using the _based keyword and a far *; If you _were_ going to manipulate the segment register yourself, you would add 16 NOT 8. HOWEVER, this is specifically recommended against. You CAN declare huge pointers without compiling entirely in the huge model. I believe this is much better than trying to manipulate segment registers yourself. -- Bob Goodearl -- goodearl@world.std.com
mojo@netcom.UUCP (Morris Jones) (12/22/90)
nickel@cs.utexas.edu (Jody P. Nickel) writes: >This isn't pretty but... And I'm sure Microsoft won't condone it. The pointer >returned will always be an XXXX:0000, where XXXX is the selector for the >first 64K of the memory. To get to the next 64K you need to increment the >selector by (I'm not %100 of the value) 8. WAIT hold on there just a moment. The value might not always be 8. But SUPPOSEDLY you can be sure by adding the contents of the variable _ahincr. Check that out. I'm pretty sure that's what the SDK says, and that's how C generates code for huge pointers. Mojo netcom!mojo@apple.com -- mojo@netcom.UUCP Site Coordinating Instructor, San Jose South Morris "Mojo" Jones Skilled Motorcycling And Rider Training (S.M.A.R.T.) Campbell, CA 800-675-5559 ... 800-CC-RIDER ... 408-423-2212 AA4KB @ N6LDL.#NOCAL.CA.USA.NA / aa4kb.ampr.org / netcom!mojo@apple.com
davidds@microsoft.UUCP (David D'SOUZA) (12/26/90)
In article <600@rodan.cs.utexas.edu> nickel@cs.utexas.edu (Jody P. Nickel) writes: >This isn't pretty but... And I'm sure Microsoft won't condone it. The pointer >returned will always be an XXXX:0000, where XXXX is the selector for the >first 64K of the memory. You are pretty much assured that a GlobalAlloced memory block starts at offset 0. MS certainly can't change this without some form of backwards compatbility for all the apps that already depend on this... >To get to the next 64K you need to increment the >selector by (I'm not %100 of the value) 8. The easiest way to do this is >using the _based keyword and a far *; Something like the following. You are pretty much assured to break if you assume anything like this. >Now pBigSeg is pointing at the first 64 K and can move through it with ease. To >get at the next 64K, increment BigSeg by 8, reset pBigSeg to 0 and now you >have the next 64K. This by no means is any easier than using a huge model pointer >but if you don't want to use the huge memory model this, or something like it >is the only alternative. If you are using C, you can declare pointers to be HUGE and the C compiler will do the right thing for you. You don't have to be huge model. Just like you can declare FAR pointers if you are small model, you can declare HUGE pointers... There shouldn't be too many reasons you should worry about selector tiling if you are using C since the compiler takes care of this for you... If you are using asm, your code should be as follows: ExternA <__AHINCR> ; This external is exported by Windows kernel and you ; will get the proper value to increment your selectors ; by independent of which mode of windows you are running ; (ie. real, standard, and enhanced have different values) ; BTW: That's two underscores before the A. mov ax, es add ax, __AHINCR ; move es up 64K or to the next selector mov es, ax The C compiler generates code which links to __AHINCR exported from Kernel so it always works.
sdw@hpsad.HP.COM (Steve Warwick) (01/10/91)
Both the SDK and Petzold's book seem to avoid detailing how windows deals with movable code and data segments in protected mode programs. They instead concentrate on the software-assisted fixup methods which are required in real mode. Assuming you are willing to write applications which are restricted to protected mode, is there a clean description of the assumptions you can make about segments i.e. 1) can you assume that program code and segments are fixed (since they are segment selectors) 2) won't large model programs work fine, since data segments are also segment selectors.. 3) same for DLL code and data? more generally, 4) How does windows protected mode differ from OS/2 protected mode in terms of segment fixups, relocation and virtual memory? 5) Arn't much simpler methods of dealing with code and data movement available when your in protected mode, removing the need for windows prolog/epilogs and thunks? Will future versions of windows support such simpler models? References to articles/technical publications dealing with these issues will be appreciated. Please avoid the "I Think That ..." (Unless you wrote it...)
petergo@microsoft.UUCP (Peter GOLDE) (01/14/91)
Microsoft Systems Journal has discussed this issue in fairly good detail in the last 2 issues (and maybe others?).