cesium_libmimalloc_sys/allocator.rs
1use std::ffi::{c_char, c_int, c_void};
2
3use crate::{allocator, mi_deferred_free_fun, mi_error_fun, mi_output_fun, MI_SMALL_SIZE_MAX};
4
5extern "C" {
6 /// Allocate zero-initialized `size` bytes.
7 ///
8 /// Returns a pointer to newly allocated zero-initialized memory, or null if
9 /// out of memory.
10 pub fn mi_zalloc(size: usize) -> *mut c_void;
11
12 /// Allocate `size` bytes.
13 ///
14 /// Returns pointer to the allocated memory or null if out of memory.
15 /// Returns a unique pointer if called with `size` 0.
16 pub fn mi_malloc(size: usize) -> *mut c_void;
17
18 /// Re-allocate memory to `newsize` bytes.
19 ///
20 /// Return pointer to the allocated memory or null if out of memory. If null
21 /// is returned, the pointer `p` is not freed. Otherwise the original
22 /// pointer is either freed or returned as the reallocated result (in case
23 /// it fits in-place with the new size).
24 ///
25 /// If `p` is null, it behaves as [`mi_malloc`]. If `newsize` is larger than
26 /// the original `size` allocated for `p`, the bytes after `size` are
27 /// uninitialized.
28 pub fn mi_realloc(p: *mut c_void, newsize: usize) -> *mut c_void;
29
30 /// Allocate `size` bytes aligned by `alignment`, initialized to zero.
31 ///
32 /// Return pointer to the allocated memory or null if out of memory.
33 ///
34 /// Returns a unique pointer if called with `size` 0.
35 pub fn mi_zalloc_aligned(size: usize, alignment: usize) -> *mut c_void;
36
37 /// Allocate `size` bytes aligned by `alignment`.
38 ///
39 /// Return pointer to the allocated memory or null if out of memory.
40 ///
41 /// Returns a unique pointer if called with `size` 0.
42 pub fn mi_malloc_aligned(size: usize, alignment: usize) -> *mut c_void;
43
44 /// Re-allocate memory to `newsize` bytes, aligned by `alignment`.
45 ///
46 /// Return pointer to the allocated memory or null if out of memory. If null
47 /// is returned, the pointer `p` is not freed. Otherwise the original
48 /// pointer is either freed or returned as the reallocated result (in case
49 /// it fits in-place with the new size).
50 ///
51 /// If `p` is null, it behaves as [`mi_malloc_aligned`]. If `newsize` is
52 /// larger than the original `size` allocated for `p`, the bytes after
53 /// `size` are uninitialized.
54 pub fn mi_realloc_aligned(p: *mut c_void, newsize: usize, alignment: usize) -> *mut c_void;
55
56 /// Free previously allocated memory.
57 ///
58 /// The pointer `p` must have been allocated before (or be null).
59 pub fn mi_free(p: *mut c_void);
60
61 /// Return the available bytes in a memory block.
62 ///
63 /// The returned size can be used to call `mi_expand` successfully.
64 pub fn mi_usable_size(p: *const c_void) -> usize;
65
66 /// Allocate `count` items of `size` length each.
67 ///
68 /// Returns `null` if `count * size` overflows or on out-of-memory.
69 ///
70 /// All items are initialized to zero.
71 pub fn mi_calloc(count: usize, size: usize) -> *mut c_void;
72
73 /// Allocate `count` items of `size` length each.
74 ///
75 /// Returns `null` if `count * size` overflows or on out-of-memory,
76 /// otherwise returns the same as [`mi_malloc(count * size)`].
77 /// Equivalent to [`mi_calloc`], but returns uninitialized (and not zeroed)
78 /// bytes.
79 pub fn mi_mallocn(count: usize, size: usize) -> *mut c_void;
80
81 /// Re-allocate memory to `count` elements of `size` bytes.
82 ///
83 /// The realloc equivalent of the [`mi_mallocn`] interface. Returns `null`
84 /// if `count * size` overflows or on out-of-memory, otherwise returns the
85 /// same as [`mi_realloc(p, count * size)`].
86 pub fn mi_reallocn(p: *mut c_void, count: usize, size: usize) -> *mut c_void;
87
88 /// Try to re-allocate memory to `newsize` bytes _in place_.
89 ///
90 /// Returns null on out-of-memory or if the memory could not be expanded in
91 /// place. On success, returns the same pointer as `p`.
92 ///
93 /// If `newsize` is larger than the original `size` allocated for `p`, the
94 /// bytes after `size` are uninitialized.
95 ///
96 /// If null is returned, the original pointer is not freed.
97 ///
98 /// Note: Conceptually, this is a realloc-like which returns null if it
99 /// would be forced to reallocate memory and copy. In practice it's
100 /// equivalent testing against [`mi_usable_size`].
101 pub fn mi_expand(p: *mut c_void, newsize: usize) -> *mut c_void;
102
103 /// Re-allocate memory to `newsize` bytes.
104 ///
105 /// This differs from [`mi_realloc`] in that on failure,
106 /// `p` is freed.
107 pub fn mi_reallocf(p: *mut c_void, newsize: usize) -> *mut c_void;
108
109 /// Allocate and duplicate a nul-terminated C string.
110 ///
111 /// This can be useful for Rust code when interacting with the FFI.
112 pub fn mi_strdup(s: *const c_char) -> *mut c_char;
113
114 /// Allocate and duplicate a nul-terminated C string, up to `n` bytes.
115 ///
116 /// This can be useful for Rust code when interacting with the FFI.
117 pub fn mi_strndup(s: *const c_char, n: usize) -> *mut c_char;
118
119 /// Resolve a file path name, producing a `C` string which can be passed to
120 /// [`mi_free`].
121 ///
122 /// `resolved_name` should be null, but can also point to a buffer of at
123 /// least `PATH_MAX` bytes.
124 ///
125 /// If successful, returns a pointer to the resolved absolute file name, or
126 /// `null` on failure (with `errno` set to the error code).
127 ///
128 /// If `resolved_name` was `null`, the returned result should be freed with
129 /// [`mi_free`].
130 ///
131 /// This can rarely be useful in FFI code, but is mostly included for
132 /// completeness.
133 pub fn mi_realpath(fname: *const c_char, resolved_name: *mut c_char) -> *mut c_char;
134
135 /// Allocate `size * count` bytes aligned by `alignment`.
136 ///
137 /// Return pointer to the allocated memory or null if out of memory or if
138 /// `size * count` overflows.
139 ///
140 /// Returns a unique pointer if called with `size * count` 0.
141 pub fn mi_calloc_aligned(count: usize, size: usize, alignment: usize) -> *mut c_void;
142
143 /// Allocate `size` bytes aligned by `alignment` at a specified `offset`.
144 ///
145 /// Note that the resulting pointer itself is not aligned by the alignment,
146 /// but after `offset` bytes it will be. This can be useful for allocating
147 /// data with an inline header, where the data has a specific alignment
148 /// requirement.
149 ///
150 /// Specifically, if `p` is the returned pointer `p.add(offset)` is aligned
151 /// to `alignment`.
152 pub fn mi_malloc_aligned_at(size: usize, alignment: usize, offset: usize) -> *mut c_void;
153
154 /// Allocate `size` bytes aligned by `alignment` at a specified `offset`,
155 /// zero-initialized.
156 ///
157 /// This is a [`mi_zalloc`] equivalent of [`mi_malloc_aligned_at`].
158 pub fn mi_zalloc_aligned_at(size: usize, alignment: usize, offset: usize) -> *mut c_void;
159
160 /// Allocate `size` of bytes aligned by `alignment` and place the address of the
161 /// allocated memory to `ptr`.
162 ///
163 /// Returns zero on success, invalid argument for invalid alignment, or out-of-memory.
164 pub fn mi_posix_memalign(ptr: *mut *mut c_void, alignment: usize, size: usize) -> c_int;
165
166 /// Allocate `size` bytes aligned by `alignment` with alignment as the first
167 /// parameter.
168 ///
169 /// Return pointer to the allocated memory or null if out of memory.
170 pub fn mi_aligned_alloc(alignment: usize, size: usize) -> *mut c_void;
171
172 /// Allocate `size * count` bytes aligned by `alignment` at a specified
173 /// `offset`, zero-initialized.
174 ///
175 /// This is a [`calloc`](mi_calloc) equivalent of [`mi_malloc_aligned_at`].
176 pub fn mi_calloc_aligned_at(
177 count: usize,
178 size: usize,
179 alignment: usize,
180 offset: usize,
181 ) -> *mut c_void;
182
183 /// Re-allocate memory to `newsize` bytes aligned by `alignment` at a
184 /// specified `offset`.
185 ///
186 /// This is a [`realloc`](mi_realloc) equivalent of [`mi_malloc_aligned_at`].
187 pub fn mi_realloc_aligned_at(
188 p: *mut c_void,
189 newsize: usize,
190 alignment: usize,
191 offset: usize,
192 ) -> *mut c_void;
193
194 /// Zero initialized [re-allocation](allocator::mi_realloc).
195 ///
196 /// In general, only valid on memory originally allocated by zero
197 /// initialization: [`mi_calloc`],
198 /// [`mi_zalloc`],
199 /// [`mi_zalloc_aligned`], ...
200 pub fn mi_rezalloc(p: *mut c_void, newsize: usize) -> *mut c_void;
201
202 /// Zero initialized [re-allocation](allocator::mi_realloc), following `calloc`
203 /// paramater conventions.
204 ///
205 /// In general, only valid on memory originally allocated by zero
206 /// initialization: [`mi_calloc`],
207 /// [`mi_zalloc`],
208 /// [`mi_zalloc_aligned`], ...
209 pub fn mi_recalloc(p: *mut c_void, newcount: usize, size: usize) -> *mut c_void;
210
211 /// Aligned version of [`mi_rezalloc`].
212 pub fn mi_rezalloc_aligned(p: *mut c_void, newsize: usize, alignment: usize) -> *mut c_void;
213
214 /// Offset-aligned version of [`mi_rezalloc`].
215 pub fn mi_rezalloc_aligned_at(
216 p: *mut c_void,
217 newsize: usize,
218 alignment: usize,
219 offset: usize,
220 ) -> *mut c_void;
221
222 /// Aligned version of [`mi_recalloc`].
223 pub fn mi_recalloc_aligned(
224 p: *mut c_void,
225 newcount: usize,
226 size: usize,
227 alignment: usize,
228 ) -> *mut c_void;
229
230 /// Offset-aligned version of [`mi_recalloc`].
231 pub fn mi_recalloc_aligned_at(
232 p: *mut c_void,
233 newcount: usize,
234 size: usize,
235 alignment: usize,
236 offset: usize,
237 ) -> *mut c_void;
238
239 /// Allocate an object of no more than [`MI_SMALL_SIZE_MAX`] bytes.
240 ///
241 /// Does not check that `size` is indeed small.
242 ///
243 /// Note: Currently [`mi_malloc`] checks if `size` is
244 /// small and calls this if
245 /// so at runtime, so its' only worth using if you know for certain.
246 pub fn mi_malloc_small(size: usize) -> *mut c_void;
247
248 /// Allocate an zero-initialized object of no more than
249 /// [`MI_SMALL_SIZE_MAX`] bytes.
250 ///
251 /// Does not check that `size` is indeed small.
252 ///
253 /// Note: Currently [`mi_zalloc`] checks if `size` is
254 /// small and calls this if so at runtime, so its' only worth using if you
255 /// know for certain.
256 pub fn mi_zalloc_small(size: usize) -> *mut c_void;
257
258 /// Return the used allocation size.
259 ///
260 /// Returns the size `n` that will be allocated, where `n >= size`.
261 ///
262 /// Generally, `mi_usable_size(mi_malloc(size)) == mi_good_size(size)`. This
263 /// can be used to reduce internal wasted space when allocating buffers for
264 /// example.
265 ///
266 /// See [`mi_usable_size`].
267 pub fn mi_good_size(size: usize) -> usize;
268
269 /// Eagerly free memory.
270 ///
271 /// If `force` is true, aggressively return memory to the OS (can be
272 /// expensive!)
273 ///
274 /// Regular code should not have to call this function. It can be beneficial
275 /// in very narrow circumstances; in particular, when a long running thread
276 /// allocates a lot of blocks that are freed by other threads it may improve
277 /// resource usage by calling this every once in a while.
278 pub fn mi_collect(force: bool);
279
280 /// Checked free: If `p` came from mimalloc's heap (as decided by
281 /// [`mi_is_in_heap_region`]), this is [`mi_free(p)`], but
282 /// otherwise it is a no-op.
283 pub fn mi_cfree(p: *mut c_void);
284
285 /// Returns true if this is a pointer into a memory region that has been
286 /// reserved by the mimalloc heap.
287 ///
288 /// This function is described by the mimalloc documentation as "relatively
289 /// fast".
290 ///
291 /// See also [`mi_heap_check_owned`](allocator::mi_is_in_heap_region), which is (much) slower and slightly
292 /// more precise, but only concerns a single `mi_heap`.
293 pub fn mi_is_in_heap_region(p: *const c_void) -> bool;
294
295 /// Layout-aware deallocation: Like [`mi_free`], but accepts
296 /// the size and alignment as well.
297 ///
298 /// Note: unlike some allocators that require this information for
299 /// performance, mimalloc doesn't need it (as of the current version,
300 /// v2.0.0), and so it currently implements this as a (debug) assertion that
301 /// verifies that `p` is actually aligned to `alignment` and is usable for
302 /// at least `size` bytes, before delegating to `mi_free`.
303 ///
304 /// However, currently there's no way to have this crate enable mimalloc's
305 /// debug assertions, so these checks aren't particularly useful.
306 ///
307 /// Note: It's legal to pass null to this function, and you are not required
308 /// to use this to deallocate memory from an aligned allocation function.
309 pub fn mi_free_size_aligned(p: *mut c_void, size: usize, alignment: usize);
310
311 /// Size-aware deallocation: Like [`mi_free`], but accepts
312 /// the size and alignment as well.
313 ///
314 /// Note: unlike some allocators that require this information for
315 /// performance, mimalloc doesn't need it (as of the current version,
316 /// v2.0.0), and so it currently implements this as a (debug) assertion that
317 /// verifies that `p` is actually aligned to `alignment` and is usable for
318 /// at least `size` bytes, before delegating to `mi_free`.
319 ///
320 /// However, currently there's no way to have this crate enable mimalloc's
321 /// debug assertions, so these checks aren't particularly useful.
322 ///
323 /// Note: It's legal to pass null to this function.
324 pub fn mi_free_size(p: *mut c_void, size: usize);
325
326 /// Alignment-aware deallocation: Like [`mi_free`], but
327 /// accepts the size and alignment as well.
328 ///
329 /// Note: unlike some allocators that require this information for
330 /// performance, mimalloc doesn't need it (as of the current version,
331 /// v2.0.0), and so it currently implements this as a (debug) assertion that
332 /// verifies that `p` is actually aligned to `alignment` and is usable for
333 /// at least `size` bytes, before delegating to `mi_free`.
334 ///
335 /// However, currently there's no way to have this crate enable mimalloc's
336 /// debug assertions, so these checks aren't particularly useful.
337 ///
338 /// Note: It's legal to pass null to this function.
339 pub fn mi_free_aligned(p: *mut c_void, alignment: usize);
340
341 /// Print the main statistics.
342 ///
343 /// Ignores the passed in argument, and outputs to the registered output
344 /// function or stderr by default.
345 ///
346 /// Most detailed when using a debug build.
347 pub fn mi_stats_print(_: *mut c_void);
348
349 /// Print the main statistics.
350 ///
351 /// Pass `None` for `out` to use the default. If `out` is provided, `arc` is
352 /// passed as it's second parameter.
353 ///
354 /// Most detailed when using a debug build.
355 pub fn mi_stats_print_out(out: mi_output_fun, arg: *mut c_void);
356
357 /// Reset statistics.
358 ///
359 /// Note: This function is thread safe.
360 pub fn mi_stats_reset();
361
362 /// Merge thread local statistics with the main statistics and reset.
363 ///
364 /// Note: This function is thread safe.
365 pub fn mi_stats_merge();
366
367 /// Return the mimalloc version number.
368 ///
369 /// For example version 1.6.3 would return the number `163`.
370 pub fn mi_version() -> c_int;
371
372 /// Initialize mimalloc on a thread.
373 ///
374 /// Should not be used as on most systems (pthreads, windows) this is done
375 /// automatically.
376 pub fn mi_thread_init();
377
378 /// Initialize the process.
379 ///
380 /// Should not be used on most systems, as it's called by thread_init or the
381 /// process loader.
382 pub fn mi_process_init();
383
384 /// Return process information (time and memory usage). All parameters are
385 /// optional (nullable) out-params:
386 ///
387 /// | Parameter | Description |
388 /// | :- | :- |
389 /// | `elapsed_msecs` | Elapsed wall-clock time of the process in milli-seconds. |
390 /// | `user_msecs` | User time in milli-seconds (as the sum over all threads). |
391 /// | `system_msecs` | System time in milli-seconds. |
392 /// | `current_rss` | Current working set size (touched pages). |
393 /// | `peak_rss` | Peak working set size (touched pages). |
394 /// | `current_commit` | Current committed memory (backed by the page file). |
395 /// | `peak_commit` | Peak committed memory (backed by the page file). |
396 /// | `page_faults` | Count of hard page faults. |
397 ///
398 /// The `current_rss` is precise on Windows and MacOSX; other systems
399 /// estimate this using `current_commit`. The `commit` is precise on Windows
400 /// but estimated on other systems as the amount of read/write accessible
401 /// memory reserved by mimalloc.
402 pub fn mi_process_info(
403 elapsed_msecs: *mut usize,
404 user_msecs: *mut usize,
405 system_msecs: *mut usize,
406 current_rss: *mut usize,
407 peak_rss: *mut usize,
408 current_commit: *mut usize,
409 peak_commit: *mut usize,
410 page_faults: *mut usize,
411 );
412
413 /// Uninitialize mimalloc on a thread.
414 ///
415 /// Should not be used as on most systems (pthreads, windows) this is done
416 /// automatically. Ensures that any memory that is not freed yet (but will
417 /// be freed by other threads in the future) is properly handled.
418 ///
419 /// Note: This function is thread safe.
420 pub fn mi_thread_done();
421
422 /// Print out heap statistics for this thread.
423 ///
424 /// Pass `None` for `out` to use the default. If `out` is provided, `arc` is
425 /// passed as it's second parameter
426 ///
427 /// Most detailed when using a debug build.
428 ///
429 /// Note: This function is thread safe.
430 pub fn mi_thread_stats_print_out(out: mi_output_fun, arg: *mut c_void);
431
432 /// Register an output function.
433 ///
434 /// - `out` The output function, use `None` to output to stderr.
435 /// - `arg` Argument that will be passed on to the output function.
436 ///
437 /// The `out` function is called to output any information from mimalloc,
438 /// like verbose or warning messages.
439 ///
440 /// Note: This function is thread safe.
441 pub fn mi_register_output(out: mi_output_fun, arg: *mut c_void);
442
443 /// Register a deferred free function.
444 ///
445 /// - `deferred_free` Address of a deferred free-ing function or `None` to
446 /// unregister.
447 /// - `arg` Argument that will be passed on to the deferred free function.
448 ///
449 /// Some runtime systems use deferred free-ing, for example when using
450 /// reference counting to limit the worst case free time.
451 ///
452 /// Such systems can register (re-entrant) deferred free function to free
453 /// more memory on demand.
454 ///
455 /// - When the `force` parameter is `true` all possible memory should be
456 /// freed.
457 ///
458 /// - The per-thread `heartbeat` parameter is monotonically increasing and
459 /// guaranteed to be deterministic if the program allocates
460 /// deterministically.
461 ///
462 /// - The `deferred_free` function is guaranteed to be called
463 /// deterministically after some number of allocations (regardless of
464 /// freeing or available free memory).
465 ///
466 /// At most one `deferred_free` function can be active.
467 ///
468 /// Note: This function is thread safe.
469 pub fn mi_register_deferred_free(out: mi_deferred_free_fun, arg: *mut c_void);
470
471 /// Register an error callback function.
472 ///
473 /// The `errfun` function is called on an error in mimalloc after emitting
474 /// an error message (through the output function).
475 ///
476 /// It as always legal to just return from the `errfun` function in which
477 /// case allocation functions generally return null or ignore the condition.
478 ///
479 /// The default function only calls abort() when compiled in secure mode
480 /// with an `EFAULT` error. The possible error codes are:
481 ///
482 /// - `EAGAIN` (11): Double free was detected (only in debug and secure
483 /// mode).
484 /// - `EFAULT` (14): Corrupted free list or meta-data was detected (only in
485 /// debug and secure mode).
486 /// - `ENOMEM` (12): Not enough memory available to satisfy the request.
487 /// - `EOVERFLOW` (75): Too large a request, for example in `mi_calloc`, the
488 /// `count` and `size` parameters are too large.
489 /// - `EINVAL` (22): Trying to free or re-allocate an invalid pointer.
490 ///
491 /// Note: This function is thread safe.
492 pub fn mi_register_error(out: mi_error_fun, arg: *mut c_void);
493}