home *** CD-ROM | disk | FTP | other *** search
- /* MEMORY.C */
-
- /* Memory management presents a challenge if one desires to be compatible
- with OS/2. The problem centers on the fact that memory references
- (e.g., a memory address) differ between the real (8086) and protected
- (80286) modes of operation. In the real mode, a memory reference is
- is via a "segment/offset" while in the protected mode, a memory reference
- is via a "descriptor/offset". Both are 32-bit items with the 16-bit
- offset working the same in both. However, segments and descriptors are
- not necessarily the same. If compatibility with OS/2 and DOS is an
- objective, then one must not use a descriptor as if it were a segment.
- It is however safe to use a segment as if it were a descriptor. In
- effect, this means you cannot treat the segment as if it is related to
- a memory address by a factor of 16. A segment must be treated as if
- were a descriptor. That is, a segment is treated as a reference (not
- necessarily an address) to the beginning of an area of memory which can
- be up to 64K. Each byte within the area of memory is accessed via the
- offset mechanism. */
-
- /* The data structure for memory is handled as follows: At the beginning
- of execution, all available far memory is allocated in 64K chunks, with
- a "memory descriptor" for each chunk. The memory desciptors for these
- chunks are linked together into memory pools. Initially, all descriptors
- are linked to the free pool. As a chunk is needed, it is allocated to
- a pool. Some pools are needed only for a brief time. In these cases,
- when a chunk is no longer needed it is returned to the free pool. */
-
-
- /*+-------------------------------------------------------------------------+
- | |
- | add_chunk_to_pool |
- | |
- +-------------------------------------------------------------------------+*/
-
- memory_descriptor_ptr add_chunk_to_pool(pool_descriptor_ptr pool,
- bit_32 size)
- BeginDeclarations
- #define Pool (*pool)
- memory_descriptor_ptr desc;
- #define Desc (*desc)
- memory_descriptor_ptr prior;
- #define Prior (*prior)
- EndDeclarations
- BeginCode
- prior = Null;
- desc = free_pool.memory_descriptor_list;
- While desc IsNotNull
- BeginWhile
- If Desc.available NotLessThan size
- Then
- If prior IsNull
- Then
- free_pool.memory_descriptor_list = Desc.next;
- Else
- Prior.next = Desc.next;
- EndIf;
- free_pool.pool_size -= Desc.available;
- Pool.pool_size += Desc.available;
- Desc.next = Pool.memory_descriptor_list;
- Pool.memory_descriptor_list = desc;
- far_set(Desc.chunk, 0, Bit_16(Desc.available));
- return(desc);
- EndIf;
- prior = desc;
- Next(desc);
- EndWhile;
- linker_error (8,"No more free far memory for pool \"%s\"\n."
- "\tTry running again with smaller buffersize and/or\n"
- "\tvirtualized fixup processing.\n",
- Pool.pool_id);
- return(desc); /* To kill warning */
- EndCode
- #undef Pool
- #undef Desc
- #undef Prior
-
- /*+-------------------------------------------------------------------------+
- | |
- | allocate_memory |
- | |
- +-------------------------------------------------------------------------+*/
-
- byte_ptr allocate_memory (pool_descriptor_ptr pool, bit_32 size)
- BeginDeclarations
- #define Pool (*pool)
- #define Desc (*desc)
- #define Prev (*prev)
- memory_descriptor_ptr desc;
- memory_descriptor_ptr prev;
- byte_ptr element;
- EndDeclarations
- BeginCode
-
- /* Traverse the memory descriptor list and allocate the space from the
- first memory descriptor which has enough available space for the entire
- element to be allocated. */
-
- prev = NULL;
- desc = Pool.memory_descriptor_list;
- While desc IsNotNull
- BeginWhile
- If size NotGreaterThan Desc.available
- Then /* We can take the element from this chunk */
- Pool.used_bytes += size;
- element = Desc.unused_base;
- Desc.unused_base += Bit_16(size);
- Desc.available -= size;
- If prev IsNotNull
- Then
- Prev.next = Desc.next;
- Desc.next = Pool.memory_descriptor_list;
- Pool.memory_descriptor_list = desc;
- EndIf;
- return(element);
- EndIf;
- prev = desc;
- Next(desc);
- EndWhile;
-
- /* Well, none of the memory descriptors had enough space to allocate this
- element. So, we will have to get another chunk, add it to this pool and
- allocate the space from the new chunk. */
-
- desc = add_chunk_to_pool(pool, size);
- Pool.used_bytes += size;
- element = Desc.unused_base;
- Desc.unused_base += Bit_16(size);
- Desc.available -= size;
- return(element);
- EndCode
- #undef Pool
- #undef Desc
- #undef Prev
-
- /*+-------------------------------------------------------------------------+
- | |
- | initialize_memory |
- | |
- | O/S dependent |
- | |
- +-------------------------------------------------------------------------+*/
-
- void initialize_memory()
- BeginDeclarations
- byte huge *far_memory;
- bit_32 far_memory_size;
- bit_32 size_this_chunk;
- bit_16 rc;
- memory_descriptor_ptr desc;
- #define Desc (*desc)
- EndDeclarations
- BeginCode
- /* First step for PC-DOS is to gobble all free paragraphs above the heap.
- The variable "far_memory" will point to that area. */
-
- inregs.h.ah = 0x48; /* DOS allocate memory */
- inregs.x.bx = 0xFFFF; /* Ask for too much memory */
- rc = intdos(Addr(inregs),Addr(outregs));/* Do the allocate expecting to fail*/
- If (outregs.x.cflag IsFalse) OrIf (rc IsNot 8)
- Then
- DOS_error("Problem allocating memory above heap.\n");
- EndIf;
- inregs.x.bx = outregs.x.bx; /* Ask for the right amount this time*/
- DOS_int21("Problem allocating memory above heap.\n");
-
- far_memory = (byte huge *) MakeFarPtr(outregs.x.ax,0);
- far_memory_size = Bit_32(inregs.x.bx) ShiftedLeft 4;
- If far_memory_size LessThan 65536L
- Then
- linker_error(8,"Too little memory above heap.\n"
- "\tTry running again with smaller buffersize and/or\n"
- "\tvirtualized fixup processing.\n");
- EndIf;
-
- /* Initialize the static pool with it's first chunk. This is a little
- tricky because the initial value of several data structures are
- initialized simutaneously. */
-
- far_set(BytePtr(far_memory), 0, 0); /* Clear initial chunk */
- desc = (memory_descriptor_ptr) far_memory;
- static_pool.memory_descriptor_list = desc;
- static_pool.used_bytes = sizeof(memory_descriptor_type);
- static_pool.pool_size =
- Desc.size =
- Desc.available = 65536L;
- Desc.chunk =
- Desc.unused_base = BytePtr(far_memory);
- Desc.next = NULL;
- far_memory += Desc.available;
- far_memory_size -= Desc.available;
- Desc.available -= sizeof(memory_descriptor_type);
- Desc.unused_base += sizeof(memory_descriptor_type);
-
- /* Now set up the free pool */
-
- free_pool.pool_size =
- free_pool.used_bytes = 0L;
- free_pool.memory_descriptor_list = NULL;
- While far_memory_size IsNotZero
- BeginWhile
- desc = (memory_descriptor_ptr)
- allocate_memory(Addr(static_pool),
- Bit_32(sizeof(memory_descriptor_type)));
- If far_memory_size Exceeds 65536L
- Then
- size_this_chunk = 65536L;
- Else
- size_this_chunk = far_memory_size;
- EndIf;
- Desc.chunk =
- Desc.unused_base = BytePtr(far_memory);
- Desc.size =
- Desc.available = size_this_chunk;
- free_pool.pool_size += size_this_chunk;
- Desc.next = free_pool.memory_descriptor_list;
- free_pool.memory_descriptor_list = desc;
- far_memory += size_this_chunk;
- far_memory_size -= size_this_chunk;
- EndWhile;
- free_pool.pool_id = "Free pool";
- static_pool.pool_id = "Static pool";
- dynamic_pool.pool_id = "Dynamic pool";
- dynamic_pool.memory_descriptor_list = Null;
- dynamic_pool.pool_size =
- dynamic_pool.used_bytes = 0L;
- return;
- EndCode
- #undef Desc
-
- /*+-------------------------------------------------------------------------+
- | |
- | release_pool |
- | |
- +-------------------------------------------------------------------------+*/
-
- void release_pool(pool_descriptor_ptr pool)
- BeginDeclarations
- #define Pool (*pool)
- memory_descriptor_ptr desc;
- #define Desc (*desc)
- memory_descriptor_ptr next;
- EndDeclarations
- BeginCode
- desc = Pool.memory_descriptor_list;
- While desc IsNotNull
- BeginWhile
- Desc.available = Desc.size;
- Desc.unused_base = Desc.chunk;
- free_pool.pool_size += Desc.available;
- next = Desc.next;
- Desc.next = free_pool.memory_descriptor_list;
- free_pool.memory_descriptor_list = desc;
- desc = next;
- EndWhile;
- Pool.memory_descriptor_list = Null;
- Pool.pool_size =
- Pool.used_bytes = 0L;
- return;
- EndCode
- #undef Pool
- #undef Desc
-