00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef _HEAP_H_
00036 #define _HEAP_H_
00037
00038 #include "config.h"
00039
00040 #include "arch-specific.h"
00041 #include "superblock.h"
00042 #include "heapstats.h"
00043
00044 class processHeap;
00045
00046
00047 class hoardHeap {
00048
00049 public:
00050
00051 hoardHeap (void);
00052
00053
00054
00055 enum { SUPERBLOCK_SIZE = 16384 };
00056
00057
00058
00059 enum { EMPTY_FRACTION = SUPERBLOCK_FULLNESS_GROUP - 1 };
00060
00061
00062
00063
00064 enum { RESET_LEAST_EMPTY_BIN = SUPERBLOCK_FULLNESS_GROUP - 2 };
00065
00066
00067
00068
00069 enum { MAX_EMPTY_SUPERBLOCKS = 1 } ;
00070
00071
00072
00073
00074
00075 enum { MAX_HEAPS = 64 };
00076
00077
00078 enum { MAX_HEAPS_MASK = MAX_HEAPS - 1 };
00079
00080
00081
00082
00083
00084 enum { SIZE_CLASSES = 132 };
00085
00086
00087 enum { ALIGNMENT = sizeof(double) };
00088
00089
00090 enum { ALIGNMENT_MASK = ALIGNMENT - 1};
00091
00092
00093 enum { HEAP_MAGIC = 0x0badcafe };
00094
00095
00096 inline void getStats (int sizeclass, int& U, int& A);
00097
00098
00099 #if HEAP_STATS
00100
00101 inline int maxInUse (int sizeclass);
00102
00103
00104 inline int maxAllocated (int sizeclass);
00105 #endif
00106
00107
00108 void insertSuperblock (int sizeclass,
00109 superblock * sb,
00110 processHeap * pHeap);
00111
00112
00113 superblock * removeMaxSuperblock (int sizeclass);
00114
00115
00116 inline superblock * findAvailableSuperblock (int sizeclass,
00117 block *& b,
00118 processHeap * pHeap);
00119
00120
00121 inline void lock (void);
00122
00123
00124 inline void unlock (void);
00125
00126
00127 inline void setIndex (int i);
00128
00129
00130 inline int getIndex (void);
00131
00132
00133
00134
00135 int freeBlock (block *& b,
00136 superblock *& sb,
00137 int sizeclass,
00138 processHeap * pHeap);
00139
00141
00142
00143 inline static int sizeClass (const size_t sz);
00144
00145
00146 inline static size_t sizeFromClass (const int sizeclass);
00147
00148
00149 inline static int getReleaseThreshold (const int sizeclass);
00150
00151
00152 inline static int numBlocks (const int sizeclass);
00153
00154
00155 inline static size_t align (const size_t sz);
00156
00157 private:
00158
00159
00160
00161 hoardHeap (const hoardHeap&);
00162 const hoardHeap& operator= (const hoardHeap&);
00163
00164
00165 inline void recycle (superblock *);
00166
00167
00168 inline superblock * reuse (int sizeclass);
00169
00170
00171 inline void removeSuperblock (superblock *, int sizeclass);
00172
00173 public:
00174
00175 void moveSuperblock (superblock *,
00176 int sizeclass,
00177 int fromBin,
00178 int toBin);
00179 private:
00180
00181
00182
00183 inline void incStats (int sizeclass, int updateU, int updateA);
00184
00185 public:
00186 inline void incUStats (int sizeclass);
00187 private:
00188
00189 inline void decStats (int sizeclass, int updateU, int updateA);
00190 inline void decUStats (int sizeclass);
00191
00193
00194 #if HEAP_DEBUG
00195
00196 const unsigned long _magic;
00197 #else
00198 #define _magic HEAP_MAGIC
00199 #endif
00200
00201
00202 heapStats _stats[SIZE_CLASSES];
00203
00204
00205 hoardLockType _lock;
00206
00207
00208 int _index;
00209
00210
00211 superblock * _reusableSuperblocks;
00212 int _reusableSuperblocksCount;
00213
00214
00215 superblock * _superblocks[SUPERBLOCK_FULLNESS_GROUP][SIZE_CLASSES];
00216
00217
00218 int _leastEmptyBin[SIZE_CLASSES];
00219
00220
00221 static size_t _sizeTable[SIZE_CLASSES];
00222
00223
00224 static size_t _threshold[SIZE_CLASSES];
00225
00226 public:
00227
00228 class _initNumProcs {
00229 public:
00230 _initNumProcs(void);
00231 };
00232
00233 friend class _initNumProcs;
00234 protected:
00235
00236 static int _numProcessors;
00237 static int _numProcessorsMask;
00238 };
00239
00240
00241
00242 void hoardHeap::incStats (int sizeclass, int updateU, int updateA) {
00243 assert (_magic == HEAP_MAGIC);
00244 assert (updateU >= 0);
00245 assert (updateA >= 0);
00246 assert (sizeclass >= 0);
00247 assert (sizeclass < SIZE_CLASSES);
00248 _stats[sizeclass].incStats (updateU, updateA);
00249 }
00250
00251
00252
00253 void hoardHeap::incUStats (int sizeclass) {
00254 assert (_magic == HEAP_MAGIC);
00255 assert (sizeclass >= 0);
00256 assert (sizeclass < SIZE_CLASSES);
00257 _stats[sizeclass].incUStats ();
00258 }
00259
00260
00261 void hoardHeap::decStats (int sizeclass, int updateU, int updateA) {
00262 assert (_magic == HEAP_MAGIC);
00263 assert (updateU >= 0);
00264 assert (updateA >= 0);
00265 assert (sizeclass >= 0);
00266 assert (sizeclass < SIZE_CLASSES);
00267 _stats[sizeclass].decStats (updateU, updateA);
00268 }
00269
00270
00271 void hoardHeap::decUStats (int sizeclass)
00272 {
00273 assert (_magic == HEAP_MAGIC);
00274 assert (sizeclass >= 0);
00275 assert (sizeclass < SIZE_CLASSES);
00276 _stats[sizeclass].decUStats();
00277 }
00278
00279
00280 void hoardHeap::getStats (int sizeclass, int& U, int& A) {
00281 assert (_magic == HEAP_MAGIC);
00282 assert (sizeclass >= 0);
00283 assert (sizeclass < SIZE_CLASSES);
00284 _stats[sizeclass].getStats (U, A);
00285 }
00286
00287
00288 #if HEAP_STATS
00289 int hoardHeap::maxInUse (int sizeclass) {
00290 assert (_magic == HEAP_MAGIC);
00291 return _stats[sizeclass].getUmax();
00292 }
00293
00294
00295 int hoardHeap::maxAllocated (int sizeclass) {
00296 assert (_magic == HEAP_MAGIC);
00297 return _stats[sizeclass].getAmax();
00298 }
00299 #endif
00300
00301
00302 superblock * hoardHeap::findAvailableSuperblock (int sizeclass,
00303 block *& b,
00304 processHeap * pHeap)
00305 {
00306 assert (this);
00307 assert (_magic == HEAP_MAGIC);
00308 assert (sizeclass >= 0);
00309 assert (sizeclass < SIZE_CLASSES);
00310
00311 superblock * sb = NULL;
00312 int reUsed = 0;
00313
00314
00315
00316
00317
00318
00319
00320 for (int i = _leastEmptyBin[sizeclass]; i >= 0; i--) {
00321 sb = _superblocks[i][sizeclass];
00322 if (sb == NULL) {
00323 if (i == _leastEmptyBin[sizeclass]) {
00324
00325
00326 _leastEmptyBin[sizeclass]--;
00327 }
00328 } else {
00329 assert (sb->getOwner() == this);
00330 break;
00331 }
00332 }
00333
00334 if (sb == NULL) {
00335
00336 sb = reuse (sizeclass);
00337 if (sb) {
00338 assert (sb->getOwner() == this);
00339 reUsed = 1;
00340 }
00341 }
00342
00343 if (sb != NULL) {
00344
00345
00346 assert (sb->isValid());
00347
00348 assert (sb->getOwner() == this);
00349
00350 int oldFullness = sb->getFullness();
00351
00352
00353
00354 b = sb->getBlock();
00355 assert (b != NULL);
00356
00357
00358 incUStats (sizeclass);
00359
00360 if (reUsed) {
00361 insertSuperblock (sizeclass, sb, pHeap);
00362
00363
00364 decStats (sizeclass,
00365 sb->getNumBlocks() - sb->getNumAvailable(),
00366 sb->getNumBlocks());
00367 } else {
00368
00369
00370 int fullness = sb->getFullness();
00371
00372 if (fullness != oldFullness) {
00373
00374 moveSuperblock (sb, sizeclass, oldFullness, fullness);
00375 }
00376 }
00377 }
00378
00379
00380 assert ((sb == NULL) || (b != NULL));
00381
00382 assert ((b == NULL) || (sb != NULL));
00383
00384 return sb;
00385 }
00386
00387
00388 int hoardHeap::sizeClass (const size_t sz) {
00389
00390
00391 int sizeclass = 0;
00392 while (_sizeTable[sizeclass] < sz)
00393 {
00394 sizeclass++;
00395 assert (sizeclass < SIZE_CLASSES);
00396 }
00397 return sizeclass;
00398 }
00399
00400
00401 size_t hoardHeap::sizeFromClass (const int sizeclass) {
00402 assert (sizeclass >= 0);
00403 assert (sizeclass < SIZE_CLASSES);
00404 return _sizeTable[sizeclass];
00405 }
00406
00407
00408 int hoardHeap::getReleaseThreshold (const int sizeclass) {
00409 assert (sizeclass >= 0);
00410 assert (sizeclass < SIZE_CLASSES);
00411 return _threshold[sizeclass];
00412 }
00413
00414
00415 int hoardHeap::numBlocks (const int sizeclass) {
00416 assert (sizeclass >= 0);
00417 assert (sizeclass < SIZE_CLASSES);
00418 const size_t s = sizeFromClass (sizeclass);
00419 assert (s > 0);
00420 const int blksize = align (sizeof(block) + s);
00421
00422 int nb = MAX (1, ((SUPERBLOCK_SIZE - sizeof(superblock)) / blksize));
00423 return nb;
00424 }
00425
00426
00427 void hoardHeap::lock (void)
00428 {
00429 assert (_magic == HEAP_MAGIC);
00430 hoardLock (_lock);
00431 }
00432
00433
00434 void hoardHeap::unlock (void) {
00435 assert (_magic == HEAP_MAGIC);
00436 hoardUnlock (_lock);
00437 }
00438
00439
00440 size_t hoardHeap::align (const size_t sz)
00441 {
00442
00443
00444
00445 return (sz + ALIGNMENT_MASK) & ~((size_t) ALIGNMENT_MASK);
00446 }
00447
00448
00449 void hoardHeap::setIndex (int i)
00450 {
00451 _index = i;
00452 }
00453
00454
00455 int hoardHeap::getIndex (void)
00456 {
00457 return _index;
00458 }
00459
00460
00461
00462
00463 void hoardHeap::recycle (superblock * sb)
00464 {
00465 assert (sb != NULL);
00466 assert (sb->getOwner() == this);
00467 assert (sb->getNumBlocks() > 1);
00468 assert (sb->getNext() == NULL);
00469 assert (sb->getPrev() == NULL);
00470 assert (hoardHeap::numBlocks(sb->getBlockSizeClass()) > 1);
00471 sb->insertBefore (_reusableSuperblocks);
00472 _reusableSuperblocks = sb;
00473 ++_reusableSuperblocksCount;
00474
00475 }
00476
00477
00478 superblock * hoardHeap::reuse (int sizeclass)
00479 {
00480 if (_reusableSuperblocks == NULL) {
00481 return NULL;
00482 }
00483
00484
00485
00486 if (hoardHeap::numBlocks(sizeclass) <= 1) {
00487 return NULL;
00488 }
00489
00490
00491 assert (_reusableSuperblocksCount > 0);
00492 superblock * sb = _reusableSuperblocks;
00493 _reusableSuperblocks = sb->getNext();
00494 sb->remove();
00495 assert (sb->getNumBlocks() > 1);
00496 --_reusableSuperblocksCount;
00497
00498
00499 if (sb->getBlockSizeClass() != sizeclass) {
00500 decStats (sb->getBlockSizeClass(),
00501 sb->getNumBlocks() - sb->getNumAvailable(),
00502 sb->getNumBlocks());
00503
00504
00505 sb->superblock::~superblock();
00506
00507 sb = new ((char *) sb) superblock (numBlocks(sizeclass), sizeclass, this);
00508
00509 incStats (sizeclass,
00510 sb->getNumBlocks() - sb->getNumAvailable(),
00511 sb->getNumBlocks());
00512 }
00513
00514 assert (sb->getOwner() == this);
00515 assert (sb->getBlockSizeClass() == sizeclass);
00516 return sb;
00517 }
00518
00519 #endif // _HEAP_H_