Skip to content

Commit 219d6a1

Browse files
committed
Added granular logging, added const correctness, and clarified variable names
1 parent a2012c0 commit 219d6a1

3 files changed

Lines changed: 320 additions & 265 deletions

File tree

engine/utils/allocators/Tlsf.cpp

Lines changed: 106 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
#define MAX_SL_BUCKETS 16
2828
#define FL(size) 63 - __builtin_clzll(size)
29-
#define SL(size, fl) (size >> fl) & ((1 << MIN_SIZE_INDEX) - 1);
29+
#define SL(size, firstLevel) (size >> firstLevel) & ((1 << MIN_SIZE_INDEX) - 1);
3030
#define FLAG_OFFSET 3
3131
#define INVALID_INDEX(T) std::numeric_limits<T>::max()
3232
#define MIN_ALLOCATION_SIZE 16
@@ -44,9 +44,21 @@ template<typename T>
4444
TlsfAllocator<T>::TlsfAllocator(const T size)
4545
{
4646
T paddedSize = PAD_SIZE(size);
47-
if (size == 0 || size < MIN_ALLOCATION_SIZE || size > (INVALID_INDEX(T) - METADATA_OVERHEAD) ||
48-
paddedSize < size)
47+
48+
if (size == 0 || size < MIN_ALLOCATION_SIZE)
49+
{
50+
CC_LOG_ERROR("CONSTRUCTOR: Size must be greater than or equal to {}", MIN_ALLOCATION_SIZE);
51+
return;
52+
}
53+
54+
if (size > (INVALID_INDEX(T) - METADATA_OVERHEAD) || paddedSize < size)
55+
{
56+
T max_size = INVALID_INDEX(T) - METADATA_OVERHEAD;
57+
CC_LOG_ERROR("CONSTRUCTOR: size: {} is above allowed allocator limit of {}",
58+
size,
59+
max_size);
4960
return;
61+
}
5062

5163
T maxBuckets = (FL(size) - MIN_SIZE_INDEX) + 1;
5264

@@ -68,7 +80,7 @@ TlsfAllocator<T>::TlsfAllocator(const T size)
6880
"Allocation returned null. This should not happen and implies an implementation failure.")
6981

7082
freeList = (FreeBlockNode**) (data + paddedSize);
71-
slBitmasks = (uint16_t*) (data + paddedSize + freeListSize);
83+
secondLevelBitmasks = (uint16_t*) (data + paddedSize + freeListSize);
7284

7385
CreateHeader(data, paddedSize, FREE);
7486

@@ -85,11 +97,11 @@ TlsfAllocator<T>::~TlsfAllocator()
8597
bytesRemaining = 0;
8698
totalSize = 0;
8799

88-
flBitmask = 0;
100+
firstLevelBitmask = 0;
89101

90102
data = nullptr;
91103
freeList = nullptr;
92-
slBitmasks = nullptr;
104+
secondLevelBitmasks = nullptr;
93105
}
94106

95107
template<typename T>
@@ -104,10 +116,40 @@ template<typename T>
104116
void* TlsfAllocator<T>::Allocate(const T& size)
105117
{
106118
T requiredSize = sizeof(BlockHeader) + size + sizeof(BlockFooter);
107-
if (!data || capacity == 0 || size == 0 || requiredSize < size ||
108-
requiredSize > totalBytesRemaining || size < MIN_ALLOCATION_SIZE)
119+
120+
if (!data)
121+
{
122+
CC_LOG_ERROR(
123+
"ALLOCATE: Allocator's buffer is a nullptr. This should not happen and indicates a bug")
124+
return nullptr;
125+
}
126+
127+
if (capacity == 0 | size == 0)
128+
{
129+
CC_LOG_ERROR("ALLOCATE: Cannot allocate memory from an allocator with a capacity of 0")
109130
return nullptr;
131+
}
110132

133+
if (requiredSize < size)
134+
{
135+
CC_LOG_ERROR("ALLOCATE: Requested size is too large and has caused an overflow")
136+
return nullptr;
137+
}
138+
139+
if (requiredSize > totalBytesRemaining)
140+
{
141+
CC_LOG_ERROR("ALLOCATE: Not enough free space available for an allocation of size: {}",
142+
size)
143+
return nullptr;
144+
}
145+
146+
if (size < MIN_ALLOCATION_SIZE)
147+
{
148+
CC_LOG_ERROR(
149+
"ALLOCATE: Requested size is too small. Allocations must not be smaller than {} bytes",
150+
MIN_ALLOCATION_SIZE)
151+
return nullptr;
152+
}
111153
FreeBlockNode* block = FindFreeBlock(requiredSize);
112154

113155
if (!block) return nullptr;
@@ -127,8 +169,16 @@ template<typename T>
127169
void TlsfAllocator<T>::Deallocate(void** ptr)
128170
{
129171
uint8_t* raw = (uint8_t*) *ptr;
130-
if (!raw) return;
131-
if (raw < data || raw >= (data + capacity)) return;
172+
if (!raw)
173+
{
174+
CC_LOG_ERROR("DEALLOCATE: Cannot deallocate nullptr. This may indicate a larger bug")
175+
return;
176+
}
177+
if (raw < data || raw >= (data + capacity))
178+
{
179+
CC_LOG_ERROR("DEALLOCATE: Provided pointer is out of the allocator's pointer range")
180+
return;
181+
}
132182

133183
BlockHeader* header = GetHeader(raw);
134184

@@ -188,8 +238,8 @@ typename TlsfAllocator<T>::BlockHeader* TlsfAllocator<T>::TrySplitBlock(
188238
template<typename T>
189239
void TlsfAllocator<T>::AddNewBlock(const T size, BlockHeader* header)
190240
{
191-
T fl = 0, sl = 0, index;
192-
index = CalculateFreeBlockIndices(size, fl, sl);
241+
T firstLevel = 0, secondLevel = 0, index;
242+
index = CalculateFreeBlockIndices(size, firstLevel, secondLevel);
193243

194244
CreateHeader(TO_BYTES(header), size, FREE);
195245
FreeBlockNode* node = CreateFreeBlock(TO_BYTES(GetFreeBlock(header)), nullptr, freeList[index]);
@@ -198,8 +248,8 @@ void TlsfAllocator<T>::AddNewBlock(const T size, BlockHeader* header)
198248
if (node && node->next) node->next->prev = node;
199249

200250
freeList[index] = node;
201-
flBitmask |= (1ULL << fl);
202-
slBitmasks[fl] |= (1 << sl);
251+
firstLevelBitmask |= (1ULL << firstLevel);
252+
secondLevelBitmasks[firstLevel] |= (1 << secondLevel);
203253
}
204254

205255
template<typename T>
@@ -235,17 +285,17 @@ bool TlsfAllocator<T>::RemoveFreeBlock(TlsfAllocator::FreeBlockNode* node)
235285

236286
T oldSize = GetHeaderSize(header);
237287

238-
T fl, sl, index;
288+
T firstLevel, secondLevel, index;
239289

240-
index = CalculateFreeBlockIndices(oldSize, fl, sl);
290+
index = CalculateFreeBlockIndices(oldSize, firstLevel, secondLevel);
241291

242292
if (!node->prev) freeList[index] = node->next;
243293
else node->prev->next = node->next;
244294

245295
if (node->next) node->next->prev = node->prev;
246296

247-
if (!freeList[index]) slBitmasks[fl] &= ~(1 << sl);
248-
if (!slBitmasks[fl]) flBitmask &= ~(1ULL << fl);
297+
if (!freeList[index]) secondLevelBitmasks[firstLevel] &= ~(1 << secondLevel);
298+
if (!secondLevelBitmasks[firstLevel]) firstLevelBitmask &= ~(1ULL << firstLevel);
249299

250300
node->next = nullptr;
251301
node->prev = nullptr;
@@ -256,44 +306,45 @@ bool TlsfAllocator<T>::RemoveFreeBlock(TlsfAllocator::FreeBlockNode* node)
256306
template<typename T>
257307
typename TlsfAllocator<T>::FreeBlockNode* TlsfAllocator<T>::FindFreeBlock(const T& size)
258308
{
259-
T fl, sl, index;
260-
index = CalculateFreeBlockIndices(size, fl, sl);
309+
T firstLevel, secondLevel, index;
310+
index = CalculateFreeBlockIndices(size, firstLevel, secondLevel);
261311

262-
if (!IsFree(fl, sl)) index = GetNextFreeSlotIndex(fl, sl);
312+
if (!IsFree(firstLevel, secondLevel)) index = GetNextFreeSlotIndex(firstLevel, secondLevel);
263313
if (index == INVALID_INDEX(T)) return nullptr;
264314

265315
return freeList[index];
266316
}
267317

268318
template<typename T>
269-
const T TlsfAllocator<T>::GetNextFreeSlotIndex(T& fl, T& sl)
319+
const T TlsfAllocator<T>::GetNextFreeSlotIndex(T& firstLevel, T& secondLevel)
270320
{
271-
sl = __builtin_ctz(slBitmasks[fl] & ~(((1 << (sl + 1)) - 1)));
321+
secondLevel =
322+
__builtin_ctz(secondLevelBitmasks[firstLevel] & ~(((1 << (secondLevel + 1)) - 1)));
272323

273-
if (sl == 32) sl = 0;
274-
if (sl) return fl * MAX_SL_BUCKETS + sl;
324+
if (secondLevel == 32) secondLevel = 0;
325+
if (secondLevel) return firstLevel * MAX_SL_BUCKETS + secondLevel;
275326

276-
fl = flBitmask & ~(((1ULL << (fl + 1)) - 1));
327+
firstLevel = firstLevelBitmask & ~(((1ULL << (firstLevel + 1)) - 1));
277328

278-
if (!fl) return INVALID_INDEX(T);
329+
if (!firstLevel) return INVALID_INDEX(T);
279330

280-
fl = __builtin_ctzll(fl);
281-
CC_ASSERT(slBitmasks[fl] > 0,
331+
firstLevel = __builtin_ctzll(firstLevel);
332+
CC_ASSERT(secondLevelBitmasks[firstLevel] > 0,
282333
"SlBitmasks is returning 0. This should not be happening and indicates an "
283334
"implementation error.")
284335

285-
sl = __builtin_ctz(slBitmasks[fl]);
336+
secondLevel = __builtin_ctz(secondLevelBitmasks[firstLevel]);
286337

287-
return fl * MAX_SL_BUCKETS + sl;
338+
return firstLevel * MAX_SL_BUCKETS + secondLevel;
288339
}
289340

290341
template<typename T>
291-
T TlsfAllocator<T>::CalculateFreeBlockIndices(T size, OUT T& fl, OUT T& sl)
342+
T TlsfAllocator<T>::CalculateFreeBlockIndices(T size, OUT T& firstLevel, OUT T& secondLevel)
292343
{
293344
T rawFl = FL(size);
294-
fl = rawFl - MIN_SIZE_INDEX;
295-
sl = SL(size, fl);
296-
return fl * MAX_SL_BUCKETS + sl;
345+
firstLevel = rawFl - MIN_SIZE_INDEX;
346+
secondLevel = SL(size, firstLevel);
347+
return firstLevel * MAX_SL_BUCKETS + secondLevel;
297348
}
298349

299350
template<typename T>
@@ -306,7 +357,7 @@ void TlsfAllocator<T>::CreateFooter(uint8_t* ptr, const T size)
306357

307358
template<typename T>
308359
typename TlsfAllocator<T>::BlockHeader* TlsfAllocator<T>::GetHeader(
309-
TlsfAllocator::FreeBlockNode* node)
360+
TlsfAllocator::FreeBlockNode* node) const
310361
{
311362
if (!node) return nullptr;
312363
uint8_t* rawHeader = TO_BYTES(node) - HEADER_SIZE;
@@ -315,7 +366,7 @@ typename TlsfAllocator<T>::BlockHeader* TlsfAllocator<T>::GetHeader(
315366
}
316367

317368
template<typename T>
318-
typename TlsfAllocator<T>::BlockHeader* TlsfAllocator<T>::GetHeader(uint8_t* ptr)
369+
typename TlsfAllocator<T>::BlockHeader* TlsfAllocator<T>::GetHeader(uint8_t* ptr) const
319370
{
320371
if (!ptr) return nullptr;
321372
uint8_t* rawHeader = ptr - HEADER_SIZE;
@@ -325,7 +376,7 @@ typename TlsfAllocator<T>::BlockHeader* TlsfAllocator<T>::GetHeader(uint8_t* ptr
325376

326377
template<typename T>
327378
typename TlsfAllocator<T>::BlockHeader* TlsfAllocator<T>::GetPrevHeader(
328-
TlsfAllocator::BlockHeader* header)
379+
TlsfAllocator::BlockHeader* header) const
329380
{
330381
if (!header) return nullptr;
331382
uint8_t* rawPrevFooter = TO_BYTES(GetPrevFooter(header));
@@ -337,7 +388,7 @@ typename TlsfAllocator<T>::BlockHeader* TlsfAllocator<T>::GetPrevHeader(
337388

338389
template<typename T>
339390
typename TlsfAllocator<T>::BlockHeader* TlsfAllocator<T>::GetNextHeader(
340-
TlsfAllocator::BlockHeader* header)
391+
TlsfAllocator::BlockHeader* header) const
341392
{
342393
if (!header) return nullptr;
343394
uint8_t* rawHeader = TO_BYTES(header);
@@ -361,7 +412,7 @@ typename TlsfAllocator<T>::FreeBlockNode* TlsfAllocator<T>::CreateFreeBlock(
361412
}
362413

363414
template<typename T>
364-
typename TlsfAllocator<T>::FreeBlockNode* TlsfAllocator<T>::GetFreeBlock(BlockHeader* header)
415+
typename TlsfAllocator<T>::FreeBlockNode* TlsfAllocator<T>::GetFreeBlock(BlockHeader* header) const
365416
{
366417
if (!header || !IsFree(header)) return nullptr;
367418
uint8_t* rawBlock = TO_BYTES(header) + HEADER_SIZE;
@@ -370,14 +421,15 @@ typename TlsfAllocator<T>::FreeBlockNode* TlsfAllocator<T>::GetFreeBlock(BlockHe
370421
}
371422

372423
template<typename T>
373-
typename TlsfAllocator<T>::FreeBlockNode* TlsfAllocator<T>::GetFreeBlock(const T fl, const T sl)
424+
typename TlsfAllocator<T>::FreeBlockNode* TlsfAllocator<T>::GetFreeBlock(const T firstLevel,
425+
const T secondLevel) const
374426
{
375-
return freeList[fl * MAX_SL_BUCKETS + sl];
427+
return freeList[firstLevel * MAX_SL_BUCKETS + secondLevel];
376428
}
377429

378430
template<typename T>
379431
typename TlsfAllocator<T>::BlockFooter* TlsfAllocator<T>::GetFooter(
380-
TlsfAllocator::BlockHeader* header)
432+
TlsfAllocator::BlockHeader* header) const
381433
{
382434
if (!header) return nullptr;
383435
T size = GetHeaderSize(header);
@@ -388,7 +440,7 @@ typename TlsfAllocator<T>::BlockFooter* TlsfAllocator<T>::GetFooter(
388440

389441
template<typename T>
390442
typename TlsfAllocator<T>::BlockFooter* TlsfAllocator<T>::GetPrevFooter(
391-
TlsfAllocator::BlockHeader* header)
443+
TlsfAllocator::BlockHeader* header) const
392444
{
393445
if (!header) return nullptr;
394446
uint8_t* rawFooter = TO_BYTES(header) - FOOTER_SIZE;
@@ -397,37 +449,37 @@ typename TlsfAllocator<T>::BlockFooter* TlsfAllocator<T>::GetPrevFooter(
397449
}
398450

399451
template<typename T>
400-
uint8_t* TlsfAllocator<T>::GetBlockData(TlsfAllocator::BlockHeader* header)
452+
uint8_t* TlsfAllocator<T>::GetBlockData(TlsfAllocator::BlockHeader* header) const
401453
{
402454
return TO_BYTES(header) + HEADER_SIZE;
403455
}
404456

405457
template<typename T>
406-
const T TlsfAllocator<T>::GetHeaderSize(BlockHeader* header)
458+
const T TlsfAllocator<T>::GetHeaderSize(BlockHeader* header) const
407459
{
408460
return header->sizeAndFlags >> FLAG_OFFSET;
409461
}
410462

411463
template<typename T>
412-
bool TlsfAllocator<T>::IsFree(BlockHeader* header)
464+
bool TlsfAllocator<T>::IsFree(BlockHeader* header) const
413465
{
414466
return header->sizeAndFlags & FREE;
415467
}
416468

417469
template<typename T>
418-
bool TlsfAllocator<T>::IsFree(T fl, T sl)
470+
bool TlsfAllocator<T>::IsFree(T firstLevel, T secondLevel) const
419471
{
420-
return slBitmasks[fl] & (1 << sl);
472+
return secondLevelBitmasks[firstLevel] & (1 << secondLevel);
421473
}
422474

423475
template<typename T>
424-
bool TlsfAllocator<T>::IsFull()
476+
bool TlsfAllocator<T>::IsFull() const
425477
{
426478
return totalBytesRemaining == 0;
427479
}
428480

429481
template<typename T>
430-
bool TlsfAllocator<T>::PrevBlockIsFree(BlockHeader* header)
482+
bool TlsfAllocator<T>::PrevBlockIsFree(BlockHeader* header) const
431483
{
432484
uint8_t* raw = TO_BYTES(header);
433485
if (raw == data) return false;
@@ -442,19 +494,19 @@ bool TlsfAllocator<T>::PrevBlockIsFree(BlockHeader* header)
442494
}
443495

444496
template<typename T>
445-
bool TlsfAllocator<T>::IsValid(uint8_t* ptr)
497+
bool TlsfAllocator<T>::IsValid(uint8_t* ptr) const
446498
{
447499
return ptr && ptr >= data && ptr < (data + (capacity + HEADER_SIZE + FOOTER_SIZE));
448500
}
449501

450502
template<typename T>
451-
const T TlsfAllocator<T>::Capacity()
503+
const T TlsfAllocator<T>::Capacity() const
452504
{
453505
return capacity;
454506
}
455507

456508
template<typename T>
457-
const T TlsfAllocator<T>::BytesRemaining()
509+
const T TlsfAllocator<T>::BytesRemaining() const
458510
{
459511
return bytesRemaining;
460512
}

0 commit comments

Comments
 (0)