mem-pool.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * Memory Pool implementation logic.
  3. */
  4. #include "cache.h"
  5. #include "mem-pool.h"
  6. #define BLOCK_GROWTH_SIZE 1024*1024 - sizeof(struct mp_block);
  7. /*
  8. * Allocate a new mp_block and insert it after the block specified in
  9. * `insert_after`. If `insert_after` is NULL, then insert block at the
  10. * head of the linked list.
  11. */
  12. static struct mp_block *mem_pool_alloc_block(struct mem_pool *pool,
  13. size_t block_alloc,
  14. struct mp_block *insert_after)
  15. {
  16. struct mp_block *p;
  17. pool->pool_alloc += sizeof(struct mp_block) + block_alloc;
  18. p = xmalloc(st_add(sizeof(struct mp_block), block_alloc));
  19. p->next_free = (char *)p->space;
  20. p->end = p->next_free + block_alloc;
  21. if (insert_after) {
  22. p->next_block = insert_after->next_block;
  23. insert_after->next_block = p;
  24. } else {
  25. p->next_block = pool->mp_block;
  26. pool->mp_block = p;
  27. }
  28. return p;
  29. }
  30. void mem_pool_init(struct mem_pool *pool, size_t initial_size)
  31. {
  32. memset(pool, 0, sizeof(*pool));
  33. pool->block_alloc = BLOCK_GROWTH_SIZE;
  34. if (initial_size > 0)
  35. mem_pool_alloc_block(pool, initial_size, NULL);
  36. }
  37. void mem_pool_discard(struct mem_pool *pool, int invalidate_memory)
  38. {
  39. struct mp_block *block, *block_to_free;
  40. block = pool->mp_block;
  41. while (block)
  42. {
  43. block_to_free = block;
  44. block = block->next_block;
  45. if (invalidate_memory)
  46. memset(block_to_free->space, 0xDD, ((char *)block_to_free->end) - ((char *)block_to_free->space));
  47. free(block_to_free);
  48. }
  49. pool->mp_block = NULL;
  50. pool->pool_alloc = 0;
  51. }
  52. void *mem_pool_alloc(struct mem_pool *pool, size_t len)
  53. {
  54. struct mp_block *p = NULL;
  55. void *r;
  56. /* round up to a 'uintmax_t' alignment */
  57. if (len & (sizeof(uintmax_t) - 1))
  58. len += sizeof(uintmax_t) - (len & (sizeof(uintmax_t) - 1));
  59. if (pool->mp_block &&
  60. pool->mp_block->end - pool->mp_block->next_free >= len)
  61. p = pool->mp_block;
  62. if (!p) {
  63. if (len >= (pool->block_alloc / 2))
  64. return mem_pool_alloc_block(pool, len, pool->mp_block);
  65. p = mem_pool_alloc_block(pool, pool->block_alloc, NULL);
  66. }
  67. r = p->next_free;
  68. p->next_free += len;
  69. return r;
  70. }
  71. void *mem_pool_calloc(struct mem_pool *pool, size_t count, size_t size)
  72. {
  73. size_t len = st_mult(count, size);
  74. void *r = mem_pool_alloc(pool, len);
  75. memset(r, 0, len);
  76. return r;
  77. }
  78. char *mem_pool_strdup(struct mem_pool *pool, const char *str)
  79. {
  80. size_t len = strlen(str) + 1;
  81. char *ret = mem_pool_alloc(pool, len);
  82. return memcpy(ret, str, len);
  83. }
  84. char *mem_pool_strndup(struct mem_pool *pool, const char *str, size_t len)
  85. {
  86. char *p = memchr(str, '\0', len);
  87. size_t actual_len = (p ? p - str : len);
  88. char *ret = mem_pool_alloc(pool, actual_len+1);
  89. ret[actual_len] = '\0';
  90. return memcpy(ret, str, actual_len);
  91. }
  92. int mem_pool_contains(struct mem_pool *pool, void *mem)
  93. {
  94. struct mp_block *p;
  95. /* Check if memory is allocated in a block */
  96. for (p = pool->mp_block; p; p = p->next_block)
  97. if ((mem >= ((void *)p->space)) &&
  98. (mem < ((void *)p->end)))
  99. return 1;
  100. return 0;
  101. }
  102. void mem_pool_combine(struct mem_pool *dst, struct mem_pool *src)
  103. {
  104. struct mp_block *p;
  105. /* Append the blocks from src to dst */
  106. if (dst->mp_block && src->mp_block) {
  107. /*
  108. * src and dst have blocks, append
  109. * blocks from src to dst.
  110. */
  111. p = dst->mp_block;
  112. while (p->next_block)
  113. p = p->next_block;
  114. p->next_block = src->mp_block;
  115. } else if (src->mp_block) {
  116. /*
  117. * src has blocks, dst is empty.
  118. */
  119. dst->mp_block = src->mp_block;
  120. } else {
  121. /* src is empty, nothing to do. */
  122. }
  123. dst->pool_alloc += src->pool_alloc;
  124. src->pool_alloc = 0;
  125. src->mp_block = NULL;
  126. }