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>
4444TlsfAllocator<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
95107template <typename T>
@@ -104,10 +116,40 @@ template<typename T>
104116void * 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>
127169void 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(
188238template <typename T>
189239void 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
205255template <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)
256306template <typename T>
257307typename 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
268318template <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
290341template <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
299350template <typename T>
@@ -306,7 +357,7 @@ void TlsfAllocator<T>::CreateFooter(uint8_t* ptr, const T size)
306357
307358template <typename T>
308359typename 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
317368template <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
326377template <typename T>
327378typename 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
338389template <typename T>
339390typename 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
363414template <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
372423template <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
378430template <typename T>
379431typename 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
389441template <typename T>
390442typename 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
399451template <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
405457template <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
411463template <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
417469template <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
423475template <typename T>
424- bool TlsfAllocator<T>::IsFull()
476+ bool TlsfAllocator<T>::IsFull() const
425477{
426478 return totalBytesRemaining == 0 ;
427479}
428480
429481template <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
444496template <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
450502template <typename T>
451- const T TlsfAllocator<T>::Capacity()
503+ const T TlsfAllocator<T>::Capacity() const
452504{
453505 return capacity;
454506}
455507
456508template <typename T>
457- const T TlsfAllocator<T>::BytesRemaining()
509+ const T TlsfAllocator<T>::BytesRemaining() const
458510{
459511 return bytesRemaining;
460512}
0 commit comments