Skip to content

Malloc replacement with support for shared and persistent memory allocation

Notifications You must be signed in to change notification settings

ChrisDodd/shm_malloc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NO WARRANTY - NO WARRANTY - NO WARRANTY - NO WARRANTY - NO WARRANTY

THIS CODE IS RELESED AS IS, WITH NO WARRANTY OF ANY KIND.

NO WARRANTY - NO WARRANTY - NO WARRANTY - NO WARRANTY - NO WARRANTY


These malloc routines are based primarily on the paper "Efficient Kernel
Memory Allocation on Shared-Memory Multiprocessors", by McKenney and
Slingwine, which appears in the USENIX Winter 1993 conference proceedings.

The basic idea is to reduce the number of interlocks required by using
small per-process free lists.  Interlocks are only required when the
free lists are empty or overflow.

This per-process free list idea is used only for blocks smaller than 1
page.  For these small blocks, all allocations are rounded up to a
power-of-two size and one free list is used for each size.  Blocks are
allocated by splitting an entire page into blocks of the same size, so
that no extra per-block storage is required for in-use blocks.

Larger allocations are always rounded up to a multiple of the page size.
Free pages are kept in a sorted list, and a best-fit allocation scheme
is used.

When compiled directly, the source will produce malloc replacement code.

When compiled with -DMALLOC_DEBUG, it will add in extra guard and consistency
checks as an aid to debugging heap corruption problems.

When compiled with -DSHM, the source will produce a shared-memory malloc
package, which uses mmap to get memory from the system (so it may also
be used as persistent storage).  There are a number of important routines.

void *shm_malloc(size_t);
void *shm_calloc(int, int);
void *shm_realloc(void *, size_t);
void shm_free(void *);
    These are used instead of the standard malloc routines.

void shm_init(char *filename [, void (*init)()]);
    This must be called in each process to get access to the shared memory.
    If the file doesn't (yet) exist, it will be created and initialized to
    `all free'.  It contains code to avoid race conditions, so you can call
    it in multiple processes simultaneously and the right thing will happen

    The optional init function will be called if this is a newly created
    file.  Only one process will call this function if multiple processes
    call shm_init on a new file simultaneously; the others will wait for it
    to finish.

void shm_fini();
    This must be called in each process before exiting (unless shm_destroy
    is called).  It frees up all the process internal tables and `disconnects'
    from the shared memory.

void shm_destroy();
    This works as shm_fini and also removes the shared memory file.  Other
    processes which are trying to use the shared memory may fail mysteriously
    after this is called.

void shm_child();
    This should be called in the child process if a process calls fork
    after it calls shm_init, before the child process calls any other
    shared memory routine.  The child can safely call exit or exec
    without calling shm_child, as long as it calls no shared memory
    routines before then.

void *shm_global();
void shm_set_global(void *);
    These two routines give all process who have mapped a shared memory file
    (with shm_init) acces to a single global variable.  Usually a pointer
    into the shared memory.  Initialized to 0 when shm_init is called for
    a non-existant file.

The code is arranged so that all processes will map the memory at the same
address.  This precludes the possibility of mapping multiple shared memory
files into one process, but its almost impossible to work without it.  The
shared memory load address is a constant that will need to be changed for
any port.

You have a choice of 4 different locking schemes for the global tables:
System V semaphores, File locks, atomic test-and-set spin locks, and
pthreads mutexes.  You can choose between them by compiling with one of:
    -DLOCKTYPE=SYSVSEM
    -DLOCKTYPE=FLOCK
    -DLOCKTYPE=SPINLOCK
    -DLOCKTYPE=PMUTEX
Put this into the `CFLAGS' in the Makefile, or use it on the command line
when compiling malloc.c manually.  The default is posix mutexes on posix
systems, otherwise spinlocks if it is supported, otherwise file locks.
Currently spinlocks are only supported when using GCC on the following
processors:
    m68k
    m88k
    sparc
    alpha
    i386
    ppc
    x86_64
To add support for an additional processor, you'll need to add appropriate
macros to `atomic.h'.

I've tested this code on the following machines:
    sparc SunOS 4
    sparc SunOS 5
    mips IRIX 5
    alpha OSF/1
    i586 FreeBSD 2.1.5
    rs6k AIX 4.2
    Linux 2.6.38

On FreeBSD and AIX, the code does not work if the shared memory file is on
an NFS-mounted partition.  On all systems, its a bit slower to use an NFS
file, so you're better off using a local file if possible.

Note that the fact that you can use a file on a NFS server does NOT mean
that you can use this code for distributed shared memory -- it won't
work.  In general ANY TIME two different client machines try to modify
the same file on a NFS server, all bets are off and everything will
break.  NFS is an abbreviation for `Not a File System.'

On hppa HP-UX 9 machines, this code is known to crash the machine.  On
i86 FreeBSD 2.0 it also frequently crashes the machine.

I'd appreciate reciving a copy of any bug-fixes, enhancements, or ports
anyone makes with this code.

Chris Dodd
[email protected]

About

Malloc replacement with support for shared and persistent memory allocation

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published