Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 705 lines (589 sloc) 16.943 kb
f0d4f47 Initial revision
James McCartney authored
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
b7013ee @danstowell Update address of Free Software Foundation (debian source-checking tools...
danstowell authored
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
f0d4f47 Initial revision
James McCartney authored
19 */
20
21 #include <string.h>
22 #include <stdexcept>
23 #include "SC_AllocPool.h"
24 #include "SC_BoundsMacros.h"
25 #include <assert.h>
59296a9 @timblechmann common: more pathscale compile fixes
timblechmann authored
26 #include <string>
f0d4f47 Initial revision
James McCartney authored
27
d769495 remove trailing whitespaces
Tim Blechmann authored
28 /*
f0d4f47 Initial revision
James McCartney authored
29 Requests are `small' if both the corresponding and the next bin are small
30 */
31
32 #if DEBUG
33 #define check_pool() DoCheckPool()
34 #define check_free_chunk(P) DoCheckFreeChunk(P)
35 #define check_inuse_chunk(P) DoCheckInUseChunk(P)
36 #define check_chunk(P) DoCheckChunk(P)
37 #define check_malloced_chunk(P,N) DoCheckAllocedChunk(P,N)
38 #define garbage_fill(P) DoGarbageFill(P)
39 #else
40 #define check_pool()
d769495 remove trailing whitespaces
Tim Blechmann authored
41 #define check_free_chunk(P)
f0d4f47 Initial revision
James McCartney authored
42 #define check_inuse_chunk(P)
43 #define check_chunk(P)
44 #define check_malloced_chunk(P,N)
45 #define garbage_fill(P)
46 #endif
47
83f43aa @timblechmann win32 compile fixes
timblechmann authored
48 #define aligned_OK(m) ((((size_t)(m)) & kAlignMask) == 0)
f0d4f47 Initial revision
James McCartney authored
49
50 /*
51 void* allocmem(AllocPool *pool, int32 size);
52 void* allocmem(AllocPool *pool, int32 size)
53 {
54 return pool->Alloc(size);
55 }
56
57 void* reallocmem(AllocPool *pool, void* ptr, int32 size);
58 void* reallocmem(AllocPool *pool, void* ptr, int32 size)
59 {
60 return pool->Realloc(ptr, size);
61 }
62
63 void freemem(AllocPool *pool, void* ptr);
64 void freemem(AllocPool *pool, void* ptr)
65 {
66 pool->Free(ptr);
67 }
68 */
69 void AllocPool::InitAlloc()
70 {
71 if (mAreaInitSize == 0) return;
72
73 /* alloc initial area */
74 NewArea(mAreaInitSize);
75 /* get chunk */
76 AllocAreaPtr area = mAreas;
77 AllocChunkPtr chunk = &area->mChunk;
d769495 remove trailing whitespaces
Tim Blechmann authored
78 LinkFree(chunk);
79
f0d4f47 Initial revision
James McCartney authored
80 check_pool();
81 }
82
83 void AllocPool::InitBins()
84 {
85 for (int i=0; i<kNumAllocBins; ++i) {
86 mBins[i].BeEmpty();
87 }
88 for (int i=0; i<4; ++i) {
89 mBinBlocks[i] = 0;
90 }
91 }
92
d769495 remove trailing whitespaces
Tim Blechmann authored
93 AllocPool::AllocPool(NewAreaFunc inAllocArea, FreeAreaFunc inFreeArea,
f0d4f47 Initial revision
James McCartney authored
94 size_t inAreaInitSize, size_t inAreaMoreSize)
d769495 remove trailing whitespaces
Tim Blechmann authored
95 {
f0d4f47 Initial revision
James McCartney authored
96 InitBins();
97 mAreaInitSize = inAreaInitSize;
98 mAreaMoreSize = inAreaMoreSize;
99 mAllocArea = inAllocArea;
100 mFreeArea = inFreeArea;
101 mAreas = 0;
102 check_pool();
d769495 remove trailing whitespaces
Tim Blechmann authored
103
f0d4f47 Initial revision
James McCartney authored
104 InitAlloc();
105 }
106
107 AllocPool::~AllocPool()
108 {
109 FreeAll();
110 }
111
112 void AllocPool::FreeAll()
113 {
114 check_pool();
115 AllocAreaPtr area = mAreas;
116 if (area) {
117 AllocAreaPtr firstArea = area;
118 do {
119 AllocAreaPtr nextarea = area->mNext;
120 (mFreeArea)(area->mUnalignedPointerToThis);
121 area = nextarea;
122 } while (area != firstArea);
123 mAreas = NULL;
124 }
125 InitBins();
126 check_pool();
127 }
128
129 void AllocPool::FreeAllInternal()
130 {
131 check_pool();
132 InitBins();
133
134 AllocAreaPtr area = mAreas;
135 if (area) {
136 AllocAreaPtr firstArea = area;
137 do {
138 AllocAreaPtr nextarea = area->mNext;
139 size_t size = area->mSize;
888c5c9 * [linux] build process split between scsynth/sclang and plugins
Stefan Kersten authored
140 AllocChunkPtr chunk = &area->mChunk;
f0d4f47 Initial revision
James McCartney authored
141 chunk->SetSizeFree(size);
d769495 remove trailing whitespaces
Tim Blechmann authored
142 chunk->SetNeighborsInUse(size);
f0d4f47 Initial revision
James McCartney authored
143 LinkFree(chunk);
144 area = nextarea;
145 } while (area != firstArea);
146 }
147 check_pool();
148 }
149
150 void AllocPool::Reinit()
151 {
152 FreeAll();
153 InitAlloc();
154 }
155
156 void AllocPool::Free(void *inPtr)
d769495 remove trailing whitespaces
Tim Blechmann authored
157 {
2e13dde @timblechmann common: alloc pool - bypass memory pools with preprocessor definition
timblechmann authored
158 #ifdef DISABLE_MEMORY_POOLS
159 free(inPtr);
160 return;
161 #endif
f0d4f47 Initial revision
James McCartney authored
162
163 check_pool();
164 if (inPtr == 0) return; /* free(0) has no effect */
165
166 AllocChunkPtr chunk = MemToChunk(inPtr);
167
168 check_inuse_chunk(chunk);
169 garbage_fill(chunk);
d769495 remove trailing whitespaces
Tim Blechmann authored
170
f0d4f47 Initial revision
James McCartney authored
171 size_t size = chunk->Size();
172
173 if (!chunk->PrevInUse()) /* consolidate backward */
174 {
175 size_t prevSize = chunk->PrevSize();
1301d08 @danstowell SC_AllocPool fix: ChunkAtOffset takes signed long argument, rather than ...
danstowell authored
176 chunk = chunk->ChunkAtOffset(0L-prevSize);
f0d4f47 Initial revision
James McCartney authored
177 size += prevSize;
178 UnlinkFree(chunk);
179 }
180
181 AllocChunkPtr next = chunk->ChunkAtOffset(size);
182 if (!next->InUse()) /* consolidate forward */
183 {
184 size += next->Size();
185 UnlinkFree(next);
186 }
d769495 remove trailing whitespaces
Tim Blechmann authored
187
f0d4f47 Initial revision
James McCartney authored
188 chunk->SetSizeFree(size);
189 if (mAreaMoreSize && chunk->IsArea()) {
190 // whole area is free
191 FreeArea(chunk);
192 } else {
d769495 remove trailing whitespaces
Tim Blechmann authored
193 LinkFree(chunk);
f0d4f47 Initial revision
James McCartney authored
194 }
195 check_pool();
196 }
197
198
199
200 AllocAreaPtr AllocPool::NewArea(size_t inAreaSize)
201 {
202 void *ptr = (AllocAreaPtr)(mAllocArea)(inAreaSize + kAreaOverhead);
888c5c9 * [linux] build process split between scsynth/sclang and plugins
Stefan Kersten authored
203
be196c3 @timblechmann common: compile fixes for sunCC
timblechmann authored
204 if (ptr == NULL)
205 throw std::runtime_error(std::string("Could not allocate new area"));
206
888c5c9 * [linux] build process split between scsynth/sclang and plugins
Stefan Kersten authored
207 // AllocAreaPtr area = (AllocAreaPtr)((unsigned long)ptr & ~kAlignMask);
83f43aa @timblechmann win32 compile fixes
timblechmann authored
208 AllocAreaPtr area = (AllocAreaPtr)(((size_t)ptr + kAlignMask) & ~kAlignMask);
209 assert((area >= ptr) && ((void*)((size_t)area & ~kAlignMask) == area));
888c5c9 * [linux] build process split between scsynth/sclang and plugins
Stefan Kersten authored
210
f0d4f47 Initial revision
James McCartney authored
211 area->mUnalignedPointerToThis = ptr;
888c5c9 * [linux] build process split between scsynth/sclang and plugins
Stefan Kersten authored
212
f0d4f47 Initial revision
James McCartney authored
213 /* link in area */
214 if (mAreas) {
215 area->mNext = mAreas;
216 area->mPrev = mAreas->mPrev;
217 area->mNext->mPrev = area;
218 area->mPrev->mNext = area;
219 } else {
220 area->mNext = area;
221 area->mPrev = area;
222 }
223 mAreas = area;
888c5c9 * [linux] build process split between scsynth/sclang and plugins
Stefan Kersten authored
224
f0d4f47 Initial revision
James McCartney authored
225 /* set area size */
226 area->mSize = inAreaSize;
227 area->mChunk.BeEmpty();
228 area->mChunk.SetNeighborsInUse(inAreaSize);
229 area->mChunk.SetSizeFree(inAreaSize);
d769495 remove trailing whitespaces
Tim Blechmann authored
230
f0d4f47 Initial revision
James McCartney authored
231 return area;
232 }
233
d769495 remove trailing whitespaces
Tim Blechmann authored
234 void AllocPool::FreeArea(AllocChunkPtr chunk)
f0d4f47 Initial revision
James McCartney authored
235 {
236 AllocAreaPtr area = (AllocAreaPtr)((char*)chunk - sizeof(AllocAreaHdr));
237
238 if (area->mNext == area) {
239 mAreas = NULL;
240 } else {
241 /* unlink area */
242 mAreas = area->mPrev->mNext = area->mNext;
243 area->mNext->mPrev = area->mPrev;
244 }
d769495 remove trailing whitespaces
Tim Blechmann authored
245
f0d4f47 Initial revision
James McCartney authored
246 (mFreeArea)(area->mUnalignedPointerToThis);
247 }
248
249
250 size_t AllocPool::TotalFree()
251 {
252 size_t total = 0;
253 for (int i=0; i<kNumAllocBins; ++i) {
254 AllocChunkPtr bin = mBins + i;
255 if (bin->Prev() != bin) {
256 for (AllocChunkPtr candidate = bin->Prev(); candidate != bin; candidate = candidate->Prev()) {
257 total += candidate->Size();
258 }
259 }
260 }
261 return total;
262 }
263
264 size_t AllocPool::LargestFreeChunk()
265 {
266 int word = 0;
267 for (int i=3; i>=0; --i) {
268 if (mBinBlocks[i]) {
269 word = i;
270 break;
271 }
272 }
273 int binBits = (int)mBinBlocks[word];
274 int bitPosition = NUMBITS(binBits) - 1;
275 int index = (word << 5) + bitPosition;
276 AllocChunkPtr bin = mBins + index;
f828f13 @timblechmann printf pointers as pointers to point 64bit pointers correctly
timblechmann authored
277 //postbuf("** %p %p %p %p\n", mBinBlocks[0], mBinBlocks[1], mBinBlocks[2], mBinBlocks[3]);
278 //postbuf("%d %d %d %p %p %p\n", word, bitPosition, index, binBits, bin->Prev(), bin->Next());
d769495 remove trailing whitespaces
Tim Blechmann authored
279
f0d4f47 Initial revision
James McCartney authored
280 AllocChunkPtr candidate;
281 size_t maxsize = 0;
282 for (candidate = bin->Prev(); candidate != bin; candidate = candidate->Prev()) {
283 size_t candidate_size = candidate->Size();
284 maxsize = sc_max(maxsize, candidate_size);
285 //postbuf(" %d %d\n", maxsize, candidate_size);
286 }
d769495 remove trailing whitespaces
Tim Blechmann authored
287
f0d4f47 Initial revision
James McCartney authored
288 /*for (int i=0; i<kNumAllocBins; ++i) {
289 bin = mBins + i;
290 if (bin->Prev() != bin) {
291 postbuf("* %d %d\n", i, bin->Prev()->Size());
292 }
293 }*/
294 return maxsize;
295 }
296
297 void* AllocPool::Alloc(size_t inReqSize)
298 {
2e13dde @timblechmann common: alloc pool - bypass memory pools with preprocessor definition
timblechmann authored
299 #ifdef DISABLE_MEMORY_POOLS
300 return malloc(inReqSize);
301 #endif
302
f0d4f47 Initial revision
James McCartney authored
303 // OK it has a lot of gotos, but these remove a whole lot of common code
304 // that was obfuscating the original version of this function.
305 // So here I am choosing the OnceAndOnlyOnce principle over the caveats on gotos.
306 // The gotos only jump forward and only to the exit paths of the function
307
308 // The old bin block scheme has been replaced by 4 x 32 bit words so that each bin has a bit
309 // and the next bin is found using a count leading zeroes instruction. Much faster.
310 // Also now each bin's flag can be kept accurate. This simplifies the searching code quite a bit.
d769495 remove trailing whitespaces
Tim Blechmann authored
311
f0d4f47 Initial revision
James McCartney authored
312 // Also fwiw, changed 'victim' in the original code to 'candidate'. 'victim' just bothered me.
d769495 remove trailing whitespaces
Tim Blechmann authored
313
f0d4f47 Initial revision
James McCartney authored
314
315 AllocChunkPtr candidate; /* inspected/selected chunk */
316 size_t candidate_size; /* its size */
317 AllocChunkPtr remainder; /* remainder from a split */
318 int32 remainder_size; /* its size */
319 AllocAreaPtr area;
320 size_t areaSize;
d769495 remove trailing whitespaces
Tim Blechmann authored
321
f0d4f47 Initial revision
James McCartney authored
322 size_t size = RequestToSize(inReqSize);
d769495 remove trailing whitespaces
Tim Blechmann authored
323 int index = BinIndex(size);
f0d4f47 Initial revision
James McCartney authored
324 assert(index < 128);
325 AllocChunkPtr bin = mBins + index;
d769495 remove trailing whitespaces
Tim Blechmann authored
326
f0d4f47 Initial revision
James McCartney authored
327 check_pool();
d769495 remove trailing whitespaces
Tim Blechmann authored
328
f0d4f47 Initial revision
James McCartney authored
329 /* Check for exact match in a bin */
330 if (index < kMaxSmallBin) { /* Faster version for small requests */
331 /* No traversal or size check necessary for small bins. */
332 candidate = bin->Prev();
333
334 /* Also scan the next one, since it would have a remainder < kMinAllocSize */
335 if (candidate == bin) candidate = (++bin)->Prev();
336 if (candidate != bin) {
337 candidate_size = candidate->Size();
338 goto found_exact_fit;
339 }
d769495 remove trailing whitespaces
Tim Blechmann authored
340
f0d4f47 Initial revision
James McCartney authored
341 index += 2; /* Set for bin scan below. We've already scanned 2 bins. */
342 } else {
343 for (candidate = bin->Prev(); candidate != bin; candidate = candidate->Prev()) {
344
345 candidate_size = candidate->Size();
346 remainder_size = (int)(candidate_size - size);
347 if (remainder_size >= (int32)kMinAllocSize) { /* too big */
348 --index; /* adjust to rescan below after checking last remainder */
d769495 remove trailing whitespaces
Tim Blechmann authored
349 break;
f0d4f47 Initial revision
James McCartney authored
350 } else if (remainder_size >= 0) { /* exact fit */
351 goto found_exact_fit;
352 }
353 }
354 ++index;
355 }
356
d769495 remove trailing whitespaces
Tim Blechmann authored
357 for(; (index = NextFullBin(index)) >= 0; ++index) {
f0d4f47 Initial revision
James McCartney authored
358 bin = mBins + index;
359
360 /* Find and use first big enough chunk ... */
361 for (candidate = bin->Prev(); candidate != bin; candidate = candidate->Prev()) {
362 candidate_size = candidate->Size();
363 remainder_size = (int)(candidate_size - size);
364 if (remainder_size >= (int32)kMinAllocSize) { /* split */
365 UnlinkFree(candidate);
366 goto found_bigger_fit;
367 } else if (remainder_size >= 0) goto found_exact_fit;
368 }
d769495 remove trailing whitespaces
Tim Blechmann authored
369 }
f0d4f47 Initial revision
James McCartney authored
370 check_pool();
d769495 remove trailing whitespaces
Tim Blechmann authored
371
f0d4f47 Initial revision
James McCartney authored
372 if (mAreaMoreSize == 0) { /* pool has a non-growable area */
373 if (mAreas != NULL /* fixed size area exhausted */
374 || size > mAreaInitSize) /* too big anyway */
375 goto found_nothing;
376 areaSize = mAreaInitSize;
377 goto split_new_area;
378 }
d769495 remove trailing whitespaces
Tim Blechmann authored
379
f0d4f47 Initial revision
James McCartney authored
380 if (size > mAreaMoreSize) {
381 areaSize = size;
382 goto whole_new_area;
383 } else {
384 areaSize = mAreaMoreSize;
385 goto split_new_area;
386 }
d769495 remove trailing whitespaces
Tim Blechmann authored
387
f0d4f47 Initial revision
James McCartney authored
388 // exit paths:
389 found_nothing:
390 //ipostbuf("alloc failed. size: %d\n", inReqSize);
be196c3 @timblechmann common: compile fixes for sunCC
timblechmann authored
391 throw std::runtime_error(std::string("alloc failed, increase server's memory allocation (e.g. via ServerOptions)"));
d769495 remove trailing whitespaces
Tim Blechmann authored
392
f0d4f47 Initial revision
James McCartney authored
393 whole_new_area:
394 //ipostbuf("whole_new_area\n");
395 area = NewArea(areaSize);
396 if (!area) return 0;
d769495 remove trailing whitespaces
Tim Blechmann authored
397 candidate = &area->mChunk;
f0d4f47 Initial revision
James McCartney authored
398 candidate_size = candidate->Size();
399 goto return_chunk;
d769495 remove trailing whitespaces
Tim Blechmann authored
400
f0d4f47 Initial revision
James McCartney authored
401 split_new_area:
402 //ipostbuf("split_new_area\n");
403 area = NewArea(areaSize);
404 if (!area) return 0;
405 candidate = &area->mChunk;
406 candidate_size = candidate->Size();
407 remainder_size = (int)(areaSize - size);
408 // FALL THROUGH
409 found_bigger_fit:
410 //ipostbuf("found_bigger_fit\n");
411 remainder = candidate->ChunkAtOffset(size);
412 remainder->SetSizeFree(remainder_size);
413 candidate_size -= remainder_size;
414 LinkFree(remainder);
415 goto return_chunk;
d769495 remove trailing whitespaces
Tim Blechmann authored
416
f0d4f47 Initial revision
James McCartney authored
417 found_exact_fit:
418 check_pool();
419 UnlinkFree(candidate);
420 // FALL THROUGH
421 return_chunk:
422
423 candidate->SetSizeInUse(candidate_size);
424 check_malloced_chunk(candidate, candidate_size);
425 check_pool();
426 garbage_fill(candidate);
427 return candidate->ToPtr();
428 }
429
430
431 void* AllocPool::Realloc(void* inPtr, size_t inReqSize)
432 {
2e13dde @timblechmann common: alloc pool - bypass memory pools with preprocessor definition
timblechmann authored
433 #ifdef DISABLE_MEMORY_POOLS
434 return realloc(inPtr, inReqSize);
435 #endif
436
437
f0d4f47 Initial revision
James McCartney authored
438 void *outPtr;
439 AllocChunkPtr prev;
440 check_pool();
441 bool docopy = false;
d769495 remove trailing whitespaces
Tim Blechmann authored
442
f0d4f47 Initial revision
James McCartney authored
443 /* realloc of null is supposed to be same as malloc */
444 if (inPtr == 0) return Alloc(inReqSize);
445
446 AllocChunkPtr oldChunk = MemToChunk(inPtr);
447 AllocChunkPtr newChunk = oldChunk;
448 size_t oldsize = oldChunk->Size();
449 size_t newsize = oldsize;
450 size_t size = RequestToSize(inReqSize);
451 size_t nextsize, prevsize;
452 check_inuse_chunk(oldChunk);
453
454 if (oldsize < size) {
455 /* Try expanding forward */
456 AllocChunkPtr next = oldChunk->NextChunk();
457 if (!next->InUse()) {
458 nextsize = next->Size();
459 /* Forward into next chunk */
460 if (nextsize + newsize >= size) {
461 UnlinkFree(next);
462 newsize += nextsize;
463 goto split;
464 }
465 } else {
466 next = 0;
467 nextsize = 0;
468 }
469
470
471 /* Try shifting backwards. */
472 prev = oldChunk->PrevChunk();
473 if (!prev->InUse()) {
474 prevsize = prev->Size();
475
476 /* try forward + backward first to save a later consolidation */
477 if (next != 0) {
478 /* into next chunk */
479 if (nextsize + prevsize + newsize >= size) {
480 newsize += nextsize + prevsize;
481 UnlinkFree(next);
482 goto alloc_prev;
483 }
484 }
485
486 /* backward only */
487 if (prev != 0 && prevsize + newsize >= size) {
488 newsize += prevsize;
489 goto alloc_prev;
490 }
491 }
492
493 /* Must allocate */
494
495 outPtr = Alloc(inReqSize);
496
497 check_pool();
498 if (outPtr == 0) {
499 //ipostbuf("realloc failed. size: %d\n", inReqSize);
be196c3 @timblechmann common: compile fixes for sunCC
timblechmann authored
500 throw std::runtime_error(std::string("realloc failed, increase server's memory allocation (e.g. via ServerOptions)"));
f0d4f47 Initial revision
James McCartney authored
501 }
502
503 /* Otherwise copy, free, and exit */
504 memcpy(outPtr, inPtr, oldsize - sizeof(AllocChunk));
505 Free(inPtr);
506 return outPtr;
507 } else goto split;
508
509 alloc_prev:
510 UnlinkFree(prev);
511 newChunk = prev;
512 docopy = true;
513 // FALL THROUGH
514 split: /* split off extra room in old or expanded chunk */
515 //check_pool();
516 if (newsize - size >= kMinAllocSize) { /* split off remainder */
517 size_t remainder_size = newsize - size;
518 AllocChunkPtr remainder = newChunk->ChunkAtOffset(size);
519 remainder->SetSizeInUse(remainder_size);
520 newChunk->SetSizeInUse(size);
521 Free(remainder->ToPtr()); /* let free() deal with it */
522 } else {
523 newChunk->SetSizeInUse(newsize);
524 }
525 outPtr = newChunk->ToPtr();
526 if (docopy) {
527 memmove(outPtr, inPtr, oldsize - sizeof(AllocChunk));
528 }
529 check_inuse_chunk(newChunk);
530 check_pool();
531 garbage_fill(newChunk);
532 return outPtr;
533 }
534
535 void AllocPool::LinkFree(AllocChunkPtr inChunk)
d769495 remove trailing whitespaces
Tim Blechmann authored
536 {
f0d4f47 Initial revision
James McCartney authored
537 size_t size = inChunk->Size();
497d830 @timblechmann common/sclang: more integer type fixes
timblechmann authored
538 size_t index = BinIndex(size);
d769495 remove trailing whitespaces
Tim Blechmann authored
539
f0d4f47 Initial revision
James McCartney authored
540 AllocChunkPtr bin = mBins + index;
541
542 if (index < kNumSmallBins || bin->IsEmpty()) {
543 inChunk->InsertAfter(bin);
544 MarkBinBlock(index);
545 } else {
546 AllocChunkPtr link = bin->Next();
547 while (link != bin && size < link->Size()) link = link->Next();
548 inChunk->InsertBefore(link);
549 }
550 }
551
552 void AllocPool::DoCheckArea(AllocAreaPtr area)
d769495 remove trailing whitespaces
Tim Blechmann authored
553 {
f0d4f47 Initial revision
James McCartney authored
554 assert(area->mChunk.PrevInUse());
d769495 remove trailing whitespaces
Tim Blechmann authored
555
f0d4f47 Initial revision
James McCartney authored
556 AllocChunkPtr p = &area->mChunk;
557 while (p->mSize != kChunkInUse) {
558 if (p->InUse()) {
559 DoCheckInUseChunk(p);
560 } else {
561 DoCheckFreeChunk(p);
562 }
563 p = p->NextChunk();
564 }
565 }
566
d352b66 compile fixes for AllocPool
Tim Blechmann authored
567 void AllocPool::DoCheckBin(AllocChunkPtr bin, long index)
f0d4f47 Initial revision
James McCartney authored
568 {
569 AllocChunkPtr p = bin->Next();
570
571 while (p != bin) {
572 assert(BinIndex(p->Size()) == index);
573 DoCheckFreeChunk(p);
574 p = p->Next();
575 }
576 }
577
578
579 void AllocPool::DoCheckPool()
580 {
581 AllocAreaPtr area = mAreas;
582 if (area) {
583 do {
584 AllocAreaPtr nextarea = area->mNext;
585 DoCheckArea(area);
586 area = nextarea;
587 } while (area != mAreas);
588 }
589
590 for (int i=0; i<kNumAllocBins; ++i) {
591 AllocChunkPtr b = mBins + i;
592 DoCheckBin(b, i);
593 }
594 }
595
596
597 void AllocPool::DoCheckChunk(AllocChunkPtr p)
60bc341 use #ifndef NDEBUG instead of __attribute__((__unused__)) to suppress un...
Ross Bencina authored
598 {
599 #ifndef NDEBUG
f0d4f47 Initial revision
James McCartney authored
600 size_t size = p->Size();
601 //size_t maxsize = mAreaInitSize > mAreaMoreSize ? mAreaInitSize : mAreaMoreSize;
602 // assert(size < maxsize);
60bc341 use #ifndef NDEBUG instead of __attribute__((__unused__)) to suppress un...
Ross Bencina authored
603
604 AllocChunkPtr next = p->ChunkAtOffset(size);
605 #endif
f0d4f47 Initial revision
James McCartney authored
606 assert(p->mSize == next->mPrevSize);
607 }
608
609
d769495 remove trailing whitespaces
Tim Blechmann authored
610 void AllocPool::DoCheckFreeChunk(AllocChunkPtr p)
611 {
f0d4f47 Initial revision
James McCartney authored
612 size_t size = p->Size();
60bc341 use #ifndef NDEBUG instead of __attribute__((__unused__)) to suppress un...
Ross Bencina authored
613 #ifndef NDEBUG
614 AllocChunkPtr next = p->ChunkAtOffset(size);
615 #endif
f0d4f47 Initial revision
James McCartney authored
616 DoCheckChunk(p);
617
618 /* Check whether it claims to be free ... */
619 assert(!p->InUse());
620
621 /* Unless an end marker, must have OK fields */
622 if (size >= kMinAllocSize)
623 {
624 assert((size & kAlignMask) == 0);
625 assert(aligned_OK(p->ToPtr()));
626 /* ... and is fully consolidated */
627 assert(p->PrevInUse());
628 assert(next->InUse());
d769495 remove trailing whitespaces
Tim Blechmann authored
629
f0d4f47 Initial revision
James McCartney authored
630 /* ... and has minimally sane links */
631 assert(p->Next()->Prev() == p);
632 assert(p->Prev()->Next() == p);
633 }
634 else /* end markers are always of size 0 */
d769495 remove trailing whitespaces
Tim Blechmann authored
635 assert(size == 0);
f0d4f47 Initial revision
James McCartney authored
636 }
637
d769495 remove trailing whitespaces
Tim Blechmann authored
638 void AllocPool::DoCheckInUseChunk(AllocChunkPtr p)
639 {
f0d4f47 Initial revision
James McCartney authored
640 size_t size = p->Size();
641 AllocChunkPtr next = p->NextChunk();
642
643 DoCheckChunk(p);
644
645 /* Check whether it claims to be in use ... */
646 assert(p->InUse());
647
648 /* ... and is surrounded by OK chunks.
649 Since more things can be checked with free chunks than inuse ones,
650 if an inuse chunk borders them and debug is on, it's worth doing them.
651 */
652 if (!p->PrevInUse()) {
653 size_t prevsize = p->PrevSize();
654 if (prevsize > 0) {
655 AllocChunkPtr prv = p->PrevChunk();
656 assert(prv->NextChunk() == p);
657 DoCheckFreeChunk(prv);
658 }
659 }
660 if (!p->ChunkAtOffset(size)->InUse()) {
661 DoCheckFreeChunk(next);
662 }
663 }
664
d769495 remove trailing whitespaces
Tim Blechmann authored
665 void AllocPool::DoCheckAllocedChunk(AllocChunkPtr p, size_t s)
f0d4f47 Initial revision
James McCartney authored
666 {
60bc341 use #ifndef NDEBUG instead of __attribute__((__unused__)) to suppress un...
Ross Bencina authored
667 #ifndef NDEBUG
f0d4f47 Initial revision
James McCartney authored
668 size_t size = p->Size();
60bc341 use #ifndef NDEBUG instead of __attribute__((__unused__)) to suppress un...
Ross Bencina authored
669 long room = size - s;
670 #endif
f0d4f47 Initial revision
James McCartney authored
671
672 DoCheckInUseChunk(p);
673
674 /* Legal size ... */
675 assert(size >= kMinAllocSize);
676 assert((size & kAlignMask) == 0);
677 assert(room >= 0);
678 assert(room < kMinAllocSize);
679
680 /* ... and alignment */
681 assert(aligned_OK(p->ToPtr()));
682
683
684 /* ... and was allocated at front of an available chunk */
d769495 remove trailing whitespaces
Tim Blechmann authored
685 assert(p->PrevInUse()); // huh?? - jmc
f0d4f47 Initial revision
James McCartney authored
686
687 }
688
689 void AllocPool::DoGarbageFill(AllocChunkPtr p)
690 {
691 long size = (p->Size() - sizeof(AllocChunk));
692 DoGarbageFill(p, size);
693 }
694
695 void AllocPool::DoGarbageFill(AllocChunkPtr p, long size)
696 {
697 size /= sizeof(long);
698 long *ptr = (long*)p->ToPtr();
699 for (int i=0; i<size; ++i) {
700 ptr[i] = 0xA3A56955;
701 }
702 }
703
704
Something went wrong with that request. Please try again.