tlsf_control_functions.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. /*
  2. * SPDX-FileCopyrightText: 2024 Matthew Conte
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #pragma once
  7. #include "tlsf_block_functions.h"
  8. #if defined(__cplusplus)
  9. extern "C" {
  10. #define tlsf_decl static inline
  11. #else
  12. #define tlsf_decl rt_always_inline
  13. #endif
  14. enum tlsf_config
  15. {
  16. /* All allocation sizes and addresses are aligned to 4 bytes. */
  17. ALIGN_SIZE_LOG2 = 2,
  18. ALIGN_SIZE = (1 << ALIGN_SIZE_LOG2),
  19. };
  20. typedef struct
  21. {
  22. int32_t total;
  23. int32_t used;
  24. int32_t max_used;
  25. } mem_record_t;
  26. /* The TLSF control structure. */
  27. typedef struct control_t
  28. {
  29. /* Empty lists point at this block to indicate they are free. */
  30. block_header_t block_null;
  31. /* Local parameter for the pool. Given the maximum
  32. * value of each field, all the following parameters
  33. * can fit on 4 bytes when using bitfields
  34. */
  35. unsigned int fl_index_count: 5; // 5 cumulated bits
  36. unsigned int fl_index_shift: 3; // 8 cumulated bits
  37. unsigned int fl_index_max: 6; // 14 cumulated bits
  38. unsigned int sl_index_count: 6; // 20 cumulated bits
  39. /* log2 of number of linear subdivisions of block sizes. Larger
  40. ** values require more memory in the control structure. Values of
  41. ** 4 or 5 are typical.
  42. */
  43. unsigned int sl_index_count_log2: 3; // 23 cumulated bits
  44. unsigned int small_block_size: 8; // 31 cumulated bits
  45. /* size of the metadata ( size of control block,
  46. * sl_bitmap and blocks )
  47. */
  48. size_t size;
  49. /* Bitmaps for free lists. */
  50. unsigned int fl_bitmap;
  51. unsigned int *sl_bitmap;
  52. /* Head of free lists. */
  53. block_header_t **blocks;
  54. mem_record_t mem_rec;
  55. } control_t;
  56. /*
  57. ** Architecture-specific bit manipulation routines.
  58. **
  59. ** TLSF achieves O(1) cost for malloc and free operations by limiting
  60. ** the search for a free block to a free list of guaranteed size
  61. ** adequate to fulfill the request, combined with efficient free list
  62. ** queries using bitmasks and architecture-specific bit-manipulation
  63. ** routines.
  64. **
  65. ** Most modern processors provide instructions to count leading zeroes
  66. ** in a word, find the lowest and highest set bit, etc. These
  67. ** specific implementations will be used when available, falling back
  68. ** to a reasonably efficient generic implementation.
  69. **
  70. ** NOTE: TLSF spec relies on ffs/fls returning value 0..31.
  71. ** ffs/fls return 1-32 by default, returning 0 for error.
  72. */
  73. /*
  74. ** Detect whether or not we are building for a 32- or 64-bit (LP/LLP)
  75. ** architecture. There is no reliable portable method at compile-time.
  76. */
  77. #if defined(__alpha__) || defined(__ia64__) || defined(__x86_64__) || defined(_WIN64) || defined(__LP64__) || defined(__LLP64__)
  78. #define TLSF_64BIT
  79. #endif
  80. /*
  81. ** gcc 3.4 and above have builtin support, specialized for architecture.
  82. ** Some compilers masquerade as gcc; patchlevel test filters them out.
  83. */
  84. #if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && defined(__GNUC_PATCHLEVEL__)
  85. #if defined(__SNC__)
  86. /* SNC for Playstation 3. */
  87. tlsf_decl int tlsf_ffs(unsigned int word)
  88. {
  89. const unsigned int reverse = word & (~word + 1);
  90. const int bit = 32 - __builtin_clz(reverse);
  91. return bit - 1;
  92. }
  93. #else
  94. tlsf_decl int tlsf_ffs(unsigned int word) { return __builtin_ffs(word) - 1; }
  95. #endif
  96. tlsf_decl int tlsf_fls(unsigned int word)
  97. {
  98. const int bit = word ? 32 - __builtin_clz(word) : 0;
  99. return bit - 1;
  100. }
  101. #elif defined(_MSC_VER) && (_MSC_VER >= 1400) && (defined(_M_IX86) || defined(_M_X64))
  102. /* Microsoft Visual C++ support on x86/X64 architectures. */
  103. #include <intrin.h>
  104. #pragma intrinsic(_BitScanReverse)
  105. #pragma intrinsic(_BitScanForward)
  106. tlsf_decl int tlsf_fls(unsigned int word)
  107. {
  108. unsigned long index;
  109. return _BitScanReverse(&index, word) ? index : -1;
  110. }
  111. tlsf_decl int tlsf_ffs(unsigned int word)
  112. {
  113. unsigned long index;
  114. return _BitScanForward(&index, word) ? index : -1;
  115. }
  116. #elif defined(_MSC_VER) && defined(_M_PPC)
  117. /* Microsoft Visual C++ support on PowerPC architectures. */
  118. #include <ppcintrinsics.h>
  119. tlsf_decl int tlsf_fls(unsigned int word)
  120. {
  121. const int bit = 32 - _CountLeadingZeros(word);
  122. return bit - 1;
  123. }
  124. tlsf_decl int tlsf_ffs(unsigned int word)
  125. {
  126. const unsigned int reverse = word & (~word + 1);
  127. const int bit = 32 - _CountLeadingZeros(reverse);
  128. return bit - 1;
  129. }
  130. #elif defined(__ARMCC_VERSION)
  131. /* RealView Compilation Tools for ARM */
  132. tlsf_decl int tlsf_ffs(unsigned int word)
  133. {
  134. const unsigned int reverse = word & (~word + 1);
  135. const int bit = 32 - __clz(reverse);
  136. return bit - 1;
  137. }
  138. tlsf_decl int tlsf_fls(unsigned int word)
  139. {
  140. const int bit = word ? 32 - __clz(word) : 0;
  141. return bit - 1;
  142. }
  143. #elif defined(__ghs__)
  144. /* Green Hills support for PowerPC */
  145. #include <ppc_ghs.h>
  146. tlsf_decl int tlsf_ffs(unsigned int word)
  147. {
  148. const unsigned int reverse = word & (~word + 1);
  149. const int bit = 32 - __CLZ32(reverse);
  150. return bit - 1;
  151. }
  152. tlsf_decl int tlsf_fls(unsigned int word)
  153. {
  154. const int bit = word ? 32 - __CLZ32(word) : 0;
  155. return bit - 1;
  156. }
  157. #else
  158. /* Fall back to generic implementation. */
  159. tlsf_decl int tlsf_fls_generic(unsigned int word)
  160. {
  161. int bit = 32;
  162. if (!word) { bit -= 1; }
  163. if (!(word & 0xffff0000))
  164. {
  165. word <<= 16;
  166. bit -= 16;
  167. }
  168. if (!(word & 0xff000000))
  169. {
  170. word <<= 8;
  171. bit -= 8;
  172. }
  173. if (!(word & 0xf0000000))
  174. {
  175. word <<= 4;
  176. bit -= 4;
  177. }
  178. if (!(word & 0xc0000000))
  179. {
  180. word <<= 2;
  181. bit -= 2;
  182. }
  183. if (!(word & 0x80000000))
  184. {
  185. word <<= 1;
  186. bit -= 1;
  187. }
  188. return bit;
  189. }
  190. /* Implement ffs in terms of fls. */
  191. tlsf_decl int tlsf_ffs(unsigned int word) { return tlsf_fls_generic(word & (~word + 1)) - 1; }
  192. tlsf_decl int tlsf_fls(unsigned int word) { return tlsf_fls_generic(word) - 1; }
  193. #endif
  194. /* Possibly 64-bit version of tlsf_fls. */
  195. #if defined(TLSF_64BIT)
  196. tlsf_decl int tlsf_fls_sizet(size_t size)
  197. {
  198. int high = (int)(size >> 32);
  199. int bits = 0;
  200. if (high) { bits = 32 + tlsf_fls(high); }
  201. else
  202. {
  203. bits = tlsf_fls((int)size & 0xffffffff);
  204. }
  205. return bits;
  206. }
  207. #else
  208. #define tlsf_fls_sizet tlsf_fls
  209. #endif
  210. tlsf_decl size_t align_up(size_t x, size_t align)
  211. {
  212. tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two");
  213. return (x + (align - 1)) & ~(align - 1);
  214. }
  215. tlsf_decl size_t align_down(size_t x, size_t align)
  216. {
  217. tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two");
  218. return x - (x & (align - 1));
  219. }
  220. tlsf_decl void *align_ptr(const void *ptr, size_t align)
  221. {
  222. const tlsfptr_t aligned = (tlsf_cast(tlsfptr_t, ptr) + (align - 1)) & ~(align - 1);
  223. tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two");
  224. return tlsf_cast(void *, aligned);
  225. }
  226. tlsf_decl size_t tlsf_align_size(void) { return ALIGN_SIZE; }
  227. tlsf_decl size_t tlsf_block_size_min(void) { return block_size_min; }
  228. tlsf_decl size_t tlsf_block_size_max(control_t *control)
  229. {
  230. if (control == NULL) { return 0; }
  231. return tlsf_cast(size_t, 1) << control->fl_index_max;
  232. }
  233. /*
  234. ** Adjust an allocation size to be aligned to word size, and no smaller
  235. ** than internal minimum.
  236. */
  237. tlsf_decl size_t adjust_request_size(control_t *control, size_t size, size_t align)
  238. {
  239. size_t adjust = 0;
  240. if (size)
  241. {
  242. const size_t aligned = align_up(size, align);
  243. /* aligned sized must not exceed block_size_max or we'll go out of bounds on sl_bitmap */
  244. if (aligned < tlsf_block_size_max(control)) { adjust = tlsf_max(aligned, block_size_min); }
  245. }
  246. return adjust;
  247. }
  248. /*
  249. ** TLSF utility functions. In most cases, these are direct translations of
  250. ** the documentation found in the white paper.
  251. */
  252. tlsf_decl void mapping_insert(control_t *control, size_t size, int *fli, int *sli)
  253. {
  254. int fl, sl;
  255. if (size < control->small_block_size)
  256. {
  257. /* Store small blocks in first list. */
  258. fl = 0;
  259. sl = tlsf_cast(int, size) / (control->small_block_size / control->sl_index_count);
  260. }
  261. else
  262. {
  263. fl = tlsf_fls_sizet(size);
  264. sl = tlsf_cast(int, size >> (fl - control->sl_index_count_log2)) ^ (1 << control->sl_index_count_log2);
  265. fl -= (control->fl_index_shift - 1);
  266. }
  267. *fli = fl;
  268. *sli = sl;
  269. }
  270. /* This version rounds up to the next block size (for allocations) */
  271. tlsf_decl void mapping_search(control_t *control, size_t *size, int *fli, int *sli)
  272. {
  273. if (*size >= control->small_block_size)
  274. {
  275. const size_t round = (1 << (tlsf_fls_sizet(*size) - control->sl_index_count_log2));
  276. *size = align_up(*size, round);
  277. }
  278. mapping_insert(control, *size, fli, sli);
  279. }
  280. tlsf_decl block_header_t *search_suitable_block(control_t *control, int *fli, int *sli)
  281. {
  282. int fl = *fli;
  283. int sl = *sli;
  284. /*
  285. ** First, search for a block in the list associated with the given
  286. ** fl/sl index.
  287. */
  288. unsigned int sl_map = control->sl_bitmap[fl] & (~0U << sl);
  289. if (!sl_map)
  290. {
  291. /* No block exists. Search in the next largest first-level list. */
  292. const unsigned int fl_map = control->fl_bitmap & (~0U << (fl + 1));
  293. if (!fl_map)
  294. {
  295. /* No free blocks available, memory has been exhausted. */
  296. return 0;
  297. }
  298. fl = tlsf_ffs(fl_map);
  299. *fli = fl;
  300. sl_map = control->sl_bitmap[fl];
  301. }
  302. tlsf_assert(sl_map && "internal error - second level bitmap is null");
  303. sl = tlsf_ffs(sl_map);
  304. *sli = sl;
  305. /* Return the first block in the free list. */
  306. return control->blocks[fl * control->sl_index_count + sl];
  307. }
  308. /* Remove a free block from the free list.*/
  309. tlsf_decl void remove_free_block(control_t *control, block_header_t *block, int fl, int sl)
  310. {
  311. block_header_t *prev = block->prev_free;
  312. block_header_t *next = block->next_free;
  313. tlsf_assert(prev && "prev_free field can not be null");
  314. tlsf_assert(next && "next_free field can not be null");
  315. next->prev_free = prev;
  316. prev->next_free = next;
  317. /* If this block is the head of the free list, set new head. */
  318. if (control->blocks[fl * control->sl_index_count + sl] == block)
  319. {
  320. control->blocks[fl * control->sl_index_count + sl] = next;
  321. /* If the new head is null, clear the bitmap. */
  322. if (next == &control->block_null)
  323. {
  324. control->sl_bitmap[fl] &= ~(1U << sl);
  325. /* If the second bitmap is now empty, clear the fl bitmap. */
  326. if (!control->sl_bitmap[fl]) { control->fl_bitmap &= ~(1U << fl); }
  327. }
  328. }
  329. }
  330. /* Insert a free block into the free block list. */
  331. tlsf_decl void insert_free_block(control_t *control, block_header_t *block, int fl, int sl)
  332. {
  333. block_header_t *current = control->blocks[fl * control->sl_index_count + sl];
  334. tlsf_assert(current && "free list cannot have a null entry");
  335. tlsf_assert(block && "cannot insert a null entry into the free list");
  336. block->next_free = current;
  337. block->prev_free = &control->block_null;
  338. current->prev_free = block;
  339. tlsf_assert(block_to_ptr(block) == align_ptr(block_to_ptr(block), ALIGN_SIZE) && "block not aligned properly");
  340. /*
  341. ** Insert the new block at the head of the list, and mark the first-
  342. ** and second-level bitmaps appropriately.
  343. */
  344. control->blocks[fl * control->sl_index_count + sl] = block;
  345. control->fl_bitmap |= (1U << fl);
  346. control->sl_bitmap[fl] |= (1U << sl);
  347. }
  348. /* Remove a given block from the free list. */
  349. tlsf_decl void block_remove(control_t *control, block_header_t *block)
  350. {
  351. int fl, sl;
  352. mapping_insert(control, block_size(block), &fl, &sl);
  353. remove_free_block(control, block, fl, sl);
  354. }
  355. /* Insert a given block into the free list. */
  356. tlsf_decl void block_insert(control_t *control, block_header_t *block)
  357. {
  358. int fl, sl;
  359. mapping_insert(control, block_size(block), &fl, &sl);
  360. insert_free_block(control, block, fl, sl);
  361. }
  362. tlsf_decl int block_can_split(block_header_t *block, size_t size) { return block_size(block) >= sizeof(block_header_t) + size; }
  363. /* Split a block into two, the second of which is free. */
  364. tlsf_decl block_header_t *block_split(block_header_t *block, size_t size)
  365. {
  366. /* Calculate the amount of space left in the remaining block.
  367. * REMINDER: remaining pointer's first field is `prev_phys_block` but this field is part of the
  368. * previous physical block. */
  369. block_header_t *remaining = offset_to_block(block_to_ptr(block), size - block_header_overhead);
  370. /* `size` passed as an argument is the first block's new size, thus, the remaining block's size
  371. * is `block_size(block) - size`. However, the block's data must be precedeed by the data size.
  372. * This field is NOT part of the size, so it has to be substracted from the calculation. */
  373. const size_t remain_size = block_size(block) - (size + block_header_overhead);
  374. tlsf_assert(block_to_ptr(remaining) == align_ptr(block_to_ptr(remaining), ALIGN_SIZE) && "remaining block not aligned properly");
  375. tlsf_assert(block_size(block) == remain_size + size + block_header_overhead);
  376. block_set_size(remaining, remain_size);
  377. tlsf_assert(block_size(remaining) >= block_size_min && "block split with invalid size");
  378. block_set_size(block, size);
  379. block_mark_as_free(remaining);
  380. /**
  381. * Here is the final outcome of this function:
  382. *
  383. * block remaining (block_ptr + size - BHO)
  384. * + +
  385. * | |
  386. * v v
  387. * +----------------------------------------------------------------------+
  388. * |0000| |xxxxxxxxxxxxxxxxxxxxxx|xxxx| |###########################|
  389. * |0000| |xxxxxxxxxxxxxxxxxxxxxx|xxxx| |###########################|
  390. * |0000| |xxxxxxxxxxxxxxxxxxxxxx|xxxx| |###########################|
  391. * |0000| |xxxxxxxxxxxxxxxxxxxxxx|xxxx| |###########################|
  392. * +----------------------------------------------------------------------+
  393. * | | | |
  394. * + +<------------------------->+ +<------------------------->
  395. * BHO `size` (argument) bytes BHO `remain_size` bytes
  396. *
  397. * Where BHO = block_header_overhead,
  398. * 0: part of the memory owned by a `block`'s previous neighbour,
  399. * x: part of the memory owned by `block`.
  400. * #: part of the memory owned by `remaining`.
  401. */
  402. return remaining;
  403. }
  404. /*!
  405. * @brief Weak function filling the given memory with a given fill pattern.
  406. *
  407. * @param start: pointer to the start of the memory region to fill
  408. * @param size: size of the memory region to fill
  409. * @param is_free: Indicate if the pattern to use the fill the region should be
  410. * an after free or after allocation pattern.
  411. */
  412. __attribute__((weak)) void block_absorb_post_hook(void *start, size_t size, bool is_free);
  413. /* Absorb a free block's storage into an adjacent previous free block. */
  414. tlsf_decl block_header_t *block_absorb(block_header_t *prev, block_header_t *block)
  415. {
  416. tlsf_assert(!block_is_last(prev) && "previous block can't be last");
  417. /* Note: Leaves flags untouched. */
  418. prev->size += block_size(block) + block_header_overhead;
  419. block_link_next(prev);
  420. if (block_absorb_post_hook != NULL) { block_absorb_post_hook(block, sizeof(block_header_t), POISONING_AFTER_FREE); }
  421. return prev;
  422. }
  423. /* Merge a just-freed block with an adjacent previous free block. */
  424. tlsf_decl block_header_t *block_merge_prev(control_t *control, block_header_t *block)
  425. {
  426. if (block_is_prev_free(block))
  427. {
  428. block_header_t *prev = block_prev(block);
  429. tlsf_assert(prev && "prev physical block can't be null");
  430. tlsf_assert(block_is_free(prev) && "prev block is not free though marked as such");
  431. block_remove(control, prev);
  432. block = block_absorb(prev, block);
  433. }
  434. return block;
  435. }
  436. /* Merge a just-freed block with an adjacent free block. */
  437. tlsf_decl block_header_t *block_merge_next(control_t *control, block_header_t *block)
  438. {
  439. block_header_t *next = block_next(block);
  440. tlsf_assert(next && "next physical block can't be null");
  441. if (block_is_free(next))
  442. {
  443. tlsf_assert(!block_is_last(block) && "previous block can't be last");
  444. block_remove(control, next);
  445. block = block_absorb(block, next);
  446. }
  447. return block;
  448. }
  449. /* Trim any trailing block space off the end of a block, return to pool. */
  450. tlsf_decl void block_trim_free(control_t *control, block_header_t *block, size_t size)
  451. {
  452. tlsf_assert(block_is_free(block) && "block must be free");
  453. if (block_can_split(block, size))
  454. {
  455. block_header_t *remaining_block = block_split(block, size);
  456. block_link_next(block);
  457. block_set_prev_free(remaining_block);
  458. block_insert(control, remaining_block);
  459. }
  460. }
  461. /* Trim any trailing block space off the end of a used block, return to pool. */
  462. tlsf_decl void block_trim_used(control_t *control, block_header_t *block, size_t size)
  463. {
  464. tlsf_assert(!block_is_free(block) && "block must be used");
  465. if (block_can_split(block, size))
  466. {
  467. /* If the next block is free, we must coalesce. */
  468. block_header_t *remaining_block = block_split(block, size);
  469. block_set_prev_used(remaining_block);
  470. remaining_block = block_merge_next(control, remaining_block);
  471. block_insert(control, remaining_block);
  472. }
  473. }
  474. tlsf_decl block_header_t *block_trim_free_leading(control_t *control, block_header_t *block, size_t size)
  475. {
  476. block_header_t *remaining_block = block;
  477. if (block_can_split(block, size))
  478. {
  479. /* We want to split `block` in two: the first block will be freed and the
  480. * second block will be returned. */
  481. remaining_block = block_split(block, size - block_header_overhead);
  482. /* `remaining_block` is the second block, mark its predecessor (first
  483. * block) as free. */
  484. block_set_prev_free(remaining_block);
  485. block_link_next(block);
  486. /* Put back the first block into the free memory list. */
  487. block_insert(control, block);
  488. }
  489. return remaining_block;
  490. }
  491. tlsf_decl block_header_t *block_locate_free(control_t *control, size_t *size)
  492. {
  493. int fl = 0, sl = 0;
  494. block_header_t *block = 0;
  495. if (*size)
  496. {
  497. mapping_search(control, size, &fl, &sl);
  498. /*
  499. ** mapping_search can futz with the size, so for excessively large sizes it can sometimes wind up
  500. ** with indices that are off the end of the block array.
  501. ** So, we protect against that here, since this is the only callsite of mapping_search.
  502. ** Note that we don't need to check sl, since it comes from a modulo operation that guarantees it's always in range.
  503. */
  504. if (fl < control->fl_index_count) { block = search_suitable_block(control, &fl, &sl); }
  505. }
  506. if (block)
  507. {
  508. tlsf_assert(block_size(block) >= *size);
  509. remove_free_block(control, block, fl, sl);
  510. }
  511. return block;
  512. }
  513. tlsf_decl void *block_prepare_used(control_t *control, block_header_t *block, size_t size)
  514. {
  515. void *p = 0;
  516. if (block)
  517. {
  518. tlsf_assert(size && "size must be non-zero");
  519. block_trim_free(control, block, size);
  520. block_mark_as_used(block);
  521. p = block_to_ptr(block);
  522. control->mem_rec.used += (block_size(block) + tlsf_alloc_overhead());
  523. if (control->mem_rec.used > control->mem_rec.max_used) { control->mem_rec.max_used = control->mem_rec.used; }
  524. }
  525. return p;
  526. }
  527. #undef tlsf_decl
  528. #if defined(__cplusplus)
  529. };
  530. #endif