Eneboo - Documentación para desarrolladores
|
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