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