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}