TIP: Click on subject to list as thread! ANSI
echo: os2prog
to: Eddy Thilleman
from: Denis Tonn
date: 1998-12-22 19:05:06
subject: more power

Original from  Eddy Thilleman  to Denis Tonn on 12-20-1998
Original Subject: more power

                         ---------------------------------------

 Part 2.. 

 DT> Ram is allocated in 4K pages, but "address space" is allocated
 DT> in 64K blocks. 
 
ET> Has the 64KB blocks something to do with the GDT selectors in the processor?
 
 DT> If you want to discuss the differences between ram, address
 DT> space, and memory, come on over to the OS2PROG echo. 
 
ET> OK, please fill me in! :-)

 DT> This topic is usually only interesting to programmers.
 
ET> That I'm.

 Ok.. I'll try and describe the differences between RAM, address 
space, and memory. 

  The first part is easy. Memory is virtualized in OS/2. This means 
that when you allocate memory, it does not always exist in RAM. 
Portions of it will, as the program is actively using that memory 
area, but unused (or infrequently used) will not be backed by RAM 
pages until it is needed. 
 RAM is the portions of "memory" that are being actively used. 

 The concepts of "address space" and "memory" are interlinked. 

 In the simplest terms, an "address space" is a set of valid 
accessable addresses. This will be different depending on the code 
that is running, the system address space, a DLL with protected data
(Warp 3 GA and OS/2 2.x only), or an application (process name). 

 Each process in OS/2 effectively has a separate LDT and page tables. 
There is a guaranteed minimum of 64MB of "private" address space 
wherein the "addresses" within a process will access different 
"memory" than other processes. Thus, the same address in different 
processes can access totally different pieces of "memory". Task 
switching that crosses processes includes changing the active LDT and 
the pages tables. Note that the "system adress space" is affected by 
this process switching, since the particular LDT and page tables 
decribing the process private memory is changed too. 

 There is also "shared memory", typically DLL code and shared data 
areas which can be "mapped" across many processes. Under OS/2, this 
shared memory will be at the same address regardless of which process 
is running. When an application loads a DLL module that is already 
available in the system (from another process) the system will simply 
enable the LDT and page tables for that process to access that DLL. 
Keeping the shared code/data at the same location in all processes 
means the same pointers (and loader fixups) can be used in all 
processes. Shared memory is also part of the "address space" of a 
process, even though it may have been "loaded" or
"allocated" by a 
different process. 
 Shared memory is allocated from the top of the 512MB line (discussed 
in the previous message) down. There will be "holes" in the address 
space of each process since not all processes will have access to the 
whole set of DLL's or shared data areas in the "system" at once. 

 Now, there is a concept of "instance data" allocated in the "shared 
address arena". There may be times where a DLL acts like a finite 
state machine and needs to maintain a separate "state" for each
process which it operates in. DLL instance data is an area of memory
that is allocated in the "shared address area" that *DOES* switch for
each process. Since it is allocated from the shared arena, it will be
at the same "address" in each process, but contain different data (and
therefore a different "state" of the FSM in the process). The
"usage" 
and "structure" of the data is the same in all processes but the 
actual data is different. 

 Lastly, there are a couple of flourishs. Read only data (and code is 
always read only) located in the private address space that is the 
same in multiple processes (say 2 or more copies of CMD.EXE running) 
can be "shared" via some page table manipulation. This allows one RAM 
page to "back" the private code for multiple processes. The loader 
uses the full drive/path/filespec as the method to determine if it can
safely the same read only page to back multiple processes. There is 
also an area of the "shared arena" that is not "tiled",
thus allowing 
multiple small (16 bit only) DLL's to occupy the same RAM page. This 
reduces (somewhat) the exhaustion of addresses in the shared arena. 

 The following diagram might help a bit:

       4GB    +----------------------------------+
              |                                  |
              |     Kernel and System Data       |
              |                                  |
              |      |      |      |      |      |
              |      |      |      |      |      |
     512MB    +------+------+------+------+------+
              | DLL1 | ???? | DLL1 | DLL1 | ???? |
              +------+------+------+------+------+
              | ???? | DLL2 | ???? | DLL2 | DLL2 |
              +------+------+------+------+------+
              | ???? | ???? | DLL3 | ???? | DLL3 |
              +------+------+------+------+------+
              | xxxx | ???? | xxxx | xxxx | ???? |
              +------+------+------+------+------+
              | ???? | wwww | ???? | yyyy | zzzz |
              +------+------+------+------+------+
              \_ _ _ | _ _ _|_ _ _ | _ _ _|_ _ _ /
              / ???????????????????????????????? \
              |      |      |      |      +------+
              |      |      |      |      | ffff |
      64MB    +------+------+------+------+      |
              |      | cccc |      |      |      |
              |      |      |      | eeee |      |
              |      +------+      +------+      |
              | bbbb | aaaa | dddd | aaaa | ffff |
              |      +------+      +------+      |
              | bbbb | cccc | dddd | eeee | ffff |
       64K    +------+------+------+------+------+
                PID1   PID2   PID3   PID4   PID5

 Each of the above processes (PID) will have a separate LDT and set of
page tables. Only one process will be active at any instant (on a uni 
processor system). The ???? are unused (and invalid) addresses for a 
process. Access to the system memory addresses are prevented by the 
limit field in the descriptor tables for each application (or DLL). 
The kernel's decriptor covers all 4GB, and therefor can access all 
"addresses", but the "memory" will be different depending on the 
"context" of the active process. 
 You can see that different processes have access to common DLL 
code, but not all processes will have access to them all. The xxxx 
address is a common data area (memory) to various processes. The wwww,
yyyy, and zzzz are examples of DLL instance data. It is at the same
"address" in each process, but is still separate for each process. The
aaaa is an example of a common read only piece of code in the
executable (same process name). This is not controllable by the
programmer, although the user can affect this. As long as the
executable is loaded from the same file the system will automaticly
make this optimization via the page tables. 
 PID 1 thru 4 are still using less than 64MB of "private" space, but 
PID 5 has grown beyond that line. 
 

 Some notes for programmers: 
  It is possible for an app to "grow" it's address space upwards until
it hits the bottom of the "shared address" range, or for an app (or 
DLL) to allocate memory in the "shared address range" until it "grows 
down" to the top of the largest app's "private address range". At this
time, the large app cannot allocate any more "private memory" and NO 
applications can allocate any more addresses in the shared arena. In 
the vast majority of cases, this is caused by a memory leak (allocated
but fail to release) somewhere. 
 Both applications and DLL's can allocate memory in either the private 
arena or shared arena.
 As you can see, shared addresses (not the "memory") should be treated
as a scarce resource, and used only when required. In particular, 
DLL instance data should not be used when private memory will do. In 
most cases a single allocation of instance data is all that is needed 
since it can contain the pointers to addresses in the private arena 
allocated by the DLL "on behalf" of the application. 

 OS/2 does not automaticly "back" valid addresses on allocation. All 
it does is mark the page tables as "valid" and assumes the 
responsibility of "backing" it when the app uses it. This means that 
an app can "allocate" a large amount of "memory",
(thereby reserving a 
large amount of addresses) that could exceed the available "swap 
space". EG: 50MB free space on the swap drive. An app allocates 200MB 
of "memory", and the start to "use it". If the app
completes after it 
has used 100K, then the swapper (may) have grown by 100K and 
everything is fine. But if the app uses more than 50MB of "memory" 
OS/2 cannot "back" the memory somewhere (RAM or swapper) so it will 
generate an exception, an exception most applications cannot handle 
(what? The RC from the alloc was fine, but I can't use it?). The 
MEMMAN=COMMIT statement in config.sys will force the swapper to "grow"
by whatever amount the app "allocates", thus failing the original API
call rather than defering it to when the app attempts to "use" the 
memory. This is not desirable for "normal" operation since the 
overhead of preallocating the swap space is time consuming, and most 
apps never use their full "allocations" anyway. If you experiment with
the above config.sys statement, you will find out how much most apps 
are "allocating" and never using. 
 Obviously, this can also affect the "available address space" for 
the process and the system. Allocating a large amount of "memory" DOES
reserve the "addresses", thereby reducing the amount of "shared 
addresses" available to the process and the system as a whole. Again, 
it is particularly important to avoid large allocations of "memory" in
the shared arena. In fact, it is not a good idea to aggressively 
allocate private "memory" either .. 

 Warp server SMP and the Aurora beta allow applications to "allocate" 
in the area above the 512MB limit (up to a config.sys controlled limit
of 3.0GB total). Memory allocated in the region above 512MB can only 
be accessed by 32 bit code. It is up to the application to specify 
that memory usable by 16:16 code be allocated in the region below the
512MB address line (the "compatability region") when it allocates it. 
The memory above the 512MB line has a similar organization into 
"private" and "shared" regions as the memory below the
512MB line. 

 Enough for now.. Ask away.. 



   Denis       

 All opinions are my very own, IBM has no claim upon them
. 
. 
.
 

 




--- Maximus/2 3.01
* Origin: T-Board - (604) 277-4574 (1:153/908)
SEEN-BY: 396/1 632/0 371 633/260 262 267 270 371 635/444 506 728 639/252
SEEN-BY: 670/218
@PATH: 153/908 8086 800 140/1 396/1 633/260 635/506 728 633/267

SOURCE: echomail via fidonet.ozzmosis.com

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.