Difference between revisions of "Memory management"

From Embedded Xinu
Jump to navigation Jump to search
(Added stubs for memory management page)
 
(→‎Memory Allocators: Defined the memory allocators)
Line 3: Line 3:
 
== Memory Allocators ==
 
== Memory Allocators ==
  
Embedded Xinu uses two main memory allocators that work in tandem to provide dynamic memory to both kernel and user software.
+
Embedded Xinu maintains two memory allocators that work in tandem to provide dynamic memory to both kernel and user software.  The first allocator is the kernel allocator which allocates small chunks of memory from the global memory heap as needed by the kernel.  The second allocator is a user allocator, that allocates memory from a pre-thread memory heap as needed by user processes.
  
 
=== Kernel Allocator ===
 
=== Kernel Allocator ===
  
The kernel allocator trusts the programmer to keep track of accounting information on the stack and provides no mapping or protection.
+
The most basic memory allocator in the system is the kernel allocator which uses the <code>memget</code> and <code>memfree</code> functions.  This operates on the global kernel heap that uses the <code>memlist</code> global variable.  In this allocator the kernel developer is trusted to keep track of the accounting information for memory blocks.  This makes a rather straightforward API.
 +
 
 +
<source lang="c">
 +
void *memptr = memget(nbytes);
 +
memfree(memptr, nbytes);
 +
</source>
 +
 
 +
As can be seen in the above API, the allocation function takes a single parameter (<code>nbytes</code>) which is the number of bytes requested.  The deallocation function takes two parameters (<code>memptr</code> and <code>nbytes</code>), where <code>memptr</code> is the memory address allocated via the <code>memget</code> function and <code>nbytes</code> is the number of bytes requested with the original call.
  
 
=== User Allocator ===
 
=== User Allocator ===
  
The user allocator stores accounting information adjacent to the allocated memory and provides distinct address spaces for each running thread.
+
Unlike the kernel allocator, the user allocator does not trust the programmer to remember the amount of memory requested and instead stores the accounting information immediately before the allocated memory.  To the programmer the API for user memory is simply:
 +
 
 +
<source lang="c">
 +
void *memptr = malloc(nbytes);
 +
free(memptr);
 +
</source>
 +
 
 +
This allocator works on a per-thread memory list of free memory, this allows memory to be owned by the calling thread and prevents other threads from having access to the memory.  This forms the basis of memory protection.
 +
 
 +
When a request for memory comes in to the allocator, it attempts to satisfy the request with free memory that has already been allocated to thread.  If that fails, the allocator will then attempt to acquire memory from the region allocator (described below).  Since the region allocator works at page granularity, any excess memory is inserted into the thread's free memory list for future requests.  When a block of memory is free'd, the memory is returned to the thread's free memory list.
 +
 
 +
It is not until the thread is killed that the memory is removed from the thread's protection domain and made available to the region allocator.
  
 
==== Region Allocator ====
 
==== Region Allocator ====
  
The region allocator runs below the user allocator and provides more page aligned memory regions upon request.
+
The region allocator works beneath the user allocator and is initialized during the boot process.  During system boot Embedded Xinu uses <code>UHEAP_SIZE</code> as defined in <code>xinu.conf</code> to allocate memory for the user heap.  This memory is allocated via the kernel <code>memget()</code> function and is then passed to the <code>memRegionInit()</code> function.  Once the region allocator is initialized, the only user level interface to the region allocator is hidden behind the <code>malloc</code> and <code>free</code> routines.
  
 
== Memory Protection ==
 
== Memory Protection ==

Revision as of 22:00, 29 July 2009

Memory management is an important aspect of any operating system, as such Embedded Xinu makes use of some aspects of the underlying hardware to build up a simple to understand memory management system.

Memory Allocators

Embedded Xinu maintains two memory allocators that work in tandem to provide dynamic memory to both kernel and user software. The first allocator is the kernel allocator which allocates small chunks of memory from the global memory heap as needed by the kernel. The second allocator is a user allocator, that allocates memory from a pre-thread memory heap as needed by user processes.

Kernel Allocator

The most basic memory allocator in the system is the kernel allocator which uses the memget and memfree functions. This operates on the global kernel heap that uses the memlist global variable. In this allocator the kernel developer is trusted to keep track of the accounting information for memory blocks. This makes a rather straightforward API.

void *memptr = memget(nbytes);
memfree(memptr, nbytes);

As can be seen in the above API, the allocation function takes a single parameter (nbytes) which is the number of bytes requested. The deallocation function takes two parameters (memptr and nbytes), where memptr is the memory address allocated via the memget function and nbytes is the number of bytes requested with the original call.

User Allocator

Unlike the kernel allocator, the user allocator does not trust the programmer to remember the amount of memory requested and instead stores the accounting information immediately before the allocated memory. To the programmer the API for user memory is simply:

void *memptr = malloc(nbytes);
free(memptr);

This allocator works on a per-thread memory list of free memory, this allows memory to be owned by the calling thread and prevents other threads from having access to the memory. This forms the basis of memory protection.

When a request for memory comes in to the allocator, it attempts to satisfy the request with free memory that has already been allocated to thread. If that fails, the allocator will then attempt to acquire memory from the region allocator (described below). Since the region allocator works at page granularity, any excess memory is inserted into the thread's free memory list for future requests. When a block of memory is free'd, the memory is returned to the thread's free memory list.

It is not until the thread is killed that the memory is removed from the thread's protection domain and made available to the region allocator.

Region Allocator

The region allocator works beneath the user allocator and is initialized during the boot process. During system boot Embedded Xinu uses UHEAP_SIZE as defined in xinu.conf to allocate memory for the user heap. This memory is allocated via the kernel memget() function and is then passed to the memRegionInit() function. Once the region allocator is initialized, the only user level interface to the region allocator is hidden behind the malloc and free routines.

Memory Protection

Since Embedded Xinu has limited resources to work with it does not provide a virtual memory system. It does take advantage of separate address spaces for each user thread running in the system, which provides simple memory protection for low overhead costs.

Translation Lookaside Buffer

To facilitate memory protect Embedded Xinu uses the translation lookaside buffer (TLB) build into the MIPS processors of the WRT54GL series of routers.