cesium_libmimalloc_sys/lib.rs
1// Copyright 2019 Octavian Oncescu, MIT License
2
3#![allow(nonstandard_style)]
4
5use core::ffi::c_void;
6use std::ffi::{c_char, c_int, c_ulonglong};
7
8use crate::heap::*;
9
10pub mod options;
11pub mod heap;
12pub mod allocator;
13
14/// The maximum number of bytes which may be used as an argument to a function
15/// in the `_small` family ([`mi_malloc_small`](allocator::mi_malloc_small), [`mi_zalloc_small`](allocator::mi_zalloc_small), etc).
16pub const MI_SMALL_SIZE_MAX: usize = 128 * core::mem::size_of::<*mut c_void>();
17
18/// An output callback. Must be thread-safe.
19///
20/// See [`mi_stats_print_out`](allocator::mi_stats_print_out), [`mi_thread_stats_print_out`](allocator::mi_thread_stats_print_out), [`mi_register_output`](allocator::mi_register_output)
21pub type mi_output_fun = Option<unsafe extern "C" fn(msg: *const c_char, arg: *mut c_void)>;
22
23/// Type of deferred free functions. Must be thread-safe.
24///
25/// - `force`: If true, all outstanding items should be freed.
26/// - `heartbeat` A monotonically increasing count.
27/// - `arg` Argument that was passed at registration to hold extra state.
28///
29/// See [`mi_register_deferred_free`](allocator::mi_register_deferred_free)
30pub type mi_deferred_free_fun =
31Option<unsafe extern "C" fn(force: bool, heartbeat: c_ulonglong, arg: *mut c_void)>;
32
33/// Type of error callback functions. Must be thread-safe.
34///
35/// - `err`: Error code (see [`mi_register_error`](allocator::mi_register_error) for a list).
36/// - `arg`: Argument that was passed at registration to hold extra state.
37///
38/// See [`mi_register_error`](allocator::mi_register_error)
39pub type mi_error_fun = Option<unsafe extern "C" fn(code: c_int, arg: *mut c_void)>;
40
41/// Runtime options. All options are false by default.
42pub type mi_option_t = c_int;
43
44// Note: mimalloc doc website seems to have the order of show_stats and
45// show_errors reversed as of 1.6.3, however what I have here is correct:
46// https://github.com/microsoft/mimalloc/issues/266#issuecomment-653822341
47
48/// Print error messages to `stderr`.
49pub const mi_option_show_errors: mi_option_t = 0;
50
51/// Print statistics to `stderr` when the program is done.
52pub const mi_option_show_stats: mi_option_t = 1;
53
54/// Print verbose messages to `stderr`.
55pub const mi_option_verbose: mi_option_t = 2;
56
57/// ### The following options are experimental
58
59/// Option (experimental) Use large OS pages (2MiB in size) if possible.
60///
61/// Use large OS pages (2MiB) when available; for some workloads this can
62/// significantly improve performance. Use mi_option_verbose to check if
63/// the large OS pages are enabled -- usually one needs to explicitly allow
64/// large OS pages (as on Windows and Linux). However, sometimes the OS is
65/// very slow to reserve contiguous physical memory for large OS pages so
66/// use with care on systems that can have fragmented memory (for that
67/// reason, we generally recommend to use mi_option_reserve_huge_os_pages
68/// instead whenever possible).
69pub const mi_option_large_os_pages: mi_option_t = 6;
70
71/// Option (experimental) The number of huge OS pages (1GiB in size) to reserve at the start of the program.
72///
73/// This reserves the huge pages at startup and sometimes this can give a large (latency) performance
74/// improvement on big workloads. Usually it is better to not use MIMALLOC_LARGE_OS_PAGES in
75/// combination with this setting. Just like large OS pages, use with care as reserving contiguous
76/// physical memory can take a long time when memory is fragmented (but reserving the huge pages is
77/// done at startup only once). Note that we usually need to explicitly enable huge OS pages (as on
78/// Windows and Linux)). With huge OS pages, it may be beneficial to set the setting
79/// mi_option_eager_commit_delay=N (N is 1 by default) to delay the initial N segments (of 4MiB) of
80/// a thread to not allocate in the huge OS pages; this prevents threads that are short lived and
81/// allocate just a little to take up space in the huge OS page area (which cannot be reset).
82pub const mi_option_reserve_huge_os_pages: mi_option_t = 7;
83
84/// Option (experimental) Reserve huge OS pages at node N.
85///
86/// The huge pages are usually allocated evenly among NUMA nodes.
87/// You can use mi_option_reserve_huge_os_pages_at=N where `N` is the numa node (starting at 0) to allocate all
88/// the huge pages at a specific numa node instead.
89pub const mi_option_reserve_huge_os_pages_at: mi_option_t = 8;
90
91/// Option (experimental) Reserve specified amount of OS memory at startup, e.g. "1g" or "512m".
92pub const mi_option_reserve_os_memory: mi_option_t = 9;
93
94/// Option (experimental) the first N segments per thread are not eagerly committed (=1).
95pub const mi_option_eager_commit_delay: mi_option_t = 14;
96
97/// Option (experimental) Pretend there are at most N NUMA nodes; Use 0 to use the actual detected NUMA nodes at runtime.
98pub const mi_option_use_numa_nodes: mi_option_t = 16;
99
100/// Option (experimental) If set to 1, do not use OS memory for allocation (but only pre-reserved arenas)
101pub const mi_option_limit_os_alloc: mi_option_t = 17;
102
103/// Option (experimental) OS tag to assign to mimalloc'd memory
104pub const mi_option_os_tag: mi_option_t = 18;
105
106/// Option (experimental)
107pub const mi_option_max_errors: mi_option_t = 19;
108
109/// Option (experimental)
110pub const mi_option_max_warnings: mi_option_t = 20;
111
112/// Option (experimental)
113pub const mi_option_max_segment_reclaim: mi_option_t = 21;
114
115/// Last option.
116pub const _mi_option_last: mi_option_t = 26;
117
118/// Visitor function passed to [`mi_heap_visit_blocks`]
119///
120/// Should return `true` to continue, and `false` to stop visiting (i.e. break)
121///
122/// This function is always first called for every `area` with `block` as a null
123/// pointer. If `visit_all_blocks` was `true`, the function is then called for
124/// every allocated block in that area.
125pub type mi_block_visit_fun = Option<
126 unsafe extern "C" fn(
127 heap: *const mi_heap_t,
128 area: *const mi_heap_area_t,
129 block: *mut c_void,
130 block_size: usize,
131 arg: *mut c_void,
132 ) -> bool,
133>;
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138
139 #[test]
140 fn runtime_stable_option() {
141 unsafe {
142 assert_eq!(mi_option_get(mi_option_show_errors), 0);
143 mi_option_set(mi_option_show_errors, 1);
144 assert_eq!(mi_option_get(mi_option_show_errors), 1);
145
146 assert_eq!(mi_option_get(mi_option_show_stats), 0);
147 mi_option_set(mi_option_show_stats, 1);
148 assert_eq!(mi_option_get(mi_option_show_stats), 1);
149
150 assert_eq!(mi_option_get(mi_option_verbose), 0);
151 mi_option_set(mi_option_verbose, 1);
152 assert_eq!(mi_option_get(mi_option_verbose), 1);
153 }
154 }
155}