mimalloc.h 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. /* ----------------------------------------------------------------------------
  2. Copyright (c) 2018-2021, Microsoft Research, Daan Leijen
  3. This is free software; you can redistribute it and/or modify it under the
  4. terms of the MIT license. A copy of the license can be found in the file
  5. "LICENSE" at the root of this distribution.
  6. -----------------------------------------------------------------------------*/
  7. #pragma once
  8. #ifndef MIMALLOC_H
  9. #define MIMALLOC_H
  10. #define MI_MALLOC_VERSION 171 // major + 2 digits minor
  11. // ------------------------------------------------------
  12. // Compiler specific attributes
  13. // ------------------------------------------------------
  14. #ifdef __cplusplus
  15. #if (__cplusplus >= 201103L) || (_MSC_VER > 1900) // C++11
  16. #define mi_attr_noexcept noexcept
  17. #else
  18. #define mi_attr_noexcept throw()
  19. #endif
  20. #else
  21. #define mi_attr_noexcept
  22. #endif
  23. #if defined(__cplusplus) && (__cplusplus >= 201703)
  24. #define mi_decl_nodiscard [[nodiscard]]
  25. #elif (__GNUC__ >= 4) || defined(__clang__) // includes clang, icc, and clang-cl
  26. #define mi_decl_nodiscard __attribute__((warn_unused_result))
  27. #elif (_MSC_VER >= 1700)
  28. #define mi_decl_nodiscard _Check_return_
  29. #else
  30. #define mi_decl_nodiscard
  31. #endif
  32. #if defined(_MSC_VER) || defined(__MINGW32__)
  33. #if !defined(MI_SHARED_LIB)
  34. #define mi_decl_export
  35. #elif defined(MI_SHARED_LIB_EXPORT)
  36. #define mi_decl_export __declspec(dllexport)
  37. #else
  38. #define mi_decl_export __declspec(dllimport)
  39. #endif
  40. #if defined(__MINGW32__)
  41. #define mi_decl_restrict
  42. #define mi_attr_malloc __attribute__((malloc))
  43. #else
  44. #if (_MSC_VER >= 1900) && !defined(__EDG__)
  45. #define mi_decl_restrict __declspec(allocator) __declspec(restrict)
  46. #else
  47. #define mi_decl_restrict __declspec(restrict)
  48. #endif
  49. #define mi_attr_malloc
  50. #endif
  51. #define mi_cdecl __cdecl
  52. #define mi_attr_alloc_size(s)
  53. #define mi_attr_alloc_size2(s1,s2)
  54. #define mi_attr_alloc_align(p)
  55. #elif defined(__GNUC__) // includes clang and icc
  56. #define mi_cdecl // leads to warnings... __attribute__((cdecl))
  57. #define mi_decl_export __attribute__((visibility("default")))
  58. #define mi_decl_restrict
  59. #define mi_attr_malloc __attribute__((malloc))
  60. #if (defined(__clang_major__) && (__clang_major__ < 4)) || (__GNUC__ < 5)
  61. #define mi_attr_alloc_size(s)
  62. #define mi_attr_alloc_size2(s1,s2)
  63. #define mi_attr_alloc_align(p)
  64. #elif defined(__INTEL_COMPILER)
  65. #define mi_attr_alloc_size(s) __attribute__((alloc_size(s)))
  66. #define mi_attr_alloc_size2(s1,s2) __attribute__((alloc_size(s1,s2)))
  67. #define mi_attr_alloc_align(p)
  68. #else
  69. #define mi_attr_alloc_size(s) __attribute__((alloc_size(s)))
  70. #define mi_attr_alloc_size2(s1,s2) __attribute__((alloc_size(s1,s2)))
  71. #define mi_attr_alloc_align(p) __attribute__((alloc_align(p)))
  72. #endif
  73. #else
  74. #define mi_cdecl
  75. #define mi_decl_export
  76. #define mi_decl_restrict
  77. #define mi_attr_malloc
  78. #define mi_attr_alloc_size(s)
  79. #define mi_attr_alloc_size2(s1,s2)
  80. #define mi_attr_alloc_align(p)
  81. #endif
  82. // ------------------------------------------------------
  83. // Includes
  84. // ------------------------------------------------------
  85. #include <stddef.h> // size_t
  86. #include <stdbool.h> // bool
  87. #ifdef __cplusplus
  88. extern "C" {
  89. #endif
  90. // ------------------------------------------------------
  91. // Standard malloc interface
  92. // ------------------------------------------------------
  93. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
  94. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_calloc(size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2);
  95. mi_decl_nodiscard mi_decl_export void* mi_realloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2);
  96. mi_decl_export void* mi_expand(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2);
  97. mi_decl_export void mi_free(void* p) mi_attr_noexcept;
  98. mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_strdup(const char* s) mi_attr_noexcept mi_attr_malloc;
  99. mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_strndup(const char* s, size_t n) mi_attr_noexcept mi_attr_malloc;
  100. mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_realpath(const char* fname, char* resolved_name) mi_attr_noexcept mi_attr_malloc;
  101. // ------------------------------------------------------
  102. // Extended functionality
  103. // ------------------------------------------------------
  104. #define MI_SMALL_WSIZE_MAX (128)
  105. #define MI_SMALL_SIZE_MAX (MI_SMALL_WSIZE_MAX*sizeof(void*))
  106. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_small(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
  107. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc_small(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
  108. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
  109. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_mallocn(size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2);
  110. mi_decl_nodiscard mi_decl_export void* mi_reallocn(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_alloc_size2(2,3);
  111. mi_decl_nodiscard mi_decl_export void* mi_reallocf(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2);
  112. mi_decl_nodiscard mi_decl_export size_t mi_usable_size(const void* p) mi_attr_noexcept;
  113. mi_decl_nodiscard mi_decl_export size_t mi_good_size(size_t size) mi_attr_noexcept;
  114. // ------------------------------------------------------
  115. // Internals
  116. // ------------------------------------------------------
  117. typedef void (mi_cdecl mi_deferred_free_fun)(bool force, unsigned long long heartbeat, void* arg);
  118. mi_decl_export void mi_register_deferred_free(mi_deferred_free_fun* deferred_free, void* arg) mi_attr_noexcept;
  119. typedef void (mi_cdecl mi_output_fun)(const char* msg, void* arg);
  120. mi_decl_export void mi_register_output(mi_output_fun* out, void* arg) mi_attr_noexcept;
  121. typedef void (mi_cdecl mi_error_fun)(int err, void* arg);
  122. mi_decl_export void mi_register_error(mi_error_fun* fun, void* arg);
  123. mi_decl_export void mi_collect(bool force) mi_attr_noexcept;
  124. mi_decl_export int mi_version(void) mi_attr_noexcept;
  125. mi_decl_export void mi_stats_reset(void) mi_attr_noexcept;
  126. mi_decl_export void mi_stats_merge(void) mi_attr_noexcept;
  127. mi_decl_export void mi_stats_print(void* out) mi_attr_noexcept; // backward compatibility: `out` is ignored and should be NULL
  128. mi_decl_export void mi_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept;
  129. mi_decl_export void mi_process_init(void) mi_attr_noexcept;
  130. mi_decl_export void mi_thread_init(void) mi_attr_noexcept;
  131. mi_decl_export void mi_thread_done(void) mi_attr_noexcept;
  132. mi_decl_export void mi_thread_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept;
  133. mi_decl_export void mi_process_info(size_t* elapsed_msecs, size_t* user_msecs, size_t* system_msecs,
  134. size_t* current_rss, size_t* peak_rss,
  135. size_t* current_commit, size_t* peak_commit, size_t* page_faults) mi_attr_noexcept;
  136. // -------------------------------------------------------------------------------------
  137. // Aligned allocation
  138. // Note that `alignment` always follows `size` for consistency with unaligned
  139. // allocation, but unfortunately this differs from `posix_memalign` and `aligned_alloc`.
  140. // -------------------------------------------------------------------------------------
  141. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2);
  142. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
  143. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2);
  144. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
  145. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_calloc_aligned(size_t count, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2) mi_attr_alloc_align(3);
  146. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_calloc_aligned_at(size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2);
  147. mi_decl_nodiscard mi_decl_export void* mi_realloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(2) mi_attr_alloc_align(3);
  148. mi_decl_nodiscard mi_decl_export void* mi_realloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(2);
  149. // -------------------------------------------------------------------------------------
  150. // Heaps: first-class, but can only allocate from the same thread that created it.
  151. // -------------------------------------------------------------------------------------
  152. struct mi_heap_s;
  153. typedef struct mi_heap_s mi_heap_t;
  154. mi_decl_nodiscard mi_decl_export mi_heap_t* mi_heap_new(void);
  155. mi_decl_export void mi_heap_delete(mi_heap_t* heap);
  156. mi_decl_export void mi_heap_destroy(mi_heap_t* heap);
  157. mi_decl_export mi_heap_t* mi_heap_set_default(mi_heap_t* heap);
  158. mi_decl_export mi_heap_t* mi_heap_get_default(void);
  159. mi_decl_export mi_heap_t* mi_heap_get_backing(void);
  160. mi_decl_export void mi_heap_collect(mi_heap_t* heap, bool force) mi_attr_noexcept;
  161. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
  162. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_zalloc(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
  163. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_calloc(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3);
  164. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_mallocn(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3);
  165. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_small(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
  166. mi_decl_nodiscard mi_decl_export void* mi_heap_realloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(3);
  167. mi_decl_nodiscard mi_decl_export void* mi_heap_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_alloc_size2(3,4);
  168. mi_decl_nodiscard mi_decl_export void* mi_heap_reallocf(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(3);
  169. mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_strdup(mi_heap_t* heap, const char* s) mi_attr_noexcept mi_attr_malloc;
  170. mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n) mi_attr_noexcept mi_attr_malloc;
  171. mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char* resolved_name) mi_attr_noexcept mi_attr_malloc;
  172. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(3);
  173. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
  174. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_zalloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(3);
  175. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_zalloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
  176. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_calloc_aligned(mi_heap_t* heap, size_t count, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3) mi_attr_alloc_align(4);
  177. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_calloc_aligned_at(mi_heap_t* heap, size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3);
  178. mi_decl_nodiscard mi_decl_export void* mi_heap_realloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(3) mi_attr_alloc_align(4);
  179. mi_decl_nodiscard mi_decl_export void* mi_heap_realloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(3);
  180. // --------------------------------------------------------------------------------
  181. // Zero initialized re-allocation.
  182. // Only valid on memory that was originally allocated with zero initialization too.
  183. // e.g. `mi_calloc`, `mi_zalloc`, `mi_zalloc_aligned` etc.
  184. // see <https://github.com/microsoft/mimalloc/issues/63#issuecomment-508272992>
  185. // --------------------------------------------------------------------------------
  186. mi_decl_nodiscard mi_decl_export void* mi_rezalloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2);
  187. mi_decl_nodiscard mi_decl_export void* mi_recalloc(void* p, size_t newcount, size_t size) mi_attr_noexcept mi_attr_alloc_size2(2,3);
  188. mi_decl_nodiscard mi_decl_export void* mi_rezalloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(2) mi_attr_alloc_align(3);
  189. mi_decl_nodiscard mi_decl_export void* mi_rezalloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(2);
  190. mi_decl_nodiscard mi_decl_export void* mi_recalloc_aligned(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept mi_attr_alloc_size2(2,3) mi_attr_alloc_align(4);
  191. mi_decl_nodiscard mi_decl_export void* mi_recalloc_aligned_at(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size2(2,3);
  192. mi_decl_nodiscard mi_decl_export void* mi_heap_rezalloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(3);
  193. mi_decl_nodiscard mi_decl_export void* mi_heap_recalloc(mi_heap_t* heap, void* p, size_t newcount, size_t size) mi_attr_noexcept mi_attr_alloc_size2(3,4);
  194. mi_decl_nodiscard mi_decl_export void* mi_heap_rezalloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(3) mi_attr_alloc_align(4);
  195. mi_decl_nodiscard mi_decl_export void* mi_heap_rezalloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(3);
  196. mi_decl_nodiscard mi_decl_export void* mi_heap_recalloc_aligned(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept mi_attr_alloc_size2(3,4) mi_attr_alloc_align(5);
  197. mi_decl_nodiscard mi_decl_export void* mi_heap_recalloc_aligned_at(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size2(3,4);
  198. // ------------------------------------------------------
  199. // Analysis
  200. // ------------------------------------------------------
  201. mi_decl_export bool mi_heap_contains_block(mi_heap_t* heap, const void* p);
  202. mi_decl_export bool mi_heap_check_owned(mi_heap_t* heap, const void* p);
  203. mi_decl_export bool mi_check_owned(const void* p);
  204. // An area of heap space contains blocks of a single size.
  205. typedef struct mi_heap_area_s {
  206. void* blocks; // start of the area containing heap blocks
  207. size_t reserved; // bytes reserved for this area (virtual)
  208. size_t committed; // current available bytes for this area
  209. size_t used; // bytes in use by allocated blocks
  210. size_t block_size; // size in bytes of each block
  211. } mi_heap_area_t;
  212. typedef bool (mi_cdecl mi_block_visit_fun)(const mi_heap_t* heap, const mi_heap_area_t* area, void* block, size_t block_size, void* arg);
  213. mi_decl_export bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_all_blocks, mi_block_visit_fun* visitor, void* arg);
  214. // Experimental
  215. mi_decl_nodiscard mi_decl_export bool mi_is_in_heap_region(const void* p) mi_attr_noexcept;
  216. mi_decl_nodiscard mi_decl_export bool mi_is_redirected(void) mi_attr_noexcept;
  217. mi_decl_export int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t timeout_msecs) mi_attr_noexcept;
  218. mi_decl_export int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msecs) mi_attr_noexcept;
  219. mi_decl_export int mi_reserve_os_memory(size_t size, bool commit, bool allow_large) mi_attr_noexcept;
  220. mi_decl_export bool mi_manage_os_memory(void* start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node) mi_attr_noexcept;
  221. // deprecated
  222. mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept;
  223. // ------------------------------------------------------
  224. // Convenience
  225. // ------------------------------------------------------
  226. #define mi_malloc_tp(tp) ((tp*)mi_malloc(sizeof(tp)))
  227. #define mi_zalloc_tp(tp) ((tp*)mi_zalloc(sizeof(tp)))
  228. #define mi_calloc_tp(tp,n) ((tp*)mi_calloc(n,sizeof(tp)))
  229. #define mi_mallocn_tp(tp,n) ((tp*)mi_mallocn(n,sizeof(tp)))
  230. #define mi_reallocn_tp(p,tp,n) ((tp*)mi_reallocn(p,n,sizeof(tp)))
  231. #define mi_recalloc_tp(p,tp,n) ((tp*)mi_recalloc(p,n,sizeof(tp)))
  232. #define mi_heap_malloc_tp(hp,tp) ((tp*)mi_heap_malloc(hp,sizeof(tp)))
  233. #define mi_heap_zalloc_tp(hp,tp) ((tp*)mi_heap_zalloc(hp,sizeof(tp)))
  234. #define mi_heap_calloc_tp(hp,tp,n) ((tp*)mi_heap_calloc(hp,n,sizeof(tp)))
  235. #define mi_heap_mallocn_tp(hp,tp,n) ((tp*)mi_heap_mallocn(hp,n,sizeof(tp)))
  236. #define mi_heap_reallocn_tp(hp,p,tp,n) ((tp*)mi_heap_reallocn(hp,p,n,sizeof(tp)))
  237. #define mi_heap_recalloc_tp(hp,p,tp,n) ((tp*)mi_heap_recalloc(hp,p,n,sizeof(tp)))
  238. // ------------------------------------------------------
  239. // Options, all `false` by default
  240. // ------------------------------------------------------
  241. typedef enum mi_option_e {
  242. // stable options
  243. mi_option_show_errors,
  244. mi_option_show_stats,
  245. mi_option_verbose,
  246. // the following options are experimental
  247. mi_option_eager_commit,
  248. mi_option_eager_region_commit,
  249. mi_option_reset_decommits,
  250. mi_option_large_os_pages, // implies eager commit
  251. mi_option_reserve_huge_os_pages,
  252. mi_option_reserve_os_memory,
  253. mi_option_segment_cache,
  254. mi_option_page_reset,
  255. mi_option_abandoned_page_reset,
  256. mi_option_segment_reset,
  257. mi_option_eager_commit_delay,
  258. mi_option_reset_delay,
  259. mi_option_use_numa_nodes,
  260. mi_option_limit_os_alloc,
  261. mi_option_os_tag,
  262. mi_option_max_errors,
  263. mi_option_max_warnings,
  264. _mi_option_last
  265. } mi_option_t;
  266. mi_decl_nodiscard mi_decl_export bool mi_option_is_enabled(mi_option_t option);
  267. mi_decl_export void mi_option_enable(mi_option_t option);
  268. mi_decl_export void mi_option_disable(mi_option_t option);
  269. mi_decl_export void mi_option_set_enabled(mi_option_t option, bool enable);
  270. mi_decl_export void mi_option_set_enabled_default(mi_option_t option, bool enable);
  271. mi_decl_nodiscard mi_decl_export long mi_option_get(mi_option_t option);
  272. mi_decl_export void mi_option_set(mi_option_t option, long value);
  273. mi_decl_export void mi_option_set_default(mi_option_t option, long value);
  274. // -------------------------------------------------------------------------------------------------------
  275. // "mi" prefixed implementations of various posix, Unix, Windows, and C++ allocation functions.
  276. // (This can be convenient when providing overrides of these functions as done in `mimalloc-override.h`.)
  277. // note: we use `mi_cfree` as "checked free" and it checks if the pointer is in our heap before free-ing.
  278. // -------------------------------------------------------------------------------------------------------
  279. mi_decl_export void mi_cfree(void* p) mi_attr_noexcept;
  280. mi_decl_export void* mi__expand(void* p, size_t newsize) mi_attr_noexcept;
  281. mi_decl_nodiscard mi_decl_export size_t mi_malloc_size(const void* p) mi_attr_noexcept;
  282. mi_decl_nodiscard mi_decl_export size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept;
  283. mi_decl_export int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept;
  284. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(1);
  285. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_valloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
  286. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_pvalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
  287. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(1);
  288. mi_decl_nodiscard mi_decl_export void* mi_reallocarray(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_alloc_size2(2,3);
  289. mi_decl_nodiscard mi_decl_export void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept;
  290. mi_decl_nodiscard mi_decl_export void* mi_aligned_offset_recalloc(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept;
  291. mi_decl_nodiscard mi_decl_export mi_decl_restrict unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept mi_attr_malloc;
  292. mi_decl_nodiscard mi_decl_export mi_decl_restrict unsigned char* mi_mbsdup(const unsigned char* s) mi_attr_noexcept mi_attr_malloc;
  293. mi_decl_export int mi_dupenv_s(char** buf, size_t* size, const char* name) mi_attr_noexcept;
  294. mi_decl_export int mi_wdupenv_s(unsigned short** buf, size_t* size, const unsigned short* name) mi_attr_noexcept;
  295. mi_decl_export void mi_free_size(void* p, size_t size) mi_attr_noexcept;
  296. mi_decl_export void mi_free_size_aligned(void* p, size_t size, size_t alignment) mi_attr_noexcept;
  297. mi_decl_export void mi_free_aligned(void* p, size_t alignment) mi_attr_noexcept;
  298. // The `mi_new` wrappers implement C++ semantics on out-of-memory instead of directly returning `NULL`.
  299. // (and call `std::get_new_handler` and potentially raise a `std::bad_alloc` exception).
  300. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new(size_t size) mi_attr_malloc mi_attr_alloc_size(1);
  301. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_aligned(size_t size, size_t alignment) mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2);
  302. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_nothrow(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
  303. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_aligned_nothrow(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2);
  304. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_n(size_t count, size_t size) mi_attr_malloc mi_attr_alloc_size2(1, 2);
  305. mi_decl_nodiscard mi_decl_export void* mi_new_realloc(void* p, size_t newsize) mi_attr_alloc_size(2);
  306. mi_decl_nodiscard mi_decl_export void* mi_new_reallocn(void* p, size_t newcount, size_t size) mi_attr_alloc_size2(2, 3);
  307. #ifdef __cplusplus
  308. }
  309. #endif
  310. // ---------------------------------------------------------------------------------------------
  311. // Implement the C++ std::allocator interface for use in STL containers.
  312. // (note: see `mimalloc-new-delete.h` for overriding the new/delete operators globally)
  313. // ---------------------------------------------------------------------------------------------
  314. #ifdef __cplusplus
  315. #include <cstdint> // PTRDIFF_MAX
  316. #if (__cplusplus >= 201103L) || (_MSC_VER > 1900) // C++11
  317. #include <type_traits> // std::true_type
  318. #include <utility> // std::forward
  319. #endif
  320. template<class T> struct mi_stl_allocator {
  321. typedef T value_type;
  322. typedef std::size_t size_type;
  323. typedef std::ptrdiff_t difference_type;
  324. typedef value_type& reference;
  325. typedef value_type const& const_reference;
  326. typedef value_type* pointer;
  327. typedef value_type const* const_pointer;
  328. template <class U> struct rebind { typedef mi_stl_allocator<U> other; };
  329. mi_stl_allocator() mi_attr_noexcept = default;
  330. mi_stl_allocator(const mi_stl_allocator&) mi_attr_noexcept = default;
  331. template<class U> mi_stl_allocator(const mi_stl_allocator<U>&) mi_attr_noexcept { }
  332. mi_stl_allocator select_on_container_copy_construction() const { return *this; }
  333. void deallocate(T* p, size_type) { mi_free(p); }
  334. #if (__cplusplus >= 201703L) // C++17
  335. mi_decl_nodiscard T* allocate(size_type count) { return static_cast<T*>(mi_new_n(count, sizeof(T))); }
  336. mi_decl_nodiscard T* allocate(size_type count, const void*) { return allocate(count); }
  337. #else
  338. mi_decl_nodiscard pointer allocate(size_type count, const void* = 0) { return static_cast<pointer>(mi_new_n(count, sizeof(value_type))); }
  339. #endif
  340. #if ((__cplusplus >= 201103L) || (_MSC_VER > 1900)) // C++11
  341. using propagate_on_container_copy_assignment = std::true_type;
  342. using propagate_on_container_move_assignment = std::true_type;
  343. using propagate_on_container_swap = std::true_type;
  344. using is_always_equal = std::true_type;
  345. template <class U, class ...Args> void construct(U* p, Args&& ...args) { ::new(p) U(std::forward<Args>(args)...); }
  346. template <class U> void destroy(U* p) mi_attr_noexcept { p->~U(); }
  347. #else
  348. void construct(pointer p, value_type const& val) { ::new(p) value_type(val); }
  349. void destroy(pointer p) { p->~value_type(); }
  350. #endif
  351. size_type max_size() const mi_attr_noexcept { return (PTRDIFF_MAX/sizeof(value_type)); }
  352. pointer address(reference x) const { return &x; }
  353. const_pointer address(const_reference x) const { return &x; }
  354. };
  355. template<class T1,class T2> bool operator==(const mi_stl_allocator<T1>& , const mi_stl_allocator<T2>& ) mi_attr_noexcept { return true; }
  356. template<class T1,class T2> bool operator!=(const mi_stl_allocator<T1>& , const mi_stl_allocator<T2>& ) mi_attr_noexcept { return false; }
  357. #endif // __cplusplus
  358. #endif