Eneboo - Documentación para desarrolladores
|
00001 // -*- C++ -*- 00002 00003 /* 00004 00005 Heap Layers: An Extensible Memory Allocation Infrastructure 00006 00007 Copyright (C) 2000-2007 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 00027 #ifndef _HOARDMANAGER_H_ 00028 #define _HOARDMANAGER_H_ 00029 00030 #include <cstdlib> 00031 #include <new> 00032 00033 // Hoard-specific Heap Layers 00034 #include "sassert.h" 00035 #include "statistics.h" 00036 #include "emptyclass.h" 00037 #include "array.h" 00038 #include "manageonesuperblock.h" 00039 00040 00041 // Generic Heap Layers 00042 #include "bins.h" 00043 #include "basehoardmanager.h" 00044 #include "emptyhoardmanager.h" 00045 #include "guard.h" 00046 #include "hldefines.h" 00047 00048 using namespace HL; 00049 00058 namespace Hoard { 00059 00060 template <class SourceHeap, 00061 class ParentHeap, 00062 class SuperblockType_, 00063 int EmptinessClasses, 00064 class LockType, 00065 class thresholdFunctionClass, 00066 class HeapType> 00067 class HoardManager : public BaseHoardManager<SuperblockType_>, 00068 public thresholdFunctionClass 00069 { 00070 public: 00071 00072 HoardManager (void) 00073 : _magic (MAGIC_NUMBER) 00074 {} 00075 00076 virtual ~HoardManager (void) {} 00077 00078 typedef SuperblockType_ SuperblockType; 00079 00081 enum { Alignment = sizeof(double) }; 00082 00083 00084 MALLOC_FUNCTION INLINE void * malloc (size_t sz) 00085 { 00086 Check<HoardManager, sanityCheck> check (this); 00087 const int binIndex = binType::getSizeClass(sz); 00088 size_t realSize = binType::getClassSize (binIndex); 00089 assert (realSize >= sz); 00090 00091 // Iterate until we succeed in allocating memory. 00092 void * ptr = getObject (binIndex, realSize); 00093 if (ptr) { 00094 return ptr; 00095 } else { 00096 return slowPathMalloc (realSize); 00097 } 00098 } 00099 00100 00102 NO_INLINE void put (SuperblockType * s, size_t sz) { 00103 HL::Guard<LockType> l (_theLock); 00104 00105 assert (s->getOwner() != this); 00106 Check<HoardManager, sanityCheck> check (this); 00107 00108 const int binIndex = binType::getSizeClass(sz); 00109 00110 // Check to see whether this superblock puts us over. 00111 Statistics& stats = _stats(binIndex); 00112 int a = stats.getAllocated() + s->getTotalObjects(); 00113 int u = stats.getInUse() + (s->getTotalObjects() - s->getObjectsFree()); 00114 00115 if (thresholdFunctionClass::function (u, a, sz)) { 00116 // We've crossed the threshold function, 00117 // so we move this superblock up to the parent. 00118 _ph.put (reinterpret_cast<typename ParentHeap::SuperblockType *>(s), sz); 00119 } else { 00120 unlocked_put (s, sz); 00121 } 00122 } 00123 00124 00126 NO_INLINE SuperblockType * get (size_t sz, HeapType * dest) { 00127 HL::Guard<LockType> l (_theLock); 00128 Check<HoardManager, sanityCheck> check (this); 00129 const int binIndex = binType::getSizeClass (sz); 00130 SuperblockType * s = _otherBins(binIndex).get(); 00131 if (s) { 00132 assert (s->isValidSuperblock()); 00133 00134 // Update the statistics, removing objects in use and allocated for s. 00135 decStatsSuperblock (s, binIndex); 00136 s->setOwner (dest); 00137 } 00138 // printf ("getting sb %x (size %d) on %x\n", (void *) s, sz, (void *) this); 00139 return s; 00140 } 00141 00143 INLINE void free (void * ptr) { 00144 Check<HoardManager, sanityCheck> check (this); 00145 00146 // Get the corresponding superblock. 00147 SuperblockType * s = SuperHeap::getSuperblock (ptr); 00148 00149 assert (s->getOwner() == this); 00150 00151 // Find out which bin it belongs to. 00152 // Note that we assume that all pointers have been correctly 00153 // normalized at this point. 00154 assert (s->normalize (ptr) == ptr); 00155 00156 const size_t sz = s->getObjectSize (); 00157 const int binIndex = binType::getSizeClass (sz); 00158 00159 // Free the object. 00160 _otherBins(binIndex).free (ptr); 00161 00162 00163 // Update statistics. 00164 Statistics& stats = _stats(binIndex); 00165 int u = stats.getInUse(); 00166 const int a = stats.getAllocated(); 00167 if (u > 0) 00168 u--; 00169 stats.setInUse (u); 00170 00171 // Free up a superblock if we've crossed the emptiness threshold. 00172 00173 if (thresholdFunctionClass::function (u, a, sz)) { 00174 00175 slowPathFree (binIndex, u, a); 00176 00177 } 00178 } 00179 00180 INLINE void lock (void) { 00181 _theLock.lock(); 00182 } 00183 00184 INLINE void unlock (void) { 00185 _theLock.unlock(); 00186 } 00187 00188 private: 00189 00190 typedef BaseHoardManager<SuperblockType_> SuperHeap; 00191 00192 enum { SuperblockSize = sizeof(SuperblockType_) }; 00193 00195 HL::sassert<((SuperblockSize & (SuperblockSize-1)) == 0)> verifyPowerOfTwo; 00196 00197 enum { MAGIC_NUMBER = 0xfeeddadd }; 00198 00200 const unsigned long _magic; 00201 00202 inline int isValid (void) const { 00203 return (_magic == MAGIC_NUMBER); 00204 } 00205 00206 sassert<sizeof(typename SuperblockType::Header) % sizeof(double) == 0> 00207 verifyHeaderRightSize; 00208 00209 00211 typedef HL::bins<typename SuperblockType::Header, SuperblockSize> binType; 00212 00214 enum { NumBins = binType::NUM_BINS }; 00215 00216 NO_INLINE void slowPathFree (int binIndex, int u, int a) { 00217 // We've crossed the threshold. 00218 // Remove a superblock and give it to the 'parent heap.' 00219 Check<HoardManager, sanityCheck> check (this); 00220 00221 // printf ("HoardManager: this = %x, getting a superblock\n", this); 00222 00223 SuperblockType * sb = _otherBins(binIndex).get (); 00224 00225 // We should always get one. 00226 assert (sb); 00227 if (sb) { 00228 00229 const size_t sz = binType::getClassSize (binIndex); 00230 Statistics& stats = _stats(binIndex); 00231 int totalObjects = sb->getTotalObjects(); 00232 stats.setInUse (u - (totalObjects - sb->getObjectsFree())); 00233 stats.setAllocated (a - totalObjects); 00234 00235 // Give it to the parent heap. 00238 _ph.put (reinterpret_cast<typename ParentHeap::SuperblockType *>(sb), sz); 00239 assert (sb->isValidSuperblock()); 00240 00241 } 00242 } 00243 00244 00245 NO_INLINE void unlocked_put (SuperblockType * s, size_t sz) { 00246 if (!s || !s->isValidSuperblock()) { 00247 return; 00248 } 00249 00250 Check<HoardManager, sanityCheck> check (this); 00251 00252 const int binIndex = binType::getSizeClass(sz); 00253 00254 // Now put it on this heap. 00255 s->setOwner (reinterpret_cast<HeapType *>(this)); 00256 _otherBins(binIndex).put (s); 00257 00258 // Update the heap statistics with the allocated and in use stats 00259 // for the superblock. 00260 00261 addStatsSuperblock (s, binIndex); 00262 assert (s->isValidSuperblock()); 00263 00264 } 00265 00266 void addStatsSuperblock (SuperblockType * s, int binIndex) { 00267 Statistics& stats = _stats(binIndex); 00268 00269 int a = stats.getAllocated(); 00270 int u = stats.getInUse(); 00271 int totalObjects = s->getTotalObjects(); 00272 stats.setInUse (u + (totalObjects - s->getObjectsFree())); 00273 stats.setAllocated (a + totalObjects); 00274 } 00275 00276 00277 void decStatsSuperblock (SuperblockType * s, int binIndex) { 00278 Statistics& stats = _stats(binIndex); 00279 00280 int a = stats.getAllocated(); 00281 int u = stats.getInUse(); 00282 int totalObjects = s->getTotalObjects(); 00283 stats.setInUse (u - (totalObjects - s->getObjectsFree())); 00284 stats.setAllocated (a - totalObjects); 00285 } 00286 00287 MALLOC_FUNCTION NO_INLINE void * slowPathMalloc (size_t sz) { 00288 const int binIndex = binType::getSizeClass (sz); 00289 size_t realSize = binType::getClassSize (binIndex); 00290 assert (realSize >= sz); 00291 for (;;) { 00292 Check<HoardManager, sanityCheck> check (this); 00293 void * ptr = getObject (binIndex, realSize); 00294 if (ptr) { 00295 return ptr; 00296 } else { 00297 Check<HoardManager, sanityCheck> check (this); 00298 // Return null if we can't allocate another superblock. 00299 if (!getAnotherSuperblock (realSize)) { 00300 // fprintf (stderr, "HoardManager::malloc - no memory.\n"); 00301 return 0; 00302 } 00303 } 00304 } 00305 } 00306 00308 MALLOC_FUNCTION INLINE void * getObject (int binIndex, size_t sz) { 00309 Check<HoardManager, sanityCheck> check (this); 00310 void * ptr = _otherBins(binIndex).malloc (sz); 00311 if (ptr) { 00312 // We got one. Update stats. 00313 int u = _stats(binIndex).getInUse(); 00314 _stats(binIndex).setInUse (u+1); 00315 } 00316 return ptr; 00317 } 00318 00319 friend class sanityCheck; 00320 00321 class sanityCheck { 00322 public: 00323 inline static void precondition (HoardManager * h) { 00324 checkInvariant(h); 00325 } 00326 inline static void postcondition (HoardManager * h) { 00327 checkInvariant(h); 00328 } 00329 private: 00330 inline static void checkInvariant (HoardManager * h) { 00331 assert (h->isValid()); 00332 } 00333 }; 00334 00335 public: 00336 00337 NO_INLINE void * getAnotherSuperblock (size_t sz) { 00338 00339 // NB: This function should be on the slow path. 00340 00341 SuperblockType * sb = NULL; 00342 00343 // Try the parent heap. 00344 // NOTE: We change the superblock type here! 00345 sb = reinterpret_cast<SuperblockType *>(_ph.get (sz, reinterpret_cast<ParentHeap *>(this))); 00346 00347 if (sb) { 00348 if (!sb->isValidSuperblock()) { 00349 // As above - drop any invalid superblocks. 00350 sb = NULL; 00351 } 00352 00353 } else { 00354 // Nothing - get memory from the source. 00355 void * ptr = _sourceHeap.malloc (SuperblockSize); 00356 if (!ptr) { 00357 return 0; 00358 } 00359 sb = new (ptr) SuperblockType (sz); 00360 } 00361 00362 // Put the superblock into its appropriate bin. 00363 if (sb) { 00364 unlocked_put (sb, sz); 00365 } 00366 return sb; 00367 } 00368 00369 private: 00370 00371 LockType _theLock; 00372 00374 Array<NumBins, Statistics> _stats; 00375 00376 typedef SuperblockType * SuperblockTypePointer; 00377 00378 typedef EmptyClass<SuperblockType, EmptinessClasses> OrganizedByEmptiness; 00379 00380 typedef ManageOneSuperblock<OrganizedByEmptiness> BinManager; 00381 00383 Array<NumBins, BinManager> _otherBins; 00384 00386 ParentHeap _ph; 00387 00389 SourceHeap _sourceHeap; 00390 00391 }; 00392 00393 } 00394 00395 #endif