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 00027 #ifndef _SEG_H_ 00028 #define _SEG_H_ 00029 00030 #include <assert.h> 00031 00032 #include "sassert.h" 00033 #include "reaplet.h" 00034 00035 namespace HL { 00036 00037 template <int ReapletSize, 00038 class SizeClassComputer, 00039 class TopHeap> 00040 class Seg : public TopHeap { 00041 public: 00042 00043 enum { Alignment = sizeof(double) }; 00044 00045 private: 00046 00047 Seg (void) 00048 { 00049 sassert <(sizeof(Reaplet<ReapletSize>) == ReapletSize)> verifyReapletSize; 00050 } 00051 00052 class SanityChecker { 00053 public: 00054 SanityChecker (Seg * s) 00055 : _s (s) 00056 { 00057 _s->sanityCheck(); 00058 } 00059 ~SanityChecker (void) { 00060 _s->sanityCheck(); 00061 } 00062 private: 00063 Seg * _s; 00064 }; 00065 00066 00067 #if 1 00068 enum { TopAlignment = TopHeap::Alignment }; 00069 00070 class VerifyAlignment : 00071 public sassert <TopAlignment % ReapletSize == 0> {}; 00072 #endif 00073 00074 public: 00075 00076 __forceinline Seg (void) { 00077 for (int i = 0; i < SizeClassComputer::NUM_BINS; i++) { 00078 available[i] = 0; 00079 full[i] = 0; 00080 } 00081 } 00082 00083 ~Seg (void) { 00084 clear(); 00085 } 00086 00087 __forceinline void * malloc (size_t sz) { 00088 SanityChecker c (this); 00089 assert (sz <= SizeClassComputer::BIG_OBJECT); 00090 const int SizeClass = SizeClassComputer::getSizeClass (sz); 00091 // Try to use one of our reaplets to satisfy the request. 00092 Reaplet<ReapletSize> * const xs = available[SizeClass]; 00093 if (xs) { 00094 // assert (!xs->isFull()); 00095 // We've got one. Now try to get some memory from it. 00096 void * const ptr = xs->malloc (SizeClassComputer::bins[SizeClass]); 00097 // printf ("allocated: %x\n", ptr); 00098 if (ptr) { 00099 // Success! We're out of here. 00100 return ptr; 00101 } else { 00102 // It's full. 00103 // printf ("Full - adios.\n"); 00104 removeFromAvailable (xs, SizeClass); 00105 } 00106 } 00107 // printf ("slow!\n"); 00108 // We have to go get more memory. 00109 return slowPathGetMoreMemory (sz); 00110 } 00111 00112 00113 __forceinline static size_t getSize (void * ptr) { 00114 return (enclosingReaplet (ptr))->getSize(); 00115 } 00116 00117 __forceinline void free (void * ptr) { 00118 SanityChecker c (this); 00119 // printf ("seg free: r = %x\n", r); 00120 Reaplet<ReapletSize> * r = enclosingReaplet (ptr); 00121 // printf ("freeing %x to %x\n", ptr, r); 00122 // if (sz <= SizeClassComputer::BIG_OBJECT) { 00123 // It's a small object. Free it. 00124 bool wasFull = r->isFull(); // || !r->getAmountAllocated()) { 00125 r->free (ptr); 00126 if (wasFull) { 00127 moveFromFullToAvailable (r); 00128 } 00129 } 00130 00131 void clear (void) { 00132 SanityChecker c (this); 00133 for (int i = 0; i < SizeClassComputer::NUM_BINS; i++) { 00134 clearOut (full[i]); 00135 clearOut (available[i]); 00136 } 00137 } 00138 00139 private: 00140 00141 __forceinline void * slowPathGetMoreMemory (const size_t sz) { 00142 // printf ("slowpathgetmorememory\n"); 00143 SanityChecker c (this); 00144 if (sz <= SizeClassComputer::BIG_OBJECT) { 00145 const int SizeClass = SizeClassComputer::getSizeClass (sz); 00146 do { 00147 // printf ("looking for more memory.\n"); 00148 Reaplet<ReapletSize> * xs = available[SizeClass]; 00149 // Look for an available reaplet. 00150 if (xs != 0) { 00151 assert (!xs->isFull()); 00152 // We've got one. Now try to get some memory from it. 00153 void * ptr = xs->malloc (SizeClassComputer::bins[SizeClass]); 00154 if (ptr) { 00155 // Success! 00156 // printf ("amt free = %d\n", enclosingReaplet(ptr)->getAmountFree()); 00157 // printf ("success: found more memory.\n"); 00158 return ptr; 00159 } else { 00160 // printf ("Adios!\n"); 00161 // This reaplet is out of memory. 00162 // Remove it from the available list. 00163 removeFromAvailable (xs, SizeClass); 00164 // Put it on the full list. 00165 putOnFullList (xs, SizeClass); 00166 } 00167 } else { 00168 // The current bin is empty - make another reaplet. 00169 int r = insertNewReaplet (SizeClass); 00170 if (!r) { 00171 return 0; 00172 } 00173 } 00174 } while (1); 00175 } else { 00176 return makeBigObject (sz); 00177 } 00178 } 00179 00180 __forceinline void sanityCheck (void) { 00181 #if !defined(NDEBUG) 00182 // FIX ME 00183 //#error "whoa dude. slowing things down." 00184 Reaplet<ReapletSize> * q; 00185 for (int i = 0; i < SizeClassComputer::NUM_BINS; i++) { 00186 // Visit the available list. 00187 q = available[i]; 00188 if (q) { 00189 assert (q->getPrev() == 0); 00190 } 00191 while (q) { 00192 if (q->isFull()) { 00193 // printf ("allocated = %d\n", q->getAmountAllocated()); 00194 } 00195 assert (!q->isFull()); 00196 q = (Reaplet<ReapletSize> *) q->getNext(); 00197 } 00198 // Now visit the full list. 00199 q = full[i]; 00200 if (q) { 00201 assert (q->getPrev() == 0); 00202 } 00203 while (q) { 00204 assert (q->isFull()); 00205 q = (Reaplet<ReapletSize> *) q->getNext(); 00206 } 00207 } 00208 #endif 00209 } 00210 00211 __forceinline 00212 void putOnFullList (Reaplet<ReapletSize> * xs, 00213 const int SizeClass) { 00214 // printf ("putOnFullList %d\n", SizeClass); 00215 SanityChecker c (this); 00216 // assert (!xs->isFull()); 00217 xs->setNext (full[SizeClass]); 00218 xs->setPrev (0); 00219 if (full[SizeClass]) { 00220 full[SizeClass]->setPrev (xs); 00221 } 00222 full[SizeClass] = xs; 00223 // xs->markFull(); 00224 } 00225 00226 __forceinline void clearOut (Reaplet<ReapletSize> *& list) { 00227 SanityChecker c (this); 00228 Reaplet<ReapletSize> * q; 00229 q = list; 00230 while (q) { 00231 Reaplet<ReapletSize> * c = q; 00232 q = (Reaplet<ReapletSize> *) q->getNext(); 00233 TopHeap::free (c); 00234 } 00235 list = 0; 00236 } 00237 00238 __forceinline void removeFromFullList (Reaplet<ReapletSize> * r, 00239 const size_t sz) { 00240 // printf ("removeFromFullList\n"); 00241 // prev <-> r <-> next => 00242 // prev <-> next 00243 SanityChecker c (this); 00244 // assert (r->isFull()); 00245 // Remove from full list. 00246 Reaplet<ReapletSize> * prev, * next; 00247 prev = (Reaplet<ReapletSize> *) r->getPrev(); 00248 next = (Reaplet<ReapletSize> *) r->getNext(); 00249 assert (prev != r); 00250 assert (next != r); 00251 if (prev) { 00252 prev->setNext (next); 00253 } 00254 if (next) { 00255 next->setPrev (prev); 00256 } 00257 const int SizeClass = SizeClassComputer::getSizeClass (sz); 00258 if (r == full[SizeClass]) { 00259 assert (prev == 0); 00260 full[SizeClass] = next; 00261 } 00262 assert (full[SizeClass] != r); 00263 // r->setPrev (0); 00264 // r->setNext (0); 00265 // r->markNotFull(); 00266 } 00267 00268 __forceinline 00269 void moveFromFullToAvailable (Reaplet<ReapletSize> * r) { 00270 SanityChecker c (this); 00271 const size_t sz = r->getSize(); 00272 removeFromFullList (r, sz); 00273 // Put it on the available list. 00274 addToAvailableList (r, sz); 00275 assert (r->getPrev() == 0); 00276 } 00277 00278 __forceinline 00279 void removeAndFreeReaplet (Reaplet<ReapletSize> * r) 00280 { 00281 SanityChecker c (this); 00282 assert (!r->isFull()); 00283 const size_t sz = r->getSize(); 00284 Reaplet<ReapletSize> * n 00285 = (Reaplet<ReapletSize> *) r->getNext(); 00286 Reaplet<ReapletSize> * p 00287 = (Reaplet<ReapletSize> *) r->getPrev(); 00288 if (n) { 00289 n->setPrev (p); 00290 } 00291 if (p) { 00292 p->setNext (n); 00293 } 00294 int sizeclass = SizeClassComputer::getSizeClass (sz); 00295 if (available[sizeclass] == r) { 00296 available[sizeclass] = n; 00297 } 00298 //r->setPrev ((Reaplet<ReapletSize> *) 1); 00299 //r->setNext ((Reaplet<ReapletSize> *) 1); 00300 //r->clear(); 00301 TopHeap::free (r); 00302 // printf ("reset %d\n", sz); 00303 } 00304 00305 __forceinline 00306 int insertNewReaplet (int SizeClass) 00307 { 00308 // printf ("insertNewReaplet\n"); 00309 SanityChecker c (this); 00310 void * m = TopHeap::malloc (ReapletSize); 00311 // NOTE: TopHeap *must* add a reaplet prefix. 00312 // Ensure m is aligned properly. 00313 assert (((size_t) m & (ReapletSize - 1)) == 0); 00314 if (m == 0) { 00315 // printf ("NO MORE MEMORY!\n"); 00316 // No more memory. 00317 return 0; 00318 } 00319 // Make a new Reaplet for this size class. 00320 size_t ssz = SizeClassComputer::getClassSize (SizeClass); 00321 00322 // printf ("new reaplet!: ssz = %d\n", ssz); 00323 available[SizeClass] = new (m) Reaplet<ReapletSize> (ssz); 00324 available[SizeClass]->clear(); 00325 return 1; 00326 } 00327 00328 protected: 00329 00330 __forceinline 00331 void addToAvailableList (Reaplet<ReapletSize> * r, 00332 size_t sz) 00333 { 00334 SanityChecker c (this); 00335 // assert (!r->isFull()); 00336 const int SizeClass = SizeClassComputer::getSizeClass (sz); 00337 Reaplet<ReapletSize> * head = available[SizeClass]; 00338 00339 assert (head != r); 00340 00341 // r 00342 // => r <-> head 00343 00344 r->setPrev (0); 00345 r->setNext (head); 00346 if (head) { 00347 head->setPrev (r); 00348 } 00349 available[SizeClass] = r; 00350 } 00351 00352 private: 00353 00354 NO_INLINE void removeFromAvailable (Reaplet<ReapletSize> * xs, 00355 const int SizeClass) { 00356 // printf ("removefromavailable %d.\n", SizeClass); 00357 // The reaplet xs is out of memory. 00358 // Remove it from the linked list. 00359 // Note that it is the head of the linked list. 00360 // printf ("Removing REAPLET %x\n", xs); 00361 assert (xs->isFull()); 00362 assert (xs->getPrev() == 0); 00363 Reaplet<ReapletSize> * n 00364 = (Reaplet<ReapletSize> *) xs->getNext(); 00365 if (n) { 00366 // printf ("setprev.\n"); 00367 n->setPrev (0); 00368 assert (!n->isFull()); 00369 } 00370 available[SizeClass] = n; 00371 SanityChecker c (this); 00372 // xs->setPrev ((Reaplet<ReapletSize> *) 1); 00373 // xs->setNext ((Reaplet<ReapletSize> *) 1); 00374 assert (n == 0 || (n->getPrev() == 0)); 00375 } 00376 00377 __forceinline static Reaplet<ReapletSize> * enclosingReaplet (void * ptr) { 00378 // Find the enclosing reaplet for this pointer. 00379 Reaplet<ReapletSize> * r 00380 = (Reaplet<ReapletSize> *) (((size_t) ptr) & ~(ReapletSize - 1)); 00381 return r; 00382 } 00383 00384 #if 1 00385 NO_INLINE 00386 void * makeBigObject (size_t sz) { 00387 // printf ("makeBigObject\n"); 00388 SanityChecker c (this); 00389 // printf ("make big object: %d\n", sz); 00390 // Allocate big objects from the top heap. These must be 00391 // ReapletSize aligned. 00392 assert (sz > SizeClassComputer::BIG_OBJECT); 00393 ReapletBase * m 00394 = (ReapletBase *) TopHeap::malloc (sz + sizeof(ReapletBase)); 00395 // printf ("m = %x, size = %d\n", m, ReapletSize); 00396 assert (((size_t) m & (ReapletSize - 1)) == 0); 00397 // Put a reaplet base object as a header in the beginning. We 00398 // need this for size information. 00399 if (m == 0) { 00400 return 0; 00401 } 00402 new (m) ReapletBase (sz, (char *) (m + 1)); 00403 return (void *) (m + 1); 00404 } 00405 #endif 00406 00407 Reaplet<ReapletSize> * available[SizeClassComputer::NUM_BINS]; 00408 Reaplet<ReapletSize> * full[SizeClassComputer::NUM_BINS]; 00409 }; 00410 00411 }; 00412 00413 #endif