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 size_t hoardHeap::_sizeTable[hoardHeap::SIZE_CLASSES]
00028 = {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};
00029
00030 size_t hoardHeap::_threshold[hoardHeap::SIZE_CLASSES] = {1024UL, 512UL, 341UL, 256UL, 204UL, 170UL, 146UL, 128UL, 113UL, 102UL, 93UL, 85UL, 78UL, 73UL, 68UL, 64UL, 60UL, 56UL, 53UL, 51UL, 48UL, 46UL, 44UL, 42UL, 40UL, 39UL, 37UL, 36UL, 35UL, 34UL, 33UL, 32UL, 31UL, 30UL, 29UL, 28UL, 27UL, 26UL, 26UL, 25UL, 24UL, 24UL, 23UL, 23UL, 22UL, 22UL, 21UL, 21UL, 20UL, 20UL, 20UL, 19UL, 19UL, 18UL, 18UL, 18UL, 17UL, 17UL, 17UL, 17UL, 16UL, 16UL, 16UL, 16UL, 14UL, 12UL, 11UL, 10UL, 9UL, 9UL, 8UL, 8UL, 7UL, 7UL, 6UL, 6UL, 6UL, 5UL, 5UL, 5UL, 5UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 4UL, 3UL, 3UL, 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, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL, 1UL};
00031
00032 hoardHeap::hoardHeap (void)
00033 : _index (0),
00034 _reusableSuperblocks (NULL),
00035 _reusableSuperblocksCount (0)
00036 #if HEAP_DEBUG
00037 , _magic (HEAP_MAGIC)
00038 #endif
00039 {
00040
00041 hoardLockInit (_lock);
00042 for (int i = 0; i < SUPERBLOCK_FULLNESS_GROUP; i++) {
00043 for (int j = 0; j < SIZE_CLASSES; j++) {
00044
00045 _superblocks[i][j] = NULL;
00046 }
00047 }
00048
00049
00050
00051
00052
00053
00054
00055 for (int k = 0; k < SIZE_CLASSES; k++) {
00056
00057 _leastEmptyBin[k] = RESET_LEAST_EMPTY_BIN;
00058 }
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 superblock * hoardHeap::findAvailableSuperblock (int sizeclass,
00070 block *& b,
00071 persistentHeap * persistentheap)
00072 {
00073 assert (this);
00074 assert (_magic == HEAP_MAGIC);
00075 assert (sizeclass >= 0);
00076 assert (sizeclass < SIZE_CLASSES);
00077
00078 superblock * sb = NULL;
00079 int reUsed = 0;
00080
00081
00082
00083
00084
00085
00086 std::cout << "this = " << this << ", _leastEmptyBin[sizeclass] = " << _leastEmptyBin[sizeclass] << std::endl;
00087 for (int i = 7; i >= 0; i--) {
00088 std::cout << "_superblock: " << i << ", " << sizeclass << ", "<< _superblocks[i][sizeclass] << std::endl;
00089 }
00090 for (int i = _leastEmptyBin[sizeclass]; i >= 0; i--) {
00091 sb = _superblocks[i][sizeclass];
00092 if (sb == NULL) {
00093
00094
00095 sb = persistentheap->removePartiallyFullSuperblock(i, sizeclass);
00096 std::cout << "removePartiallyFullSuperblock: " << i << ", " << sizeclass << ", "<< sb << std::endl;
00097 if (sb) {
00098
00099 std::cout << "BEFORE" << std::endl;
00100 std::cout << "this = " << this << ", _leastEmptyBin[sizeclass] = " << _leastEmptyBin[sizeclass] << std::endl;
00101 for (int i = 7; i >= 0; i--) {
00102 std::cout << "_superblock: " << i << ", " << sizeclass << ", "<< _superblocks[i][sizeclass] << std::endl;
00103 }
00104
00105 insertSuperblock (sizeclass, sb, persistentheap);
00106 std::cout << "AFTER" << std::endl;
00107 std::cout << "this = " << this << ", _leastEmptyBin[sizeclass] = " << _leastEmptyBin[sizeclass] << std::endl;
00108 for (int i = 7; i >= 0; i--) {
00109 std::cout << "_superblock: " << i << ", " << sizeclass << ", "<< _superblocks[i][sizeclass] << std::endl;
00110 }
00111
00112 assert (sb->getOwner() == this);
00113 break;
00114 }
00115 if (i == _leastEmptyBin[sizeclass]) {
00116
00117
00118 _leastEmptyBin[sizeclass]--;
00119 }
00120 } else {
00121 assert (sb->getOwner() == this);
00122 break;
00123 }
00124 }
00125
00126 if (sb == NULL) {
00127
00128 sb = reuse (sizeclass);
00129 if (sb) {
00130 assert (sb->getOwner() == this);
00131 reUsed = 1;
00132 }
00133 }
00134
00135 if (sb != NULL) {
00136
00137
00138 assert (sb->isValid());
00139
00140 assert (sb->getOwner() == this);
00141
00142 int oldFullness = sb->getFullness();
00143
00144
00145
00146 b = sb->acquireBlock();
00147 assert (b != NULL);
00148
00149
00150 incUStats (sizeclass);
00151
00152 if (reUsed) {
00153 insertSuperblock (sizeclass, sb, persistentheap);
00154
00155
00156 decStats (sizeclass,
00157 sb->getNumBlocks() - sb->getNumAvailable(),
00158 sb->getNumBlocks());
00159 } else {
00160
00161
00162 int fullness = sb->getFullness();
00163
00164 if (fullness != oldFullness) {
00165
00166 moveSuperblock (sb, sizeclass, oldFullness, fullness);
00167 }
00168 }
00169 }
00170
00171
00172 assert ((sb == NULL) || (b != NULL));
00173
00174 assert ((b == NULL) || (sb != NULL));
00175
00176 return sb;
00177 }
00178
00179
00180
00181 void hoardHeap::insertSuperblock (int sizeclass,
00182 superblock * sb,
00183 persistentHeap *)
00184 {
00185 assert (sb->isValid());
00186 assert (sb->getBlockSizeClass() == sizeclass);
00187 assert (sb->getPrev() == NULL);
00188 assert (sb->getNext() == NULL);
00189 assert (_magic == HEAP_MAGIC);
00190
00191
00192 sb->setOwner (this);
00193
00194
00195
00196 sb->computeFullness();
00197 int fullness = sb->getFullness();
00198
00199
00200 incStats (sizeclass,
00201 sb->getNumBlocks() - sb->getNumAvailable(),
00202 sb->getNumBlocks());
00203
00204 if ((fullness == 0) &&
00205 (sb->getNumBlocks() > 1) &&
00206 (sb->getNumBlocks() == sb->getNumAvailable())) {
00207
00208
00209 recycle (sb);
00210 } else {
00211
00212 superblock *& head = _superblocks[fullness][sizeclass];
00213 sb->insertBefore (head);
00214 head = sb;
00215 assert (head->isValid());
00216
00217
00218 _leastEmptyBin[sizeclass] = RESET_LEAST_EMPTY_BIN;
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 void hoardHeap::insertSuperblock (int sizeclass,
00237 superblock * sb,
00238 processHeap *)
00239 {
00240 assert (sb->isValid());
00241 assert (sb->getBlockSizeClass() == sizeclass);
00242 assert (sb->getPrev() == NULL);
00243 assert (sb->getNext() == NULL);
00244 assert (_magic == HEAP_MAGIC);
00245
00246
00247 sb->setOwner (this);
00248
00249
00250
00251 sb->computeFullness();
00252 int fullness = sb->getFullness();
00253
00254
00255 incStats (sizeclass,
00256 sb->getNumBlocks() - sb->getNumAvailable(),
00257 sb->getNumBlocks());
00258
00259 if ((fullness == 0) &&
00260 (sb->getNumBlocks() > 1) &&
00261 (sb->getNumBlocks() == sb->getNumAvailable())) {
00262
00263
00264 recycle (sb);
00265 } else {
00266
00267 superblock *& head = _superblocks[fullness][sizeclass];
00268 sb->insertBefore (head);
00269 head = sb;
00270 assert (head->isValid());
00271
00272
00273 _leastEmptyBin[sizeclass] = RESET_LEAST_EMPTY_BIN;
00274
00275 }
00276 }
00277
00278
00279 superblock * hoardHeap::removeMaxSuperblock (int sizeclass)
00280 {
00281 assert (_magic == HEAP_MAGIC);
00282
00283 superblock * head = NULL;
00284
00285
00286
00287 head = reuse (sizeclass);
00288 if (head) {
00289
00290
00291 decStats (sizeclass,
00292 0,
00293 head->getNumBlocks());
00294
00295 return head;
00296 }
00297
00298
00299
00300
00301
00302
00303
00304 int i = 0;
00305
00306
00307
00308 while (i < SUPERBLOCK_FULLNESS_GROUP) {
00309 head = _superblocks[i][sizeclass];
00310 if (head) {
00311 break;
00312 }
00313 i++;
00314 }
00315
00316 if (!head) {
00317 return NULL;
00318 }
00319
00320
00321
00322 assert (head->getNumAvailable() * EMPTY_FRACTION >= head->getNumBlocks());
00323
00324 removeSuperblock (head, sizeclass);
00325
00326 assert (head->isValid());
00327 assert (head->getPrev() == NULL);
00328 assert (head->getNext() == NULL);
00329 return head;
00330 }
00331
00332 superblock * hoardHeap::removePartiallyFullSuperblock (int fullness, int sizeclass)
00333 {
00334 assert (_magic == HEAP_MAGIC);
00335
00336 superblock * head = NULL;
00337
00338 head = _superblocks[fullness][sizeclass];
00339
00340 if (!head) {
00341 return NULL;
00342 }
00343
00344
00345
00346 assert (head->getNumAvailable() * EMPTY_FRACTION >= head->getNumBlocks());
00347
00348 removeSuperblock (head, sizeclass);
00349
00350 assert (head->isValid());
00351 assert (head->getPrev() == NULL);
00352 assert (head->getNext() == NULL);
00353 return head;
00354 }
00355
00356
00357 void hoardHeap::removeSuperblock (superblock * sb,
00358 int sizeclass)
00359 {
00360 assert (_magic == HEAP_MAGIC);
00361
00362 assert (sb->isValid());
00363 assert (sb->getOwner() == this);
00364 assert (sb->getBlockSizeClass() == sizeclass);
00365
00366 for (int i = 0; i < SUPERBLOCK_FULLNESS_GROUP; i++) {
00367 if (sb == _superblocks[i][sizeclass]) {
00368 _superblocks[i][sizeclass] = sb->getNext();
00369 if (_superblocks[i][sizeclass] != NULL) {
00370 assert (_superblocks[i][sizeclass]->isValid());
00371 }
00372 break;
00373 }
00374 }
00375
00376 sb->remove();
00377 decStats (sizeclass, sb->getNumBlocks() - sb->getNumAvailable(), sb->getNumBlocks());
00378 }
00379
00380
00381 void hoardHeap::moveSuperblock (superblock * sb,
00382 int sizeclass,
00383 int fromBin,
00384 int toBin)
00385 {
00386 assert (_magic == HEAP_MAGIC);
00387 assert (sb->isValid());
00388 assert (sb->getOwner() == this);
00389 assert (sb->getBlockSizeClass() == sizeclass);
00390 assert (sb->getFullness() == toBin);
00391
00392
00393
00394 superblock *& oldHead = _superblocks[fromBin][sizeclass];
00395 if (sb == oldHead) {
00396 oldHead = sb->getNext();
00397 if (oldHead != NULL) {
00398 assert (oldHead->isValid());
00399 }
00400 }
00401
00402 sb->remove();
00403
00404
00405
00406 superblock *& newHead = _superblocks[toBin][sizeclass];
00407 sb->insertBefore (newHead);
00408 newHead = sb;
00409 assert (newHead->isValid());
00410
00411
00412 _leastEmptyBin[sizeclass] = RESET_LEAST_EMPTY_BIN;
00413 }
00414
00415
00416
00417
00418 int hoardHeap::freeBlock (block *& b,
00419 superblock *& sb,
00420 int sizeclass,
00421 persistentHeap * persistentheap)
00422 {
00423 assert (sb->isValid());
00424 assert (b->isValid());
00425 assert (this == sb->getOwner());
00426
00427 const int oldFullness = sb->getFullness();
00428 sb->putBlock (b);
00429 std::cout << "freeBlock: " << b << " this = " << this
00430 << ", sizeclass = " << sizeclass
00431 << ", size = " << sizeFromClass(sizeclass) << std::endl;
00432
00433 decUStats (sizeclass);
00434 const int newFullness = sb->getFullness();
00435
00436
00437 if (sb->getNumBlocks() == 1) {
00438
00439 assert(0);
00440 removeSuperblock (sb, sizeclass);
00441 #if HEAP_LOG
00442
00443 MemoryRequest m;
00444 m.deallocate ((int) sb->getNumBlocks() * (int) sizeFromClass(sb->getBlockSizeClass()));
00445 persistentheap->getLog(getIndex()).append(m);
00446 #endif
00447 #if HEAP_FRAG_STATS
00448 persistentheap->setDeallocated (0, sb->getNumBlocks() * sizeFromClass(sb->getBlockSizeClass()));
00449 #endif
00450 sb->superblock::~superblock();
00451 hoardFreeMemory (sb);
00452 return 1;
00453 }
00454
00455
00456 if (newFullness != oldFullness) {
00457 moveSuperblock (sb, sizeclass, oldFullness, newFullness);
00458 } else {
00459
00460
00461 superblock *& head = _superblocks[newFullness][sizeclass];
00462 if (sb != head) {
00463 sb->remove();
00464 sb->insertBefore (head);
00465 head = sb;
00466 }
00467 }
00468
00469
00470
00471
00472 if ((newFullness == 0) &&
00473 (sb->getNumBlocks() == sb->getNumAvailable())) {
00474
00475 removeSuperblock (sb, sizeclass);
00476 if (_numProcessors == 1) {
00477 hoardFreeMemory (sb);
00478 } else {
00479 recycle (sb);
00480
00481
00482 incStats (sizeclass, 0, sb->getNumBlocks());
00483 }
00484 }
00485
00486
00487 if (this == (hoardHeap *) persistentheap) {
00488 return 0;
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 if (_numProcessors > 1) {
00508
00509 int inUse, allocated;
00510 getStats (sizeclass, inUse, allocated);
00511 const bool crossedThreshold
00512 = ((inUse < allocated - getReleaseThreshold(sizeclass)) &&
00513 (EMPTY_FRACTION * inUse < EMPTY_FRACTION * allocated - allocated));
00514 if (crossedThreshold) {
00515
00516
00517
00518 superblock * const maxSb = removeMaxSuperblock (sizeclass);
00519 assert (maxSb != NULL);
00520
00521
00522
00523 assert (maxSb->getNumBlocks() >= maxSb->getNumAvailable());
00524
00525
00526 persistentheap->release (maxSb);
00527
00528 }
00529 }
00530
00531 return 0;
00532 }
00533
00534
00535
00536 int hoardHeap::_numProcessors;
00537 int hoardHeap::_numProcessorsMask;
00538
00539 hoardHeap::_initNumProcs::_initNumProcs(void)
00540 {
00541 hoardHeap::_numProcessors = hoardGetNumProcessors();
00542 hoardHeap::_numProcessorsMask = (1 << (lg(hoardGetNumProcessors()) + 4)) - 1;
00543 if (hoardHeap::_numProcessors > MAX_HEAPS) {
00544 hoardHeap::_numProcessorsMask = MAX_HEAPS_MASK;
00545 }
00546 }
00547
00548 static hoardHeap::_initNumProcs initProcs;