lzham_mem.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. // File: lzham_mem.cpp
  2. // See Copyright Notice and license at the end of include/lzham.h
  3. #include "lzham_core.h"
  4. #ifdef __APPLE__
  5. #include <malloc/malloc.h>
  6. #elif defined(__FreeBSD__) || defined(__NetBSD__)
  7. #include <malloc_np.h>
  8. #if defined(__FreeBSD__)
  9. #define malloc(size) aligned_alloc((LZHAM_MIN_ALLOC_ALIGNMENT), (size))
  10. #endif
  11. #else
  12. #include <malloc.h>
  13. #endif
  14. using namespace lzham;
  15. #define LZHAM_MEM_STATS 0
  16. // ESENTHEL CHANGED
  17. #ifdef LZHAM_USE_WIN32_API
  18. #define MallocSize(p, size) _msize(p)
  19. #elif defined __APPLE__
  20. #define MallocSize(p, size) malloc_size(p)
  21. #elif defined ANDROID
  22. #define MallocSize(p, size) size
  23. #else
  24. #define MallocSize(p, size) malloc_usable_size(p)
  25. #endif
  26. namespace lzham
  27. {
  28. #if LZHAM_64BIT_POINTERS
  29. const uint64 MAX_POSSIBLE_BLOCK_SIZE = 0x400000000ULL;
  30. #else
  31. const uint32 MAX_POSSIBLE_BLOCK_SIZE = 0x7FFF0000U;
  32. #endif
  33. #if LZHAM_MEM_STATS
  34. #if LZHAM_64BIT_POINTERS
  35. typedef atomic64_t mem_stat_t;
  36. #define LZHAM_MEM_COMPARE_EXCHANGE atomic_compare_exchange64
  37. #else
  38. typedef atomic32_t mem_stat_t;
  39. #define LZHAM_MEM_COMPARE_EXCHANGE atomic_compare_exchange32
  40. #endif
  41. static volatile atomic32_t g_total_blocks;
  42. static volatile mem_stat_t g_total_allocated;
  43. static volatile mem_stat_t g_max_allocated;
  44. static mem_stat_t update_total_allocated(int block_delta, mem_stat_t byte_delta)
  45. {
  46. atomic32_t cur_total_blocks;
  47. for ( ; ; )
  48. {
  49. cur_total_blocks = g_total_blocks;
  50. atomic32_t new_total_blocks = static_cast<atomic32_t>(cur_total_blocks + block_delta);
  51. LZHAM_ASSERT(new_total_blocks >= 0);
  52. if (atomic_compare_exchange32(&g_total_blocks, new_total_blocks, cur_total_blocks) == cur_total_blocks)
  53. break;
  54. }
  55. mem_stat_t cur_total_allocated, new_total_allocated;
  56. for ( ; ; )
  57. {
  58. cur_total_allocated = g_total_allocated;
  59. new_total_allocated = static_cast<mem_stat_t>(cur_total_allocated + byte_delta);
  60. LZHAM_ASSERT(new_total_allocated >= 0);
  61. if (LZHAM_MEM_COMPARE_EXCHANGE(&g_total_allocated, new_total_allocated, cur_total_allocated) == cur_total_allocated)
  62. break;
  63. }
  64. for ( ; ; )
  65. {
  66. mem_stat_t cur_max_allocated = g_max_allocated;
  67. mem_stat_t new_max_allocated = LZHAM_MAX(new_total_allocated, cur_max_allocated);
  68. if (LZHAM_MEM_COMPARE_EXCHANGE(&g_max_allocated, new_max_allocated, cur_max_allocated) == cur_max_allocated)
  69. break;
  70. }
  71. return new_total_allocated;
  72. }
  73. #endif // LZHAM_MEM_STATS
  74. static void* lzham_default_realloc(void* p, size_t size, size_t* pActual_size, lzham_bool movable, void* pUser_data)
  75. {
  76. LZHAM_NOTE_UNUSED(pUser_data);
  77. void* p_new;
  78. if (!p)
  79. {
  80. p_new = malloc(size);
  81. LZHAM_ASSERT( (reinterpret_cast<ptr_bits_t>(p_new) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1)) == 0 );
  82. if (pActual_size)
  83. *pActual_size = p_new ? MallocSize(p_new, size) : 0;
  84. }
  85. else if (!size)
  86. {
  87. free(p);
  88. p_new = NULL;
  89. if (pActual_size)
  90. *pActual_size = 0;
  91. }
  92. else
  93. {
  94. void* p_final_block = p;
  95. #ifdef WIN32
  96. p_new = _expand(p, size);
  97. #else
  98. p_new = NULL;
  99. #endif
  100. if (p_new)
  101. {
  102. LZHAM_ASSERT( (reinterpret_cast<ptr_bits_t>(p_new) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1)) == 0 );
  103. p_final_block = p_new;
  104. }
  105. else if (movable)
  106. {
  107. p_new = realloc(p, size);
  108. if (p_new)
  109. {
  110. LZHAM_ASSERT( (reinterpret_cast<ptr_bits_t>(p_new) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1)) == 0 );
  111. p_final_block = p_new;
  112. }
  113. }
  114. if (pActual_size)
  115. *pActual_size = MallocSize(p_final_block, size);
  116. }
  117. return p_new;
  118. }
  119. #if LZHAM_MEM_STATS
  120. static size_t lzham_default_msize(void* p, void* pUser_data)
  121. {
  122. LZHAM_NOTE_UNUSED(pUser_data);
  123. return p ? _msize(p) : 0;
  124. }
  125. #endif
  126. static lzham_realloc_func g_pRealloc = lzham_default_realloc;
  127. #if LZHAM_MEM_STATS
  128. static lzham_msize_func g_pMSize = lzham_default_msize;
  129. #endif
  130. static void* g_pUser_data;
  131. static inline void lzham_mem_error(const char* p_msg)
  132. {
  133. lzham_assert(p_msg, __FILE__, __LINE__);
  134. }
  135. void* lzham_malloc(size_t size, size_t* pActual_size)
  136. {
  137. size = (size + sizeof(uint32) - 1U) & ~(sizeof(uint32) - 1U);
  138. if (!size)
  139. size = sizeof(uint32);
  140. if (size > MAX_POSSIBLE_BLOCK_SIZE)
  141. {
  142. lzham_mem_error("lzham_malloc: size too big");
  143. return NULL;
  144. }
  145. size_t actual_size = size;
  146. uint8* p_new = static_cast<uint8*>((*g_pRealloc)(NULL, size, &actual_size, true, g_pUser_data));
  147. if (pActual_size)
  148. *pActual_size = actual_size;
  149. if ((!p_new) || (actual_size < size))
  150. {
  151. lzham_mem_error("lzham_malloc: out of memory");
  152. return NULL;
  153. }
  154. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(p_new) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1)) == 0);
  155. #if LZHAM_MEM_STATS
  156. update_total_allocated(1, static_cast<mem_stat_t>(actual_size));
  157. #endif
  158. return p_new;
  159. }
  160. void* lzham_realloc(void* p, size_t size, size_t* pActual_size, bool movable)
  161. {
  162. if ((ptr_bits_t)p & (LZHAM_MIN_ALLOC_ALIGNMENT - 1))
  163. {
  164. lzham_mem_error("lzham_realloc: bad ptr");
  165. return NULL;
  166. }
  167. if (size > MAX_POSSIBLE_BLOCK_SIZE)
  168. {
  169. lzham_mem_error("lzham_malloc: size too big");
  170. return NULL;
  171. }
  172. #if LZHAM_MEM_STATS
  173. size_t cur_size = p ? (*g_pMSize)(p, g_pUser_data) : 0;
  174. #endif
  175. size_t actual_size = size;
  176. void* p_new = (*g_pRealloc)(p, size, &actual_size, movable, g_pUser_data);
  177. if (pActual_size)
  178. *pActual_size = actual_size;
  179. LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(p_new) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1)) == 0);
  180. #if LZHAM_MEM_STATS
  181. int num_new_blocks = 0;
  182. if (p)
  183. {
  184. if (!p_new)
  185. num_new_blocks = -1;
  186. }
  187. else if (p_new)
  188. {
  189. num_new_blocks = 1;
  190. }
  191. update_total_allocated(num_new_blocks, static_cast<mem_stat_t>(actual_size) - static_cast<mem_stat_t>(cur_size));
  192. #endif
  193. return p_new;
  194. }
  195. void lzham_free(void* p)
  196. {
  197. if (!p)
  198. return;
  199. if (reinterpret_cast<ptr_bits_t>(p) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1))
  200. {
  201. lzham_mem_error("lzham_free: bad ptr");
  202. return;
  203. }
  204. #if LZHAM_MEM_STATS
  205. size_t cur_size = (*g_pMSize)(p, g_pUser_data);
  206. update_total_allocated(-1, -static_cast<mem_stat_t>(cur_size));
  207. #endif
  208. (*g_pRealloc)(p, 0, NULL, true, g_pUser_data);
  209. }
  210. #if LZHAM_MEM_STATS
  211. size_t lzham_msize(void* p)
  212. {
  213. if (!p)
  214. return 0;
  215. if (reinterpret_cast<ptr_bits_t>(p) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1))
  216. {
  217. lzham_mem_error("lzham_msize: bad ptr");
  218. return 0;
  219. }
  220. return (*g_pMSize)(p, g_pUser_data);
  221. }
  222. #endif
  223. void LZHAM_CDECL lzham_lib_set_memory_callbacks(lzham_realloc_func pRealloc, lzham_msize_func pMSize, void* pUser_data)
  224. {
  225. if ((!pRealloc) || (!pMSize))
  226. {
  227. g_pRealloc = lzham_default_realloc;
  228. #if LZHAM_MEM_STATS
  229. g_pMSize = lzham_default_msize;
  230. #endif
  231. g_pUser_data = NULL;
  232. }
  233. else
  234. {
  235. g_pRealloc = pRealloc;
  236. #if LZHAM_MEM_STATS
  237. g_pMSize = pMSize;
  238. #endif
  239. g_pUser_data = pUser_data;
  240. }
  241. }
  242. void lzham_print_mem_stats()
  243. {
  244. #if LZHAM_MEM_STATS
  245. printf("Current blocks: %u, allocated: %I64u, max ever allocated: %I64i\n", g_total_blocks, (int64)g_total_allocated, (int64)g_max_allocated);
  246. #endif
  247. }
  248. } // namespace lzham