1/* ----------------------------------------------------------------------------
2Copyright (c) 2018-2022, Microsoft Research, Daan Leijen
3This is free software; you can redistribute it and/or modify it under the
4terms 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 207 // 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 (defined(__GNUC__) && (__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 #if defined(MI_SHARED_LIB) && defined(MI_SHARED_LIB_EXPORT)
62 #define mi_decl_export __attribute__((visibility("default")))
63 #else
64 #define mi_decl_export
65 #endif
66 #define mi_cdecl // leads to warnings... __attribute__((cdecl))
67 #define mi_decl_restrict
68 #define mi_attr_malloc __attribute__((malloc))
69 #if (defined(__clang_major__) && (__clang_major__ < 4)) || (__GNUC__ < 5)
70 #define mi_attr_alloc_size(s)
71 #define mi_attr_alloc_size2(s1,s2)
72 #define mi_attr_alloc_align(p)
73 #elif defined(__INTEL_COMPILER)
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)
77 #else
78 #define mi_attr_alloc_size(s) __attribute__((alloc_size(s)))
79 #define mi_attr_alloc_size2(s1,s2) __attribute__((alloc_size(s1,s2)))
80 #define mi_attr_alloc_align(p) __attribute__((alloc_align(p)))
81 #endif
82#else
83 #define mi_cdecl
84 #define mi_decl_export
85 #define mi_decl_restrict
86 #define mi_attr_malloc
87 #define mi_attr_alloc_size(s)
88 #define mi_attr_alloc_size2(s1,s2)
89 #define mi_attr_alloc_align(p)
90#endif
91
92// ------------------------------------------------------
93// Includes
94// ------------------------------------------------------
95
96#include <stddef.h> // size_t
97#include <stdbool.h> // bool
98#include <stdint.h> // INTPTR_MAX
99
100#ifdef __cplusplus
101extern "C" {
102#endif
103
104// ------------------------------------------------------
105// Standard malloc interface
106// ------------------------------------------------------
107
108mi_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);
109mi_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);
110mi_decl_nodiscard mi_decl_export void* mi_realloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2);
111mi_decl_export void* mi_expand(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2);
112
113mi_decl_export void mi_free(void* p) mi_attr_noexcept;
114mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_strdup(const char* s) mi_attr_noexcept mi_attr_malloc;
115mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_strndup(const char* s, size_t n) mi_attr_noexcept mi_attr_malloc;
116mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_realpath(const char* fname, char* resolved_name) mi_attr_noexcept mi_attr_malloc;
117
118// ------------------------------------------------------
119// Extended functionality
120// ------------------------------------------------------
121#define MI_SMALL_WSIZE_MAX (128)
122#define MI_SMALL_SIZE_MAX (MI_SMALL_WSIZE_MAX*sizeof(void*))
123
124mi_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);
125mi_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);
126mi_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);
127
128mi_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);
129mi_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);
130mi_decl_nodiscard mi_decl_export void* mi_reallocf(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2);
131
132mi_decl_nodiscard mi_decl_export size_t mi_usable_size(const void* p) mi_attr_noexcept;
133mi_decl_nodiscard mi_decl_export size_t mi_good_size(size_t size) mi_attr_noexcept;
134
135
136// ------------------------------------------------------
137// Internals
138// ------------------------------------------------------
139
140typedef void (mi_cdecl mi_deferred_free_fun)(bool force, unsigned long long heartbeat, void* arg);
141mi_decl_export void mi_register_deferred_free(mi_deferred_free_fun* deferred_free, void* arg) mi_attr_noexcept;
142
143typedef void (mi_cdecl mi_output_fun)(const char* msg, void* arg);
144mi_decl_export void mi_register_output(mi_output_fun* out, void* arg) mi_attr_noexcept;
145
146typedef void (mi_cdecl mi_error_fun)(int err, void* arg);
147mi_decl_export void mi_register_error(mi_error_fun* fun, void* arg);
148
149mi_decl_export void mi_collect(bool force) mi_attr_noexcept;
150mi_decl_export int mi_version(void) mi_attr_noexcept;
151mi_decl_export void mi_stats_reset(void) mi_attr_noexcept;
152mi_decl_export void mi_stats_merge(void) mi_attr_noexcept;
153mi_decl_export void mi_stats_print(void* out) mi_attr_noexcept; // backward compatibility: `out` is ignored and should be NULL
154mi_decl_export void mi_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept;
155
156mi_decl_export void mi_process_init(void) mi_attr_noexcept;
157mi_decl_export void mi_thread_init(void) mi_attr_noexcept;
158mi_decl_export void mi_thread_done(void) mi_attr_noexcept;
159mi_decl_export void mi_thread_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept;
160
161mi_decl_export void mi_process_info(size_t* elapsed_msecs, size_t* user_msecs, size_t* system_msecs,
162 size_t* current_rss, size_t* peak_rss,
163 size_t* current_commit, size_t* peak_commit, size_t* page_faults) mi_attr_noexcept;
164
165// -------------------------------------------------------------------------------------
166// Aligned allocation
167// Note that `alignment` always follows `size` for consistency with unaligned
168// allocation, but unfortunately this differs from `posix_memalign` and `aligned_alloc`.
169// -------------------------------------------------------------------------------------
170#if (INTPTR_MAX > INT32_MAX)
171#define MI_ALIGNMENT_MAX (16*1024*1024UL) // maximum supported alignment is 16MiB
172#else
173#define MI_ALIGNMENT_MAX (1024*1024UL) // maximum supported alignment for 32-bit systems is 1MiB
174#endif
175
176mi_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);
177mi_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);
178mi_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);
179mi_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);
180mi_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);
181mi_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);
182mi_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);
183mi_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);
184
185
186// -------------------------------------------------------------------------------------
187// Heaps: first-class, but can only allocate from the same thread that created it.
188// -------------------------------------------------------------------------------------
189
190struct mi_heap_s;
191typedef struct mi_heap_s mi_heap_t;
192
193mi_decl_nodiscard mi_decl_export mi_heap_t* mi_heap_new(void);
194mi_decl_export void mi_heap_delete(mi_heap_t* heap);
195mi_decl_export void mi_heap_destroy(mi_heap_t* heap);
196mi_decl_export mi_heap_t* mi_heap_set_default(mi_heap_t* heap);
197mi_decl_export mi_heap_t* mi_heap_get_default(void);
198mi_decl_export mi_heap_t* mi_heap_get_backing(void);
199mi_decl_export void mi_heap_collect(mi_heap_t* heap, bool force) mi_attr_noexcept;
200
201mi_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);
202mi_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);
203mi_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);
204mi_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);
205mi_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);
206
207mi_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);
208mi_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);
209mi_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);
210
211mi_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;
212mi_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;
213mi_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;
214
215mi_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);
216mi_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);
217mi_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);
218mi_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);
219mi_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);
220mi_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);
221mi_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);
222mi_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);
223
224
225// --------------------------------------------------------------------------------
226// Zero initialized re-allocation.
227// Only valid on memory that was originally allocated with zero initialization too.
228// e.g. `mi_calloc`, `mi_zalloc`, `mi_zalloc_aligned` etc.
229// see <https://github.com/microsoft/mimalloc/issues/63#issuecomment-508272992>
230// --------------------------------------------------------------------------------
231
232mi_decl_nodiscard mi_decl_export void* mi_rezalloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2);
233mi_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);
234
235mi_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);
236mi_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);
237mi_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);
238mi_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);
239
240mi_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);
241mi_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);
242
243mi_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);
244mi_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);
245mi_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);
246mi_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);
247
248
249// ------------------------------------------------------
250// Analysis
251// ------------------------------------------------------
252
253mi_decl_export bool mi_heap_contains_block(mi_heap_t* heap, const void* p);
254mi_decl_export bool mi_heap_check_owned(mi_heap_t* heap, const void* p);
255mi_decl_export bool mi_check_owned(const void* p);
256
257// An area of heap space contains blocks of a single size.
258typedef struct mi_heap_area_s {
259 void* blocks; // start of the area containing heap blocks
260 size_t reserved; // bytes reserved for this area (virtual)
261 size_t committed; // current available bytes for this area
262 size_t used; // number of allocated blocks
263 size_t block_size; // size in bytes of each block
264 size_t full_block_size; // size in bytes of a full block including padding and metadata.
265} mi_heap_area_t;
266
267typedef 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);
268
269mi_decl_export bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_all_blocks, mi_block_visit_fun* visitor, void* arg);
270
271// Experimental
272mi_decl_nodiscard mi_decl_export bool mi_is_in_heap_region(const void* p) mi_attr_noexcept;
273mi_decl_nodiscard mi_decl_export bool mi_is_redirected(void) mi_attr_noexcept;
274
275mi_decl_export int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t timeout_msecs) mi_attr_noexcept;
276mi_decl_export int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msecs) mi_attr_noexcept;
277
278mi_decl_export int mi_reserve_os_memory(size_t size, bool commit, bool allow_large) mi_attr_noexcept;
279mi_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;
280
281mi_decl_export void mi_debug_show_arenas(void) mi_attr_noexcept;
282
283// Experimental: heaps associated with specific memory arena's
284typedef int mi_arena_id_t;
285mi_decl_export void* mi_arena_area(mi_arena_id_t arena_id, size_t* size);
286mi_decl_export int mi_reserve_huge_os_pages_at_ex(size_t pages, int numa_node, size_t timeout_msecs, bool exclusive, mi_arena_id_t* arena_id) mi_attr_noexcept;
287mi_decl_export int mi_reserve_os_memory_ex(size_t size, bool commit, bool allow_large, bool exclusive, mi_arena_id_t* arena_id) mi_attr_noexcept;
288mi_decl_export bool mi_manage_os_memory_ex(void* start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node, bool exclusive, mi_arena_id_t* arena_id) mi_attr_noexcept;
289
290#if MI_MALLOC_VERSION >= 200
291mi_decl_nodiscard mi_decl_export mi_heap_t* mi_heap_new_in_arena(mi_arena_id_t arena_id);
292#endif
293
294// deprecated
295mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept;
296
297
298// ------------------------------------------------------
299// Convenience
300// ------------------------------------------------------
301
302#define mi_malloc_tp(tp) ((tp*)mi_malloc(sizeof(tp)))
303#define mi_zalloc_tp(tp) ((tp*)mi_zalloc(sizeof(tp)))
304#define mi_calloc_tp(tp,n) ((tp*)mi_calloc(n,sizeof(tp)))
305#define mi_mallocn_tp(tp,n) ((tp*)mi_mallocn(n,sizeof(tp)))
306#define mi_reallocn_tp(p,tp,n) ((tp*)mi_reallocn(p,n,sizeof(tp)))
307#define mi_recalloc_tp(p,tp,n) ((tp*)mi_recalloc(p,n,sizeof(tp)))
308
309#define mi_heap_malloc_tp(hp,tp) ((tp*)mi_heap_malloc(hp,sizeof(tp)))
310#define mi_heap_zalloc_tp(hp,tp) ((tp*)mi_heap_zalloc(hp,sizeof(tp)))
311#define mi_heap_calloc_tp(hp,tp,n) ((tp*)mi_heap_calloc(hp,n,sizeof(tp)))
312#define mi_heap_mallocn_tp(hp,tp,n) ((tp*)mi_heap_mallocn(hp,n,sizeof(tp)))
313#define mi_heap_reallocn_tp(hp,p,tp,n) ((tp*)mi_heap_reallocn(hp,p,n,sizeof(tp)))
314#define mi_heap_recalloc_tp(hp,p,tp,n) ((tp*)mi_heap_recalloc(hp,p,n,sizeof(tp)))
315
316
317// ------------------------------------------------------
318// Options
319// ------------------------------------------------------
320
321typedef enum mi_option_e {
322 // stable options
323 mi_option_show_errors,
324 mi_option_show_stats,
325 mi_option_verbose,
326 // some of the following options are experimental
327 // (deprecated options are kept for binary backward compatibility with v1.x versions)
328 mi_option_eager_commit,
329 mi_option_deprecated_eager_region_commit,
330 mi_option_deprecated_reset_decommits,
331 mi_option_large_os_pages, // use large (2MiB) OS pages, implies eager commit
332 mi_option_reserve_huge_os_pages, // reserve N huge OS pages (1GiB) at startup
333 mi_option_reserve_huge_os_pages_at, // reserve huge OS pages at a specific NUMA node
334 mi_option_reserve_os_memory, // reserve specified amount of OS memory at startup
335 mi_option_deprecated_segment_cache,
336 mi_option_page_reset,
337 mi_option_abandoned_page_decommit,
338 mi_option_deprecated_segment_reset,
339 mi_option_eager_commit_delay,
340 mi_option_decommit_delay,
341 mi_option_use_numa_nodes, // 0 = use available numa nodes, otherwise use at most N nodes.
342 mi_option_limit_os_alloc, // 1 = do not use OS memory for allocation (but only reserved arenas)
343 mi_option_os_tag,
344 mi_option_max_errors,
345 mi_option_max_warnings,
346 mi_option_max_segment_reclaim,
347 mi_option_allow_decommit,
348 mi_option_segment_decommit_delay,
349 mi_option_decommit_extend_delay,
350 _mi_option_last
351} mi_option_t;
352
353
354mi_decl_nodiscard mi_decl_export bool mi_option_is_enabled(mi_option_t option);
355mi_decl_export void mi_option_enable(mi_option_t option);
356mi_decl_export void mi_option_disable(mi_option_t option);
357mi_decl_export void mi_option_set_enabled(mi_option_t option, bool enable);
358mi_decl_export void mi_option_set_enabled_default(mi_option_t option, bool enable);
359
360mi_decl_nodiscard mi_decl_export long mi_option_get(mi_option_t option);
361mi_decl_nodiscard mi_decl_export long mi_option_get_clamp(mi_option_t option, long min, long max);
362mi_decl_export void mi_option_set(mi_option_t option, long value);
363mi_decl_export void mi_option_set_default(mi_option_t option, long value);
364
365
366// -------------------------------------------------------------------------------------------------------
367// "mi" prefixed implementations of various posix, Unix, Windows, and C++ allocation functions.
368// (This can be convenient when providing overrides of these functions as done in `mimalloc-override.h`.)
369// note: we use `mi_cfree` as "checked free" and it checks if the pointer is in our heap before free-ing.
370// -------------------------------------------------------------------------------------------------------
371
372mi_decl_export void mi_cfree(void* p) mi_attr_noexcept;
373mi_decl_export void* mi__expand(void* p, size_t newsize) mi_attr_noexcept;
374mi_decl_nodiscard mi_decl_export size_t mi_malloc_size(const void* p) mi_attr_noexcept;
375mi_decl_nodiscard mi_decl_export size_t mi_malloc_good_size(size_t size) mi_attr_noexcept;
376mi_decl_nodiscard mi_decl_export size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept;
377
378mi_decl_export int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept;
379mi_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);
380mi_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);
381mi_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);
382mi_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);
383
384mi_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);
385mi_decl_nodiscard mi_decl_export int mi_reallocarr(void* p, size_t count, size_t size) mi_attr_noexcept;
386mi_decl_nodiscard mi_decl_export void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept;
387mi_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;
388
389mi_decl_nodiscard mi_decl_export mi_decl_restrict unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept mi_attr_malloc;
390mi_decl_nodiscard mi_decl_export mi_decl_restrict unsigned char* mi_mbsdup(const unsigned char* s) mi_attr_noexcept mi_attr_malloc;
391mi_decl_export int mi_dupenv_s(char** buf, size_t* size, const char* name) mi_attr_noexcept;
392mi_decl_export int mi_wdupenv_s(unsigned short** buf, size_t* size, const unsigned short* name) mi_attr_noexcept;
393
394mi_decl_export void mi_free_size(void* p, size_t size) mi_attr_noexcept;
395mi_decl_export void mi_free_size_aligned(void* p, size_t size, size_t alignment) mi_attr_noexcept;
396mi_decl_export void mi_free_aligned(void* p, size_t alignment) mi_attr_noexcept;
397
398// The `mi_new` wrappers implement C++ semantics on out-of-memory instead of directly returning `NULL`.
399// (and call `std::get_new_handler` and potentially raise a `std::bad_alloc` exception).
400mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new(size_t size) mi_attr_malloc mi_attr_alloc_size(1);
401mi_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);
402mi_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);
403mi_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);
404mi_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);
405mi_decl_nodiscard mi_decl_export void* mi_new_realloc(void* p, size_t newsize) mi_attr_alloc_size(2);
406mi_decl_nodiscard mi_decl_export void* mi_new_reallocn(void* p, size_t newcount, size_t size) mi_attr_alloc_size2(2, 3);
407
408#ifdef __cplusplus
409}
410#endif
411
412// ---------------------------------------------------------------------------------------------
413// Implement the C++ std::allocator interface for use in STL containers.
414// (note: see `mimalloc-new-delete.h` for overriding the new/delete operators globally)
415// ---------------------------------------------------------------------------------------------
416#ifdef __cplusplus
417
418#include <cstddef> // std::size_t
419#include <cstdint> // PTRDIFF_MAX
420#if (__cplusplus >= 201103L) || (_MSC_VER > 1900) // C++11
421#include <type_traits> // std::true_type
422#include <utility> // std::forward
423#endif
424
425template<class T> struct mi_stl_allocator {
426 typedef T value_type;
427 typedef std::size_t size_type;
428 typedef std::ptrdiff_t difference_type;
429 typedef value_type& reference;
430 typedef value_type const& const_reference;
431 typedef value_type* pointer;
432 typedef value_type const* const_pointer;
433 template <class U> struct rebind { typedef mi_stl_allocator<U> other; };
434
435 mi_stl_allocator() mi_attr_noexcept = default;
436 mi_stl_allocator(const mi_stl_allocator&) mi_attr_noexcept = default;
437 template<class U> mi_stl_allocator(const mi_stl_allocator<U>&) mi_attr_noexcept { }
438 mi_stl_allocator select_on_container_copy_construction() const { return *this; }
439 void deallocate(T* p, size_type) { mi_free(p); }
440
441 #if (__cplusplus >= 201703L) // C++17
442 mi_decl_nodiscard T* allocate(size_type count) { return static_cast<T*>(mi_new_n(count, sizeof(T))); }
443 mi_decl_nodiscard T* allocate(size_type count, const void*) { return allocate(count); }
444 #else
445 mi_decl_nodiscard pointer allocate(size_type count, const void* = 0) { return static_cast<pointer>(mi_new_n(count, sizeof(value_type))); }
446 #endif
447
448 #if ((__cplusplus >= 201103L) || (_MSC_VER > 1900)) // C++11
449 using propagate_on_container_copy_assignment = std::true_type;
450 using propagate_on_container_move_assignment = std::true_type;
451 using propagate_on_container_swap = std::true_type;
452 using is_always_equal = std::true_type;
453 template <class U, class ...Args> void construct(U* p, Args&& ...args) { ::new(p) U(std::forward<Args>(args)...); }
454 template <class U> void destroy(U* p) mi_attr_noexcept { p->~U(); }
455 #else
456 void construct(pointer p, value_type const& val) { ::new(p) value_type(val); }
457 void destroy(pointer p) { p->~value_type(); }
458 #endif
459
460 size_type max_size() const mi_attr_noexcept { return (PTRDIFF_MAX/sizeof(value_type)); }
461 pointer address(reference x) const { return &x; }
462 const_pointer address(const_reference x) const { return &x; }
463};
464
465template<class T1,class T2> bool operator==(const mi_stl_allocator<T1>& , const mi_stl_allocator<T2>& ) mi_attr_noexcept { return true; }
466template<class T1,class T2> bool operator!=(const mi_stl_allocator<T1>& , const mi_stl_allocator<T2>& ) mi_attr_noexcept { return false; }
467#endif // __cplusplus
468
469#endif
470