mfree.c

Go to the documentation of this file.
00001 /* @(#)root/clib:$Id: mfree.c 27502 2009-02-19 01:09:07Z rdm $ */
00002 /* Author: */
00003 
00004 /* Free a block of memory allocated by `mmalloc'.
00005    Copyright 1990, 1991, 1992 Free Software Foundation
00006 
00007    Written May 1989 by Mike Haertel.
00008    Heavily modified Mar 1992 by Fred Fish.  (fnf@cygnus.com)
00009 
00010 The GNU C Library is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU Library General Public License as
00012 published by the Free Software Foundation; either version 2 of the
00013 License, or (at your option) any later version.
00014 
00015 The GNU C Library is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 Library General Public License for more details.
00019 
00020 You should have received a copy of the GNU Library General Public
00021 License along with the GNU C Library; see the file COPYING.LIB.  If
00022 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00023 Boston, MA 02111-1307, USA.
00024 
00025    The author may be reached (Email) at the address mike@ai.mit.edu,
00026    or (US mail) as Mike Haertel c/o Free Software Foundation. */
00027 
00028 #include "mmprivate.h"
00029 
00030 /* Return memory to the heap.
00031    Like `mfree' but don't call a mfree_hook if there is one.  */
00032 
00033 void
00034 __mmalloc_free (mdp, ptr)
00035   struct mdesc *mdp;
00036   PTR ptr;
00037 {
00038   int type;
00039   size_t block, blocks;
00040   register size_t i;
00041   struct mmlist *prev, *next;
00042 
00043   block = BLOCK (ptr);
00044 
00045   type = mdp -> heapinfo[block].busy.type;
00046   switch (type)
00047     {
00048     case 0:
00049       /* Get as many statistics as early as we can.  */
00050       mdp -> heapstats.chunks_used--;
00051       mdp -> heapstats.bytes_used -=
00052           mdp -> heapinfo[block].busy.info.size * BLOCKSIZE;
00053       mdp -> heapstats.bytes_free +=
00054           mdp -> heapinfo[block].busy.info.size * BLOCKSIZE;
00055 
00056       /* Find the free cluster previous to this one in the free list.
00057          Start searching at the last block referenced; this may benefit
00058          programs with locality of allocation.  */
00059       i = mdp -> heapindex;
00060       if (i > block)
00061         {
00062           while (i > block)
00063             {
00064               i = mdp -> heapinfo[i].free.prev;
00065             }
00066         }
00067       else
00068         {
00069           do
00070             {
00071               i = mdp -> heapinfo[i].free.next;
00072             }
00073           while ((i != 0) && (i < block));
00074           i = mdp -> heapinfo[i].free.prev;
00075         }
00076 
00077       /* Determine how to link this block into the free list.  */
00078       if (block == i + mdp -> heapinfo[i].free.size)
00079         {
00080           /* Coalesce this block with its predecessor.  */
00081           mdp -> heapinfo[i].free.size +=
00082             mdp -> heapinfo[block].busy.info.size;
00083           block = i;
00084         }
00085       else
00086         {
00087           /* Really link this block back into the free list.  */
00088           mdp -> heapinfo[block].free.size =
00089             mdp -> heapinfo[block].busy.info.size;
00090           mdp -> heapinfo[block].free.next = mdp -> heapinfo[i].free.next;
00091           mdp -> heapinfo[block].free.prev = i;
00092           mdp -> heapinfo[i].free.next = block;
00093           mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev = block;
00094           mdp -> heapstats.chunks_free++;
00095         }
00096 
00097       /* Now that the block is linked in, see if we can coalesce it
00098          with its successor (by deleting its successor from the list
00099          and adding in its size).  */
00100       if (block + mdp -> heapinfo[block].free.size ==
00101           mdp -> heapinfo[block].free.next)
00102         {
00103           mdp -> heapinfo[block].free.size
00104             += mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.size;
00105           mdp -> heapinfo[block].free.next
00106             = mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.next;
00107           mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev = block;
00108           mdp -> heapstats.chunks_free--;
00109         }
00110 
00111       /* Now see if we can return stuff to the system.  */
00112       blocks = mdp -> heapinfo[block].free.size;
00113       if (blocks >= FINAL_FREE_BLOCKS && block + blocks == mdp -> heaplimit
00114           && mdp -> morecore (mdp, 0) == ADDRESS (block + blocks))
00115         {
00116           register size_t bytes = blocks * BLOCKSIZE;
00117           mdp -> heaplimit -= blocks;
00118           mdp -> morecore (mdp, -(ptrdiff_t)bytes);
00119           mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next
00120             = mdp -> heapinfo[block].free.next;
00121           mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev
00122             = mdp -> heapinfo[block].free.prev;
00123           block = mdp -> heapinfo[block].free.prev;
00124           mdp -> heapstats.chunks_free--;
00125           mdp -> heapstats.bytes_free -= bytes;
00126         }
00127 
00128       /* Set the next search to begin at this block.  */
00129       mdp -> heapindex = block;
00130       break;
00131 
00132     default:
00133       /* Do some of the statistics.  */
00134       mdp -> heapstats.chunks_used--;
00135       mdp -> heapstats.bytes_used -= 1 << type;
00136       mdp -> heapstats.chunks_free++;
00137       mdp -> heapstats.bytes_free += 1 << type;
00138 
00139       /* Get the address of the first free fragment in this block.  */
00140       prev = (struct mmlist *)
00141         ((char *) ADDRESS(block) +
00142          (mdp -> heapinfo[block].busy.info.frag.first << type));
00143 
00144       if (mdp -> heapinfo[block].busy.info.frag.nfree ==
00145           (BLOCKSIZE >> type) - 1)
00146         {
00147           /* If all fragments of this block are free, remove them
00148              from the fragment list and free the whole block.  */
00149           next = prev;
00150           for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i)
00151             {
00152               next = next -> next;
00153             }
00154           prev -> prev -> next = next;
00155           if (next != NULL)
00156             {
00157               next -> prev = prev -> prev;
00158             }
00159           mdp -> heapinfo[block].busy.type = 0;
00160           mdp -> heapinfo[block].busy.info.size = 1;
00161 
00162           /* Keep the statistics accurate.  */
00163           mdp -> heapstats.chunks_used++;
00164           mdp -> heapstats.bytes_used += BLOCKSIZE;
00165           mdp -> heapstats.chunks_free -= BLOCKSIZE >> type;
00166           mdp -> heapstats.bytes_free -= BLOCKSIZE;
00167 
00168           mfree ((PTR) mdp, (PTR) ADDRESS(block));
00169         }
00170       else if (mdp -> heapinfo[block].busy.info.frag.nfree != 0)
00171         {
00172           /* If some fragments of this block are free, link this
00173              fragment into the fragment list after the first free
00174              fragment of this block. */
00175           next = (struct mmlist *) ptr;
00176           next -> next = prev -> next;
00177           next -> prev = prev;
00178           prev -> next = next;
00179           if (next -> next != NULL)
00180             {
00181               next -> next -> prev = next;
00182             }
00183           ++mdp -> heapinfo[block].busy.info.frag.nfree;
00184         }
00185       else
00186         {
00187           /* No fragments of this block are free, so link this
00188              fragment into the fragment list and announce that
00189              it is the first free fragment of this block. */
00190           prev = (struct mmlist *) ptr;
00191           mdp -> heapinfo[block].busy.info.frag.nfree = 1;
00192           mdp -> heapinfo[block].busy.info.frag.first =
00193             RESIDUAL (ptr, BLOCKSIZE) >> type;
00194           prev -> next = mdp -> fraghead[type].next;
00195           prev -> prev = &mdp -> fraghead[type];
00196           prev -> prev -> next = prev;
00197           if (prev -> next != NULL)
00198             {
00199               prev -> next -> prev = prev;
00200             }
00201         }
00202       break;
00203     }
00204 }
00205 
00206 /* Return memory to the heap.  */
00207 
00208 void
00209 mfree (md, ptr)
00210   PTR md;
00211   PTR ptr;
00212 {
00213   struct mdesc *mdp;
00214   register struct alignlist *l;
00215 
00216   if (ptr != NULL)
00217     {
00218       mdp = MD_TO_MDP (md);
00219       for (l = mdp -> aligned_blocks; l != NULL; l = l -> next)
00220         {
00221           if (l -> aligned == ptr)
00222             {
00223               l -> aligned = NULL;  /* Mark the slot in the list as free. */
00224               ptr = l -> exact;
00225               break;
00226             }
00227         }
00228       if (mdp -> mfree_hook != NULL)
00229         {
00230           (*mdp -> mfree_hook) (md, ptr);
00231         }
00232       else
00233         {
00234           __mmalloc_free (mdp, ptr);
00235         }
00236     }
00237 }
00238 
00239 /* When using this package, provide a version of malloc/realloc/free built
00240    on top of it, so that if we use the default sbrk() region we will not
00241    collide with another malloc package trying to do the same thing, if
00242    the application contains any "hidden" calls to malloc/realloc/free (such
00243    as inside a system library). */
00244 
00245 #ifndef NO_SBRK_MALLOC
00246 
00247 void
00248 free (ptr)
00249   PTR ptr;
00250 {
00251   mfree ((PTR) NULL, ptr);
00252 }
00253 
00254 #endif

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