tlsf_block_functions.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * SPDX-FileCopyrightText: 2006-2016 Matthew Conte
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #pragma once
  7. #if defined(__cplusplus)
  8. extern "C" {
  9. #endif
  10. /*
  11. ** Constants definition for poisoning.
  12. ** These defines are used as 3rd argument of tlsf_poison_fill_region() for readability purposes.
  13. */
  14. #define POISONING_AFTER_FREE true
  15. #define POISONING_AFTER_MALLOC !POISONING_AFTER_FREE
  16. /* A type used for casting when doing pointer arithmetic. */
  17. typedef ptrdiff_t tlsfptr_t;
  18. /*
  19. ** Cast and min/max macros.
  20. */
  21. #if !defined(tlsf_cast)
  22. #define tlsf_cast(t, exp) ((t)(exp))
  23. #endif
  24. #if !defined(tlsf_min)
  25. #define tlsf_min(a, b) ((a) < (b) ? (a) : (b))
  26. #endif
  27. #if !defined(tlsf_max)
  28. #define tlsf_max(a, b) ((a) > (b) ? (a) : (b))
  29. #endif
  30. /*
  31. ** Set assert macro, if it has not been provided by the user.
  32. */
  33. #if !defined(tlsf_assert)
  34. #define tlsf_assert RT_ASSERT
  35. #endif
  36. typedef struct block_header_t
  37. {
  38. /* Points to the previous physical block. */
  39. struct block_header_t *prev_phys_block;
  40. /* The size of this block, excluding the block header. */
  41. size_t size;
  42. /* Next and previous free blocks. */
  43. struct block_header_t *next_free;
  44. struct block_header_t *prev_free;
  45. } block_header_t;
  46. /* User data starts directly after the size field in a used block. */
  47. #define block_start_offset (offsetof(block_header_t, size) + sizeof(size_t))
  48. /*
  49. ** A free block must be large enough to store its header minus the size of
  50. ** the prev_phys_block field, and no larger than the number of addressable
  51. ** bits for FL_INDEX.
  52. */
  53. #define block_size_min (sizeof(block_header_t) - sizeof(block_header_t *))
  54. /*
  55. ** Since block sizes are always at least a multiple of 4, the two least
  56. ** significant bits of the size field are used to store the block status:
  57. ** - bit 0: whether block is busy or free
  58. ** - bit 1: whether previous block is busy or free
  59. */
  60. #define block_header_free_bit (1UL << 0)
  61. #define block_header_prev_free_bit (1UL << 1)
  62. /*
  63. ** The size of the block header exposed to used blocks is the size field.
  64. ** The prev_phys_block field is stored *inside* the previous free block.
  65. */
  66. #define block_header_overhead (sizeof(size_t))
  67. /*
  68. ** block_header_t member functions.
  69. */
  70. #define tlsf_decl rt_always_inline
  71. tlsf_decl size_t block_size(const block_header_t *block)
  72. { return block->size & ~(block_header_free_bit | block_header_prev_free_bit); }
  73. tlsf_decl void block_set_size(block_header_t *block, size_t size)
  74. {
  75. const size_t oldsize = block->size;
  76. block->size = size | (oldsize & (block_header_free_bit | block_header_prev_free_bit));
  77. }
  78. tlsf_decl int block_is_last(const block_header_t *block) { return block_size(block) == 0; }
  79. tlsf_decl int block_is_free(const block_header_t *block)
  80. { return tlsf_cast(int, block->size &block_header_free_bit); }
  81. tlsf_decl void block_set_free(block_header_t *block) { block->size |= block_header_free_bit; }
  82. tlsf_decl void block_set_used(block_header_t *block) { block->size &= ~block_header_free_bit; }
  83. tlsf_decl int block_is_prev_free(const block_header_t *block)
  84. { return tlsf_cast(int, block->size &block_header_prev_free_bit); }
  85. tlsf_decl void block_set_prev_free(block_header_t *block) { block->size |= block_header_prev_free_bit; }
  86. tlsf_decl void block_set_prev_used(block_header_t *block) { block->size &= ~block_header_prev_free_bit; }
  87. tlsf_decl block_header_t *block_from_ptr(const void *ptr)
  88. { return tlsf_cast(block_header_t *, tlsf_cast(unsigned char *, ptr) - block_start_offset); }
  89. tlsf_decl void *block_to_ptr(const block_header_t *block)
  90. { return tlsf_cast(void *, tlsf_cast(unsigned char *, block) + block_start_offset); }
  91. /* Return location of next block after block of given size. */
  92. tlsf_decl block_header_t *offset_to_block(const void *ptr, size_t size)
  93. { return tlsf_cast(block_header_t *, tlsf_cast(tlsfptr_t, ptr) + size); }
  94. /* Return location of previous block. */
  95. tlsf_decl block_header_t *block_prev(const block_header_t *block)
  96. {
  97. tlsf_assert(block_is_prev_free(block) && "previous block must be free");
  98. return block->prev_phys_block;
  99. }
  100. /* Return location of next existing block. */
  101. tlsf_decl block_header_t *block_next(const block_header_t *block)
  102. {
  103. block_header_t *next = offset_to_block(block_to_ptr(block), block_size(block) - block_header_overhead);
  104. tlsf_assert(!block_is_last(block));
  105. return next;
  106. }
  107. /* Link a new block with its physical neighbor, return the neighbor. */
  108. tlsf_decl block_header_t *block_link_next(block_header_t *block)
  109. {
  110. block_header_t *next = block_next(block);
  111. next->prev_phys_block = block;
  112. return next;
  113. }
  114. tlsf_decl void block_mark_as_free(block_header_t *block)
  115. {
  116. /* Link the block to the next block, first. */
  117. block_header_t *next = block_link_next(block);
  118. block_set_prev_free(next);
  119. block_set_free(block);
  120. }
  121. tlsf_decl void block_mark_as_used(block_header_t *block)
  122. {
  123. block_header_t *next = block_next(block);
  124. block_set_prev_used(next);
  125. block_set_used(block);
  126. }
  127. #if defined(__cplusplus)
  128. };
  129. #endif