161 lines
6.4 KiB
Plaintext
161 lines
6.4 KiB
Plaintext
|
The GNU mmalloc (mapped-malloc) package. fnf@cygnus.com
|
||
|
|
||
|
|
||
|
Description
|
||
|
-----------
|
||
|
|
||
|
This is a heavily modified version of GNU malloc which has been extended to
|
||
|
use mmap() as the basic mechanism for for obtaining memory from the system,
|
||
|
rather than sbrk(). This gives it several advantages over the
|
||
|
more traditional malloc:
|
||
|
|
||
|
* Providing suitable precautions are taken to avoid memory region
|
||
|
collisions, sbrk() is now available for use by applications that
|
||
|
use this package and still need to use some memory management
|
||
|
package that includes functions like malloc/realloc/free.
|
||
|
|
||
|
* Several different memory pools can be used, each of them growing
|
||
|
or shinking under control of mmap(), with the mmalloc functions
|
||
|
using a specific pool on a call by call basis.
|
||
|
|
||
|
* By using mmap, it is easy to create data pools which are intended to
|
||
|
be persistent and exist as a filesystem object after the creating
|
||
|
process has gone away.
|
||
|
|
||
|
* Because multiple memory pools can be managed, data used for a
|
||
|
specific purpose can be allocated into it's own memory pool, making
|
||
|
it easier to allow applications to "dump" and "restore" initialized
|
||
|
malloc-managed memory regions. I.E., the "unexec" hack popularized
|
||
|
by GNU emacs could potentially go away.
|
||
|
|
||
|
|
||
|
Implementation
|
||
|
--------------
|
||
|
|
||
|
The mmalloc functions contain no internal static state. All of mmalloc
|
||
|
internal data is allocated in the mapped in region, along with the user
|
||
|
data that it manages. This allows it to manage multiple such regions
|
||
|
and to "pick up where it left off" when such regions are later dynamically
|
||
|
mapped back in.
|
||
|
|
||
|
In some sense, malloc has been "purified" to contain no internal state
|
||
|
information and generalized to use multiple memory regions rather than a
|
||
|
single region managed by sbrk(). However the new routines now need an
|
||
|
extra parameter which informs malloc which memory region it is dealing
|
||
|
with (along with other information).
|
||
|
|
||
|
For ease of initial implementation, and to avoid exporting or importing
|
||
|
any more global variables or routines than necessary, this package is
|
||
|
implemented with all functions contained within a single source file.
|
||
|
At some future point, once everything has stabilized, it may be desirable
|
||
|
split it up into separate files.
|
||
|
|
||
|
The functions initially provided by mmalloc are:
|
||
|
|
||
|
void *mmalloc_attach (int fd, void *baseaddr);
|
||
|
void *mmalloc_detach (void *md);
|
||
|
int mmalloc_errno (void *md);
|
||
|
int mmalloc_setkey (void *md, int keynum, void *key);
|
||
|
void *mmalloc_getkey (void *md, int keynum);
|
||
|
|
||
|
void *mmalloc (void *md, size_t size);
|
||
|
void *mrealloc (void *md, void *ptr, size_t size);
|
||
|
void *mvalloc (void *md, size_t size);
|
||
|
void mfree (void *md, void *ptr);
|
||
|
|
||
|
Backwards Compatibility
|
||
|
-----------------------
|
||
|
|
||
|
To allow a single malloc package to be used in a given application, provision
|
||
|
is made for the traditional malloc/realloc/free functions to be implemented
|
||
|
as special cases of the mmalloc functions. In particular, if any of the
|
||
|
functions that expect malloc descriptors are called with a NULL pointer rather
|
||
|
than a valid malloc descriptor, then they default to using an mmap'd region
|
||
|
starting at the current sbrk() value and mapped to /dev/zero. Applications
|
||
|
can simply include the following defines to use the mmalloc versions:
|
||
|
|
||
|
#define malloc(size) mmalloc ((void *)0, (size))
|
||
|
#define realloc(ptr,size) mrealloc ((void *)0, (ptr), (size));
|
||
|
#define free(ptr) mfree ((void *)0, (ptr))
|
||
|
|
||
|
or replace the existing malloc/realloc/free calls with the above patterns
|
||
|
if the #define's cause problems.
|
||
|
|
||
|
Note that this does not prevent calls to malloc/realloc/free within
|
||
|
libraries from continuing to use the library version of malloc, so if this
|
||
|
is a problem, the compatibility issue needs to be dealt with in another way.
|
||
|
|
||
|
|
||
|
Function Descriptions
|
||
|
---------------------
|
||
|
|
||
|
void *mmalloc_attach (int fd, void *baseaddr);
|
||
|
|
||
|
Initialize access to a mmalloc managed region.
|
||
|
|
||
|
If FD is a valid file descriptor for an open file then data for the
|
||
|
mmalloc managed region is mapped to that file, otherwise "/dev/zero"
|
||
|
is used and the data will not exist in any filesystem object.
|
||
|
|
||
|
If the open file corresponding to FD is from a previous use of
|
||
|
mmalloc and passes some basic sanity checks to ensure that it is
|
||
|
compatible with the current mmalloc package, then it's data is
|
||
|
mapped in and is immediately accessible at the same addresses in
|
||
|
the current process as the process that created the file.
|
||
|
|
||
|
If BASEADDR is not NULL, the mapping is established starting at the
|
||
|
specified address in the process address space. If BASEADDR is NULL,
|
||
|
the mmalloc package chooses a suitable address at which to start the
|
||
|
mapped region, which will be the value of the previous mapping if
|
||
|
opening an existing file which was previously built by mmalloc, or
|
||
|
for new files will be a value chosen by mmap.
|
||
|
|
||
|
Specifying BASEADDR provides more control over where the regions
|
||
|
start and how big they can be before bumping into existing mapped
|
||
|
regions or future mapped regions.
|
||
|
|
||
|
On success, returns a "malloc descriptor" which is used in subsequent
|
||
|
calls to other mmalloc package functions. It is explicitly "void *"
|
||
|
("char *" for systems that don't fully support void) so that users
|
||
|
of the package don't have to worry about the actual implementation
|
||
|
details.
|
||
|
|
||
|
On failure returns NULL.
|
||
|
|
||
|
void *mmalloc_detach (void *md);
|
||
|
|
||
|
Terminate access to a mmalloc managed region by closing the base
|
||
|
file and unmapping all memory pages associated with the region.
|
||
|
|
||
|
Returns NULL on success.
|
||
|
|
||
|
Returns the malloc descriptor on failure, which can subsequently
|
||
|
be used for further action (such as obtaining more information about
|
||
|
the nature of the failure).
|
||
|
|
||
|
void *mmalloc (void *md, size_t size);
|
||
|
|
||
|
Given an mmalloc descriptor MD, allocate additional memory of
|
||
|
SIZE bytes in the associated mapped region.
|
||
|
|
||
|
void *mrealloc (void *md, void *ptr, size_t size);
|
||
|
|
||
|
Given an mmalloc descriptor MD and a pointer to memory previously
|
||
|
allocated by mmalloc in PTR, reallocate the memory to be SIZE bytes
|
||
|
long, possibly moving the existing contents of memory if necessary.
|
||
|
|
||
|
void *mvalloc (void *md, size_t size);
|
||
|
|
||
|
Like mmalloc but the resulting memory is aligned on a page boundary.
|
||
|
|
||
|
void mfree (void *md, void *ptr);
|
||
|
|
||
|
Given an mmalloc descriptor MD and a pointer to memory previously
|
||
|
allocated by mmalloc in PTR, free the previously allocated memory.
|
||
|
|
||
|
int mmalloc_errno (void *md);
|
||
|
|
||
|
Given a mmalloc descriptor, if the last mmalloc operation
|
||
|
failed for some reason due to a system call failure, then
|
||
|
returns the associated errno. Returns 0 otherwise.
|