Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
New module: mmalloc (mapped malloc)
authormquinson <mquinson@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Wed, 5 May 2010 21:38:00 +0000 (21:38 +0000)
committermquinson <mquinson@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Wed, 5 May 2010 21:38:00 +0000 (21:38 +0000)
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@7693 48e7efb5-ca39-0410-a469-dd3cf9ba447f

29 files changed:
.gitignore
ChangeLog
acmacro/bfd_need_declarations.m4 [new file with mode: 0644]
configure.ac
src/Makefile.am
src/xbt/mmalloc/COPYING.LIB [new file with mode: 0644]
src/xbt/mmalloc/TODO [new file with mode: 0644]
src/xbt/mmalloc/attach.c [new file with mode: 0644]
src/xbt/mmalloc/detach.c [new file with mode: 0644]
src/xbt/mmalloc/include/ansidecl.h [new file with mode: 0644]
src/xbt/mmalloc/keys.c [new file with mode: 0644]
src/xbt/mmalloc/mcalloc.c [new file with mode: 0644]
src/xbt/mmalloc/mfree.c [new file with mode: 0644]
src/xbt/mmalloc/mm.c [new file with mode: 0644]
src/xbt/mmalloc/mmalloc.c [new file with mode: 0644]
src/xbt/mmalloc/mmalloc.h [new file with mode: 0644]
src/xbt/mmalloc/mmalloc.info [new file with mode: 0644]
src/xbt/mmalloc/mmalloc.texi [new file with mode: 0644]
src/xbt/mmalloc/mmap-sup.c [new file with mode: 0644]
src/xbt/mmalloc/mmcheck.c [new file with mode: 0644]
src/xbt/mmalloc/mmemalign.c [new file with mode: 0644]
src/xbt/mmalloc/mmprivate.h [new file with mode: 0644]
src/xbt/mmalloc/mmstats.c [new file with mode: 0644]
src/xbt/mmalloc/mmtrace.awk [new file with mode: 0644]
src/xbt/mmalloc/mmtrace.c [new file with mode: 0644]
src/xbt/mmalloc/mrealloc.c [new file with mode: 0644]
src/xbt/mmalloc/mvalloc.c [new file with mode: 0644]
src/xbt/mmalloc/sbrk-sup.c [new file with mode: 0644]
src/xbt/mmalloc/test/mmalloc_test.c [new file with mode: 0644]

index ec574ac..1cad565 100644 (file)
@@ -22,9 +22,28 @@ _*.c
 *~
 *.swp
 *_simulator
+
 config.log
 config.status
+config.cache
+config.guess
+config.sub
 Makefile.in
+autom4te.cache
+aclocal.m4
+acmacro/libtool.m4
+acmacro/ltoptions.m4
+acmacro/ltsugar.m4
+acmacro/ltversion.m4
+acmacro/lt~obsolete.m4
+configure
+install-sh
+libtool
+ltmain.sh
+depcomp
+missing
+texinfo.tex
+
 *_unit.c
 src/simgrid.jar
 src/simgrid_units_main.c
@@ -83,20 +102,6 @@ doc/using_bib.html
 doc/using_bib.latin1.html
 doc/using_bib.latin1.html.tmp
 
-aclocal.m4
-acmacro/libtool.m4
-acmacro/ltoptions.m4
-acmacro/ltsugar.m4
-acmacro/ltversion.m4
-acmacro/lt~obsolete.m4
-config.guess
-config.sub
-configure
-install-sh
-libtool
-ltmain.sh
-
-autom4te.cache/*
 doc/Doxyfile
 include/simgrid_config.h
 include/instr/tracing_config.h
index ad90087..7fb0258 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,7 @@ SimGrid (3.5) unstable; urgency=low
 
  XBT
  * New data container: setset (set of sets of elements)
+ * New module: mmalloc (mapped malloc)
  * New function: xbt_dict_cursor_set_data()
  * New function: xbt_fifo_get_last_item()
  * Bug fix in xbt_dynar_shrink(): use the right element size
diff --git a/acmacro/bfd_need_declarations.m4 b/acmacro/bfd_need_declarations.m4
new file mode 100644 (file)
index 0000000..68ef008
--- /dev/null
@@ -0,0 +1,28 @@
+dnl See whether we need a declaration for a function.
+AC_DEFUN([BFD_NEED_DECLARATION],
+[AC_MSG_CHECKING([whether $1 must be declared])
+AC_CACHE_VAL(bfd_cv_decl_needed_$1,
+[AC_TRY_COMPILE([
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif],
+[char *(*pfn) = (char *(*)) $1],
+bfd_cv_decl_needed_$1=no, bfd_cv_decl_needed_$1=yes)])
+AC_MSG_RESULT($bfd_cv_decl_needed_$1)
+if test $bfd_cv_decl_needed_$1 = yes; then
+  AC_DEFINE([NEED_DECLARATION_]translit($1, [a-z], [A-Z]), 1,
+           [Define if $1 is not declared in system header files.])
+fi
+])dnl
+
index aae4941..33f3d8e 100644 (file)
@@ -20,6 +20,14 @@ AC_LANG([C])
 AC_PROG_CXX
 AM_PROG_GCJ
 
+dnl ########### Addition for mmalloc (to be integrated into Cmake tools)
+AC_FUNC_MMAP
+AC_CHECK_HEADERS(limits.h stddef.h unistd.h)
+
+BFD_NEED_DECLARATION(sbrk)
+BFD_NEED_DECLARATION(getpagesize)
+dnl ########### end of addition for mmalloc
+
 AM_INIT_AUTOMAKE([gnu -Wno-portability])
 AC_CONFIG_MACRO_DIR(acmacro) 
 ACLOCAL="$ACLOCAL -I acmacro"
index dbe4cd4..992a5f8 100644 (file)
@@ -170,7 +170,22 @@ XBT_SRC=\
   xbt/config.c                                                               \
   xbt/cunit.c                                                                \
   xbt/graphxml_parse.c                                                       \
-  xbt/setset.c
+  xbt/setset.c                                                               \
+  xbt/mmalloc/mm.c
+
+#### mmalloc cruft -- to be integrated into cmake
+
+EXTRA_DIST+= \
+  xbt/mmalloc/ansidecl.h  xbt/mmalloc/keys.c      xbt/mmalloc/mmalloc.c  \
+  xbt/mmalloc/mm.c        xbt/mmalloc/mmprivate.h xbt/mmalloc/mrealloc.c \
+  xbt/mmalloc/attach.c    xbt/mmalloc/mcalloc.c   xbt/mmalloc/mmalloc.h  \
+  xbt/mmalloc/mmcheck.c   xbt/mmalloc/mmstats.c   xbt/mmalloc/mvalloc.c  \
+  xbt/mmalloc/detach.c    xbt/mmalloc/mfree.c     xbt/mmalloc/mmap-sup.c \
+  xbt/mmalloc/mmemalign.c xbt/mmalloc/mmtrace.c   xbt/mmalloc/sbrk-sup.c
+
+# info_TEXINFOS= xbt/mmalloc/mmalloc.texi
+
+### End of mmalloc cruft
 
 XBT_RL_SRC = \
   xbt/xbt_rl_synchro.c         \
diff --git a/src/xbt/mmalloc/COPYING.LIB b/src/xbt/mmalloc/COPYING.LIB
new file mode 100644 (file)
index 0000000..eb685a5
--- /dev/null
@@ -0,0 +1,481 @@
+                 GNU LIBRARY GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+                    675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+\f
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+  Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs.  This
+license, the GNU Library General Public License, applies to certain
+designated libraries.  This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+  The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it.  Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program.  However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+  Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+  However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.)  The hope is that this
+will lead to faster development of free libraries.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+  Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+\f
+                 GNU LIBRARY GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License").  Each licensee is
+addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    c) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    d) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+\f
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                           NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+     Appendix: How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This 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.
+
+    This 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 this library; if not, write to the Free
+    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/src/xbt/mmalloc/TODO b/src/xbt/mmalloc/TODO
new file mode 100644 (file)
index 0000000..9412043
--- /dev/null
@@ -0,0 +1,17 @@
+Things that still need attention:
+
+   *   Make implementation changes necessary to allow multiple processes
+       to use the mmalloc managed region simultaneously.  This requires,
+       at the minimum, some sort of cooperative locking that ensures that
+       only one process at a time is changing any of the mmalloc managed
+       data structures (its ok for the mmalloc managed data regions to be
+       changed at any time since we don't care about their contents).
+
+   *   In order to support multiple processes using the mmalloc managed
+       region, the malloc descriptor needs to be broken into two parts,
+       one part which is specific to the given process and is maintained
+       separately on a per process basis, and another part which is common
+       to all processes.  As an example, the file descriptor is specific
+       to a given process, as are the morecore and abortfunc pointers.
+       However magic[], the version number, the flags field, etc are
+       common to all processes.
diff --git a/src/xbt/mmalloc/attach.c b/src/xbt/mmalloc/attach.c
new file mode 100644 (file)
index 0000000..2fe1de9
--- /dev/null
@@ -0,0 +1,228 @@
+/* Initialization for access to a mmap'd malloc managed region.
+   Copyright 1992, 2000 Free Software Foundation, Inc.
+
+   Contributed by Fred Fish at Cygnus Support.   fnf@cygnus.com
+
+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., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#include <sys/types.h>
+#include <fcntl.h> /* After sys/types.h, at least for dpx/2.  */
+#include <sys/stat.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>    /* Prototypes for lseek */
+#endif
+#include "mmprivate.h"
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+
+#if defined(HAVE_MMAP)
+
+/* Forward declarations/prototypes for local functions */
+
+static struct mdesc *reuse PARAMS ((int));
+
+/* 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 an anonymous
+   map is used if supported by the underlying OS. In case of running in
+   an OS without support of anonymous mappings then "/dev/zero" is used 
+   and in both cases 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 (ignoring
+   the BASEADDR parameter).
+
+   For non valid FDs or empty files ones the mapping is established 
+   starting at the specified address BASEADDR in the process address 
+   space.
+
+   The provided BASEADDR should be choosed carefully in order to avoid
+   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. */
+
+PTR
+mmalloc_attach (fd, baseaddr)
+  int fd;
+  PTR baseaddr;
+{
+  struct mdesc mtemp;
+  struct mdesc *mdp;
+  PTR mbase;
+  struct stat sbuf;
+
+  /* First check to see if FD is a valid file descriptor, and if so, see
+     if the file has any current contents (size > 0).  If it does, then
+     attempt to reuse the file.  If we can't reuse the file, either
+     because it isn't a valid mmalloc produced file, was produced by an
+     obsolete version, or any other reason, then we fail to attach to
+     this file. */
+
+  if (fd >= 0)
+  {
+    if (fstat (fd, &sbuf) < 0)
+         return (NULL);
+
+    else if (sbuf.st_size > 0)
+         return ((PTR) reuse (fd));
+  }
+
+  /* If the user provided NULL BASEADDR then fail */
+  if (baseaddr == NULL)
+    return (NULL);
+
+  /* We start off with the malloc descriptor allocated on the stack, until
+     we build it up enough to call _mmalloc_mmap_morecore() to allocate the
+     first page of the region and copy it there.  Ensure that it is zero'd and
+     then initialize the fields that we know values for. */
+
+  mdp = &mtemp;
+  memset ((char *) mdp, 0, sizeof (mtemp));
+  strncpy (mdp -> magic, MMALLOC_MAGIC, MMALLOC_MAGIC_SIZE);
+  mdp -> headersize = sizeof (mtemp);
+  mdp -> version = MMALLOC_VERSION;
+  mdp -> morecore = __mmalloc_mmap_morecore;
+  mdp -> fd = fd;
+  mdp -> base = mdp -> breakval = mdp -> top = baseaddr;
+
+  /* If we have not been passed a valid open file descriptor for the file
+     to map to, then we go for an anonymous map */
+
+  if(mdp -> fd < 0)
+    mdp -> flags |= MMALLOC_ANONYMOUS;
+
+  /* If we have not been passed a valid open file descriptor for the file
+     to map to, then open /dev/zero and use that to map to. */
+
+/*  if (mdp -> fd < 0)*/
+/*  {*/
+/*    if ((mdp -> fd = open ("/dev/zero", O_RDWR)) < 0)*/
+/*     {*/
+/*       return (NULL);*/
+/*     }*/
+/*    else*/
+/*     {*/
+/*       mdp -> flags |= MMALLOC_DEVZERO;*/
+/*     }*/
+/*  }*/
+
+  /* Now try to map in the first page, copy the malloc descriptor structure
+     there, and arrange to return a pointer to this new copy.  If the mapping
+     fails, then close the file descriptor if it was opened by us, and arrange
+     to return a NULL. */
+
+  if ((mbase = mdp -> morecore (mdp, sizeof (mtemp))) != NULL)
+  {
+    memcpy (mbase, mdp, sizeof (mtemp));
+//    mdp = (struct mdesc *) mbase;
+  }
+  else
+  {
+    abort();
+//    mdp = NULL;
+  }
+  
+  return ((PTR) mbase);
+}
+
+/* Given an valid file descriptor on an open file, test to see if that file
+   is a valid mmalloc produced file, and if so, attempt to remap it into the
+   current process at the same address to which it was previously mapped.
+
+   Note that we have to update the file descriptor number in the malloc-
+   descriptor read from the file to match the current valid one, before
+   trying to map the file in, and again after a successful mapping and
+   after we've switched over to using the mapped in malloc descriptor 
+   rather than the temporary one on the stack.
+
+   Once we've switched over to using the mapped in malloc descriptor, we
+   have to update the pointer to the morecore function, since it almost
+   certainly will be at a different address if the process reusing the
+   mapped region is from a different executable.
+
+   Also note that if the heap being remapped previously used the mmcheckf()
+   routines, we need to update the hooks since their target functions
+   will have certainly moved if the executable has changed in any way.
+   We do this by calling mmcheckf() internally.
+
+   Returns a pointer to the malloc descriptor if successful, or NULL if
+   unsuccessful for some reason. */
+
+static struct mdesc *
+reuse (fd)
+  int fd;
+{
+  struct mdesc mtemp;
+  struct mdesc *mdp = NULL;
+
+  if (lseek (fd, 0L, SEEK_SET) != 0)
+    return NULL;
+  if (read (fd, (char *) &mtemp, sizeof (mtemp)) != sizeof (mtemp))
+    return NULL;
+  if (mtemp.headersize != sizeof (mtemp))
+    return NULL;
+  if (strcmp (mtemp.magic, MMALLOC_MAGIC) != 0)
+    return NULL;
+  if (mtemp.version > MMALLOC_VERSION)
+    return NULL;
+
+  mtemp.fd = fd;
+  if (__mmalloc_remap_core (&mtemp) == mtemp.base)
+  {
+    mdp = (struct mdesc *) mtemp.base;
+       mdp -> fd = fd;
+       mdp -> morecore = __mmalloc_mmap_morecore;
+       if (mdp -> mfree_hook != NULL)
+       {
+         mmcheckf ((PTR) mdp, (void (*) PARAMS ((void))) NULL, 1);
+       }
+  }
+  return (mdp);
+}
+
+#else  /* !defined (HAVE_MMAP) */
+
+/* For systems without mmap, the library still supplies an entry point
+   to link to, but trying to initialize access to an mmap'd managed region
+   always fails. */
+
+/* ARGSUSED */
+PTR
+mmalloc_attach (fd, baseaddr)
+  int fd;
+  PTR baseaddr;
+{
+   return (NULL);
+}
+
+#endif /* defined (HAVE_MMAP) */
+
diff --git a/src/xbt/mmalloc/detach.c b/src/xbt/mmalloc/detach.c
new file mode 100644 (file)
index 0000000..1780679
--- /dev/null
@@ -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 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., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#include <sys/types.h>
+#include "mmprivate.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)
+     PTR 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.breakval)) == NULL)
+       {
+         /* Deallocating failed.  Update the original malloc descriptor
+            with any changes */
+         *(struct mdesc *) md = mtemp;
+       }
+      else
+       {
+         if (mtemp.flags & MMALLOC_DEVZERO)
+           {
+             close (mtemp.fd);
+           }
+         md = NULL;
+       }
+    }
+
+  return (md);
+}
diff --git a/src/xbt/mmalloc/include/ansidecl.h b/src/xbt/mmalloc/include/ansidecl.h
new file mode 100644 (file)
index 0000000..d2c8776
--- /dev/null
@@ -0,0 +1,315 @@
+/* ANSI and traditional C compatability macros
+   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* ANSI and traditional C compatibility macros
+
+   ANSI C is assumed if __STDC__ is #defined.
+
+   Macro               ANSI C definition       Traditional C definition
+   -----               ---- - ----------       ----------- - ----------
+   ANSI_PROTOTYPES     1                       not defined
+   PTR                 `void *'                `char *'
+   PTRCONST            `void *const'           `char *'
+   LONG_DOUBLE         `long double'           `double'
+   const               not defined             `'
+   volatile            not defined             `'
+   signed              not defined             `'
+   VA_START(ap, var)   va_start(ap, var)       va_start(ap)
+
+   Note that it is safe to write "void foo();" indicating a function
+   with no return value, in all K+R compilers we have been able to test.
+
+   For declaring functions with prototypes, we also provide these:
+
+   PARAMS ((prototype))
+   -- for functions which take a fixed number of arguments.  Use this
+   when declaring the function.  When defining the function, write a
+   K+R style argument list.  For example:
+
+       char *strcpy PARAMS ((char *dest, char *source));
+       ...
+       char *
+       strcpy (dest, source)
+            char *dest;
+            char *source;
+       { ... }
+
+
+   VPARAMS ((prototype, ...))
+   -- for functions which take a variable number of arguments.  Use
+   PARAMS to declare the function, VPARAMS to define it.  For example:
+
+       int printf PARAMS ((const char *format, ...));
+       ...
+       int
+       printf VPARAMS ((const char *format, ...))
+       {
+          ...
+       }
+
+   For writing functions which take variable numbers of arguments, we
+   also provide the VA_OPEN, VA_CLOSE, and VA_FIXEDARG macros.  These
+   hide the differences between K+R <varargs.h> and C89 <stdarg.h> more
+   thoroughly than the simple VA_START() macro mentioned above.
+
+   VA_OPEN and VA_CLOSE are used *instead of* va_start and va_end.
+   Immediately after VA_OPEN, put a sequence of VA_FIXEDARG calls
+   corresponding to the list of fixed arguments.  Then use va_arg
+   normally to get the variable arguments, or pass your va_list object
+   around.  You do not declare the va_list yourself; VA_OPEN does it
+   for you.
+
+   Here is a complete example:
+
+       int
+       printf VPARAMS ((const char *format, ...))
+       {
+          int result;
+
+          VA_OPEN (ap, format);
+          VA_FIXEDARG (ap, const char *, format);
+
+          result = vfprintf (stdout, format, ap);
+          VA_CLOSE (ap);
+
+          return result;
+       }
+
+
+   You can declare variables either before or after the VA_OPEN,
+   VA_FIXEDARG sequence.  Also, VA_OPEN and VA_CLOSE are the beginning
+   and end of a block.  They must appear at the same nesting level,
+   and any variables declared after VA_OPEN go out of scope at
+   VA_CLOSE.  Unfortunately, with a K+R compiler, that includes the
+   argument list.  You can have multiple instances of VA_OPEN/VA_CLOSE
+   pairs in a single function in case you need to traverse the
+   argument list more than once.
+
+   For ease of writing code which uses GCC extensions but needs to be
+   portable to other compilers, we provide the GCC_VERSION macro that
+   simplifies testing __GNUC__ and __GNUC_MINOR__ together, and various
+   wrappers around __attribute__.  Also, __extension__ will be #defined
+   to nothing if it doesn't work.  See below.
+
+   This header also defines a lot of obsolete macros:
+   CONST, VOLATILE, SIGNED, PROTO, EXFUN, DEFUN, DEFUN_VOID,
+   AND, DOTS, NOARGS.  Don't use them.  */
+
+#ifndef        _ANSIDECL_H
+#define _ANSIDECL_H    1
+
+/* Every source file includes this file,
+   so they will all get the switch for lint.  */
+/* LINTLIBRARY */
+
+/* Using MACRO(x,y) in cpp #if conditionals does not work with some
+   older preprocessors.  Thus we can't define something like this:
+
+#define HAVE_GCC_VERSION(MAJOR, MINOR) \
+  (__GNUC__ > (MAJOR) || (__GNUC__ == (MAJOR) && __GNUC_MINOR__ >= (MINOR)))
+
+and then test "#if HAVE_GCC_VERSION(2,7)".
+
+So instead we use the macro below and test it against specific values.  */
+
+/* This macro simplifies testing whether we are using gcc, and if it
+   is of a particular minimum version. (Both major & minor numbers are
+   significant.)  This macro will evaluate to 0 if we are not using
+   gcc at all.  */
+#ifndef GCC_VERSION
+#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
+#endif /* GCC_VERSION */
+
+#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32) || (defined(__alpha) && defined(__cplusplus))
+/* All known AIX compilers implement these things (but don't always
+   define __STDC__).  The RISC/OS MIPS compiler defines these things
+   in SVR4 mode, but does not define __STDC__.  */
+/* eraxxon@alumni.rice.edu: The Compaq C++ compiler, unlike many other
+   C++ compilers, does not define __STDC__, though it acts as if this
+   was so. (Verified versions: 5.7, 6.2, 6.3, 6.5) */
+
+#define ANSI_PROTOTYPES        1
+#define PTR            void *
+#define PTRCONST       void *const
+#define LONG_DOUBLE    long double
+
+#define PARAMS(ARGS)           ARGS
+#define VPARAMS(ARGS)          ARGS
+#define VA_START(VA_LIST, VAR) va_start(VA_LIST, VAR)
+
+/* variadic function helper macros */
+/* "struct Qdmy" swallows the semicolon after VA_OPEN/VA_FIXEDARG's
+   use without inhibiting further decls and without declaring an
+   actual variable.  */
+#define VA_OPEN(AP, VAR)       { va_list AP; va_start(AP, VAR); { struct Qdmy
+#define VA_CLOSE(AP)           } va_end(AP); }
+#define VA_FIXEDARG(AP, T, N)  struct Qdmy
+#undef const
+#undef volatile
+#undef signed
+
+/* inline requires special treatment; it's in C99, and GCC >=2.7 supports
+   it too, but it's not in C89.  */
+#undef inline
+#if __STDC_VERSION__ > 199901L
+/* it's a keyword */
+#else
+# if GCC_VERSION >= 2007
+#  define inline __inline__   /* __inline__ prevents -pedantic warnings */
+# else
+#  define inline  /* nothing */
+# endif
+#endif
+
+/* These are obsolete.  Do not use.  */
+#ifndef IN_GCC
+#define CONST          const
+#define VOLATILE       volatile
+#define SIGNED         signed
+
+#define PROTO(type, name, arglist)     type name arglist
+#define EXFUN(name, proto)             name proto
+#define DEFUN(name, arglist, args)     name(args)
+#define DEFUN_VOID(name)               name(void)
+#define AND            ,
+#define DOTS           , ...
+#define NOARGS         void
+#endif /* ! IN_GCC */
+
+#else  /* Not ANSI C.  */
+
+#undef  ANSI_PROTOTYPES
+#define PTR            char *
+#define PTRCONST       PTR
+#define LONG_DOUBLE    double
+
+#define PARAMS(args)           ()
+#define VPARAMS(args)          (va_alist) va_dcl
+#define VA_START(va_list, var) va_start(va_list)
+
+#define VA_OPEN(AP, VAR)               { va_list AP; va_start(AP); { struct Qdmy
+#define VA_CLOSE(AP)                   } va_end(AP); }
+#define VA_FIXEDARG(AP, TYPE, NAME)    TYPE NAME = va_arg(AP, TYPE)
+
+/* some systems define these in header files for non-ansi mode */
+#undef const
+#undef volatile
+#undef signed
+#undef inline
+#define const
+#define volatile
+#define signed
+#define inline
+
+#ifndef IN_GCC
+#define CONST
+#define VOLATILE
+#define SIGNED
+
+#define PROTO(type, name, arglist)     type name ()
+#define EXFUN(name, proto)             name()
+#define DEFUN(name, arglist, args)     name arglist args;
+#define DEFUN_VOID(name)               name()
+#define AND            ;
+#define DOTS
+#define NOARGS
+#endif /* ! IN_GCC */
+
+#endif /* ANSI C.  */
+
+/* Define macros for some gcc attributes.  This permits us to use the
+   macros freely, and know that they will come into play for the
+   version of gcc in which they are supported.  */
+
+#if (GCC_VERSION < 2007)
+# define __attribute__(x)
+#endif
+
+/* Attribute __malloc__ on functions was valid as of gcc 2.96. */
+#ifndef ATTRIBUTE_MALLOC
+# if (GCC_VERSION >= 2096)
+#  define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
+# else
+#  define ATTRIBUTE_MALLOC
+# endif /* GNUC >= 2.96 */
+#endif /* ATTRIBUTE_MALLOC */
+
+/* Attributes on labels were valid as of gcc 2.93. */
+#ifndef ATTRIBUTE_UNUSED_LABEL
+# if (GCC_VERSION >= 2093)
+#  define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED
+# else
+#  define ATTRIBUTE_UNUSED_LABEL
+# endif /* GNUC >= 2.93 */
+#endif /* ATTRIBUTE_UNUSED_LABEL */
+
+#ifndef ATTRIBUTE_UNUSED
+#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif /* ATTRIBUTE_UNUSED */
+
+#ifndef ATTRIBUTE_NORETURN
+#define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
+#endif /* ATTRIBUTE_NORETURN */
+
+/* Attribute `nonnull' was valid as of gcc 3.3.  */
+#ifndef ATTRIBUTE_NONNULL
+# if (GCC_VERSION >= 3003)
+#  define ATTRIBUTE_NONNULL(m) __attribute__ ((__nonnull__ (m)))
+# else
+#  define ATTRIBUTE_NONNULL(m)
+# endif /* GNUC >= 3.3 */
+#endif /* ATTRIBUTE_NONNULL */
+
+/* Use ATTRIBUTE_PRINTF when the format specifier must not be NULL.
+   This was the case for the `printf' format attribute by itself
+   before GCC 3.3, but as of 3.3 we need to add the `nonnull'
+   attribute to retain this behavior.  */
+#ifndef ATTRIBUTE_PRINTF
+#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n))) ATTRIBUTE_NONNULL(m)
+#define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2)
+#define ATTRIBUTE_PRINTF_2 ATTRIBUTE_PRINTF(2, 3)
+#define ATTRIBUTE_PRINTF_3 ATTRIBUTE_PRINTF(3, 4)
+#define ATTRIBUTE_PRINTF_4 ATTRIBUTE_PRINTF(4, 5)
+#define ATTRIBUTE_PRINTF_5 ATTRIBUTE_PRINTF(5, 6)
+#endif /* ATTRIBUTE_PRINTF */
+
+/* Use ATTRIBUTE_NULL_PRINTF when the format specifier may be NULL.  A
+   NULL format specifier was allowed as of gcc 3.3.  */
+#ifndef ATTRIBUTE_NULL_PRINTF
+# if (GCC_VERSION >= 3003)
+#  define ATTRIBUTE_NULL_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n)))
+# else
+#  define ATTRIBUTE_NULL_PRINTF(m, n)
+# endif /* GNUC >= 3.3 */
+# define ATTRIBUTE_NULL_PRINTF_1 ATTRIBUTE_NULL_PRINTF(1, 2)
+# define ATTRIBUTE_NULL_PRINTF_2 ATTRIBUTE_NULL_PRINTF(2, 3)
+# define ATTRIBUTE_NULL_PRINTF_3 ATTRIBUTE_NULL_PRINTF(3, 4)
+# define ATTRIBUTE_NULL_PRINTF_4 ATTRIBUTE_NULL_PRINTF(4, 5)
+# define ATTRIBUTE_NULL_PRINTF_5 ATTRIBUTE_NULL_PRINTF(5, 6)
+#endif /* ATTRIBUTE_NULL_PRINTF */
+
+/* We use __extension__ in some places to suppress -pedantic warnings
+   about GCC extensions.  This feature didn't work properly before
+   gcc 2.8.  */
+#if GCC_VERSION < 2008
+#define __extension__
+#endif
+
+#endif /* ansidecl.h   */
diff --git a/src/xbt/mmalloc/keys.c b/src/xbt/mmalloc/keys.c
new file mode 100644 (file)
index 0000000..35f00d1
--- /dev/null
@@ -0,0 +1,66 @@
+/* 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 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., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, 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 "mmprivate.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);
+}
diff --git a/src/xbt/mmalloc/mcalloc.c b/src/xbt/mmalloc/mcalloc.c
new file mode 100644 (file)
index 0000000..c9fcc07
--- /dev/null
@@ -0,0 +1,54 @@
+/* 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., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#include <sys/types.h>  /* GCC on HP/UX needs this before string.h. */
+#include <string.h>    /* Prototypes for memcpy, memmove, memset, etc */
+
+#include "mmprivate.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)
+    {
+      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). */
+
+PTR
+calloc (nmemb, size)
+  size_t nmemb;
+  size_t size;
+{
+  return (mcalloc ((PTR) NULL, nmemb, size));
+}
diff --git a/src/xbt/mmalloc/mfree.c b/src/xbt/mmalloc/mfree.c
new file mode 100644 (file)
index 0000000..a602355
--- /dev/null
@@ -0,0 +1,247 @@
+/* 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., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, 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 "mmprivate.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 *)
+       ((PTR) 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 ((PTR) mdp, (PTR) 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) (mdp, 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). */
+
+void
+free (ptr)
+  PTR ptr;
+{
+  mfree ((PTR) NULL, ptr);
+}
diff --git a/src/xbt/mmalloc/mm.c b/src/xbt/mmalloc/mm.c
new file mode 100644 (file)
index 0000000..d487e0c
--- /dev/null
@@ -0,0 +1,40 @@
+/* Build the entire mmalloc library as a single object module. This
+   avoids having clients pick up part of their allocation routines
+   from mmalloc and part from libc, which results in undefined
+   behavior.  It should also still be possible to build the library
+   as a standard library with multiple objects.
+
+   Copyright 1996, 2000 Free Software Foundation
+
+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., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>    /* Prototypes for lseek, sbrk (maybe) */
+#endif
+#include "mcalloc.c"
+#include "mfree.c"
+#include "mmalloc.c"
+#include "mmcheck.c"
+#include "mmemalign.c"
+#include "mmstats.c"
+#include "mmtrace.c"
+#include "mrealloc.c"
+#include "mvalloc.c"
+#include "mmap-sup.c"
+#include "attach.c"
+#include "detach.c"
+#include "keys.c"
+#include "sbrk-sup.c"
diff --git a/src/xbt/mmalloc/mmalloc.c b/src/xbt/mmalloc/mmalloc.c
new file mode 100644 (file)
index 0000000..a677000
--- /dev/null
@@ -0,0 +1,336 @@
+/* Memory allocator `malloc'.
+   Copyright 1990, 1991, 1992 Free Software Foundation
+
+   Written May 1989 by Mike Haertel.
+   Heavily modified Mar 1992 by Fred Fish for mmap'd version.
+
+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., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, 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 <string.h>    /* Prototypes for memcpy, memmove, memset, etc */
+#include <stdio.h>
+#include "mmprivate.h"
+
+/* Prototypes for local functions */
+
+static int initialize PARAMS ((struct mdesc *));
+static PTR morecore PARAMS ((struct mdesc *, size_t));
+static PTR align PARAMS ((struct mdesc *, size_t));
+
+/* Aligned allocation.  */
+
+static PTR
+align (mdp, size)
+  struct mdesc *mdp;
+  size_t size;
+{
+  PTR result;
+  unsigned long int adj;
+
+  result = mdp -> morecore (mdp, size);
+  adj = RESIDUAL (result, BLOCKSIZE);
+  if (adj != 0)
+    {
+      adj = BLOCKSIZE - adj;
+      mdp -> morecore (mdp, adj);
+      result = (PTR) result + adj;
+    }
+  return (result);
+}
+
+/* Set everything up and remember that we have.  */
+
+static int
+initialize (mdp)
+  struct mdesc *mdp;
+{
+  mdp -> heapsize = HEAP / BLOCKSIZE;
+  mdp -> heapinfo = (malloc_info *) 
+    align (mdp, mdp -> heapsize * sizeof (malloc_info));
+  if (mdp -> heapinfo == NULL)
+    {
+      return (0);
+    }
+  memset ((PTR)mdp -> heapinfo, 0, mdp -> heapsize * sizeof (malloc_info));
+  mdp -> heapinfo[0].free.size = 0;
+  mdp -> heapinfo[0].free.next = mdp -> heapinfo[0].free.prev = 0;
+  mdp -> heapindex = 0;
+  mdp -> heapbase = (PTR) mdp -> heapinfo;
+  mdp -> flags |= MMALLOC_INITIALIZED;
+  return (1);
+}
+
+/* Get neatly aligned memory, initializing or
+   growing the heap info table as necessary. */
+
+static PTR
+morecore (mdp, size)
+  struct mdesc *mdp;
+  size_t size;
+{
+  PTR result;
+  malloc_info *newinfo, *oldinfo;
+  size_t newsize;
+
+  result = align (mdp, size);
+  if (result == NULL)
+    {
+      return (NULL);
+    }
+
+  /* Check if we need to grow the info table.  */
+  if ((size_t) BLOCK ((PTR) result + size) > mdp -> heapsize)
+    {
+      newsize = mdp -> heapsize;
+      while ((size_t) BLOCK ((PTR) result + size) > newsize)
+       {
+         newsize *= 2;
+       }
+      newinfo = (malloc_info *) align (mdp, newsize * sizeof (malloc_info));
+      if (newinfo == NULL)
+       {
+         mdp -> morecore (mdp, -size);
+         return (NULL);
+       }
+      memset ((PTR) newinfo, 0, newsize * sizeof (malloc_info));
+      memcpy ((PTR) newinfo, (PTR) mdp -> heapinfo,
+             mdp -> heapsize * sizeof (malloc_info));
+      oldinfo = mdp -> heapinfo;
+      newinfo[BLOCK (oldinfo)].busy.type = 0;
+      newinfo[BLOCK (oldinfo)].busy.info.size
+       = BLOCKIFY (mdp -> heapsize * sizeof (malloc_info));
+      mdp -> heapinfo = newinfo;
+      __mmalloc_free (mdp, (PTR)oldinfo);
+      mdp -> heapsize = newsize;
+    }
+
+  mdp -> heaplimit = BLOCK ((PTR) result + size);
+  return (result);
+}
+
+/* Allocate memory from the heap.  */
+
+PTR
+mmalloc (md, size)
+  PTR md;
+  size_t size;
+{
+  struct mdesc *mdp;
+  PTR result;
+  size_t block, blocks, lastblocks, start;
+  register size_t i;
+  struct list *next;
+  register size_t log;
+
+  if (size == 0)
+    {
+      return (NULL);
+    }
+
+  mdp = MD_TO_MDP (md);
+      
+  if (mdp -> mmalloc_hook != NULL)
+    {
+      return ((*mdp -> mmalloc_hook) (md, size));
+    }
+
+  if (!(mdp -> flags & MMALLOC_INITIALIZED))
+    {
+      if (!initialize (mdp))
+       {
+         return (NULL);
+       }
+    }
+
+  if (size < sizeof (struct list))
+    {
+      size = sizeof (struct list);
+    }
+
+  /* Determine the allocation policy based on the request size.  */
+  if (size <= BLOCKSIZE / 2)
+    {
+      /* Small allocation to receive a fragment of a block.
+        Determine the logarithm to base two of the fragment size. */
+      log = 1;
+      --size;
+      while ((size /= 2) != 0)
+       {
+         ++log;
+       }
+
+      /* Look in the fragment lists for a
+        free fragment of the desired size. */
+      next = mdp -> fraghead[log].next;
+      if (next != NULL)
+       {
+         /* There are free fragments of this size.
+            Pop a fragment out of the fragment list and return it.
+            Update the block's nfree and first counters. */
+         result = (PTR) next;
+         next -> prev -> next = next -> next;
+         if (next -> next != NULL)
+           {
+             next -> next -> prev = next -> prev;
+           }
+         block = BLOCK (result);
+         if (--mdp -> heapinfo[block].busy.info.frag.nfree != 0)
+           {
+             mdp -> heapinfo[block].busy.info.frag.first =
+               RESIDUAL (next -> next, BLOCKSIZE) >> log;
+           }
+
+         /* Update the statistics.  */
+         mdp -> heapstats.chunks_used++;
+         mdp -> heapstats.bytes_used += 1 << log;
+         mdp -> heapstats.chunks_free--;
+         mdp -> heapstats.bytes_free -= 1 << log;
+       }
+      else
+       {
+         /* No free fragments of the desired size, so get a new block
+            and break it into fragments, returning the first.  */
+         result = mmalloc (md, BLOCKSIZE);
+         if (result == NULL)
+           {
+             return (NULL);
+           }
+
+         /* Link all fragments but the first into the free list.  */
+         for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i)
+           {
+             next = (struct list *) ((PTR) result + (i << log));
+             next -> next = mdp -> fraghead[log].next;
+             next -> prev = &mdp -> fraghead[log];
+             next -> prev -> next = next;
+             if (next -> next != NULL)
+               {
+                 next -> next -> prev = next;
+               }
+           }
+
+         /* Initialize the nfree and first counters for this block.  */
+         block = BLOCK (result);
+         mdp -> heapinfo[block].busy.type = log;
+         mdp -> heapinfo[block].busy.info.frag.nfree = i - 1;
+         mdp -> heapinfo[block].busy.info.frag.first = i - 1;
+
+         mdp -> heapstats.chunks_free += (BLOCKSIZE >> log) - 1;
+         mdp -> heapstats.bytes_free += BLOCKSIZE - (1 << log);
+         mdp -> heapstats.bytes_used -= BLOCKSIZE - (1 << log);
+       }
+    }
+  else
+    {
+      /* Large allocation to receive one or more blocks.
+        Search the free list in a circle starting at the last place visited.
+        If we loop completely around without finding a large enough
+        space we will have to get more memory from the system.  */
+      blocks = BLOCKIFY(size);
+      start = block = MALLOC_SEARCH_START;
+      while (mdp -> heapinfo[block].free.size < blocks)
+       {
+         block = mdp -> heapinfo[block].free.next;
+         if (block == start)
+           {
+             /* Need to get more from the system.  Check to see if
+                the new core will be contiguous with the final free
+                block; if so we don't need to get as much.  */
+             block = mdp -> heapinfo[0].free.prev;
+             lastblocks = mdp -> heapinfo[block].free.size;
+             if (mdp -> heaplimit != 0 &&
+                 block + lastblocks == mdp -> heaplimit &&
+                 mdp -> morecore (mdp, 0) == ADDRESS(block + lastblocks) &&
+                 (morecore (mdp, (blocks - lastblocks) * BLOCKSIZE)) != NULL)
+               {
+                 /* Which block we are extending (the `final free
+                    block' referred to above) might have changed, if
+                    it got combined with a freed info table.  */
+                 block = mdp -> heapinfo[0].free.prev;
+
+                 mdp -> heapinfo[block].free.size += (blocks - lastblocks);
+                 mdp -> heapstats.bytes_free +=
+                     (blocks - lastblocks) * BLOCKSIZE;
+                 continue;
+               }
+             result = morecore(mdp, blocks * BLOCKSIZE);
+             if (result == NULL)
+               {
+                 return (NULL);
+               }
+             block = BLOCK (result);
+             mdp -> heapinfo[block].busy.type = 0;
+             mdp -> heapinfo[block].busy.info.size = blocks;
+             mdp -> heapstats.chunks_used++;
+             mdp -> heapstats.bytes_used += blocks * BLOCKSIZE;
+             return (result);
+           }
+       }
+
+      /* At this point we have found a suitable free list entry.
+        Figure out how to remove what we need from the list. */
+      result = ADDRESS(block);
+      if (mdp -> heapinfo[block].free.size > blocks)
+       {
+         /* The block we found has a bit left over,
+            so relink the tail end back into the free list. */
+         mdp -> heapinfo[block + blocks].free.size
+           = mdp -> heapinfo[block].free.size - blocks;
+         mdp -> heapinfo[block + blocks].free.next
+           = mdp -> heapinfo[block].free.next;
+         mdp -> heapinfo[block + blocks].free.prev
+           = mdp -> heapinfo[block].free.prev;
+         mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next
+           = mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev
+             = mdp -> heapindex = block + blocks;
+       }
+      else
+       {
+         /* The block exactly matches our requirements,
+            so just remove it from the list. */
+         mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev
+           = mdp -> heapinfo[block].free.prev;
+         mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next
+           = mdp -> heapindex = mdp -> heapinfo[block].free.next;
+         mdp -> heapstats.chunks_free--;
+       }
+
+      mdp -> heapinfo[block].busy.type = 0;
+      mdp -> heapinfo[block].busy.info.size = blocks;
+      mdp -> heapstats.chunks_used++;
+      mdp -> heapstats.bytes_used += blocks * BLOCKSIZE;
+      mdp -> heapstats.bytes_free -= blocks * BLOCKSIZE;
+    }
+
+  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). */
+
+PTR
+malloc (size)
+  size_t size;
+{
+  PTR result;
+  result = mmalloc ((PTR) NULL, size);
+  return (result);
+}
diff --git a/src/xbt/mmalloc/mmalloc.h b/src/xbt/mmalloc/mmalloc.h
new file mode 100644 (file)
index 0000000..fa53634
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef MMALLOC_H
+#define MMALLOC_H 1
+
+#ifdef HAVE_STDDEF_H
+#  include <stddef.h>
+#else
+#  include <sys/types.h>   /* for size_t */
+#  include <stdio.h>       /* for NULL */
+#endif
+
+#include "./include/ansidecl.h"
+/* Allocate SIZE bytes of memory.  */
+
+extern PTR mmalloc PARAMS ((PTR, size_t));
+
+/* Re-allocate the previously allocated block in PTR, making the new block
+   SIZE bytes long.  */
+
+extern PTR mrealloc PARAMS ((PTR, PTR, size_t));
+
+/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0.  */
+
+extern PTR mcalloc PARAMS ((PTR, size_t, size_t));
+
+/* Free a block allocated by `mmalloc', `mrealloc' or `mcalloc'.  */
+
+extern void mfree PARAMS ((PTR, PTR));
+
+/* Allocate SIZE bytes allocated to ALIGNMENT bytes.  */
+
+extern PTR mmemalign PARAMS ((PTR, size_t, size_t));
+
+/* Allocate SIZE bytes on a page boundary.  */
+
+extern PTR mvalloc PARAMS ((PTR, size_t));
+
+/* Activate a standard collection of debugging hooks.  */
+
+extern int mmcheck PARAMS ((PTR, void (*) (void)));
+
+extern int mmcheckf PARAMS ((PTR, void (*) (void), int));
+
+/* Pick up the current statistics. (see FIXME elsewhere) */
+
+extern struct mstats mmstats PARAMS ((PTR));
+
+extern PTR mmalloc_attach PARAMS ((int, PTR));
+
+extern PTR mmalloc_detach PARAMS ((PTR));
+
+extern int mmalloc_setkey PARAMS ((PTR, int, PTR));
+
+extern PTR mmalloc_getkey PARAMS ((PTR, int));
+
+extern int mmalloc_errno PARAMS ((PTR));
+
+extern int mmtrace PARAMS ((void));
+
+extern PTR mmalloc_findbase PARAMS ((int));
+
+#endif  /* MMALLOC_H */
diff --git a/src/xbt/mmalloc/mmalloc.info b/src/xbt/mmalloc/mmalloc.info
new file mode 100644 (file)
index 0000000..60d7a8d
--- /dev/null
@@ -0,0 +1,219 @@
+This is ./mmalloc.info, produced by makeinfo version 4.6 from
+mmalloc.texi.
+
+START-INFO-DIR-ENTRY
+* Mmalloc: (mmalloc).          The GNU mapped-malloc package.
+END-INFO-DIR-ENTRY
+
+   This file documents the GNU mmalloc (mapped-malloc) package, written
+by fnf@cygnus.com, based on GNU malloc written by mike@ai.mit.edu.
+
+   Copyright (C) 1992 Free Software Foundation, Inc.
+
+   Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+   Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided also
+that the entire resulting derived work is distributed under the terms
+of a permission notice identical to this one.
+
+   Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions.
+
+\1f
+File: mmalloc.info,  Node: Top,  Next: Overview,  Prev: (dir),  Up: (dir)
+
+mmalloc
+*******
+
+This file documents the GNU memory-mapped malloc package mmalloc.
+
+* Menu:
+
+* Overview::                    Overall Description
+* Implementation::              Implementation
+
+ --- The Detailed Node Listing ---
+
+Implementation
+
+* Compatibility::               Backwards Compatibility
+* Functions::                   Function Descriptions
+
+\1f
+File: mmalloc.info,  Node: Overview,  Next: Implementation,  Prev: Top,  Up: Top
+
+Overall Description
+*******************
+
+This is a heavily modified version of GNU `malloc'.  It uses `mmap' as
+the basic mechanism for obtaining memory from the system, rather than
+`sbrk'.  This gives it several advantages over the more traditional
+malloc:
+
+   * Several different heaps can be used, each of them growing or
+     shinking under control of `mmap', with the `mmalloc' functions
+     using a specific heap on a call by call basis.
+
+   * By using `mmap', it is easy to create heaps which are intended to
+     be persistent and exist as a filesystem object after the creating
+     process has gone away.
+
+   * Because multiple heaps can be managed, data used for a specific
+     purpose can be allocated into its own heap, making it easier to
+     allow applications to "dump" and "restore" initialized
+     malloc-managed memory regions.  For example, the "unexec" hack
+     popularized by GNU Emacs could potentially go away.
+
+\1f
+File: mmalloc.info,  Node: Implementation,  Prev: Overview,  Up: Top
+
+Implementation
+**************
+
+The `mmalloc' functions contain no internal static state.  All
+`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 `mmalloc' which memory region it
+is dealing with (along with other information).  This parameter is
+called the "malloc descriptor".
+
+   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);
+
+* Menu:
+
+* Compatibility::               Backwards Compatibility
+* Functions::                   Function Descriptions
+
+\1f
+File: mmalloc.info,  Node: Compatibility,  Next: Functions,  Prev: Implementation,  Up: Implementation
+
+Backwards Compatibility
+=======================
+
+To allow a single malloc package to be used in a given application,
+provision is made for the traditional `malloc', `realloc', and `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 `sbrk' managed region.  The
+`mmalloc' package provides compatible `malloc', `realloc', and `free'
+functions using this mechanism internally.  Applications can avoid this
+extra interface layer by simply including the following defines:
+
+     #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', and `free' calls with the
+above patterns if using `#define' causes problems.
+
+\1f
+File: mmalloc.info,  Node: Functions,  Prev: Compatibility,  Up: Implementation
+
+Function Descriptions
+=====================
+
+These are the details on the functions that make up the `mmalloc'
+package.
+
+`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 its 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 identified by the
+     descriptor MD, 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.
+
+`*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.  (This function is
+     not yet implemented).
+
+
+\1f
+Tag Table:
+Node: Top\7f937
+Node: Overview\7f1370
+Node: Implementation\7f2395
+Node: Compatibility\7f3785
+Node: Functions\7f4856
+\1f
+End Tag Table
diff --git a/src/xbt/mmalloc/mmalloc.texi b/src/xbt/mmalloc/mmalloc.texi
new file mode 100644 (file)
index 0000000..0a2b9b3
--- /dev/null
@@ -0,0 +1,258 @@
+\input texinfo  @c                                  -*- Texinfo -*-
+@setfilename mmalloc.info
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* Mmalloc: (mmalloc).          The GNU mapped-malloc package.
+END-INFO-DIR-ENTRY
+@end format
+
+This file documents the GNU mmalloc (mapped-malloc) package, written by
+fnf@@cygnus.com, based on GNU malloc written by mike@@ai.mit.edu.
+
+Copyright (C) 1992 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ifinfo
+@iftex
+@c @finalout
+@setchapternewpage odd
+@settitle MMALLOC, the GNU memory-mapped malloc package
+@titlepage
+@title mmalloc
+@subtitle The GNU memory-mapped malloc package
+@author Fred Fish
+@author Cygnus Support
+@author Mike Haertel
+@author Free Software Foundation
+@page
+
+@tex
+\def\$#1${{#1}}  % Kluge: collect RCS revision info without $...$
+\xdef\manvers{\$Revision: 1.4 $}  % For use in headers, footers too
+{\parskip=0pt
+\hfill Cygnus Support\par
+\hfill fnf\@cygnus.com\par
+\hfill {\it MMALLOC, the GNU memory-mapped malloc package}, \manvers\par
+\hfill \TeX{}info \texinfoversion\par
+}
+@end tex
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1992 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end titlepage
+@end iftex
+
+@ifinfo
+@node Top, Overview, (dir), (dir)
+@top mmalloc
+This file documents the GNU memory-mapped malloc package mmalloc.
+
+@menu
+* Overview::                    Overall Description
+* Implementation::              Implementation
+
+ --- The Detailed Node Listing ---
+
+Implementation
+
+* Compatibility::               Backwards Compatibility
+* Functions::                   Function Descriptions
+@end menu
+
+@end ifinfo
+
+@node Overview, Implementation, Top, Top
+@chapter Overall Description
+
+This is a heavily modified version of GNU @code{malloc}.  It uses
+@code{mmap} as the basic mechanism for obtaining memory from the
+system, rather than @code{sbrk}.  This gives it several advantages over the
+more traditional malloc:
+
+@itemize @bullet
+@item
+Several different heaps can be used, each of them growing
+or shinking under control of @code{mmap}, with the @code{mmalloc} functions
+using a specific heap on a call by call basis.
+
+@item
+By using @code{mmap}, it is easy to create heaps which are intended to
+be persistent and exist as a filesystem object after the creating
+process has gone away.
+
+@item
+Because multiple heaps can be managed, data used for a 
+specific purpose can be allocated into its own heap, making
+it easier to allow applications to ``dump'' and ``restore'' initialized
+malloc-managed memory regions.  For example, the ``unexec'' hack popularized
+by GNU Emacs could potentially go away.
+@end itemize
+
+@node Implementation,  , Overview, Top
+@chapter Implementation
+
+The @code{mmalloc} functions contain no internal static state.  All
+@code{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 @code{sbrk}.  However the new routines now need an
+extra parameter which informs @code{mmalloc} which memory region it is dealing
+with (along with other information).  This parameter is called the
+@dfn{malloc descriptor}.
+
+The functions initially provided by @code{mmalloc} are:
+
+@example
+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);
+@end example
+
+@menu
+* Compatibility::               Backwards Compatibility
+* Functions::                   Function Descriptions
+@end menu
+
+@node Compatibility, Functions, Implementation, Implementation
+@section Backwards Compatibility
+
+To allow a single malloc package to be used in a given application,
+provision is made for the traditional @code{malloc}, @code{realloc}, and
+@code{free} functions to be implemented as special cases of the
+@code{mmalloc} functions.  In particular, if any of the functions that
+expect malloc descriptors are called with a @code{NULL} pointer rather than a
+valid malloc descriptor, then they default to using an @code{sbrk} managed
+region.
+The @code{mmalloc} package provides compatible @code{malloc}, @code{realloc},
+and @code{free} functions using this mechanism internally.
+Applications can avoid this extra interface layer by simply including the
+following defines:
+
+@example
+#define malloc(size)           mmalloc ((void *)0, (size))
+#define realloc(ptr,size)      mrealloc ((void *)0, (ptr), (size));
+#define free(ptr)              mfree ((void *)0, (ptr))
+@end example
+
+@noindent
+or replace the existing @code{malloc}, @code{realloc}, and @code{free}
+calls with the above patterns if using @code{#define} causes problems.
+
+@node Functions,  , Compatibility, Implementation
+@section Function Descriptions
+
+These are the details on the functions that make up the @code{mmalloc}
+package. 
+
+@table @code
+@item void *mmalloc_attach (int @var{fd}, void *@var{baseaddr});
+Initialize access to a @code{mmalloc} managed region.
+
+If @var{fd} is a valid file descriptor for an open file, then data for the
+@code{mmalloc} managed region is mapped to that file.   Otherwise
+@file{/dev/zero} is used and the data will not exist in any filesystem object.
+
+If the open file corresponding to @var{fd} is from a previous use of
+@code{mmalloc} and passes some basic sanity checks to ensure that it is
+compatible with the current @code{mmalloc} package, then its data is
+mapped in and is immediately accessible at the same addresses in
+the current process as the process that created the file.
+
+If @var{baseaddr} is not @code{NULL}, the mapping is established
+starting at the specified address in the process address space.  If
+@var{baseaddr} is @code{NULL}, the @code{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 @code{mmalloc}, or for new files will be a value
+chosen by @code{mmap}.
+
+Specifying @var{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 @code{mmalloc} package functions.  It is explicitly
+@samp{void *} (@samp{char *} for systems that don't fully support
+@code{void}) so that users of the package don't have to worry about the
+actual implementation details.
+
+On failure returns @code{NULL}.
+
+@item void *mmalloc_detach (void *@var{md});
+Terminate access to a @code{mmalloc} managed region identified by the
+descriptor @var{md}, by closing the base file and unmapping all memory
+pages associated with the region. 
+
+Returns @code{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).
+
+@item void *mmalloc (void *@var{md}, size_t @var{size});
+Given an @code{mmalloc} descriptor @var{md}, allocate additional memory of
+@var{size} bytes in the associated mapped region.
+
+@item *mrealloc (void *@var{md}, void *@var{ptr}, size_t @var{size});
+Given an @code{mmalloc} descriptor @var{md} and a pointer to memory
+previously allocated by @code{mmalloc} in @var{ptr}, reallocate the
+memory to be @var{size} bytes long, possibly moving the existing
+contents of memory if necessary.
+       
+@item void *mvalloc (void *@var{md}, size_t @var{size});
+Like @code{mmalloc} but the resulting memory is aligned on a page boundary.
+
+@item void mfree (void *@var{md}, void *@var{ptr});
+Given an @code{mmalloc} descriptor @var{md} and a pointer to memory previously
+allocated by @code{mmalloc} in @var{ptr}, free the previously allocated memory.
+
+@item int mmalloc_errno (void *@var{md});
+Given a @code{mmalloc} descriptor, if the last @code{mmalloc} operation
+failed for some reason due to a system call failure, then
+returns the associated @code{errno}.  Returns 0 otherwise.
+(This function is not yet implemented).
+@end table
+
+@bye
diff --git a/src/xbt/mmalloc/mmap-sup.c b/src/xbt/mmalloc/mmap-sup.c
new file mode 100644 (file)
index 0000000..ccaf7bb
--- /dev/null
@@ -0,0 +1,222 @@
+/* Support for an sbrk-like function that uses mmap.
+   Copyright 1992, 2000 Free Software Foundation, Inc.
+
+   Contributed by Fred Fish at Cygnus Support.   fnf@cygnus.com
+
+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., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#if defined(HAVE_MMAP)
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>    /* Prototypes for lseek */
+#endif
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+#include "mmprivate.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;
+#if NEED_DECLARATION_GETPAGESIZE
+extern int getpagesize PARAMS ((void));
+#endif
+
+#define PAGE_ALIGN(addr) (PTR) (((long)(addr) + pagesize - 1) & \
+                                   ~(pagesize - 1))
+
+/* Return MAP_PRIVATE if MDP represents /dev/zero.  Otherwise, return
+   MAP_SHARED.  */
+
+#define MAP_PRIVATE_OR_SHARED(MDP) ((MDP -> flags & MMALLOC_DEVZERO) \
+                                    ? MAP_PRIVATE \
+                                    : MAP_SHARED)
+
+/* Return MAP_ANONYMOUS if MDP uses anonymous mapping. Otherwise, return 0 */
+
+#define MAP_IS_ANONYMOUS(MDP) (((MDP) -> flags & MMALLOC_ANONYMOUS) \
+                              ? MAP_ANONYMOUS \
+                              : 0)
+
+/* Return -1 if MDP uses anonymous mapping. Otherwise, return MDP->FD */
+#define MAP_ANON_OR_FD(MDP) (((MDP) -> flags & MMALLOC_ANONYMOUS) \
+                              ? -1 \
+                                             : (MDP) -> fd)
+
+/*  Get core for the memory region specified by MDP, using SIZE as the
+    amount to either add to or subtract from the existing region.  Works
+    like sbrk(), but using mmap(). */
+
+PTR
+__mmalloc_mmap_morecore (mdp, size)
+  struct mdesc *mdp;
+  int size;
+{
+  PTR result = NULL;
+  off_t foffset;       /* File offset at which new mapping will start */
+  size_t mapbytes;     /* Number of bytes to map */
+  PTR moveto;  /* Address where we wish to move "break value" to */
+  PTR mapto;   /* Address we actually mapped to */
+  char buf = 0;                /* Single byte to write to extend mapped file */
+
+  if (pagesize == 0)
+    pagesize = getpagesize();
+
+  if (size == 0)
+  {
+    /* Just return the current "break" value. */
+    result = mdp -> breakval;
+  }
+  else if (size < 0)
+  {
+    /* We are deallocating memory.  If the amount requested would cause
+            us to try to deallocate back past the base of the mmap'd region
+            then do nothing, and return NULL.  Otherwise, deallocate the
+            memory and return the old break value. */
+    if (mdp -> breakval + size >= mdp -> base)
+         {
+           result = (PTR) mdp -> breakval;
+           mdp -> breakval += size;
+           moveto = PAGE_ALIGN (mdp -> breakval);
+           munmap (moveto, (size_t) (mdp -> top - moveto) - 1);
+           mdp -> top = moveto;
+         }
+  }
+  else
+  {
+    /* We are allocating memory. Make sure we have an open file
+            descriptor if not working with anonymous memory. */
+    if ( !(mdp->flags & MMALLOC_ANONYMOUS) && mdp -> fd < 0)
+         {
+           result = NULL;
+         }
+    else if (mdp -> breakval + size > mdp -> top)
+         {
+         /* The request would move us past the end of the currently
+            mapped memory, so map in enough more memory to satisfy
+            the request.  This means we also have to grow the mapped-to
+            file by an appropriate amount, since mmap cannot be used
+            to extend a file. */
+           moveto = PAGE_ALIGN (mdp -> breakval + size);
+           mapbytes = moveto - mdp -> top;
+           foffset = mdp -> top - mdp -> base;
+
+      if( mdp -> fd > 0){
+         /* FIXME:  Test results of lseek() and write() */
+        lseek (mdp -> fd, foffset + mapbytes - 1, SEEK_SET);
+             write (mdp -> fd, &buf, 1);
+      }
+           
+           /* Let's call mmap. Note that it is possible that mdp->top
+              is 0. In this case mmap will choose the address for us */
+      mapto = mmap (mdp->top, mapbytes, PROT_READ | PROT_WRITE,
+        MAP_PRIVATE_OR_SHARED(mdp) | MAP_IS_ANONYMOUS(mdp) | MAP_FIXED,
+        MAP_ANON_OR_FD(mdp), foffset);
+
+      if (mapto != (PTR) -1){
+           
+        if(mdp -> top == 0)
+          mdp -> base = mdp -> breakval = mapto;
+        
+        mdp -> top = PAGE_ALIGN (mdp -> breakval + size);
+        result = (PTR) mdp -> breakval;
+        mdp -> breakval += size;
+      }
+         }
+    else
+         {
+           result = (PTR) mdp -> breakval;
+           mdp -> breakval += size;
+         }
+  }
+  return (result);
+}
+
+PTR
+__mmalloc_remap_core (mdp)
+  struct mdesc *mdp;
+{
+  PTR base;
+
+  /* FIXME:  Quick hack, needs error checking and other attention. */
+
+  base = mmap (mdp -> base, mdp -> top - mdp -> base,
+              PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE_OR_SHARED (mdp) | MAP_FIXED,
+              mdp -> fd, 0);
+  return ((PTR) base);
+}
+
+PTR
+mmalloc_findbase (size)
+  int size;
+{
+  int fd;
+  int flags;
+  PTR base = NULL;
+
+#ifdef MAP_ANONYMOUS
+  flags = MAP_PRIVATE | MAP_ANONYMOUS;
+  fd = -1;
+#else
+#ifdef MAP_FILE
+  flags = MAP_PRIVATE | MAP_FILE;
+#else
+  flags = MAP_PRIVATE;
+#endif
+  fd = open ("/dev/zero", O_RDWR);
+  if (fd != -1)
+    {
+      return ((PTR) NULL);
+    }
+#endif
+  base = mmap (0, size, PROT_READ | PROT_WRITE, flags, fd, 0);
+  if (base != (PTR) -1)
+    {
+      munmap (base, (size_t) size);
+    }
+  if (fd != -1)
+    {
+      close (fd);
+    }
+  if (base == 0)
+    {
+      /* Don't allow mapping at address zero.  We use that value
+        to signal an error return, and besides, it is useful to
+        catch NULL pointers if it is unmapped.  Instead start
+        at the next page boundary. */
+      base = (PTR) getpagesize ();
+    }
+  else if (base == (PTR) -1)
+    {
+      base = NULL;
+    }
+  return ((PTR) base);
+}
+
+#else  /* defined(HAVE_MMAP) */
+/* Prevent "empty translation unit" warnings from the idiots at X3J11. */
+static char ansi_c_idiots = 69;
+#endif /* defined(HAVE_MMAP) */
diff --git a/src/xbt/mmalloc/mmcheck.c b/src/xbt/mmalloc/mmcheck.c
new file mode 100644 (file)
index 0000000..48936b3
--- /dev/null
@@ -0,0 +1,223 @@
+/* Standard debugging hooks for `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., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, 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 "mmprivate.h"
+
+/* Default function to call when something awful happens.  The application
+   can specify an alternate function to be called instead (and probably will
+   want to). */
+
+extern void abort PARAMS ((void));
+
+/* Arbitrary magical numbers.  */
+
+#define MAGICWORD      (unsigned int) 0xfedabeeb       /* Active chunk */
+#define MAGICWORDFREE  (unsigned int) 0xdeadbeef       /* Inactive chunk */
+#define MAGICBYTE      ((char) 0xd7)
+
+/* Each memory allocation is bounded by a header structure and a trailer
+   byte.  I.E.
+
+       <size><magicword><user's allocation><magicbyte>
+
+   The pointer returned to the user points to the first byte in the
+   user's allocation area.  The magic word can be tested to detect
+   buffer underruns and the magic byte can be tested to detect overruns. */
+
+struct hdr
+  {
+    size_t size;               /* Exact size requested by user.  */
+    unsigned long int magic;   /* Magic number to check header integrity.  */
+  };
+
+static void checkhdr PARAMS ((struct mdesc *, CONST struct hdr *));
+static void mfree_check PARAMS ((PTR, PTR));
+static PTR mmalloc_check PARAMS ((PTR, size_t));
+static PTR mrealloc_check PARAMS ((PTR, PTR, size_t));
+
+/* Check the magicword and magicbyte, and if either is corrupted then
+   call the emergency abort function specified for the heap in use. */
+
+static void
+checkhdr (mdp, hdr)
+  struct mdesc *mdp;
+  CONST struct hdr *hdr;
+{
+  if (hdr -> magic != MAGICWORD ||
+      ((char *) &hdr[1])[hdr -> size] != MAGICBYTE)
+    {
+      (*mdp -> abortfunc)();
+    }
+}
+
+static void
+mfree_check (md, ptr)
+  PTR md;
+  PTR ptr;
+{
+  struct hdr *hdr = ((struct hdr *) ptr) - 1;
+  struct mdesc *mdp;
+
+  mdp = MD_TO_MDP (md);
+  checkhdr (mdp, hdr);
+  hdr -> magic = MAGICWORDFREE;
+  mdp -> mfree_hook = NULL;
+  mfree (md, (PTR)hdr);
+  mdp -> mfree_hook = mfree_check;
+}
+
+static PTR
+mmalloc_check (md, size)
+  PTR md;
+  size_t size;
+{
+  struct hdr *hdr;
+  struct mdesc *mdp;
+  size_t nbytes;
+
+  mdp = MD_TO_MDP (md);
+  mdp -> mmalloc_hook = NULL;
+  nbytes = sizeof (struct hdr) + size + 1;
+  hdr = (struct hdr *) mmalloc (md, nbytes);
+  mdp -> mmalloc_hook = mmalloc_check;
+  if (hdr != NULL)
+    {
+      hdr -> size = size;
+      hdr -> magic = MAGICWORD;
+      hdr++;
+      *((char *) hdr + size) = MAGICBYTE;
+    }
+  return ((PTR) hdr);
+}
+
+static PTR
+mrealloc_check (md, ptr, size)
+  PTR md;
+  PTR ptr;
+  size_t size;
+{
+  struct hdr *hdr = ((struct hdr *) ptr) - 1;
+  struct mdesc *mdp;
+  size_t nbytes;
+
+  mdp = MD_TO_MDP (md);
+  checkhdr (mdp, hdr);
+  mdp -> mfree_hook = NULL;
+  mdp -> mmalloc_hook = NULL;
+  mdp -> mrealloc_hook = NULL;
+  nbytes = sizeof (struct hdr) + size + 1;
+  hdr = (struct hdr *) mrealloc (md, (PTR) hdr, nbytes);
+  mdp -> mfree_hook = mfree_check;
+  mdp -> mmalloc_hook = mmalloc_check;
+  mdp -> mrealloc_hook = mrealloc_check;
+  if (hdr != NULL)
+    {
+      hdr -> size = size;
+      hdr++;
+      *((char *) hdr + size) = MAGICBYTE;
+    }
+  return ((PTR) hdr);
+}
+
+/* Turn on default checking for mmalloc/mrealloc/mfree, for the heap specified
+   by MD.  If FUNC is non-NULL, it is a pointer to the function to call
+   to abort whenever memory corruption is detected.  By default, this is the
+   standard library function abort().
+
+   Note that we disallow installation of initial checking hooks if mmalloc
+   has been called at any time for this particular heap, since if any region
+   that is allocated prior to installation of the hooks is subsequently
+   reallocated or freed after installation of the hooks, it is guaranteed
+   to trigger a memory corruption error.  We do this by checking the state
+   of the MMALLOC_INITIALIZED flag.  If the FORCE argument is non-zero, this
+   checking is disabled and it is allowed to install the checking hooks at any
+   time.  This is useful on systems where the C runtime makes one or more
+   malloc calls before the user code had a chance to call mmcheck or mmcheckf,
+   but never calls free with these values.  Thus if we are certain that only
+   values obtained from mallocs after an mmcheck/mmcheckf will ever be passed
+   to free(), we can go ahead and force installation of the useful checking
+   hooks.
+
+   However, we can call this function at any time after the initial call,
+   to update the function pointers to the checking routines and to the
+   user defined corruption handler routine, as long as these function pointers
+   have been previously extablished by the initial call.  Note that we
+   do this automatically when remapping a previously used heap, to ensure
+   that the hooks get updated to the correct values, although the corruption
+   handler pointer gets set back to the default.  The application can then
+   call mmcheck to use a different corruption handler if desired.
+
+   Returns non-zero if checking is successfully enabled, zero otherwise. */
+
+int
+mmcheckf (md, func, force)
+  PTR md;
+  void (*func) PARAMS ((void));
+  int force;
+{
+  struct mdesc *mdp;
+  int rtnval;
+
+  mdp = MD_TO_MDP (md);
+
+  /* We can safely set or update the abort function at any time, regardless
+     of whether or not we successfully do anything else. */
+
+  mdp -> abortfunc = (func != NULL ? func : abort);
+
+  /* If we haven't yet called mmalloc the first time for this heap, or if we
+     have hooks that were previously installed, then allow the hooks to be
+     initialized or updated. */
+
+  if (force ||
+      !(mdp -> flags & MMALLOC_INITIALIZED) ||
+      (mdp -> mfree_hook != NULL))
+    {
+      mdp -> mfree_hook = mfree_check;
+      mdp -> mmalloc_hook = mmalloc_check;
+      mdp -> mrealloc_hook = mrealloc_check;
+      mdp -> flags |= MMALLOC_MMCHECK_USED;
+      rtnval = 1;
+    }
+  else
+    {
+      rtnval = 0;
+    }
+
+  return (rtnval);
+}
+
+/* This routine is for backwards compatibility only, in case there are
+   still callers to the original mmcheck function. */
+
+int
+mmcheck (md, func)
+  PTR md;
+  void (*func) PARAMS ((void));
+{
+  int rtnval;
+
+  rtnval = mmcheckf (md, func, 0);
+  return (rtnval);
+}
diff --git a/src/xbt/mmalloc/mmemalign.c b/src/xbt/mmalloc/mmemalign.c
new file mode 100644 (file)
index 0000000..595cb6c
--- /dev/null
@@ -0,0 +1,62 @@
+/* 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., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#include "mmprivate.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;
+
+  if ((result = mmalloc (md, size + alignment - 1)) != 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 -> next = mdp -> aligned_blocks;
+             mdp -> aligned_blocks = l;
+           }
+         l -> exact = result;
+         result = l -> aligned = (PTR) result + alignment - adj;
+       }
+    }
+  return (result);
+}
diff --git a/src/xbt/mmalloc/mmprivate.h b/src/xbt/mmalloc/mmprivate.h
new file mode 100644 (file)
index 0000000..eccffec
--- /dev/null
@@ -0,0 +1,344 @@
+/* Declarations for `mmalloc' and friends.
+   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., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, 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. */
+
+
+#ifndef __MMPRIVATE_H
+#define __MMPRIVATE_H 1
+
+#include "mmalloc.h"
+
+#ifdef HAVE_LIMITS_H
+#  include <limits.h>
+#else
+#  ifndef CHAR_BIT
+#    define CHAR_BIT 8
+#  endif
+#endif
+
+#ifndef MIN
+#  define MIN(A, B) ((A) < (B) ? (A) : (B))
+#endif
+
+#define MMALLOC_MAGIC          "mmalloc"       /* Mapped file magic number */
+#define MMALLOC_MAGIC_SIZE     8               /* Size of magic number buf */
+#define MMALLOC_VERSION                1               /* Current mmalloc version */
+#define MMALLOC_KEYS           16              /* Keys for application use */
+
+/* The allocator divides the heap into blocks of fixed size; large
+   requests receive one or more whole blocks, and small requests
+   receive a fragment of a block.  Fragment sizes are powers of two,
+   and all fragments of a block are the same size.  When all the
+   fragments in a block have been freed, the block itself is freed.  */
+
+#define INT_BIT                (CHAR_BIT * sizeof(int))
+#define BLOCKLOG       (INT_BIT > 16 ? 12 : 9)
+#define BLOCKSIZE      ((unsigned int) 1 << BLOCKLOG)
+#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
+
+/* The difference between two pointers is a signed int.  On machines where
+   the data addresses have the high bit set, we need to ensure that the
+   difference becomes an unsigned int when we are using the address as an
+   integral value.  In addition, when using with the '%' operator, the
+   sign of the result is machine dependent for negative values, so force
+   it to be treated as an unsigned int. */
+
+#define ADDR2UINT(addr)        ((unsigned int) ((PTR) (addr) - (PTR) NULL))
+#define RESIDUAL(addr,bsize) ((unsigned int) (ADDR2UINT (addr) % (bsize)))
+
+/* Determine the amount of memory spanned by the initial heap table
+   (not an absolute limit).  */
+
+#define HEAP           (INT_BIT > 16 ? 4194304 : 65536)
+
+/* Number of contiguous free blocks allowed to build up at the end of
+   memory before they will be returned to the system.  */
+
+#define FINAL_FREE_BLOCKS      8
+
+/* Where to start searching the free list when looking for new memory.
+   The two possible values are 0 and heapindex.  Starting at 0 seems
+   to reduce total memory usage, while starting at heapindex seems to
+   run faster.  */
+
+#define MALLOC_SEARCH_START    mdp -> heapindex
+
+/* Address to block number and vice versa.  */
+
+#define BLOCK(A) (((PTR) (A) - mdp -> heapbase) / BLOCKSIZE + 1)
+
+#define ADDRESS(B) ((PTR) (((B) - 1) * BLOCKSIZE + mdp -> heapbase))
+
+/* Data structure giving per-block information.  */
+
+typedef union
+  {
+    /* Heap information for a busy block.  */
+    struct
+      {
+       /* Zero for a large block, or positive giving the
+          logarithm to the base two of the fragment size.  */
+       int type;
+       union
+         {
+           struct
+             {
+               size_t nfree;   /* Free fragments in a fragmented block.  */
+               size_t first;   /* First free fragment of the block.  */
+             } frag;
+           /* Size (in blocks) of a large cluster.  */
+           size_t size;
+         } info;
+      } busy;
+    /* Heap information for a free block (that may be the first of
+       a free cluster).  */
+    struct
+      {
+       size_t size;            /* Size (in blocks) of a free cluster.  */
+       size_t next;            /* Index of next free cluster.  */
+       size_t prev;            /* Index of previous free cluster.  */
+      } free;
+  } malloc_info;
+
+/* List of blocks allocated with `mmemalign' (or `mvalloc').  */
+
+struct alignlist
+  {
+    struct alignlist *next;
+    PTR aligned;               /* The address that mmemaligned returned.  */
+    PTR exact;                 /* The address that malloc returned.  */
+  };
+
+/* Doubly linked lists of free fragments.  */
+
+struct list
+  {
+    struct list *next;
+    struct list *prev;
+  };
+
+/* Statistics available to the user.
+   FIXME:  By design, the internals of the malloc package are no longer
+   exported to the user via an include file, so access to this data needs
+   to be via some other mechanism, such as mmstat_<something> where the
+   return value is the <something> the user is interested in. */
+
+struct mstats
+  {
+    size_t bytes_total;                /* Total size of the heap. */
+    size_t chunks_used;                /* Chunks allocated by the user. */
+    size_t bytes_used;         /* Byte total of user-allocated chunks. */
+    size_t chunks_free;                /* Chunks in the free list. */
+    size_t bytes_free;         /* Byte total of chunks in the free list. */
+  };
+
+/* Internal structure that defines the format of the malloc-descriptor.
+   This gets written to the base address of the region that mmalloc is
+   managing, and thus also becomes the file header for the mapped file,
+   if such a file exists. */
+
+struct mdesc
+{
+  /* The "magic number" for an mmalloc file. */
+
+  char magic[MMALLOC_MAGIC_SIZE];
+
+  /* The size in bytes of this structure, used as a sanity check when reusing
+     a previously created mapped file. */
+
+  unsigned int headersize;
+
+  /* The version number of the mmalloc package that created this file. */
+
+  unsigned char version;
+
+  /* Some flag bits to keep track of various internal things. */
+
+  unsigned int flags;
+
+  /* If a system call made by the mmalloc package fails, the errno is
+     preserved for future examination. */
+
+  int saved_errno;
+
+  /* Pointer to the function that is used to get more core, or return core
+     to the system, for requests using this malloc descriptor.  For memory
+     mapped regions, this is the mmap() based routine.  There may also be
+     a single malloc descriptor that points to an sbrk() based routine
+     for systems without mmap() or for applications that call the mmalloc()
+     package with a NULL malloc descriptor.
+
+     FIXME:  For mapped regions shared by more than one process, this
+     needs to be maintained on a per-process basis. */
+
+  PTR (*morecore) PARAMS ((struct mdesc *, int));
+     
+  /* Pointer to the function that causes an abort when the memory checking
+     features are activated.  By default this is set to abort(), but can
+     be set to another function by the application using mmalloc().
+
+     FIXME:  For mapped regions shared by more than one process, this
+     needs to be maintained on a per-process basis. */
+
+  void (*abortfunc) PARAMS ((void));
+
+  /* Debugging hook for free.
+
+     FIXME:  For mapped regions shared by more than one process, this
+     needs to be maintained on a per-process basis. */
+
+  void (*mfree_hook) PARAMS ((PTR, PTR));
+
+  /* Debugging hook for `malloc'.
+
+     FIXME:  For mapped regions shared by more than one process, this
+     needs to be maintained on a per-process basis. */
+
+  PTR (*mmalloc_hook) PARAMS ((PTR, size_t));
+
+  /* Debugging hook for realloc.
+
+     FIXME:  For mapped regions shared by more than one process, this
+     needs to be maintained on a per-process basis. */
+
+  PTR (*mrealloc_hook) PARAMS ((PTR, PTR, size_t));
+
+  /* Number of info entries.  */
+
+  size_t heapsize;
+
+  /* Pointer to first block of the heap (base of the first block).  */
+
+  PTR heapbase;
+
+  /* Current search index for the heap table.  */
+  /* Search index in the info table.  */
+
+  size_t heapindex;
+
+  /* Limit of valid info table indices.  */
+
+  size_t heaplimit;
+
+  /* Block information table.
+     Allocated with malign/__mmalloc_free (not mmalloc/mfree).  */
+  /* Table indexed by block number giving per-block information.  */
+
+  malloc_info *heapinfo;
+
+  /* Instrumentation.  */
+
+  struct mstats heapstats;
+
+  /* Free list headers for each fragment size.  */
+  /* Free lists for each fragment size.  */
+
+  struct list fraghead[BLOCKLOG];
+
+  /* List of blocks allocated by memalign.  */
+
+  struct alignlist *aligned_blocks;
+
+  /* The base address of the memory region for this malloc heap.  This
+     is the location where the bookkeeping data for mmap and for malloc
+     begins. */
+
+  PTR base;
+
+  /* The current location in the memory region for this malloc heap which
+     represents the end of memory in use. */
+
+  PTR breakval;
+
+  /* The end of the current memory region for this malloc heap.  This is
+     the first location past the end of mapped memory. */
+
+  PTR top;
+
+  /* Open file descriptor for the file to which this malloc heap is mapped.
+     This will always be a valid file descriptor, since /dev/zero is used
+     by default if no open file is supplied by the client.  Also note that
+     it may change each time the region is mapped and unmapped. */
+
+  int fd;
+
+  /* An array of keys to data within the mapped region, for use by the
+     application.  */
+
+  PTR keys[MMALLOC_KEYS];
+
+};
+
+/* Bits to look at in the malloc descriptor flags word */
+
+#define MMALLOC_DEVZERO                (1 << 0)        /* Have mapped to /dev/zero */
+#define MMALLOC_ANONYMOUS (1 << 1)  /* Use anonymous mapping */
+#define MMALLOC_INITIALIZED    (1 << 2)        /* Initialized mmalloc */
+#define MMALLOC_MMCHECK_USED   (1 << 3)        /* mmcheckf() called already */
+
+/* Internal version of `mfree' used in `morecore'. */
+
+extern void __mmalloc_free PARAMS ((struct mdesc *, PTR));
+
+/* Hooks for debugging versions.  */
+
+extern void (*__mfree_hook) PARAMS ((PTR, PTR));
+extern PTR (*__mmalloc_hook) PARAMS ((PTR, size_t));
+extern PTR (*__mrealloc_hook) PARAMS ((PTR, PTR, size_t));
+
+/* A default malloc descriptor for the single sbrk() managed region. */
+
+extern struct mdesc *__mmalloc_default_mdp;
+
+/* Initialize the first use of the default malloc descriptor, which uses
+   an sbrk() region. */
+
+extern struct mdesc *__mmalloc_sbrk_init PARAMS ((void));
+
+/* Grow or shrink a contiguous mapped region using mmap().
+   Works much like sbrk() */
+
+#if defined(HAVE_MMAP)
+
+extern PTR __mmalloc_mmap_morecore PARAMS ((struct mdesc *, int));
+
+#endif
+
+/* Remap a mmalloc region that was previously mapped. */
+
+extern PTR __mmalloc_remap_core PARAMS ((struct mdesc *));
+
+/* Macro to convert from a user supplied malloc descriptor to pointer to the
+   internal malloc descriptor.  If the user supplied descriptor is NULL, then
+   use the default internal version, initializing it if necessary.  Otherwise
+   just cast the user supplied version (which is void *) to the proper type
+   (struct mdesc *). */
+
+#define MD_TO_MDP(md) \
+  ((md) == NULL \
+   ? (__mmalloc_default_mdp == NULL \
+      ? __mmalloc_sbrk_init () \
+      : __mmalloc_default_mdp) \
+   : (struct mdesc *) (md))
+
+#endif  /* __MMPRIVATE_H */
diff --git a/src/xbt/mmalloc/mmstats.c b/src/xbt/mmalloc/mmstats.c
new file mode 100644 (file)
index 0000000..ee8ee43
--- /dev/null
@@ -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., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, 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 "mmprivate.h"
+
+/* FIXME:  See the comment in mmprivate.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 =
+      (PTR) mdp -> top - (void *)mdp;
+  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);
+}
diff --git a/src/xbt/mmalloc/mmtrace.awk b/src/xbt/mmalloc/mmtrace.awk
new file mode 100644 (file)
index 0000000..d7689ce
--- /dev/null
@@ -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];
+               }
diff --git a/src/xbt/mmalloc/mmtrace.c b/src/xbt/mmalloc/mmtrace.c
new file mode 100644 (file)
index 0000000..856004c
--- /dev/null
@@ -0,0 +1,171 @@
+/* More debugging hooks for `mmalloc'.
+   Copyright 1991, 1992, 1994 Free Software Foundation
+
+   Written April 2, 1991 by John Gilmore of Cygnus Support
+   Based on mcheck.c by Mike Haertel.
+   Modified Mar 1992 by Fred Fish.  (fnf@cygnus.com)
+
+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., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#include <stdio.h>
+#include "mmprivate.h"
+
+static void tr_break PARAMS ((void));
+static void tr_freehook PARAMS ((PTR, PTR));
+static PTR tr_mallochook PARAMS ((PTR, size_t));
+static PTR tr_reallochook PARAMS ((PTR, PTR, size_t));
+
+#ifndef        __GNU_LIBRARY__
+extern char *getenv ();
+#endif
+
+static FILE *mallstream;
+
+#if 0  /* FIXME:  Disabled for now. */
+static char mallenv[] = "MALLOC_TRACE";
+static char mallbuf[BUFSIZ];   /* Buffer for the output.  */
+#endif
+
+/* Address to breakpoint on accesses to... */
+static PTR mallwatch;
+
+/* Old hook values.  */
+
+static void (*old_mfree_hook) PARAMS ((PTR, PTR));
+static PTR (*old_mmalloc_hook) PARAMS ((PTR, size_t));
+static PTR (*old_mrealloc_hook) PARAMS ((PTR, PTR, size_t));
+
+/* This function is called when the block being alloc'd, realloc'd, or
+   freed has an address matching the variable "mallwatch".  In a debugger,
+   set "mallwatch" to the address of interest, then put a breakpoint on
+   tr_break.  */
+
+static void
+tr_break ()
+{
+}
+
+static void
+tr_freehook (md, ptr)
+  PTR md;
+  PTR ptr;
+{
+  struct mdesc *mdp;
+
+  mdp = MD_TO_MDP (md);
+  /* Be sure to print it first.  */
+  fprintf (mallstream, "- %08lx\n", (unsigned long) ptr);
+  if (ptr == mallwatch)
+    tr_break ();
+  mdp -> mfree_hook = old_mfree_hook;
+  mfree (md, ptr);
+  mdp -> mfree_hook = tr_freehook;
+}
+
+static PTR
+tr_mallochook (md, size)
+  PTR md;
+  size_t size;
+{
+  PTR hdr;
+  struct mdesc *mdp;
+
+  mdp = MD_TO_MDP (md);
+  mdp -> mmalloc_hook = old_mmalloc_hook;
+  hdr = (PTR) mmalloc (md, size);
+  mdp -> mmalloc_hook = tr_mallochook;
+
+  /* We could be printing a NULL here; that's OK.  */
+  fprintf (mallstream, "+ %p 0x%lx\n", hdr, (unsigned long)size);
+
+  if (hdr == mallwatch)
+    tr_break ();
+
+  return (hdr);
+}
+
+static PTR
+tr_reallochook (md, ptr, size)
+  PTR md;
+  PTR ptr;
+  size_t size;
+{
+  PTR hdr;
+  struct mdesc *mdp;
+
+  mdp = MD_TO_MDP (md);
+
+  if (ptr == mallwatch)
+    tr_break ();
+
+  mdp -> mfree_hook = old_mfree_hook;
+  mdp -> mmalloc_hook = old_mmalloc_hook;
+  mdp -> mrealloc_hook = old_mrealloc_hook;
+  hdr = (PTR) mrealloc (md, ptr, size);
+  mdp -> mfree_hook = tr_freehook;
+  mdp -> mmalloc_hook = tr_mallochook;
+  mdp -> mrealloc_hook = tr_reallochook;
+  if (hdr == NULL)
+    /* Failed realloc.  */
+    fprintf (mallstream, "! %p 0x%lx\n", ptr, (unsigned long) size);
+  else
+    fprintf (mallstream, "< %p\n> %p 0x%lx\n", ptr,
+            hdr, (unsigned long) size);
+
+  if (hdr == mallwatch)
+    tr_break ();
+
+  return hdr;
+}
+
+/* We enable tracing if either the environment variable MALLOC_TRACE
+   is set, or if the variable mallwatch has been patched to an address
+   that the debugging user wants us to stop on.  When patching mallwatch,
+   don't forget to set a breakpoint on tr_break!  */
+
+int
+mmtrace ()
+{
+#if 0  /* FIXME!  This is disabled for now until we figure out how to
+          maintain a stack of hooks per heap, since we might have other
+          hooks (such as set by mmcheck/mmcheckf) active also. */
+  char *mallfile;
+
+  mallfile = getenv (mallenv);
+  if (mallfile  != NULL || mallwatch != NULL)
+    {
+      mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "w");
+      if (mallstream != NULL)
+       {
+         /* Be sure it doesn't mmalloc its buffer!  */
+         setbuf (mallstream, mallbuf);
+         fprintf (mallstream, "= Start\n");
+         old_mfree_hook = mdp -> mfree_hook;
+         mdp -> mfree_hook = tr_freehook;
+         old_mmalloc_hook = mdp -> mmalloc_hook;
+         mdp -> mmalloc_hook = tr_mallochook;
+         old_mrealloc_hook = mdp -> mrealloc_hook;
+         mdp -> mrealloc_hook = tr_reallochook;
+       }
+    }
+
+#endif /* 0 */
+
+  return (1);
+}
+
diff --git a/src/xbt/mmalloc/mrealloc.c b/src/xbt/mmalloc/mrealloc.c
new file mode 100644 (file)
index 0000000..e2004aa
--- /dev/null
@@ -0,0 +1,163 @@
+/* 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., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, 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 <string.h>    /* Prototypes for memcpy, memmove, memset, etc */
+
+#include "mmprivate.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)
+           {
+             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). */
+
+PTR
+realloc (ptr, size)
+  PTR ptr;
+  size_t size;
+{
+  PTR result;
+
+  result = mrealloc ((PTR) NULL, ptr, size);
+  return (result);
+}
diff --git a/src/xbt/mmalloc/mvalloc.c b/src/xbt/mmalloc/mvalloc.c
new file mode 100644 (file)
index 0000000..e44942f
--- /dev/null
@@ -0,0 +1,50 @@
+/* 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., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#include "mmprivate.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 cache_pagesize;
+#if NEED_DECLARATION_GETPAGESIZE
+extern int getpagesize PARAMS ((void));
+#endif
+
+PTR
+mvalloc (md, size)
+  PTR md;
+  size_t size;
+{
+  if (cache_pagesize == 0)
+    {
+      cache_pagesize = getpagesize ();
+    }
+
+  return (mmemalign (md, cache_pagesize, size));
+}
+
+
+PTR
+valloc (size)
+  size_t size;
+{
+  return mvalloc ((PTR) NULL, size);
+}
diff --git a/src/xbt/mmalloc/sbrk-sup.c b/src/xbt/mmalloc/sbrk-sup.c
new file mode 100644 (file)
index 0000000..10869bd
--- /dev/null
@@ -0,0 +1,101 @@
+/* Support for sbrk() regions.
+   Copyright 1992, 2000 Free Software Foundation, Inc.
+   Contributed by Fred Fish at Cygnus Support.   fnf@cygnus.com
+
+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., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#include <unistd.h>    /* Prototypes for sbrk (maybe) */
+
+#include <string.h>    /* Prototypes for memcpy, memmove, memset, etc */
+
+#include "mmprivate.h"
+
+static PTR sbrk_morecore PARAMS ((struct mdesc *, int));
+#if NEED_DECLARATION_SBRK
+extern PTR sbrk PARAMS ((int));
+#endif
+
+/* The mmalloc() package can use a single implicit malloc descriptor
+   for mmalloc/mrealloc/mfree operations which do not supply an explicit
+   descriptor.  For these operations, sbrk() is used to obtain more core
+   from the system, or return core.  This allows mmalloc() to provide
+   backwards compatibility with the non-mmap'd version. */
+
+struct mdesc *__mmalloc_default_mdp;
+
+/* Use sbrk() to get more core. */
+
+static PTR
+sbrk_morecore (mdp, size)
+  struct mdesc *mdp;
+  int size;
+{
+  PTR result;
+
+  if ((result = sbrk (size)) == (PTR) -1)
+    {
+      result = NULL;
+    }
+  else
+    {
+      mdp -> breakval += size;
+      mdp -> top += size;
+    }
+  return (result);
+}
+
+/* Initialize the default malloc descriptor if this is the first time
+   a request has been made to use the default sbrk'd region.
+
+   Since no alignment guarantees are made about the initial value returned
+   by sbrk, test the initial value and (if necessary) sbrk enough additional
+   memory to start off with alignment to BLOCKSIZE.  We actually only need
+   it aligned to an alignment suitable for any object, so this is overkill.
+   But at most it wastes just part of one BLOCKSIZE chunk of memory and
+   minimizes portability problems by avoiding us having to figure out
+   what the actual minimal alignment is.  The rest of the malloc code
+   avoids this as well, by always aligning to the minimum of the requested
+   size rounded up to a power of two, or to BLOCKSIZE.
+
+   Note that we are going to use some memory starting at this initial sbrk
+   address for the sbrk region malloc descriptor, which is a struct, so the
+   base address must be suitably aligned. */
+
+struct mdesc *
+__mmalloc_sbrk_init ()
+{
+  PTR base;
+  unsigned int adj;
+
+  base = sbrk (0);
+  adj = RESIDUAL (base, BLOCKSIZE);
+  if (adj != 0)
+    {
+      sbrk (BLOCKSIZE - adj);
+      base = sbrk (0);
+    }
+  __mmalloc_default_mdp = (struct mdesc *) sbrk (sizeof (struct mdesc));
+  memset ((char *) __mmalloc_default_mdp, 0, sizeof (struct mdesc));
+  __mmalloc_default_mdp -> morecore = sbrk_morecore;
+  __mmalloc_default_mdp -> base = base;
+  __mmalloc_default_mdp -> breakval = __mmalloc_default_mdp -> top = sbrk (0);
+  __mmalloc_default_mdp -> fd = -1;
+  return (__mmalloc_default_mdp);
+}
+
+
diff --git a/src/xbt/mmalloc/test/mmalloc_test.c b/src/xbt/mmalloc/test/mmalloc_test.c
new file mode 100644 (file)
index 0000000..656b66d
--- /dev/null
@@ -0,0 +1,52 @@
+#include "../mmalloc.h"
+#include <stdio.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+#define BUFFSIZE 204800
+#define TESTSIZE 100
+
+int main() {
+  void *A,*B;
+  int fd1,fd2;
+  void *heapA,*heapB;  
+  void * pointers[TESTSIZE];
+/*
+  unlink("heap1");
+  fd1=open("heap1",O_CREAT|O_RDWR,S_IRWXU|S_IRWXG|S_IRWXO);
+  assert(fd1>0);
+    close(fd1);
+    fd1=open("heap1",O_RDWR);
+    assert(fd1>0);
+  */
+
+  heapA = mmalloc_attach(-1,sbrk(0) + BUFFSIZE);
+  if (heapA==NULL) {
+    perror("attach 1 failed");
+    fprintf(stderr,"bye\n");
+    exit(1);
+  }
+
+  fprintf(stderr,"HeapA=%p\n",heapA);
+  
+  int i, size;
+  for(i = 0; i < TESTSIZE; i++){
+    size = rand () % 1000;
+    pointers[i] = mmalloc(heapA,size);
+    fprintf(stderr,"%d bytes allocated at %p\n",size, pointers[i]);
+  }
+  char c;
+  scanf("%c",&c);
+
+  for(i = 0; i < TESTSIZE; i++){
+    mfree(heapA,pointers[i]);
+  }  
+  
+  fprintf(stderr,"Ok bye bye\n");
+  return 0;
+}