1/* ----------------------------------------------------------------------------
2Copyright (c) 2018, 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 120 // major + 2 digits minor
12
13// ------------------------------------------------------
14// Compiler specific attributes
15// ------------------------------------------------------
16
17#ifdef __cplusplus
18 #if (__GNUC__ <= 5) || (_MSC_VER <= 1900)
19 #define mi_attr_noexcept throw()
20 #else
21 #define mi_attr_noexcept noexcept
22 #endif
23#else
24 #define mi_attr_noexcept
25#endif
26
27#ifdef _MSC_VER
28 #if !defined(MI_SHARED_LIB)
29 #define mi_decl_export
30 #elif defined(MI_SHARED_LIB_EXPORT)
31 #define mi_decl_export __declspec(dllexport)
32 #else
33 #define mi_decl_export __declspec(dllimport)
34 #endif
35 #if (_MSC_VER >= 1900) && !defined(__EDG__)
36 #define mi_decl_allocator __declspec(allocator) __declspec(restrict)
37 #else
38 #define mi_decl_allocator __declspec(restrict)
39 #endif
40 #define mi_decl_thread __declspec(thread)
41 #define mi_attr_malloc
42 #define mi_attr_alloc_size(s)
43 #define mi_attr_alloc_size2(s1,s2)
44 #define mi_cdecl __cdecl
45#elif defined(__GNUC__) || defined(__clang__)
46 #define mi_decl_thread __thread
47 #define mi_decl_export __attribute__((visibility("default")))
48 #define mi_decl_allocator
49 #define mi_attr_malloc __attribute__((malloc))
50 #if defined(__clang_major__) && (__clang_major__ < 4)
51 #define mi_attr_alloc_size(s)
52 #define mi_attr_alloc_size2(s1,s2)
53 #else
54 #define mi_attr_alloc_size(s) __attribute__((alloc_size(s)))
55 #define mi_attr_alloc_size2(s1,s2) __attribute__((alloc_size(s1,s2)))
56 #endif
57 #define mi_cdecl // leads to warnings... __attribute__((cdecl))
58#else
59 #define mi_decl_thread __thread
60 #define mi_decl_export
61 #define mi_decl_allocator
62 #define mi_attr_malloc
63 #define mi_attr_alloc_size(s)
64 #define mi_attr_alloc_size2(s1,s2)
65 #define mi_cdecl
66#endif
67
68// ------------------------------------------------------
69// Includes
70// ------------------------------------------------------
71
72#include <stddef.h> // size_t
73#include <stdbool.h> // bool
74
75#ifdef __cplusplus
76extern "C" {
77#endif
78
79// ------------------------------------------------------
80// Standard malloc interface
81// ------------------------------------------------------
82
83mi_decl_export mi_decl_allocator void* mi_malloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
84mi_decl_export mi_decl_allocator void* mi_calloc(size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2);
85mi_decl_export mi_decl_allocator void* mi_realloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
86mi_decl_export mi_decl_allocator void* mi_expand(void* p, size_t newsize) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
87
88mi_decl_export void mi_free(void* p) mi_attr_noexcept;
89mi_decl_export char* mi_strdup(const char* s) mi_attr_noexcept;
90mi_decl_export char* mi_strndup(const char* s, size_t n) mi_attr_noexcept;
91mi_decl_export char* mi_realpath(const char* fname, char* resolved_name) mi_attr_noexcept;
92
93// ------------------------------------------------------
94// Extended functionality
95// ------------------------------------------------------
96#define MI_SMALL_WSIZE_MAX (128)
97#define MI_SMALL_SIZE_MAX (MI_SMALL_WSIZE_MAX*sizeof(void*))
98
99mi_decl_export mi_decl_allocator void* mi_malloc_small(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
100mi_decl_export mi_decl_allocator void* mi_zalloc_small(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
101mi_decl_export mi_decl_allocator void* mi_zalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
102
103mi_decl_export mi_decl_allocator void* mi_mallocn(size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2);
104mi_decl_export mi_decl_allocator void* mi_reallocn(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2,3);
105mi_decl_export mi_decl_allocator void* mi_reallocf(void* p, size_t newsize) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
106
107
108mi_decl_export size_t mi_usable_size(const void* p) mi_attr_noexcept;
109mi_decl_export size_t mi_good_size(size_t size) mi_attr_noexcept;
110
111typedef void (mi_deferred_free_fun)(bool force, unsigned long long heartbeat);
112mi_decl_export void mi_register_deferred_free(mi_deferred_free_fun* deferred_free) mi_attr_noexcept;
113
114typedef void (mi_output_fun)(const char* msg);
115mi_decl_export void mi_register_output(mi_output_fun* out) mi_attr_noexcept;
116
117mi_decl_export void mi_collect(bool force) mi_attr_noexcept;
118mi_decl_export int mi_version(void) mi_attr_noexcept;
119mi_decl_export void mi_stats_reset(void) mi_attr_noexcept;
120mi_decl_export void mi_stats_merge(void) mi_attr_noexcept;
121mi_decl_export void mi_stats_print(mi_output_fun* out) mi_attr_noexcept;
122
123mi_decl_export void mi_process_init(void) mi_attr_noexcept;
124mi_decl_export void mi_thread_init(void) mi_attr_noexcept;
125mi_decl_export void mi_thread_done(void) mi_attr_noexcept;
126mi_decl_export void mi_thread_stats_print(mi_output_fun* out) mi_attr_noexcept;
127
128
129// -------------------------------------------------------------------------------------
130// Aligned allocation
131// Note that `alignment` always follows `size` for consistency with unaligned
132// allocation, but unfortunately this differs from `posix_memalign` and `aligned_alloc`.
133// -------------------------------------------------------------------------------------
134
135mi_decl_export mi_decl_allocator void* mi_malloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
136mi_decl_export mi_decl_allocator 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);
137mi_decl_export mi_decl_allocator void* mi_zalloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
138mi_decl_export mi_decl_allocator 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);
139mi_decl_export mi_decl_allocator 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);
140mi_decl_export mi_decl_allocator 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);
141mi_decl_export mi_decl_allocator void* mi_realloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
142mi_decl_export mi_decl_allocator void* mi_realloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
143
144
145// ------------------------------------------------------
146// Heaps
147// ------------------------------------------------------
148struct mi_heap_s;
149typedef struct mi_heap_s mi_heap_t;
150
151mi_decl_export mi_heap_t* mi_heap_new(void);
152mi_decl_export void mi_heap_delete(mi_heap_t* heap);
153mi_decl_export void mi_heap_destroy(mi_heap_t* heap);
154mi_decl_export mi_heap_t* mi_heap_set_default(mi_heap_t* heap);
155mi_decl_export mi_heap_t* mi_heap_get_default(void);
156mi_decl_export mi_heap_t* mi_heap_get_backing(void);
157mi_decl_export void mi_heap_collect(mi_heap_t* heap, bool force) mi_attr_noexcept;
158
159mi_decl_export mi_decl_allocator void* mi_heap_malloc(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
160mi_decl_export mi_decl_allocator void* mi_heap_zalloc(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
161mi_decl_export mi_decl_allocator 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);
162mi_decl_export mi_decl_allocator 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);
163mi_decl_export mi_decl_allocator void* mi_heap_malloc_small(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
164
165mi_decl_export mi_decl_allocator void* mi_heap_realloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(3);
166mi_decl_export mi_decl_allocator void* mi_heap_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept;
167mi_decl_export mi_decl_allocator void* mi_heap_reallocf(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(3);
168
169mi_decl_export char* mi_heap_strdup(mi_heap_t* heap, const char* s) mi_attr_noexcept;
170mi_decl_export char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n) mi_attr_noexcept;
171mi_decl_export char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char* resolved_name) mi_attr_noexcept;
172
173mi_decl_export mi_decl_allocator 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);
174mi_decl_export mi_decl_allocator 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);
175mi_decl_export mi_decl_allocator 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);
176mi_decl_export mi_decl_allocator 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);
177mi_decl_export mi_decl_allocator 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);
178mi_decl_export mi_decl_allocator 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);
179mi_decl_export mi_decl_allocator void* mi_heap_realloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(3);
180mi_decl_export mi_decl_allocator 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_malloc mi_attr_alloc_size(3);
181
182
183// --------------------------------------------------------------------------------
184// Zero initialized re-allocation.
185// Only valid on memory that was originally allocated with zero initialization too.
186// e.g. `mi_calloc`, `mi_zalloc`, `mi_zalloc_aligned` etc.
187// see <https://github.com/microsoft/mimalloc/issues/63#issuecomment-508272992>
188// --------------------------------------------------------------------------------
189
190mi_decl_export mi_decl_allocator void* mi_rezalloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
191mi_decl_export mi_decl_allocator void* mi_recalloc(void* p, size_t newcount, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2,3);
192
193mi_decl_export mi_decl_allocator void* mi_rezalloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
194mi_decl_export mi_decl_allocator void* mi_rezalloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
195mi_decl_export mi_decl_allocator void* mi_recalloc_aligned(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2,3);
196mi_decl_export mi_decl_allocator void* mi_recalloc_aligned_at(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2,3);
197
198mi_decl_export mi_decl_allocator void* mi_heap_rezalloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(3);
199mi_decl_export mi_decl_allocator void* mi_heap_recalloc(mi_heap_t* heap, void* p, size_t newcount, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(3,4);
200
201mi_decl_export mi_decl_allocator void* mi_heap_rezalloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(3);
202mi_decl_export mi_decl_allocator 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_malloc mi_attr_alloc_size(3);
203mi_decl_export mi_decl_allocator 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_malloc mi_attr_alloc_size2(3,4);
204mi_decl_export mi_decl_allocator 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_malloc mi_attr_alloc_size2(3,4);
205
206
207// ------------------------------------------------------
208// Analysis
209// ------------------------------------------------------
210
211mi_decl_export bool mi_heap_contains_block(mi_heap_t* heap, const void* p);
212
213mi_decl_export bool mi_heap_check_owned(mi_heap_t* heap, const void* p);
214mi_decl_export bool mi_check_owned(const void* p);
215
216// An area of heap space contains blocks of a single size.
217typedef struct mi_heap_area_s {
218 void* blocks; // start of the area containing heap blocks
219 size_t reserved; // bytes reserved for this area (virtual)
220 size_t committed; // current available bytes for this area
221 size_t used; // bytes in use by allocated blocks
222 size_t block_size; // size in bytes of each block
223} mi_heap_area_t;
224
225typedef 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);
226
227mi_decl_export bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_all_blocks, mi_block_visit_fun* visitor, void* arg);
228
229// Experimental
230mi_decl_export bool mi_is_in_heap_region(const void* p) mi_attr_noexcept;
231mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept;
232mi_decl_export bool mi_is_redirected() mi_attr_noexcept;
233
234// ------------------------------------------------------
235// Convenience
236// ------------------------------------------------------
237
238#define mi_malloc_tp(tp) ((tp*)mi_malloc(sizeof(tp)))
239#define mi_zalloc_tp(tp) ((tp*)mi_zalloc(sizeof(tp)))
240#define mi_calloc_tp(tp,n) ((tp*)mi_calloc(n,sizeof(tp)))
241#define mi_mallocn_tp(tp,n) ((tp*)mi_mallocn(n,sizeof(tp)))
242#define mi_reallocn_tp(p,tp,n) ((tp*)mi_reallocn(p,n,sizeof(tp)))
243#define mi_recalloc_tp(p,tp,n) ((tp*)mi_recalloc(p,n,sizeof(tp)))
244
245#define mi_heap_malloc_tp(hp,tp) ((tp*)mi_heap_malloc(hp,sizeof(tp)))
246#define mi_heap_zalloc_tp(hp,tp) ((tp*)mi_heap_zalloc(hp,sizeof(tp)))
247#define mi_heap_calloc_tp(hp,tp,n) ((tp*)mi_heap_calloc(hp,n,sizeof(tp)))
248#define mi_heap_mallocn_tp(hp,tp,n) ((tp*)mi_heap_mallocn(hp,n,sizeof(tp)))
249#define mi_heap_reallocn_tp(hp,p,tp,n) ((tp*)mi_heap_reallocn(hp,p,n,sizeof(tp)))
250#define mi_heap_recalloc_tp(hp,p,tp,n) ((tp*)mi_heap_recalloc(hp,p,n,sizeof(tp)))
251
252
253// ------------------------------------------------------
254// Options, all `false` by default
255// ------------------------------------------------------
256
257typedef enum mi_option_e {
258 // stable options
259 mi_option_show_errors,
260 mi_option_show_stats,
261 mi_option_verbose,
262 // the following options are experimental
263 mi_option_eager_commit,
264 mi_option_eager_region_commit,
265 mi_option_large_os_pages, // implies eager commit
266 mi_option_reserve_huge_os_pages,
267 mi_option_segment_cache,
268 mi_option_page_reset,
269 mi_option_cache_reset,
270 mi_option_reset_decommits,
271 mi_option_eager_commit_delay,
272 mi_option_segment_reset,
273 mi_option_os_tag,
274 mi_option_max_errors,
275 _mi_option_last
276} mi_option_t;
277
278
279mi_decl_export bool mi_option_is_enabled(mi_option_t option);
280mi_decl_export void mi_option_enable(mi_option_t option);
281mi_decl_export void mi_option_disable(mi_option_t option);
282mi_decl_export void mi_option_set_enabled(mi_option_t option, bool enable);
283mi_decl_export void mi_option_set_enabled_default(mi_option_t option, bool enable);
284
285mi_decl_export long mi_option_get(mi_option_t option);
286mi_decl_export void mi_option_set(mi_option_t option, long value);
287mi_decl_export void mi_option_set_default(mi_option_t option, long value);
288
289
290// -------------------------------------------------------------------------------------------------------
291// "mi" prefixed implementations of various posix, Unix, Windows, and C++ allocation functions.
292// (This can be convenient when providing overrides of these functions as done in `mimalloc-override.h`.)
293// -------------------------------------------------------------------------------------------------------
294
295mi_decl_export size_t mi_malloc_size(const void* p) mi_attr_noexcept;
296mi_decl_export size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept;
297mi_decl_export void mi_cfree(void* p) mi_attr_noexcept;
298mi_decl_export void* mi__expand(void* p, size_t newsize) mi_attr_noexcept;
299
300mi_decl_export int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept;
301mi_decl_export void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
302mi_decl_export void* mi_valloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
303
304mi_decl_export void* mi_pvalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
305mi_decl_export void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
306mi_decl_export void* mi_reallocarray(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2,3);
307
308mi_decl_export void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept;
309mi_decl_export void* mi_aligned_offset_recalloc(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept;
310
311mi_decl_export unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept;
312mi_decl_export unsigned char* mi_mbsdup(const unsigned char* s) mi_attr_noexcept;
313mi_decl_export int mi_dupenv_s(char** buf, size_t* size, const char* name) mi_attr_noexcept;
314mi_decl_export int mi_wdupenv_s(unsigned short** buf, size_t* size, const unsigned short* name) mi_attr_noexcept;
315
316mi_decl_export void mi_free_size(void* p, size_t size) mi_attr_noexcept;
317mi_decl_export void mi_free_size_aligned(void* p, size_t size, size_t alignment) mi_attr_noexcept;
318mi_decl_export void mi_free_aligned(void* p, size_t alignment) mi_attr_noexcept;
319
320mi_decl_export void* mi_new(size_t n) mi_attr_malloc mi_attr_alloc_size(1);
321mi_decl_export void* mi_new_aligned(size_t n, size_t alignment) mi_attr_malloc mi_attr_alloc_size(1);
322mi_decl_export void* mi_new_nothrow(size_t n) mi_attr_malloc mi_attr_alloc_size(1);
323mi_decl_export void* mi_new_aligned_nothrow(size_t n, size_t alignment) mi_attr_malloc mi_attr_alloc_size(1);
324
325#ifdef __cplusplus
326}
327#endif
328
329
330#endif
331