mrealloc.c

Go to the documentation of this file.
00001 /* @(#)root/clib:$Id: mrealloc.c 20882 2007-11-19 11:31:26Z rdm $ */
00002 /* Author: */
00003 
00004 /* Change the size of a block allocated by `mmalloc'.
00005    Copyright 1990, 1991 Free Software Foundation
00006                   Written May 1989 by Mike Haertel.
00007 
00008 The GNU C Library is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU Library General Public License as
00010 published by the Free Software Foundation; either version 2 of the
00011 License, or (at your option) any later version.
00012 
00013 The GNU C Library is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 Library General Public License for more details.
00017 
00018 You should have received a copy of the GNU Library General Public
00019 License along with the GNU C Library; see the file COPYING.LIB.  If
00020 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00021 Boston, MA 02111-1307, USA.
00022 
00023    The author may be reached (Email) at the address mike@ai.mit.edu,
00024    or (US mail) as Mike Haertel c/o Free Software Foundation. */
00025 
00026 #include <string.h>     /* Prototypes for memcpy, memmove, memset, etc */
00027 
00028 #include "mmprivate.h"
00029 
00030 /* Resize the given region to the new size, returning a pointer
00031    to the (possibly moved) region.  This is optimized for speed;
00032    some benchmarks seem to indicate that greater compactness is
00033    achieved by unconditionally allocating and copying to a
00034    new region.  This module has incestuous knowledge of the
00035    internals of both mfree and mmalloc. */
00036 
00037 PTR
00038 mrealloc (md, ptr, size)
00039   PTR md;
00040   PTR ptr;
00041   size_t size;
00042 {
00043   struct mdesc *mdp;
00044   PTR result;
00045   int type;
00046   size_t block, blocks, oldlimit;
00047 
00048   if (size == 0)
00049     {
00050       mfree (md, ptr);
00051       return (mmalloc (md, 0));
00052     }
00053   else if (ptr == NULL)
00054     {
00055       return (mmalloc (md, size));
00056     }
00057 
00058   mdp = MD_TO_MDP (md);
00059 
00060   if (mdp -> mrealloc_hook != NULL)
00061     {
00062       return ((*mdp -> mrealloc_hook) (md, ptr, size));
00063     }
00064 
00065   block = BLOCK (ptr);
00066 
00067   type = mdp -> heapinfo[block].busy.type;
00068   switch (type)
00069     {
00070     case 0:
00071       /* Maybe reallocate a large block to a small fragment.  */
00072       if (size <= BLOCKSIZE / 2)
00073         {
00074           result = mmalloc (md, size);
00075           if (result != NULL)
00076             {
00077               memcpy (result, ptr, size);
00078               mfree (md, ptr);
00079               return (result);
00080             }
00081         }
00082 
00083       /* The new size is a large allocation as well;
00084          see if we can hold it in place. */
00085       blocks = BLOCKIFY (size);
00086       if (blocks < mdp -> heapinfo[block].busy.info.size)
00087         {
00088           /* The new size is smaller; return excess memory to the free list. */
00089           mdp -> heapinfo[block + blocks].busy.type = 0;
00090           mdp -> heapinfo[block + blocks].busy.info.size
00091             = mdp -> heapinfo[block].busy.info.size - blocks;
00092           mdp -> heapinfo[block].busy.info.size = blocks;
00093           mfree (md, ADDRESS (block + blocks));
00094           result = ptr;
00095         }
00096       else if (blocks == mdp -> heapinfo[block].busy.info.size)
00097         {
00098           /* No size change necessary.  */
00099           result = ptr;
00100         }
00101       else
00102         {
00103           /* Won't fit, so allocate a new region that will.
00104              Free the old region first in case there is sufficient
00105              adjacent free space to grow without moving. */
00106           blocks = mdp -> heapinfo[block].busy.info.size;
00107           /* Prevent free from actually returning memory to the system.  */
00108           oldlimit = mdp -> heaplimit;
00109           mdp -> heaplimit = 0;
00110           mfree (md, ptr);
00111           mdp -> heaplimit = oldlimit;
00112           result = mmalloc (md, size);
00113           if (result == NULL)
00114             {
00115               mmalloc (md, blocks * BLOCKSIZE);
00116               return (NULL);
00117             }
00118           if (ptr != result)
00119             {
00120               memmove (result, ptr, blocks * BLOCKSIZE);
00121             }
00122         }
00123       break;
00124 
00125     default:
00126       /* Old size is a fragment; type is logarithm
00127          to base two of the fragment size.  */
00128       if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type))
00129         {
00130           /* The new size is the same kind of fragment.  */
00131           result = ptr;
00132         }
00133       else
00134         {
00135           /* The new size is different; allocate a new space,
00136              and copy the lesser of the new size and the old. */
00137           result = mmalloc (md, size);
00138           if (result == NULL)
00139             {
00140               return (NULL);
00141             }
00142           memcpy (result, ptr, MIN (size, (size_t) 1 << type));
00143           mfree (md, ptr);
00144         }
00145       break;
00146     }
00147 
00148   return (result);
00149 }
00150 
00151 /* When using this package, provide a version of malloc/realloc/free built
00152    on top of it, so that if we use the default sbrk() region we will not
00153    collide with another malloc package trying to do the same thing, if
00154    the application contains any "hidden" calls to malloc/realloc/free (such
00155    as inside a system library). */
00156 
00157 #ifndef NO_SBRK_MALLOC
00158 
00159 PTR
00160 realloc (ptr, size)
00161   PTR ptr;
00162   size_t size;
00163 {
00164   return (mrealloc ((PTR) NULL, ptr, size));
00165 }
00166 
00167 #endif
00168 

Generated on Tue Jul 5 14:11:25 2011 for ROOT_528-00b_version by  doxygen 1.5.1