New memory malloc malloc library, based on GNU malloc.

This commit is contained in:
Fred Fish 1992-03-15 02:16:01 +00:00
parent 009898fddb
commit 63abb1e790
15 changed files with 3018 additions and 0 deletions

50
mmalloc/.Sanitize Normal file
View File

@ -0,0 +1,50 @@
# Sanitize.in for devo.
# $Id$
#
# Each directory to survive it's way into a release will need a file
# like this one called "./.Sanitize". All keyword lines must exist,
# and must exist in the order specified by this file. Each directory
# in the tree will be processed, top down, in the following order.
# Hash started lines like this one are comments and will be deleted
# before anything else is done. Blank lines will also be squashed
# out.
# The lines between the "Do-first:" line and the "Things-to-keep:"
# line are executed as a /bin/sh shell script before anything else is
# done in this
Do-first:
# All files listed between the "Things-to-keep:" line and the
# "Files-to-sed:" line will be kept. All other files will be removed.
# Directories listed in this section will have their own Sanitize
# called. Directories not listed will be removed in their entirety
# with rm -rf.
Things-to-keep:
ChangeLog
Makefile.in
README
attach.c
config
configure.in
detach.c
keys.c
mcalloc.c
mfree.c
mmalloc.c
mmalloc.h
mmap-sup.c
mmcheck.c
mmemalign.c
mmstats.c
mmtrace.awk
mmtrace.c
mrealloc.c
mvalloc.c
sbrk-sup.c
Do-last:

5
mmalloc/ChangeLog Normal file
View File

@ -0,0 +1,5 @@
Sat Mar 14 17:34:59 1992 Fred Fish (fnf@cygnus.com)
* Initial release, incorporated into gdb.

156
mmalloc/Makefile.in Normal file
View File

@ -0,0 +1,156 @@
#
# Makefile
# Copyright (C) 1992 Cygnus Support
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#
#
# Makefile for mmalloc directory
#
# Directory containing source files. Don't clean up the spacing,
# this exact string is matched for by the "configure" script.
srcdir = .
prefix = /usr/local
bindir = $(prefix)/bin
datadir = $(prefix)/lib
libdir = $(prefix)/lib
mandir = $(datadir)/man
man1dir = $(mandir)/man1
man2dir = $(mandir)/man2
man3dir = $(mandir)/man3
man4dir = $(mandir)/man4
man5dir = $(mandir)/man5
man6dir = $(mandir)/man6
man7dir = $(mandir)/man7
man8dir = $(mandir)/man8
man9dir = $(mandir)/man9
infodir = $(datadir)/info
includedir = $(prefix)/include
docdir = $(datadir)/doc
SHELL = /bin/sh
INSTALL = install -c
INSTALL_PROGRAM = $(INSTALL)
INSTALL_DATA = $(INSTALL)
AR = ar
AR_FLAGS = qv
BISON = bison
MAKEINFO = makeinfo
RANLIB = ranlib
RM = rm
TARGETLIB = libmmalloc.a
MINUS_G = -g
CFLAGS = $(MINUS_G) -I. -I$(srcdir)/../include $(HDEFINES)
CFILES = mcalloc.c mfree.c mmalloc.c mmcheck.c mmemalign.c mmstats.c \
mmtrace.c mrealloc.c mvalloc.c mmap-sup.c attach.c detach.c \
keys.c sbrk-sup.c
HFILES = mmalloc.h
OFILES = mcalloc.o mfree.o mmalloc.o mmcheck.o mmemalign.o mmstats.o \
mmtrace.o mrealloc.o mvalloc.o mmap-sup.o attach.o detach.o \
keys.o sbrk-sup.o
#### Host, target, and site specific Makefile fragments come in here.
###
# Do we want/need any config overrides?
#
STAGESTUFF = $(TARGETLIB) *.o
all: $(TARGETLIB)
install: all
$(INSTALL_DATA) $(TARGETLIB) $(libdir)/$(TARGETLIB).n
$(RANLIB) $(libdir)/$(TARGETLIB).n
mv -f $(libdir)/$(TARGETLIB).n $(libdir)/$(TARGETLIB)
$(TARGETLIB): $(OFILES)
$(RM) -rf $@
$(AR) $(AR_FLAGS) $@ $(OFILES)
$(RANLIB) $@
$(OFILES) : $(HFILES)
.always.:
# Do nothing.
.PHONEY: all etags tags ls clean stage1 stage2 .always.
stage1: force
-mkdir stage1
-mv -f $(STAGESTUFF) stage1
stage2: force
-mkdir stage2
-mv -f $(STAGESTUFF) stage2
stage3: force
-mkdir stage3
-mv -f $(STAGESTUFF) stage3
stage4: force
-mkdir stage4
-mv -f $(STAGESTUFF) stage4
against=stage2
comparison: force
for i in *.o ; do cmp $$i $(against)/$$i || exit 1 ; done
de-stage1: force
-(cd stage1 ; mv -f * ..)
-rmdir stage1
de-stage2: force
-(cd stage2 ; mv -f * ..)
-rmdir stage2
de-stage3: force
-(cd stage3 ; mv -f * ..)
-rmdir stage3
de-stage4: force
-(cd stage4 ; mv -f * ..)
-rmdir stage4
etags tags: TAGS
TAGS: $(CFILES)
etags $(HFILES) $(CFILES)
ls:
@echo Makefile $(HFILES) $(CFILES)
# Need to deal with profiled libraries, too.
clean:
rm -f *.a *.o core errs *~ \#* TAGS *.E a.out errors
force:
Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) \
$(target_makefile_frag)
$(SHELL) ./config.status

160
mmalloc/README Executable file
View File

@ -0,0 +1,160 @@
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.

33
mmalloc/configure.in Normal file
View File

@ -0,0 +1,33 @@
# This file is a shell script that supplies the information necessary
# to tailor a template configure script into the configure script
# appropriate for this directory. For more information, check any
# existing configure script.
srctrigger=mmalloc.c
srcname="mmalloc library"
configdirs=""
# per-host:
case "${host_os}" in
sysv4)
host_makefile_frag=config/mh-sysv4
;;
sunos4*)
host_makefile_frag=config/mh-sunos4
;;
*)
;;
esac
# per-target:
#
# Local Variables:
# fill-column: 131
# End:
#

71
mmalloc/detach.c Normal file
View File

@ -0,0 +1,71 @@
/* Finish access to a mmap'd malloc managed region.
Copyright 1992 Free Software Foundation, Inc.
Contributed by Fred Fish at Cygnus Support. fnf@cygnus.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <fcntl.h>
#include "mmalloc.h"
/* Terminate access to a mmalloc managed region by unmapping all memory pages
associated with the region, and closing the file descriptor if it is one
that we opened.
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 by examining the preserved errno value.
Note that the malloc descriptor that we are using is currently located in
region we are about to unmap, so we first make a local copy of it on the
stack and use the copy. */
PTR
mmalloc_detach (md)
void *md;
{
struct mdesc mtemp;
if (md != NULL)
{
mtemp = *(struct mdesc *) md;
/* Now unmap all the pages associated with this region by asking for a
negative increment equal to the current size of the region. */
if ((mtemp.morecore (&mtemp, mtemp.base - mtemp.top)) == NULL)
{
/* Update the original malloc descriptor with any changes */
*(struct mdesc *) md = mtemp;
}
else
{
if (mtemp.flags & MMALLOC_DEVZERO)
{
(void) close (mtemp.fd);
}
md = NULL;
}
}
return (md);
}

1841
mmalloc/fsf.shar.orig Executable file

File diff suppressed because it is too large Load Diff

64
mmalloc/keys.c Normal file
View File

@ -0,0 +1,64 @@
/* Access for application keys in mmap'd malloc managed region.
Copyright 1992 Free Software Foundation, Inc.
Contributed by Fred Fish at Cygnus Support. fnf@cygnus.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This module provides access to some keys that the application can use to
provide persistent access to locations in the mapped memory section.
The intent is that these keys are to be used sparingly as sort of
persistent global variables which the application can use to reinitialize
access to data in the mapped region.
For the moment, these keys are simply stored in the malloc descriptor
itself, in an array of fixed length. This should be fixed so that there
can be an unlimited number of keys, possibly using a multilevel access
scheme of some sort. */
#include "mmalloc.h"
int
mmalloc_setkey (md, keynum, key)
PTR md;
int keynum;
PTR key;
{
struct mdesc *mdp = (struct mdesc *) md;
int result = 0;
if ((mdp != NULL) && (keynum >= 0) && (keynum < MMALLOC_KEYS))
{
mdp -> keys [keynum] = key;
result++;
}
return (result);
}
PTR
mmalloc_getkey (md, keynum)
PTR md;
int keynum;
{
struct mdesc *mdp = (struct mdesc *) md;
PTR keyval = NULL;
if ((mdp != NULL) && (keynum >= 0) && (keynum < MMALLOC_KEYS))
{
keyval = mdp -> keys [keynum];
}
return (keyval);
}

53
mmalloc/mcalloc.c Normal file
View File

@ -0,0 +1,53 @@
/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include "mmalloc.h"
/* Allocate an array of NMEMB elements each SIZE bytes long.
The entire array is initialized to zeros. */
PTR
mcalloc (md, nmemb, size)
PTR md;
register size_t nmemb;
register size_t size;
{
register PTR result;
if ((result = mmalloc (md, nmemb * size)) != NULL)
{
(void) memset (result, 0, nmemb * size);
}
return (result);
}
/* When using this package, provide a version of malloc/realloc/free built
on top of it, so that if we use the default sbrk() region we will not
collide with another malloc package trying to do the same thing, if
the application contains any "hidden" calls to malloc/realloc/free (such
as inside a system library).
NOTE: Defining our own copy of this breaks ANSI conformance. */
PTR
calloc (nmemb, size)
size_t nmemb;
size_t size;
{
return (mcalloc ((void *) NULL, nmemb, size));
}

249
mmalloc/mfree.c Normal file
View File

@ -0,0 +1,249 @@
/* Free a block of memory allocated by `mmalloc'.
Copyright 1990, 1991, 1992 Free Software Foundation
Written May 1989 by Mike Haertel.
Heavily modified Mar 1992 by Fred Fish. (fnf@cygnus.com)
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.
The author may be reached (Email) at the address mike@ai.mit.edu,
or (US mail) as Mike Haertel c/o Free Software Foundation. */
#include "mmalloc.h"
/* Return memory to the heap.
Like `mfree' but don't call a mfree_hook if there is one. */
void
__mmalloc_free (mdp, ptr)
struct mdesc *mdp;
PTR ptr;
{
int type;
size_t block, blocks;
register size_t i;
struct list *prev, *next;
block = BLOCK (ptr);
type = mdp -> heapinfo[block].busy.type;
switch (type)
{
case 0:
/* Get as many statistics as early as we can. */
mdp -> heapstats.chunks_used--;
mdp -> heapstats.bytes_used -=
mdp -> heapinfo[block].busy.info.size * BLOCKSIZE;
mdp -> heapstats.bytes_free +=
mdp -> heapinfo[block].busy.info.size * BLOCKSIZE;
/* Find the free cluster previous to this one in the free list.
Start searching at the last block referenced; this may benefit
programs with locality of allocation. */
i = mdp -> heapindex;
if (i > block)
{
while (i > block)
{
i = mdp -> heapinfo[i].free.prev;
}
}
else
{
do
{
i = mdp -> heapinfo[i].free.next;
}
while (i > 0 && i < block);
i = mdp -> heapinfo[i].free.prev;
}
/* Determine how to link this block into the free list. */
if (block == i + mdp -> heapinfo[i].free.size)
{
/* Coalesce this block with its predecessor. */
mdp -> heapinfo[i].free.size +=
mdp -> heapinfo[block].busy.info.size;
block = i;
}
else
{
/* Really link this block back into the free list. */
mdp -> heapinfo[block].free.size =
mdp -> heapinfo[block].busy.info.size;
mdp -> heapinfo[block].free.next = mdp -> heapinfo[i].free.next;
mdp -> heapinfo[block].free.prev = i;
mdp -> heapinfo[i].free.next = block;
mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev = block;
mdp -> heapstats.chunks_free++;
}
/* Now that the block is linked in, see if we can coalesce it
with its successor (by deleting its successor from the list
and adding in its size). */
if (block + mdp -> heapinfo[block].free.size ==
mdp -> heapinfo[block].free.next)
{
mdp -> heapinfo[block].free.size
+= mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.size;
mdp -> heapinfo[block].free.next
= mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.next;
mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev = block;
mdp -> heapstats.chunks_free--;
}
/* Now see if we can return stuff to the system. */
blocks = mdp -> heapinfo[block].free.size;
if (blocks >= FINAL_FREE_BLOCKS && block + blocks == mdp -> heaplimit
&& mdp -> morecore (mdp, 0) == ADDRESS (block + blocks))
{
register size_t bytes = blocks * BLOCKSIZE;
mdp -> heaplimit -= blocks;
mdp -> morecore (mdp, -bytes);
mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next
= mdp -> heapinfo[block].free.next;
mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev
= mdp -> heapinfo[block].free.prev;
block = mdp -> heapinfo[block].free.prev;
mdp -> heapstats.chunks_free--;
mdp -> heapstats.bytes_free -= bytes;
}
/* Set the next search to begin at this block. */
mdp -> heapindex = block;
break;
default:
/* Do some of the statistics. */
mdp -> heapstats.chunks_used--;
mdp -> heapstats.bytes_used -= 1 << type;
mdp -> heapstats.chunks_free++;
mdp -> heapstats.bytes_free += 1 << type;
/* Get the address of the first free fragment in this block. */
prev = (struct list *)
((char *) ADDRESS(block) +
(mdp -> heapinfo[block].busy.info.frag.first << type));
if (mdp -> heapinfo[block].busy.info.frag.nfree ==
(BLOCKSIZE >> type) - 1)
{
/* If all fragments of this block are free, remove them
from the fragment list and free the whole block. */
next = prev;
for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i)
{
next = next -> next;
}
prev -> prev -> next = next;
if (next != NULL)
{
next -> prev = prev -> prev;
}
mdp -> heapinfo[block].busy.type = 0;
mdp -> heapinfo[block].busy.info.size = 1;
/* Keep the statistics accurate. */
mdp -> heapstats.chunks_used++;
mdp -> heapstats.bytes_used += BLOCKSIZE;
mdp -> heapstats.chunks_free -= BLOCKSIZE >> type;
mdp -> heapstats.bytes_free -= BLOCKSIZE;
mfree (mdp, ADDRESS(block));
}
else if (mdp -> heapinfo[block].busy.info.frag.nfree != 0)
{
/* If some fragments of this block are free, link this
fragment into the fragment list after the first free
fragment of this block. */
next = (struct list *) ptr;
next -> next = prev -> next;
next -> prev = prev;
prev -> next = next;
if (next -> next != NULL)
{
next -> next -> prev = next;
}
++mdp -> heapinfo[block].busy.info.frag.nfree;
}
else
{
/* No fragments of this block are free, so link this
fragment into the fragment list and announce that
it is the first free fragment of this block. */
prev = (struct list *) ptr;
mdp -> heapinfo[block].busy.info.frag.nfree = 1;
mdp -> heapinfo[block].busy.info.frag.first =
RESIDUAL (ptr, BLOCKSIZE) >> type;
prev -> next = mdp -> fraghead[type].next;
prev -> prev = &mdp -> fraghead[type];
prev -> prev -> next = prev;
if (prev -> next != NULL)
{
prev -> next -> prev = prev;
}
}
break;
}
}
/* Return memory to the heap. */
void
mfree (md, ptr)
PTR md;
PTR ptr;
{
struct mdesc *mdp;
register struct alignlist *l;
if (ptr != NULL)
{
mdp = MD_TO_MDP (md);
for (l = mdp -> aligned_blocks; l != NULL; l = l -> next)
{
if (l -> aligned == ptr)
{
l -> aligned = NULL; /* Mark the slot in the list as free. */
ptr = l -> exact;
break;
}
}
if (mdp -> mfree_hook != NULL)
{
(*mdp -> mfree_hook) (md, ptr);
}
else
{
__mmalloc_free (mdp, ptr);
}
}
}
/* When using this package, provide a version of malloc/realloc/free built
on top of it, so that if we use the default sbrk() region we will not
collide with another malloc package trying to do the same thing, if
the application contains any "hidden" calls to malloc/realloc/free (such
as inside a system library).
NOTE: Defining our own copy of this breaks ANSI conformance. */
void
free (ptr)
PTR ptr;
{
mfree ((void *) NULL, ptr);
}

64
mmalloc/mmemalign.c Normal file
View File

@ -0,0 +1,64 @@
/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include "mmalloc.h"
PTR
mmemalign (md, alignment, size)
PTR md;
size_t alignment;
size_t size;
{
PTR result;
unsigned long int adj;
struct alignlist *l;
struct mdesc *mdp;
size = ((size + alignment - 1) / alignment) * alignment;
if ((result = mmalloc (md, size)) != NULL)
{
adj = RESIDUAL (result, alignment);
if (adj != 0)
{
mdp = MD_TO_MDP (md);
for (l = mdp -> aligned_blocks; l != NULL; l = l -> next)
{
if (l -> aligned == NULL)
{
/* This slot is free. Use it. */
break;
}
}
if (l == NULL)
{
l = (struct alignlist *) mmalloc (md, sizeof (struct alignlist));
if (l == NULL)
{
mfree (md, result);
return (NULL);
}
}
l -> exact = result;
result = l -> aligned = (char *) result + alignment - adj;
l -> next = mdp -> aligned_blocks;
mdp -> aligned_blocks = l;
}
}
return (result);
}

46
mmalloc/mmstats.c Normal file
View File

@ -0,0 +1,46 @@
/* Access the statistics maintained by `mmalloc'.
Copyright 1990, 1991, 1992 Free Software Foundation
Written May 1989 by Mike Haertel.
Modified Mar 1992 by Fred Fish. (fnf@cygnus.com)
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.
The author may be reached (Email) at the address mike@ai.mit.edu,
or (US mail) as Mike Haertel c/o Free Software Foundation. */
#include "mmalloc.h"
/* FIXME: See the comment in mmalloc.h where struct mstats is defined.
None of the internal mmalloc structures should be externally visible
outside the library. */
struct mstats
mmstats (md)
PTR md;
{
struct mstats result;
struct mdesc *mdp;
mdp = MD_TO_MDP (md);
result.bytes_total =
(char *) mdp -> morecore (mdp, 0) - mdp -> heapbase;
result.chunks_used = mdp -> heapstats.chunks_used;
result.bytes_used = mdp -> heapstats.bytes_used;
result.chunks_free = mdp -> heapstats.chunks_free;
result.bytes_free = mdp -> heapstats.bytes_free;
return (result);
}

36
mmalloc/mmtrace.awk Normal file
View File

@ -0,0 +1,36 @@
#
# Awk program to analyze mtrace.c output.
#
$1 == "+" { if (allocated[$2] != "")
print "+", $2, "Alloc", NR, "duplicate:", allocated[$2];
else
allocated[$2] = $3;
}
$1 == "-" { if (allocated[$2] != "") {
allocated[$2] = "";
if (allocated[$2] != "")
print "DELETE FAILED", $2, allocated[$2];
} else
print "-", $2, "Free", NR, "was never alloc'd";
}
$1 == "<" { if (allocated[$2] != "")
allocated[$2] = "";
else
print "-", $2, "Realloc", NR, "was never alloc'd";
}
$1 == ">" { if (allocated[$2] != "")
print "+", $2, "Realloc", NR, "duplicate:", allocated[$2];
else
allocated[$2] = $3;
}
# Ignore "= Start"
$1 == "=" { }
# Ignore failed realloc attempts for now
$1 == "!" { }
END { for (x in allocated)
if (allocated[x] != "")
print "+", x, allocated[x];
}

151
mmalloc/mrealloc.c Normal file
View File

@ -0,0 +1,151 @@
/* Change the size of a block allocated by `mmalloc'.
Copyright 1990, 1991 Free Software Foundation
Written May 1989 by Mike Haertel.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.
The author may be reached (Email) at the address mike@ai.mit.edu,
or (US mail) as Mike Haertel c/o Free Software Foundation. */
#include "mmalloc.h"
/* Resize the given region to the new size, returning a pointer
to the (possibly moved) region. This is optimized for speed;
some benchmarks seem to indicate that greater compactness is
achieved by unconditionally allocating and copying to a
new region. This module has incestuous knowledge of the
internals of both mfree and mmalloc. */
PTR
mrealloc (md, ptr, size)
PTR md;
PTR ptr;
size_t size;
{
struct mdesc *mdp;
PTR result;
int type;
size_t block, blocks, oldlimit;
if (size == 0)
{
mfree (md, ptr);
return (mmalloc (md, 0));
}
else if (ptr == NULL)
return (mmalloc (md, size));
mdp = MD_TO_MDP (md);
if (mdp -> mrealloc_hook != NULL)
{
return ((*mdp -> mrealloc_hook) (md, ptr, size));
}
block = BLOCK(ptr);
type = mdp -> heapinfo[block].busy.type;
switch (type)
{
case 0:
/* Maybe reallocate a large block to a small fragment. */
if (size <= BLOCKSIZE / 2)
{
result = mmalloc (md, size);
if (result != NULL)
{
memcpy (result, ptr, size);
mfree (md, ptr);
return (result);
}
}
/* The new size is a large allocation as well;
see if we can hold it in place. */
blocks = BLOCKIFY(size);
if (blocks < mdp -> heapinfo[block].busy.info.size)
{
/* The new size is smaller; return
excess memory to the free list. */
mdp -> heapinfo[block + blocks].busy.type = 0;
mdp -> heapinfo[block + blocks].busy.info.size
= mdp -> heapinfo[block].busy.info.size - blocks;
mdp -> heapinfo[block].busy.info.size = blocks;
mfree (md, ADDRESS(block + blocks));
result = ptr;
}
else if (blocks == mdp -> heapinfo[block].busy.info.size)
/* No size change necessary. */
result = ptr;
else
{
/* Won't fit, so allocate a new region that will.
Free the old region first in case there is sufficient
adjacent free space to grow without moving. */
blocks = mdp -> heapinfo[block].busy.info.size;
/* Prevent free from actually returning memory to the system. */
oldlimit = mdp -> heaplimit;
mdp -> heaplimit = 0;
mfree (md, ptr);
mdp -> heaplimit = oldlimit;
result = mmalloc (md, size);
if (result == NULL)
{
(void) mmalloc (md, blocks * BLOCKSIZE);
return NULL;
}
if (ptr != result)
memmove (result, ptr, blocks * BLOCKSIZE);
}
break;
default:
/* Old size is a fragment; type is logarithm
to base two of the fragment size. */
if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type))
/* The new size is the same kind of fragment. */
result = ptr;
else
{
/* The new size is different; allocate a new space,
and copy the lesser of the new size and the old. */
result = mmalloc (md, size);
if (result == NULL)
return (NULL);
memcpy (result, ptr, MIN(size, (size_t) 1 << type));
mfree (md, ptr);
}
break;
}
return (result);
}
/* When using this package, provide a version of malloc/realloc/free built
on top of it, so that if we use the default sbrk() region we will not
collide with another malloc package trying to do the same thing, if
the application contains any "hidden" calls to malloc/realloc/free (such
as inside a system library).
NOTE: Defining our own copy of this breaks ANSI conformance. */
PTR
realloc (ptr, size)
PTR ptr;
size_t size;
{
return (mrealloc ((void *) NULL, ptr, size));
}

39
mmalloc/mvalloc.c Normal file
View File

@ -0,0 +1,39 @@
/* Allocate memory on a page boundary.
Copyright (C) 1991 Free Software Foundation, Inc.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include "mmalloc.h"
/* Cache the pagesize for the current host machine. Note that if the host
does not readily provide a getpagesize() function, we need to emulate it
elsewhere, not clutter up this file with lots of kluges to try to figure
it out. */
static size_t pagesize;
PTR
mvalloc (md, size)
PTR md;
size_t size;
{
if (pagesize == 0)
{
pagesize = getpagesize ();
}
return (mmemalign (md, pagesize, size));
}