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 persistentHeap;
00045
00046 class hoardHeap {
00047 public:
00048
00049 hoardHeap (void);
00050
00051
00052
00053 enum { EMPTY_FRACTION = SUPERBLOCK_FULLNESS_GROUP - 1 };
00054
00055
00056
00057
00058 enum { RESET_LEAST_EMPTY_BIN = SUPERBLOCK_FULLNESS_GROUP - 2 };
00059
00060
00061
00062
00063 enum { MAX_EMPTY_SUPERBLOCKS = 1 } ;
00064
00065
00066
00067
00068
00069 enum { MAX_HEAPS = 1 };
00070
00071
00072 enum { MAX_HEAPS_MASK = MAX_HEAPS - 1 };
00073
00074
00075
00076
00077
00078 enum { SIZE_CLASSES = 132 };
00079
00080
00081 enum { ALIGNMENT = sizeof(double) };
00082
00083
00084 enum { ALIGNMENT_MASK = ALIGNMENT - 1};
00085
00086
00087 enum { HEAP_MAGIC = 0x0badcafe };
00088
00089
00090 inline void getStats (int sizeclass, int& U, int& A);
00091
00092
00093 #if HEAP_STATS
00094
00095 inline int maxInUse (int sizeclass);
00096
00097
00098 inline int maxAllocated (int sizeclass);
00099 #endif
00100
00101
00102
00103
00104 void insertSuperblock (int sizeclass,
00105 superblock * sb,
00106 persistentHeap * persistentheap);
00107
00108
00109 void insertSuperblock (int sizeclass,
00110 superblock * sb,
00111 processHeap * pHeap);
00112
00113
00114
00115 superblock * removeMaxSuperblock (int sizeclass);
00116
00117
00118 superblock * removePartiallyFullSuperblock (int fullness, int sizeclass);
00119
00120
00121 superblock * findAvailableSuperblock (int sizeclass,
00122 block *& b,
00123 persistentHeap * persistentheap);
00124
00125
00126 inline void lock (void);
00127
00128
00129 inline void unlock (void);
00130
00131
00132 inline void setIndex (int i);
00133
00134
00135 inline int getIndex (void);
00136
00137
00138
00139
00140 int freeBlock (block *& b,
00141 superblock *& sb,
00142 int sizeclass,
00143 persistentHeap * persistentheap);
00144
00146
00147
00148 inline static int sizeClass (const size_t sz);
00149
00150
00151 inline static size_t sizeFromClass (const int sizeclass);
00152
00153
00154 inline static int getReleaseThreshold (const int sizeclass);
00155
00156
00157 inline static int numBlocks (const int sizeclass);
00158
00159
00160 inline static size_t align (const size_t sz);
00161
00162 void printSuperblockList();
00163 private:
00164
00165
00166
00167 hoardHeap (const hoardHeap&);
00168 const hoardHeap& operator= (const hoardHeap&);
00169
00170
00171 inline void recycle (superblock *);
00172
00173
00174 inline superblock * reuse (int sizeclass);
00175
00176
00177 inline void removeSuperblock (superblock *, int sizeclass);
00178
00179 public:
00180
00181 void moveSuperblock (superblock *,
00182 int sizeclass,
00183 int fromBin,
00184 int toBin);
00185 private:
00186
00187
00188
00189 inline void incStats (int sizeclass, int updateU, int updateA);
00190
00191 public:
00192 inline void incUStats (int sizeclass);
00193 private:
00194
00195 inline void decStats (int sizeclass, int updateU, int updateA);
00196 inline void decUStats (int sizeclass);
00197
00199
00200 #if HEAP_DEBUG
00201
00202 const unsigned long _magic;
00203 #else
00204 #define _magic HEAP_MAGIC
00205 #endif
00206
00207
00208 heapStats _stats[SIZE_CLASSES];
00209
00210
00211 hoardLockType _lock;
00212
00213
00214 int _index;
00215
00216
00217 superblock * _reusableSuperblocks;
00218 int _reusableSuperblocksCount;
00219
00220
00221 superblock * _superblocks[SUPERBLOCK_FULLNESS_GROUP][SIZE_CLASSES];
00222
00223
00224 int _leastEmptyBin[SIZE_CLASSES];
00225
00226
00227 static size_t _sizeTable[SIZE_CLASSES];
00228
00229
00230 static size_t _threshold[SIZE_CLASSES];
00231
00232 public:
00233
00234 class _initNumProcs {
00235 public:
00236 _initNumProcs(void);
00237 };
00238
00239 friend class _initNumProcs;
00240 protected:
00241
00242 static int _numProcessors;
00243 static int _numProcessorsMask;
00244 };
00245
00246
00247
00248 void hoardHeap::incStats (int sizeclass, int updateU, int updateA) {
00249 assert (_magic == HEAP_MAGIC);
00250 assert (updateU >= 0);
00251 assert (updateA >= 0);
00252 assert (sizeclass >= 0);
00253 assert (sizeclass < SIZE_CLASSES);
00254 _stats[sizeclass].incStats (updateU, updateA);
00255 }
00256
00257
00258
00259 void hoardHeap::incUStats (int sizeclass) {
00260 assert (_magic == HEAP_MAGIC);
00261 assert (sizeclass >= 0);
00262 assert (sizeclass < SIZE_CLASSES);
00263 _stats[sizeclass].incUStats ();
00264 }
00265
00266
00267 void hoardHeap::decStats (int sizeclass, int updateU, int updateA) {
00268 assert (_magic == HEAP_MAGIC);
00269 assert (updateU >= 0);
00270 assert (updateA >= 0);
00271 assert (sizeclass >= 0);
00272 assert (sizeclass < SIZE_CLASSES);
00273 _stats[sizeclass].decStats (updateU, updateA);
00274 }
00275
00276
00277 void hoardHeap::decUStats (int sizeclass)
00278 {
00279 assert (_magic == HEAP_MAGIC);
00280 assert (sizeclass >= 0);
00281 assert (sizeclass < SIZE_CLASSES);
00282 _stats[sizeclass].decUStats();
00283 }
00284
00285
00286 void hoardHeap::getStats (int sizeclass, int& U, int& A) {
00287 assert (_magic == HEAP_MAGIC);
00288 assert (sizeclass >= 0);
00289 assert (sizeclass < SIZE_CLASSES);
00290 _stats[sizeclass].getStats (U, A);
00291 }
00292
00293
00294 #if HEAP_STATS
00295 int hoardHeap::maxInUse (int sizeclass) {
00296 assert (_magic == HEAP_MAGIC);
00297 return _stats[sizeclass].getUmax();
00298 }
00299
00300
00301 int hoardHeap::maxAllocated (int sizeclass) {
00302 assert (_magic == HEAP_MAGIC);
00303 return _stats[sizeclass].getAmax();
00304 }
00305 #endif
00306
00307
00308 int hoardHeap::sizeClass (const size_t sz) {
00309
00310
00311 int sizeclass = 0;
00312 while (_sizeTable[sizeclass] < sz)
00313 {
00314 sizeclass++;
00315 assert (sizeclass < SIZE_CLASSES);
00316 }
00317 return sizeclass;
00318 }
00319
00320
00321 size_t hoardHeap::sizeFromClass (const int sizeclass) {
00322 assert (sizeclass >= 0);
00323 assert (sizeclass < SIZE_CLASSES);
00324 return _sizeTable[sizeclass];
00325 }
00326
00327
00328 int hoardHeap::getReleaseThreshold (const int sizeclass) {
00329 assert (sizeclass >= 0);
00330 assert (sizeclass < SIZE_CLASSES);
00331 return _threshold[sizeclass];
00332 }
00333
00334
00335 int hoardHeap::numBlocks (const int sizeclass) {
00336 assert (sizeclass >= 0);
00337 assert (sizeclass < SIZE_CLASSES);
00338 const size_t s = sizeFromClass (sizeclass);
00339 assert (s > 0);
00340 const int blksize = align (s);
00341
00342 int nb = MAX (1, ((SUPERBLOCK_SIZE) / blksize));
00343 return nb;
00344 }
00345
00346
00347 void hoardHeap::lock (void)
00348 {
00349 assert (_magic == HEAP_MAGIC);
00350 hoardLock (_lock);
00351 }
00352
00353
00354 void hoardHeap::unlock (void) {
00355 assert (_magic == HEAP_MAGIC);
00356 hoardUnlock (_lock);
00357 }
00358
00359
00360 size_t hoardHeap::align (const size_t sz)
00361 {
00362
00363
00364
00365 return (sz + ALIGNMENT_MASK) & ~((size_t) ALIGNMENT_MASK);
00366 }
00367
00368
00369 void hoardHeap::setIndex (int i)
00370 {
00371 _index = i;
00372 }
00373
00374
00375 int hoardHeap::getIndex (void)
00376 {
00377 return _index;
00378 }
00379
00380
00381
00382
00383 void hoardHeap::recycle (superblock * sb)
00384 {
00385 assert (sb != NULL);
00386 assert (sb->getOwner() == this);
00387 assert (sb->getNumBlocks() > 1);
00388 assert (sb->getNext() == NULL);
00389 assert (sb->getPrev() == NULL);
00390 assert (hoardHeap::numBlocks(sb->getBlockSizeClass()) > 1);
00391 sb->insertBefore (_reusableSuperblocks);
00392 _reusableSuperblocks = sb;
00393 ++_reusableSuperblocksCount;
00394
00395 }
00396
00397
00398 superblock * hoardHeap::reuse (int sizeclass)
00399 {
00400 persistentSuperblock *psb;
00401
00402 if (_reusableSuperblocks == NULL) {
00403 return NULL;
00404 }
00405
00406
00407
00408 if (hoardHeap::numBlocks(sizeclass) <= 1) {
00409 return NULL;
00410 }
00411
00412
00413 assert (_reusableSuperblocksCount > 0);
00414 superblock * sb = _reusableSuperblocks;
00415 _reusableSuperblocks = sb->getNext();
00416 sb->remove();
00417 psb = sb->getPersistentSuperblock();
00418 assert (psb != NULL);
00419 assert (sb->getNumBlocks() > 1);
00420 --_reusableSuperblocksCount;
00421
00422
00423 if (sb->getBlockSizeClass() != sizeclass) {
00424 decStats (sb->getBlockSizeClass(),
00425 sb->getNumBlocks() - sb->getNumAvailable(),
00426 sb->getNumBlocks());
00427
00428
00429 sb->superblock::~superblock();
00430
00431
00432
00433 assert(psb->isFree() == true);
00434 int new_blksize = sizeFromClass(sizeclass);
00435 psb->setBlockSize(new_blksize);
00436 sb = new ((char *) sb) superblock (numBlocks(sizeclass), sizeclass, this, psb);
00437 psb->setSuperblock(sb);
00438
00439 incStats (sizeclass,
00440 sb->getNumBlocks() - sb->getNumAvailable(),
00441 sb->getNumBlocks());
00442 }
00443
00444 assert (sb->getOwner() == this);
00445 assert (sb->getBlockSizeClass() == sizeclass);
00446 return sb;
00447 }
00448
00449 #endif // _HEAP_H_