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