Skip to content

Commit 883e9c0

Browse files
committed
Fix block allocation size consistency for segregated lists
This commit ensures allocated blocks use the size corresponding to their FL/SL bin rather than the original requested size. This allows blocks to be consistently freed and re-allocated to the same memory location. The fix adds mapping_size() to calculate the minimum block size for a given FL/SL bin (inverse of mapping()) and updates block_find_free() to adjust the size parameter accordingly. Close #4
1 parent 5748c64 commit 883e9c0

File tree

1 file changed

+18
-1
lines changed

1 file changed

+18
-1
lines changed

tlsf.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,16 @@ INLINE void mapping(size_t size, uint32_t *fl, uint32_t *sl)
229229
ASSERT(*sl < SL_COUNT, "wrong second level");
230230
}
231231

232+
/* Calculate the minimum block size for a given FL/SL bin */
233+
INLINE size_t mapping_size(uint32_t fl, uint32_t sl)
234+
{
235+
if (fl == 0)
236+
return sl * (BLOCK_SIZE_SMALL / SL_COUNT);
237+
238+
size_t size = (size_t) 1 << (fl + FL_SHIFT - 1);
239+
return size + (sl * (size >> SL_SHIFT));
240+
}
241+
232242
INLINE tlsf_block_t *block_find_suitable(tlsf_t *t, uint32_t *fl, uint32_t *sl)
233243
{
234244
ASSERT(*fl < FL_COUNT, "wrong first level");
@@ -475,6 +485,12 @@ INLINE tlsf_block_t *block_find_free(tlsf_t *t, size_t *size)
475485
block = block_find_suitable(t, &fl, &sl);
476486
ASSERT(block, "no block found");
477487
}
488+
489+
/* Update size to match the FL/SL bin that was actually used.
490+
* This ensures that when the block is freed, it will be placed in the same
491+
* bin it was allocated from.
492+
*/
493+
*size = mapping_size(fl, sl);
478494
ASSERT(block_size(block) >= *size, "insufficient block size");
479495
remove_free_block(t, block, fl, sl);
480496
return block;
@@ -499,7 +515,8 @@ void *tlsf_aalloc(tlsf_t *t, size_t align, size_t size)
499515
!size ||
500516
((align | size) & (align - 1)) /* align!=2**x, size!=n*align */ ||
501517
align > TLSF_MAX_SIZE || sizeof(tlsf_block_t) > TLSF_MAX_SIZE ||
502-
adjust > TLSF_MAX_SIZE - align - sizeof(tlsf_block_t) /* size is too large */))
518+
adjust > TLSF_MAX_SIZE - align -
519+
sizeof(tlsf_block_t) /* size is too large */))
503520
return NULL;
504521

505522
if (align <= ALIGN_SIZE)

0 commit comments

Comments
 (0)