15 changed files with 3018 additions and 0 deletions
@ -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: |
|||
@ -0,0 +1,5 @@ |
|||
Sat Mar 14 17:34:59 1992 Fred Fish (fnf@cygnus.com) |
|||
|
|||
* Initial release, incorporated into gdb. |
|||
|
|||
|
|||
@ -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 |
|||
@ -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. |
|||
@ -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: |
|||
# |
|||
@ -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); |
|||
} |
|||
|
|||
|
|||
|
|||
File diff suppressed because it is too large
@ -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); |
|||
} |
|||
@ -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)); |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -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); |
|||
} |
|||
@ -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]; |
|||
} |
|||
@ -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)); |
|||
} |
|||
@ -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)); |
|||
} |
|||
Loading…
Reference in new issue