Eneboo - Documentación para desarrolladores
src/hoard/src/heaplayers/coalesceableheap.h
Ir a la documentación de este archivo.
00001 /* -*- C++ -*- */
00002 
00003 /*
00004 
00005   Heap Layers: An Extensible Memory Allocation Infrastructure
00006   
00007   Copyright (C) 2000-2003 by Emery Berger
00008   http://www.cs.umass.edu/~emery
00009   emery@cs.umass.edu
00010   
00011   This program is free software; you can redistribute it and/or modify
00012   it under the terms of the GNU General Public License as published by
00013   the Free Software Foundation; either version 2 of the License, or
00014   (at your option) any later version.
00015   
00016   This program is distributed in the hope that it will be useful,
00017   but WITHOUT ANY WARRANTY; without even the implied warranty of
00018   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019   GNU General Public License for more details.
00020   
00021   You should have received a copy of the GNU General Public License
00022   along with this program; if not, write to the Free Software
00023   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024 
00025 */
00026 
00033 #ifndef _COALESCEABLEHEAP_H_
00034 #define _COALESCEABLEHEAP_H_
00035 
00036 #include <assert.h>
00037 
00038 #define MULTIPLE_HEAP_SUPPORT 0
00039 
00045 namespace HL {
00046 
00047 template <class SuperHeap>
00048 class RequireCoalesceable : public SuperHeap {
00049 public:
00050 
00051   // Some thin wrappers over Header methods.
00052   inline static int getHeap (void * ptr)          { return Header::getHeader(ptr)->getHeap(); }
00053   inline static void setHeap (void * ptr, int h)  { Header::getHeader(ptr)->setHeap(h); }
00054   inline static int getPrevHeap (void * ptr)      { return Header::getHeader(ptr)->getPrevHeap(); }
00055   inline static void setPrevHeap (void * ptr, int h) { Header::getHeader(ptr)->setPrevHeap(h); }
00056 
00057   inline static size_t getSize (const void * ptr)       { return Header::getHeader(ptr)->getSize(); }
00058 
00059   inline static void setSize (void * ptr, const size_t sz) { Header::getHeader(ptr)->setSize(sz); }
00060   inline static size_t getPrevSize (void * ptr)   { return Header::getHeader(ptr)->getPrevSize(); }
00061   inline static void setPrevSize (void * ptr, const size_t sz) { Header::getHeader(ptr)->setPrevSize(sz); }
00062   inline static void markFree (void * ptr)        { Header::getHeader(ptr)->markFree(); }
00063   inline static void markInUse (void * ptr)       { Header::getHeader(ptr)->markInUse(); }
00064   inline static void markPrevInUse (void * ptr)   { Header::getHeader(ptr)->markPrevInUse(); }
00065   inline static void markMmapped (void * ptr)     { Header::getHeader(ptr)->markMmapped(); }
00066   inline static int isFree (void * ptr)           { return Header::getHeader(ptr)->isFree(); }
00067   inline static int isPrevFree (void * ptr)       { return Header::getHeader(ptr)->isPrevFree(); }
00068   inline static int isMmapped (void * ptr)        { return Header::getHeader(ptr)->isMmapped(); }
00069   inline static void * getNext (const void * ptr)       { return Header::getHeader(ptr)->getNext(); }
00070   inline static void * getPrev (const void * ptr)       { return Header::getHeader(ptr)->getPrev(); }
00071 
00072   // The Header for every object, allocated or freed.
00073   class Header {
00074           friend class RequireCoalesceable<SuperHeap>;
00075   public:
00076 
00077     //
00078     // Initialize a new object in a given buffer, with a previous & current object size.
00079     // Returns the start of the object (i.e., just past the header).
00080     //
00081     inline static void * makeObject (void * buf, const size_t prevsz, const size_t sz) {
00082           *((Header *) buf) = Header (prevsz, sz);
00083           Header * nextHeader = (Header *) ((char *) ((Header *) buf + 1) + sz);
00084 //        Header * nextHeader = h->getNextHeader();
00085 //        nextHeader->markPrevInUse();
00086           nextHeader->setPrevSize (sz);
00087       // return Header::getObject (h);
00088           return ((Header *) buf + 1);
00089     }
00090 
00091 
00092     inline void sanityCheck (void) {
00093 #ifndef NDEBUG
00094       int headerSize = sizeof(Header);
00095       assert (headerSize <= sizeof(double));
00096       assert (getSize() == getNextHeader()->getPrevSize());
00097       assert (isFree() == getNextHeader()->isPrevFree());
00098       assert (getNextHeader()->getPrev() == getObject(this));
00099 #if 0
00100       if (isPrevFree()) {
00101         assert (getPrevSize() == getHeader(getPrev())->getSize());
00102       }
00103 #endif
00104 #endif
00105     }
00106 
00107     // Get the header for a given object.
00108     inline static Header * getHeader (const void * ptr) { return ((Header *) ptr - 1); }
00109 
00110     // Get the object for a given header.
00111     inline static void * getObject (const Header * hd)  { return (void *) (hd + 1); }
00112 
00113     inline void setSize (const size_t sz)    { _size = sz; }
00114     inline void setPrevSize (const size_t sz){ _prevSize = sz; }
00115 
00116 //  private:
00117     inline size_t getPrevSize (void) const { return _prevSize; }
00118 
00119     inline void markFree (void)        {
00120                 // printf ("markFree\n");
00121                 getNextHeader()->markPrevFree();
00122         }
00123     inline void markInUse (void)       {
00124                 // printf ("markInUse\n");
00125                 getNextHeader()->markPrevInUse();
00126         }
00127     inline void markMmapped (void)     { _isMmapped = IS_MMAPPED; }
00128     inline void markNotMmapped (void)  { _isMmapped = NOT_MMAPPED; }
00129     inline int isFree (void) const     {
00130                 // printf ("isFree\n");
00131                 return getNextHeader()->isPrevFree();
00132         }
00133     inline int isNextFree (void) const {
00134                 // printf ("isNextFree\n");
00135                 return getNextHeader()->getNextHeader()->isPrevFree();
00136         }
00137     inline int isMmapped (void) const  { return (_isMmapped != NOT_MMAPPED); }
00138     inline void * getPrev (void) const {
00139         //      fprintf (stderr, "coalesceableheap.h: %x, %d\n", this, getPrevSize());
00140                 return ((char *) this) - getPrevSize(); 
00141         }
00142     inline void * getNext (void) const { 
00143                 // printf ("getNext\n");
00144                 return ((char *) (this + 2)) + getSize();
00145         }
00146 
00147     inline void markPrevFree (void)    { _prevStatus = PREV_FREE; }
00148     inline void markPrevInUse (void)   { _prevStatus = PREV_INUSE; }
00149     inline int isPrevFree (void) const { return (_prevStatus != PREV_INUSE); }
00150     inline size_t getSize (void) const { return _size; }
00151 
00152 #if MULTIPLE_HEAP_SUPPORT
00153     inline int getHeap (void) const { return _currHeap; }
00154     inline void setHeap (int h)     { _currHeap = h; }
00155     inline int getPrevHeap (void) const { return _prevHeap; }
00156     inline void setPrevHeap (int h) { _prevHeap = h; }
00157 #else
00158     inline int getHeap (void) const { return 0; }
00159     inline void setHeap (int)       {  }
00160     inline int getPrevHeap (void) const { return 0; }
00161     inline void setPrevHeap (int)   {  }
00162 #endif
00163 
00164 
00165   private:
00166 
00167     explicit inline Header (void) {}
00168     explicit inline Header (const size_t prevsz, const size_t sz)
00169       :
00170       _prevSize (prevsz),
00171       _size (sz),
00172       // Assume that objects are NOT mmapped.
00173       _isMmapped (NOT_MMAPPED)
00174 #if MULTIPLE_HEAP_SUPPORT
00175       , _prevHeap (0),
00176       _currHeap (0)
00177 #endif
00178     {
00179       assert (sizeof(Header) <= sizeof(double));
00180     }
00181 
00182     inline Header * getNextHeader (void) const {
00183       // printf ("H\n");
00184       return ((Header *) ((char *) (this + 1) + getSize()));
00185     }
00186 
00187 #if !(MULTIPLE_HEAP_SUPPORT) // original
00188 
00189     // Is the previous object free or in use?
00190     enum { PREV_INUSE = 0, PREV_FREE = 1 };
00191     unsigned int _prevStatus : 1;
00192 
00193     // Is the current object mmapped?
00194     enum { NOT_MMAPPED = 0, IS_MMAPPED = 1 };
00195     unsigned int _isMmapped : 1;
00196 
00197     // The size of the previous object.
00198     enum { NUM_BITS_STOLEN_FROM_PREVSIZE = 2 };
00199     size_t _prevSize : sizeof(size_t) * 8 - NUM_BITS_STOLEN_FROM_PREVSIZE;
00200 
00201     // The size of the current object.
00202     enum { NUM_BITS_STOLEN_FROM_SIZE = 0 };
00203     size_t _size; // : sizeof(size_t) * 8 - NUM_BITS_STOLEN_FROM_SIZE;
00204 
00205 
00206 #else // new support for scalability...
00207 
00208     // Support for 2^5 = 32 heaps.
00209     enum { NUM_BITS_FOR_HEAP = 5 };
00210 
00211     enum { NUM_BITS_STOLEN_FROM_SIZE = NUM_BITS_FOR_HEAP + 1 };     // 1 for isMmapped
00212     enum { NUM_BITS_STOLEN_FROM_PREVSIZE = NUM_BITS_FOR_HEAP + 1 }; // 1 for isPrevFree
00213 
00214     // Max object size.
00215     enum { MAX_OBJECT_SIZE = 1 << (sizeof(size_t) * 8 - NUM_BITS_STOLEN_FROM_SIZE) };
00216 
00218 
00219     // The size of the previous object.
00220     size_t _prevSize : sizeof(size_t) * 8 - NUM_BITS_STOLEN_FROM_PREVSIZE;
00221 
00222     // What's the previous heap?
00223     unsigned int _prevHeap : NUM_BITS_FOR_HEAP;
00224 
00225     // Is the previous object free or in use?
00226     enum { PREV_FREE = 0, PREV_INUSE = 1 };
00227     unsigned int _prevStatus : 1;
00228 
00230 
00231     // The size of the current object.
00232     size_t _size : sizeof(size_t) * 8 - NUM_BITS_STOLEN_FROM_SIZE;
00233 
00234     // What's the current heap?
00235     unsigned int _currHeap : NUM_BITS_FOR_HEAP;
00236 
00237     // Is the current object mmapped?
00238     enum { NOT_MMAPPED = 0, IS_MMAPPED = 1 };
00239     unsigned int _isMmapped : 1;
00240 
00241 #endif
00242   };
00243 
00244   inline static void * makeObject (void * buf, const size_t prevsz, const size_t sz) {
00245     return Header::makeObject (buf, prevsz, sz);
00246   }
00247 
00248   inline static Header * getHeader (const void * ptr) {
00249     return Header::getHeader (ptr);
00250   }
00251 
00252 };
00253 
00254 
00260 template <class SuperHeap>
00261 class CoalesceableHeap : public RequireCoalesceable<SuperHeap> {
00262 public:
00263 
00264   typedef typename RequireCoalesceable<SuperHeap>::Header Header;
00265 
00266   inline CoalesceableHeap (void)
00267   { }
00268 
00269   inline void * malloc (const size_t sz) {
00270     void * buf = SuperHeap::malloc (sz + sizeof(Header));
00271     if (buf) {
00272       Header * header = (Header *) buf;
00273 
00274       //
00275       // Record the size of this object in the current header
00276       // and the next.
00277       //
00278 
00279       header->setSize (sz);
00280 
00281       // Below was:
00282 //      Header * nextHeader = Header::getHeader (header->getNext());
00283       Header * nextHeader = (Header *) ((char *) (header + 1) + sz);
00284 
00285       nextHeader->setPrevSize (sz);
00286 
00287 #if 0
00288       //
00289       // As long as the source of this memory
00290       // is always zeroed, these assertions will hold.
00291       // The easiest way to do this is to use a ZeroHeap.
00292       //
00293       assert (header->isMmapped() == FALSE);
00294       assert (nextHeader->getSize() ==  0);
00295       assert (!nextHeader->isFree());
00296       assert (!nextHeader->isPrevFree());
00297 
00298 #else
00299 
00300       // If the memory is not zeroed, we need this section of code.
00301 
00302       //
00303       // Assume that everything allocated is NOT mmapped.
00304       // It is the responsibility of a child layer
00305       // to mark mmapped objects as such.
00306       //
00307 
00308       header->markNotMmapped ();
00309 
00310       nextHeader->setSize (0);
00311 
00312       //
00313       // Mark the subsequent "object" as in use in order to prevent
00314       // accidental coalescing.
00315       //
00316 
00317 //        (nextHeader + 1)->markPrevInUse();
00318       nextHeader->markInUse ();
00319 #endif
00320 
00321       // Below was:
00322       // return Header::getObject (header);
00323       return (header + 1);
00324     }
00325     return NULL;
00326   }
00327   
00328   inline void free (void * ptr) {
00329     assert (SuperHeap::isFree(ptr));
00330     SuperHeap::free ((Header *) ptr - 1);
00331   }
00332 
00333 
00334 };
00335 
00336 };
00337 
00338 #endif // _COALESCEABLEHEAP_H_
00339 
 Todo Clases Namespaces Archivos Funciones Variables 'typedefs' Enumeraciones Valores de enumeraciones Propiedades Amigas 'defines'