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 "superblock.h"
00025
00026 static const char version[] = "The Hoard memory allocator, version 2.1.0 (http://www.hoard.org). Copyright (C) 1998 - 2001 The University of Texas at Austin. $Id: hoardheap.cpp,v 1.84 2001/12/18 02:42:55 emery Exp $";
00027
00028 size_t hoardHeap::_sizeTable[hoardHeap::SIZE_CLASSES]
00029 = {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};
00030
00031 size_t hoardHeap::_threshold[hoardHeap::SIZE_CLASSES]
00032 = {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};
00033
00034
00035 hoardHeap::hoardHeap (void)
00036 : _index (0),
00037 _reusableSuperblocks (NULL),
00038 _reusableSuperblocksCount (0)
00039 #if HEAP_DEBUG
00040 , _magic (HEAP_MAGIC)
00041 #endif
00042 {
00043
00044 hoardLockInit (_lock);
00045 for (int i = 0; i < SUPERBLOCK_FULLNESS_GROUP; i++) {
00046 for (int j = 0; j < SIZE_CLASSES; j++) {
00047
00048 _superblocks[i][j] = NULL;
00049 }
00050 }
00051 for (int k = 0; k < SIZE_CLASSES; k++) {
00052 _leastEmptyBin[k] = 0;
00053 }
00054 }
00055
00056
00057 void hoardHeap::insertSuperblock (int sizeclass,
00058 superblock * sb,
00059 processHeap * pHeap)
00060 {
00061 assert (sb->isValid());
00062 assert (sb->getBlockSizeClass() == sizeclass);
00063 assert (sb->getPrev() == NULL);
00064 assert (sb->getNext() == NULL);
00065 assert (_magic == HEAP_MAGIC);
00066
00067
00068 sb->setOwner (this);
00069
00070
00071
00072 sb->computeFullness();
00073 int fullness = sb->getFullness();
00074
00075
00076 incStats (sizeclass,
00077 sb->getNumBlocks() - sb->getNumAvailable(),
00078 sb->getNumBlocks());
00079
00080 if ((fullness == 0) &&
00081 (sb->getNumBlocks() > 1) &&
00082 (sb->getNumBlocks() == sb->getNumAvailable())) {
00083
00084
00085 recycle (sb);
00086
00087 } else {
00088
00089
00090 superblock *& head = _superblocks[fullness][sizeclass];
00091 sb->insertBefore (head);
00092 head = sb;
00093 assert (head->isValid());
00094
00095
00096 _leastEmptyBin[sizeclass] = RESET_LEAST_EMPTY_BIN;
00097 }
00098 }
00099
00100
00101 superblock * hoardHeap::removeMaxSuperblock (int sizeclass)
00102 {
00103 assert (_magic == HEAP_MAGIC);
00104
00105 superblock * head = NULL;
00106
00107
00108
00109 head = reuse (sizeclass);
00110 if (head) {
00111
00112
00113 decStats (sizeclass,
00114 0,
00115 head->getNumBlocks());
00116
00117 return head;
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127 int i = 0;
00128
00129
00130
00131 while (i < SUPERBLOCK_FULLNESS_GROUP) {
00132 head = _superblocks[i][sizeclass];
00133 if (head) {
00134 break;
00135 }
00136 i++;
00137 }
00138
00139 if (!head) {
00140 return NULL;
00141 }
00142
00143
00144
00145 assert (head->getNumAvailable() * EMPTY_FRACTION >= head->getNumBlocks());
00146
00147 removeSuperblock (head, sizeclass);
00148
00149 assert (head->isValid());
00150 assert (head->getPrev() == NULL);
00151 assert (head->getNext() == NULL);
00152 return head;
00153 }
00154
00155
00156 void hoardHeap::removeSuperblock (superblock * sb,
00157 int sizeclass)
00158 {
00159 assert (_magic == HEAP_MAGIC);
00160
00161 assert (sb->isValid());
00162 assert (sb->getOwner() == this);
00163 assert (sb->getBlockSizeClass() == sizeclass);
00164
00165 for (int i = 0; i < SUPERBLOCK_FULLNESS_GROUP; i++) {
00166 if (sb == _superblocks[i][sizeclass]) {
00167 _superblocks[i][sizeclass] = sb->getNext();
00168 if (_superblocks[i][sizeclass] != NULL) {
00169 assert (_superblocks[i][sizeclass]->isValid());
00170 }
00171 break;
00172 }
00173 }
00174
00175 sb->remove();
00176 decStats (sizeclass, sb->getNumBlocks() - sb->getNumAvailable(), sb->getNumBlocks());
00177 }
00178
00179
00180 void hoardHeap::moveSuperblock (superblock * sb,
00181 int sizeclass,
00182 int fromBin,
00183 int toBin)
00184 {
00185 assert (_magic == HEAP_MAGIC);
00186 assert (sb->isValid());
00187 assert (sb->getOwner() == this);
00188 assert (sb->getBlockSizeClass() == sizeclass);
00189 assert (sb->getFullness() == toBin);
00190
00191
00192
00193 superblock *& oldHead = _superblocks[fromBin][sizeclass];
00194 if (sb == oldHead) {
00195 oldHead = sb->getNext();
00196 if (oldHead != NULL) {
00197 assert (oldHead->isValid());
00198 }
00199 }
00200
00201 sb->remove();
00202
00203
00204
00205 superblock *& newHead = _superblocks[toBin][sizeclass];
00206 sb->insertBefore (newHead);
00207 newHead = sb;
00208 assert (newHead->isValid());
00209
00210
00211 _leastEmptyBin[sizeclass] = RESET_LEAST_EMPTY_BIN;
00212 }
00213
00214
00215
00216
00217 int hoardHeap::freeBlock (block *& b,
00218 superblock *& sb,
00219 int sizeclass,
00220 processHeap * pHeap)
00221 {
00222 assert (sb->isValid());
00223 assert (b->isValid());
00224 assert (this == sb->getOwner());
00225
00226 const int oldFullness = sb->getFullness();
00227 sb->putBlock (b);
00228 decUStats (sizeclass);
00229 const int newFullness = sb->getFullness();
00230
00231
00232 if (sb->getNumBlocks() == 1) {
00233 removeSuperblock (sb, sizeclass);
00234 #if HEAP_LOG
00235
00236 MemoryRequest m;
00237 m.deallocate ((int) sb->getNumBlocks() * (int) sizeFromClass(sb->getBlockSizeClass()));
00238 pHeap->getLog(getIndex()).append(m);
00239 #endif
00240 #if HEAP_FRAG_STATS
00241 pHeap->setDeallocated (0, sb->getNumBlocks() * sizeFromClass(sb->getBlockSizeClass()));
00242 #endif
00243 sb->superblock::~superblock();
00244 hoardFreeMemory (sb);
00245 return 1;
00246 }
00247
00248
00249 if (newFullness != oldFullness) {
00250 moveSuperblock (sb, sizeclass, oldFullness, newFullness);
00251 } else {
00252
00253
00254 superblock *& head = _superblocks[newFullness][sizeclass];
00255 if (sb != head) {
00256 sb->remove();
00257 sb->insertBefore (head);
00258 head = sb;
00259 }
00260 }
00261
00262
00263
00264
00265 if ((newFullness == 0) &&
00266 (sb->getNumBlocks() == sb->getNumAvailable())) {
00267
00268 removeSuperblock (sb, sizeclass);
00269 if (_numProcessors == 1) {
00270 hoardFreeMemory (sb);
00271 } else {
00272 recycle (sb);
00273
00274
00275 incStats (sizeclass, 0, sb->getNumBlocks());
00276 }
00277 }
00278
00279
00280 if (this == (hoardHeap *) pHeap) {
00281 return 0;
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 if (_numProcessors > 1) {
00297
00298 int inUse, allocated;
00299 getStats (sizeclass, inUse, allocated);
00300 const bool crossedThreshold
00301 = ((inUse < allocated - getReleaseThreshold(sizeclass)) &&
00302 (EMPTY_FRACTION * inUse < EMPTY_FRACTION * allocated - allocated));
00303 if (crossedThreshold) {
00304
00305
00306
00307 superblock * const maxSb = removeMaxSuperblock (sizeclass);
00308 assert (maxSb != NULL);
00309
00310
00311
00312 assert (maxSb->getNumBlocks() >= maxSb->getNumAvailable());
00313
00314
00315 pHeap->release (maxSb);
00316
00317 }
00318 }
00319
00320 return 0;
00321 }
00322
00323
00324
00325 int hoardHeap::_numProcessors;
00326 int hoardHeap::_numProcessorsMask;
00327
00328 hoardHeap::_initNumProcs::_initNumProcs(void)
00329 {
00330 hoardHeap::_numProcessors = hoardGetNumProcessors();
00331 hoardHeap::_numProcessorsMask = (1 << (lg(hoardGetNumProcessors()) + 4)) - 1;
00332 if (hoardHeap::_numProcessors > MAX_HEAPS) {
00333 hoardHeap::_numProcessorsMask = MAX_HEAPS_MASK;
00334 }
00335 }
00336
00337 static hoardHeap::_initNumProcs initProcs;