00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00020 #include "config.h"
00021
00022 #include "hoardheap.h"
00023 #include "processheap.h"
00024 #include "persistentheap.h"
00025 #include "superblock.h"
00026
00027
00028
00029
00030
00031
00032 size_t hoardHeap::_sizeTable[hoardHeap::SIZE_CLASSES]
00033 = {8UL, 16UL, 24UL, 32UL, 40UL, 48UL, 56UL, 64UL, 72UL, 80UL, 88UL, 96UL, 104UL, 112UL, 120UL, 128UL, 136UL, 144UL, 152UL, 160UL, 168UL, 176UL, 184UL, 192UL, 200UL, 208UL, 216UL, 224UL, 232UL, 240UL, 248UL, 256UL, 264UL, 272UL, 280UL, 288UL, 296UL, 304UL, 312UL, 320UL, 328UL, 336UL, 344UL, 352UL, 360UL, 368UL, 376UL, 384UL, 392UL, 400UL, 408UL, 416UL, 424UL, 432UL, 440UL, 448UL, 456UL, 464UL, 472UL, 480UL, 488UL, 496UL, 504UL, 512UL, 576UL, 640UL, 704UL, 768UL, 832UL, 896UL, 960UL, 1024UL, 1088UL, 1152UL, 1216UL, 1280UL, 1344UL, 1408UL, 1472UL, 1536UL, 1600UL, 1664UL, 1728UL, 1792UL, 1856UL, 1920UL, 1984UL, 2048UL, 2112UL, 2560UL, 3072UL, 3584UL, 4096UL, 4608UL, 5120UL, 5632UL, 6144UL, 6656UL, 7168UL, 7680UL, 8192UL, 8704UL, 9216UL, 9728UL, 10240UL, 10752UL, 12288UL, 16384UL, 20480UL, 24576UL, 28672UL, 32768UL, 36864UL, 40960UL, 65536UL, 98304UL, 131072UL, 163840UL, 262144UL, 524288UL, 1048576UL, 2097152UL, 4194304UL, 8388608UL, 16777216UL, 33554432UL, 67108864UL, 134217728UL, 268435456UL, 536870912UL, 1073741824UL, 2147483648UL};
00034
00035 size_t hoardHeap::_threshold[hoardHeap::SIZE_CLASSES]
00036 = {2048UL, 1024UL, 682UL, 512UL, 409UL, 341UL, 292UL, 256UL, 227UL, 204UL, 186UL, 170UL, 157UL, 146UL, 136UL, 128UL, 120UL, 113UL, 107UL, 102UL, 97UL, 93UL, 89UL, 85UL, 81UL, 78UL, 75UL, 73UL, 70UL, 68UL, 66UL, 64UL, 62UL, 60UL, 58UL, 56UL, 55UL, 53UL, 52UL, 51UL, 49UL, 48UL, 47UL, 46UL, 45UL, 44UL, 43UL, 42UL, 41UL, 40UL, 40UL, 39UL, 38UL, 37UL, 37UL, 36UL, 35UL, 35UL, 34UL, 34UL, 33UL, 33UL, 32UL, 32UL, 28UL, 25UL, 23UL, 21UL, 19UL, 18UL, 17UL, 16UL, 15UL, 14UL, 13UL, 12UL, 12UL, 11UL, 11UL, 10UL, 10UL, 9UL, 9UL, 9UL, 8UL, 8UL, 8UL, 8UL, 7UL, 6UL, 5UL, 4UL, 4UL, 3UL, 3UL, 2UL, 2UL, 2UL, 2UL, 2UL, 2UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL};
00037
00038
00039 hoardHeap::hoardHeap (void)
00040 : _index (0),
00041 _reusableSuperblocks (NULL),
00042 _reusableSuperblocksCount (0)
00043 #if HEAP_DEBUG
00044 , _magic (HEAP_MAGIC)
00045 #endif
00046 {
00047
00048 hoardLockInit (_lock);
00049 for (int i = 0; i < SUPERBLOCK_FULLNESS_GROUP; i++) {
00050 for (int j = 0; j < SIZE_CLASSES; j++) {
00051
00052 _superblocks[i][j] = NULL;
00053 }
00054 }
00055
00056
00057
00058
00059
00060
00061
00062 for (int k = 0; k < SIZE_CLASSES; k++) {
00063
00064 _leastEmptyBin[k] = RESET_LEAST_EMPTY_BIN;
00065 }
00066 }
00067
00068
00069
00070
00071
00072
00073
00074 superblock * hoardHeap::findAvailableSuperblock (int sizeclass,
00075 block *& b,
00076 persistentHeap * persistentheap)
00077 {
00078 assert (this);
00079 assert (_magic == HEAP_MAGIC);
00080 assert (sizeclass >= 0);
00081 assert (sizeclass < SIZE_CLASSES);
00082
00083 superblock * sb = NULL;
00084 int reUsed = 0;
00085
00086
00087
00088
00089
00090
00091 for (int i = _leastEmptyBin[sizeclass]; i >= 0; i--) {
00092 sb = _superblocks[i][sizeclass];
00093 if (sb == NULL) {
00094
00095
00096 sb = persistentheap->removePartiallyFullSuperblock(i, sizeclass);
00097 if (sb) {
00098
00099
00100 insertSuperblock (sizeclass, sb, persistentheap);
00101
00102 assert (sb->getOwner() == this);
00103 break;
00104 }
00105 if (i == _leastEmptyBin[sizeclass]) {
00106
00107
00108 _leastEmptyBin[sizeclass]--;
00109 }
00110 } else {
00111 assert (sb->getOwner() == this);
00112 break;
00113 }
00114 }
00115
00116 if (sb == NULL) {
00117
00118 sb = reuse (sizeclass);
00119 if (sb) {
00120 assert (sb->getOwner() == this);
00121 reUsed = 1;
00122 }
00123 }
00124
00125 if (sb != NULL) {
00126
00127
00128 assert (sb->isValid());
00129
00130 assert (sb->getOwner() == this);
00131
00132 int oldFullness = sb->getFullness();
00133
00134
00135
00136 b = sb->acquireBlock();
00137 assert (b != NULL);
00138
00139
00140 incUStats (sizeclass);
00141
00142 if (reUsed) {
00143 insertSuperblock (sizeclass, sb, persistentheap);
00144
00145
00146 decStats (sizeclass,
00147 sb->getNumBlocks() - sb->getNumAvailable(),
00148 sb->getNumBlocks());
00149 } else {
00150
00151
00152 int fullness = sb->getFullness();
00153
00154 if (fullness != oldFullness) {
00155
00156 moveSuperblock (sb, sizeclass, oldFullness, fullness);
00157 }
00158 }
00159 }
00160
00161
00162 assert ((sb == NULL) || (b != NULL));
00163
00164 assert ((b == NULL) || (sb != NULL));
00165
00166 return sb;
00167 }
00168
00169
00170
00171 void hoardHeap::insertSuperblock (int sizeclass,
00172 superblock * sb,
00173 persistentHeap *)
00174 {
00175 assert (sb->isValid());
00176 assert (sb->getBlockSizeClass() == sizeclass);
00177 assert (sb->getPrev() == NULL);
00178 assert (sb->getNext() == NULL);
00179 assert (_magic == HEAP_MAGIC);
00180
00181
00182 sb->setOwner (this);
00183
00184
00185
00186 sb->computeFullness();
00187 int fullness = sb->getFullness();
00188
00189
00190 incStats (sizeclass,
00191 sb->getNumBlocks() - sb->getNumAvailable(),
00192 sb->getNumBlocks());
00193
00194 #if 0
00195 printf("hoardHeap::insertSuperBlock sb: %p\n", sb);
00196 printf("\tfullness: %d\n", fullness);
00197 printf("\tsizeclass: %d\n", sizeclass);
00198 printf("\tnumAvailable: %d\n", sb->getNumAvailable());
00199 printf("\tnumBlocks: %d\n", sb->getNumBlocks());
00200 #endif
00201
00202 if ((fullness == 0) &&
00203 (sb->getNumBlocks() > 1) &&
00204 (sb->getNumBlocks() == sb->getNumAvailable()))
00205 {
00206
00207
00208 recycle (sb);
00209 } else {
00210
00211 superblock *& head = _superblocks[fullness][sizeclass];
00212 sb->insertBefore (head);
00213 head = sb;
00214 assert (head->isValid());
00215
00216
00217 _leastEmptyBin[sizeclass] = RESET_LEAST_EMPTY_BIN;
00218 }
00219 }
00220
00221
00222 void hoardHeap::printSuperblockList()
00223 {
00224 superblock *sb = NULL;
00225
00226 std::cout << "printSuperblockList" << std::endl;
00227 for (int i = 0; i < 9; i--) {
00228 sb = _superblocks[i][12];
00229 if (sb) {
00230 std::cout << "sb: " << sb << std::endl;
00231 std::cout << " ->psb: " << sb->getPersistentSuperblock() << std::endl;
00232 }
00233 }
00234 }
00235
00236
00237 superblock * hoardHeap::removeMaxSuperblock (int sizeclass)
00238 {
00239 assert (_magic == HEAP_MAGIC);
00240
00241 superblock * head = NULL;
00242
00243
00244 head = reuse (sizeclass);
00245
00246 if (head) {
00247
00248
00249 decStats (sizeclass,
00250 0,
00251 head->getNumBlocks());
00252
00253 return head;
00254 }
00255
00256
00257
00258
00259
00260
00261
00262 int i = 0;
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 while (i < (SUPERBLOCK_FULLNESS_GROUP - 1)) {
00273 head = _superblocks[i][sizeclass];
00274 if (head) {
00275 break;
00276 }
00277 i++;
00278 }
00279
00280 if (!head) {
00281 return NULL;
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 removeSuperblock (head, sizeclass);
00293
00294 assert (head->isValid());
00295 assert (head->getPrev() == NULL);
00296 assert (head->getNext() == NULL);
00297
00298 return head;
00299 }
00300
00301 superblock * hoardHeap::removePartiallyFullSuperblock (int fullness, int sizeclass)
00302 {
00303 assert (_magic == HEAP_MAGIC);
00304
00305 superblock * head = NULL;
00306
00307 head = _superblocks[fullness][sizeclass];
00308
00309 if (!head) {
00310 return NULL;
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321 removeSuperblock (head, sizeclass);
00322
00323 assert (head->isValid());
00324 assert (head->getPrev() == NULL);
00325 assert (head->getNext() == NULL);
00326 return head;
00327 }
00328
00329
00330 void hoardHeap::removeSuperblock (superblock * sb,
00331 int sizeclass)
00332 {
00333 assert (_magic == HEAP_MAGIC);
00334
00335 assert (sb->isValid());
00336 assert (sb->getOwner() == this);
00337 assert (sb->getBlockSizeClass() == sizeclass);
00338
00339 for (int i = 0; i < SUPERBLOCK_FULLNESS_GROUP; i++) {
00340 if (sb == _superblocks[i][sizeclass]) {
00341 _superblocks[i][sizeclass] = sb->getNext();
00342 if (_superblocks[i][sizeclass] != NULL) {
00343 assert (_superblocks[i][sizeclass]->isValid());
00344 }
00345 break;
00346 }
00347 }
00348
00349 sb->remove();
00350 decStats (sizeclass, sb->getNumBlocks() - sb->getNumAvailable(), sb->getNumBlocks());
00351 }
00352
00353
00354 void hoardHeap::moveSuperblock (superblock * sb,
00355 int sizeclass,
00356 int fromBin,
00357 int toBin)
00358 {
00359 assert (_magic == HEAP_MAGIC);
00360 assert (sb->isValid());
00361 assert (sb->getOwner() == this);
00362 assert (sb->getBlockSizeClass() == sizeclass);
00363 assert (sb->getFullness() == toBin);
00364
00365
00366
00367 superblock *& oldHead = _superblocks[fromBin][sizeclass];
00368 if (sb == oldHead) {
00369 oldHead = sb->getNext();
00370 if (oldHead != NULL) {
00371 assert (oldHead->isValid());
00372 }
00373 }
00374
00375 sb->remove();
00376
00377
00378
00379 superblock *& newHead = _superblocks[toBin][sizeclass];
00380 sb->insertBefore (newHead);
00381 newHead = sb;
00382 assert (newHead->isValid());
00383
00384
00385 _leastEmptyBin[sizeclass] = RESET_LEAST_EMPTY_BIN;
00386 }
00387
00388
00389
00390
00391 int hoardHeap::freeBlock (block *& b,
00392 superblock *& sb,
00393 int sizeclass,
00394 persistentHeap * persistentheap)
00395 {
00396 assert (sb->isValid());
00397 assert (b->isValid());
00398 assert (this == sb->getOwner());
00399
00400 const int oldFullness = sb->getFullness();
00401 sb->putBlock (b);
00402 #if 0 // DEBUGPRINT
00403 std::cout << "hoardheap::freeBlock hoardheap(this) = " << this
00404 << "sb = " << sb
00405 << ", b = " << b
00406 << ", sizeclass = " << sizeclass
00407 << ", size = " << sizeFromClass(sizeclass) << std::endl;
00408 #endif
00409 decUStats (sizeclass);
00410 const int newFullness = sb->getFullness();
00411
00412
00413 if (sb->getNumBlocks() == 1) {
00414
00415 assert (0);
00416 removeSuperblock (sb, sizeclass);
00417 #if HEAP_LOG
00418
00419 MemoryRequest m;
00420 m.deallocate ((int) sb->getNumBlocks() * (int) sizeFromClass(sb->getBlockSizeClass()));
00421 persistentheap->getLog(getIndex()).append(m);
00422 #endif
00423 #if HEAP_FRAG_STATS
00424 persistentheap->setDeallocated (0, sb->getNumBlocks() * sizeFromClass(sb->getBlockSizeClass()));
00425 #endif
00426 sb->superblock::~superblock();
00427 hoardFreeMemory (sb);
00428 return 1;
00429 }
00430
00431
00432 if (newFullness != oldFullness) {
00433 moveSuperblock (sb, sizeclass, oldFullness, newFullness);
00434 } else {
00435
00436 superblock *& head = _superblocks[newFullness][sizeclass];
00437 if (sb != head) {
00438 sb->remove();
00439 sb->insertBefore (head);
00440 head = sb;
00441 }
00442 }
00443
00444
00445
00446 if ((newFullness == 0) &&
00447 (sb->getNumBlocks() == sb->getNumAvailable()))
00448 {
00449 removeSuperblock (sb, sizeclass);
00450 if (_numProcessors == 1) {
00451 assert(0);
00452 hoardFreeMemory (sb);
00453 } else {
00454 recycle (sb);
00455
00456
00457 incStats (sizeclass, 0, sb->getNumBlocks());
00458 }
00459 }
00460
00461
00462 if (this == (hoardHeap *) persistentheap) {
00463 return 0;
00464 }
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 if (_numProcessors > 1) {
00482 int inUse, allocated;
00483 getStats (sizeclass, inUse, allocated);
00484 const bool crossedThreshold
00485 = ((inUse < allocated - getReleaseThreshold(sizeclass)) &&
00486 (EMPTY_FRACTION * inUse < EMPTY_FRACTION * allocated - allocated));
00487 if (crossedThreshold) {
00488
00489
00490 superblock * const maxSb = removeMaxSuperblock (sizeclass);
00491 assert (maxSb != NULL);
00492
00493
00494
00495 assert (maxSb->getNumBlocks() >= maxSb->getNumAvailable());
00496
00497
00498 persistentheap->release (maxSb);
00499 }
00500 }
00501
00502 return 0;
00503 }
00504
00505
00506
00507 int hoardHeap::_numProcessors;
00508 int hoardHeap::_numProcessorsMask;
00509
00510 hoardHeap::_initNumProcs::_initNumProcs(void)
00511 {
00512 hoardHeap::_numProcessors = hoardGetNumProcessors();
00513 hoardHeap::_numProcessorsMask = (1 << (lg(hoardGetNumProcessors()) + 4)) - 1;
00514 if (hoardHeap::_numProcessors > MAX_HEAPS) {
00515 hoardHeap::_numProcessorsMask = MAX_HEAPS_MASK;
00516 }
00517 }
00518
00519 static hoardHeap::_initNumProcs initProcs;