Skip to main content

memapi_jemalloc_sys/
lib.rs

1//! Rust bindings to the `jemalloc` C library.
2//!
3//! `jemalloc` is a general purpose memory allocation, its documentation
4//! can be found here:
5//!
6//! * [API documentation][jemalloc_docs]
7//! * [Wiki][jemalloc_wiki] (design documents, presentations, profiling, debugging, tuning, ...)
8//!
9//! `jemalloc` exposes both a standard and a non-standard API.
10//!
11//! # Standard API
12//!
13//! The standard API includes: the [`malloc`], [`calloc`], [`realloc`], and
14//! [`free`], which conform to to ISO/IEC 9899:1990 (“ISO C90”),
15//! [`posix_memalign`] which conforms to conforms to POSIX.1-2016, and
16//! [`aligned_alloc`].
17//!
18//! Note that these standard leave some details as _implementation defined_.
19//! This docs document this behavior for `jemalloc`, but keep in mind that other
20//! standard-conforming implementations of these functions in other allocators
21//! might behave slightly different.
22//!
23//! # Non-Standard API
24//!
25//! The non-standard API includes: [`mallocx`], [`rallocx`], [`xallocx`],
26//! [`sallocx`], [`dallocx`], [`sdallocx`], and [`nallocx`]. These functions all
27//! have a `flags` argument that can be used to specify options. Use bitwise or
28//! `|` to specify one or more of the following: [`MALLOCX_LG_ALIGN`],
29//! [`MALLOCX_ALIGN`], [`MALLOCX_ZERO`], [`MALLOCX_TCACHE`],
30//! [`MALLOCX_TCACHE_NONE`], and [`MALLOCX_ARENA`].
31//!
32//! # Environment variables
33//!
34//! The `MALLOC_CONF` environment variable affects the execution of the allocation functions.
35//!
36//! For the documentation of the [`MALLCTL` namespace visit the jemalloc
37//! documenation][jemalloc_mallctl].
38//!
39//! [jemalloc_docs]: http://jemalloc.net/jemalloc.3.html
40//! [jemalloc_wiki]: https://github.com/jemalloc/jemalloc/wiki
41//! [jemalloc_mallctl]: http://jemalloc.net/jemalloc.3.html#mallctl_namespace
42#![no_std]
43#![allow(non_snake_case, non_camel_case_types)]
44#![allow(renamed_and_removed_lints)]
45#![deny(missing_docs, broken_intra_doc_links)]
46
47use libc::{c_char, c_int, c_uint, c_void, size_t};
48
49// jemalloc uses `stdbool.h` to define `bool` for which the Rust equivalent is `bool`.
50// However jemalloc also has its own `stdbool.h` that it uses when compiling with MSVC,
51// and this header defines `bool` as `BOOL` which in turn is `int`.
52#[cfg(target_env = "msvc")]
53type c_bool = c_int;
54#[cfg(not(target_env = "msvc"))]
55type c_bool = bool;
56
57/// Align the memory allocation to start at an address that is a
58/// multiple of `1 << la`.
59///
60/// # Safety
61///
62/// It does not validate that `la` is within the valid range.
63#[inline]
64pub const fn MALLOCX_LG_ALIGN(la: usize) -> c_int {
65    la as c_int
66}
67
68/// Align the memory allocation to start at an address that is a multiple of `align`,
69/// where a is a power of two.
70///
71/// # Safety
72///
73/// This macro does not validate that a is a power of 2.
74#[inline]
75pub const fn MALLOCX_ALIGN(aling: usize) -> c_int {
76    aling.trailing_zeros() as c_int
77}
78
79/// Initialize newly allocated memory to contain zero bytes.
80///
81/// In the growing reallocation case, the real size prior to reallocation
82/// defines the boundary between untouched bytes and those that are initialized
83/// to contain zero bytes.
84///
85/// If this option is not set, newly allocated memory is uninitialized.
86pub const MALLOCX_ZERO: c_int = 0x40;
87
88/// Use the thread-specific cache (_tcache_) specified by the identifier `tc`.
89///
90/// # Safety
91///
92/// `tc` must have been acquired via the `tcache.create mallctl`. This function
93/// does not validate that `tc` specifies a valid identifier.
94#[inline]
95pub const fn MALLOCX_TCACHE(tc: usize) -> c_int {
96    tc.wrapping_add(2).wrapping_shl(8) as c_int
97}
98
99/// Do not use a thread-specific cache (_tcache_).
100///
101/// Unless `MALLOCX_TCACHE(tc)` or `MALLOCX_TCACHE_NONE` is specified, an
102/// automatically managed _tcache_ will be used under many circumstances.
103///
104/// # Safety
105///
106/// This option cannot be used in the same `flags` argument as
107/// `MALLOCX_TCACHE(tc)`.
108// FIXME: This should just be a const.
109pub const MALLOCX_TCACHE_NONE: c_int = MALLOCX_TCACHE((-1isize) as usize);
110
111/// Use the arena specified by the index `a`.
112///
113/// This option has no effect for regions that were allocated via an arena other
114/// than the one specified.
115///
116/// # Safety
117///
118/// This function does not validate that `a` specifies an arena index in the
119/// valid range.
120#[inline]
121pub const fn MALLOCX_ARENA(a: usize) -> c_int {
122    (a as c_int).wrapping_add(1).wrapping_shl(20)
123}
124
125extern "C" {
126    /// Allocates `size` bytes of uninitialized memory.
127    ///
128    /// It returns a pointer to the start (lowest byte address) of the allocated
129    /// space. This pointer is suitably aligned so that it may be assigned to a
130    /// pointer to any type of object and then used to access such an object in
131    /// the space allocated until the space is explicitly deallocated. Each
132    /// yielded pointer points to an object disjoint from any other object.
133    ///
134    /// If the `size` of the space requested is zero, either a null pointer is
135    /// returned, or the behavior is as if the `size` were some nonzero value,
136    /// except that the returned pointer shall not be used to access an object.
137    ///
138    /// # Errors
139    ///
140    /// If the space cannot be allocated, a null pointer is returned and `errno`
141    /// is set to `ENOMEM`.
142    #[cfg_attr(prefixed, link_name = "_rjem_malloc")]
143    pub fn malloc(size: size_t) -> *mut c_void;
144    /// Allocates zero-initialized space for an array of `number` objects, each
145    /// of whose size is `size`.
146    ///
147    /// The result is identical to calling [`malloc`] with an argument of
148    /// `number * size`, with the exception that the allocated memory is
149    /// explicitly initialized to _zero_ bytes.
150    ///
151    /// Note: zero-initialized memory need not be the same as the
152    /// representation of floating-point zero or a null pointer constant.
153    #[cfg_attr(prefixed, link_name = "_rjem_calloc")]
154    pub fn calloc(number: size_t, size: size_t) -> *mut c_void;
155
156    /// Allocates `size` bytes of memory at an address which is a multiple of
157    /// `alignment` and is placed in `*ptr`.
158    ///
159    /// If `size` is zero, then the value placed in `*ptr` is either null, or
160    /// the behavior is as if the `size` were some nonzero value, except that
161    /// the returned pointer shall not be used to access an object.
162    ///
163    /// # Errors
164    ///
165    /// On success, it returns zero. On error, the value of `errno` is _not_ set,
166    /// `*ptr` is not modified, and the return values can be:
167    ///
168    /// - `EINVAL`: the `alignment` argument was not a power-of-two or was not a multiple of
169    ///   `mem::size_of::<*const c_void>()`.
170    /// - `ENOMEM`: there was insufficient memory to fulfill the allocation request.
171    ///
172    /// # Safety
173    ///
174    /// The behavior is _undefined_ if:
175    ///
176    /// * `ptr` is null.
177    #[cfg_attr(prefixed, link_name = "_rjem_posix_memalign")]
178    pub fn posix_memalign(ptr: *mut *mut c_void, alignment: size_t, size: size_t) -> c_int;
179
180    /// Allocates `size` bytes of memory at an address which is a multiple of
181    /// `alignment`.
182    ///
183    /// If the `size` of the space requested is zero, either a null pointer is
184    /// returned, or the behavior is as if the `size` were some nonzero value,
185    /// except that the returned pointer shall not be used to access an object.
186    ///
187    /// # Errors
188    ///
189    /// Returns null if the request fails.
190    ///
191    /// # Safety
192    ///
193    /// The behavior is _undefined_ if:
194    ///
195    /// * `alignment` is not a power-of-two
196    /// * `size` is not an integral multiple of `alignment`
197    #[cfg_attr(prefixed, link_name = "_rjem_aligned_alloc")]
198    pub fn aligned_alloc(alignment: size_t, size: size_t) -> *mut c_void;
199
200    /// Resizes the previously-allocated memory region referenced by `ptr` to
201    /// `size` bytes.
202    ///
203    /// Deallocates the old object pointed to by `ptr` and returns a pointer to
204    /// a new object that has the size specified by `size`. The contents of the
205    /// new object are the same as that of the old object prior to deallocation,
206    /// up to the lesser of the new and old sizes.
207    ///
208    /// The memory in the new object beyond the size of the old object is
209    /// uninitialized.
210    ///
211    /// The returned pointer to a new object may have the same value as a
212    /// pointer to the old object, but [`realloc`] may move the memory
213    /// allocation, resulting in a different return value than `ptr`.
214    ///
215    /// If `ptr` is null, [`realloc`] behaves identically to [`malloc`] for the
216    /// specified size.
217    ///
218    /// If the size of the space requested is zero, the behavior is
219    /// implementation-defined: either a null pointer is returned, or the
220    /// behavior is as if the size were some nonzero value, except that the
221    /// returned pointer shall not be used to access an object # Errors
222    ///
223    /// # Errors
224    ///
225    /// If memory for the new object cannot be allocated, the old object is not
226    /// deallocated, its value is unchanged, [`realloc`] returns null, and
227    /// `errno` is set to `ENOMEM`.
228    ///
229    /// # Safety
230    ///
231    /// The behavior is _undefined_ if:
232    ///
233    /// * `ptr` does not match a pointer previously returned by the memory
234    ///   allocation functions of this crate, or
235    /// * the memory region referenced by `ptr` has been deallocated.
236    #[cfg_attr(prefixed, link_name = "_rjem_realloc")]
237    pub fn realloc(ptr: *mut c_void, size: size_t) -> *mut c_void;
238
239    /// Deallocates previously-allocated memory region referenced by `ptr`.
240    ///
241    /// This makes the space available for future allocations.
242    ///
243    /// If `ptr` is null, no action occurs.
244    ///
245    /// # Safety
246    ///
247    /// The behavior is _undefined_ if:
248    ///
249    /// * `ptr` does not match a pointer earlier returned by the memory
250    ///   allocation functions of this crate, or
251    /// * the memory region referenced by `ptr` has been deallocated.
252    #[cfg_attr(prefixed, link_name = "_rjem_free")]
253    pub fn free(ptr: *mut c_void);
254
255    /// Allocates at least `size` bytes of memory according to `flags`.
256    ///
257    /// It returns a pointer to the start (lowest byte address) of the allocated
258    /// space. This pointer is suitably aligned so that it may be assigned to a
259    /// pointer to any type of object and then used to access such an object in
260    /// the space allocated until the space is explicitly deallocated. Each
261    /// yielded pointer points to an object disjoint from any other object.
262    ///
263    /// # Errors
264    ///
265    /// On success it returns a non-null pointer. A null pointer return value
266    /// indicates that insufficient contiguous memory was available to service
267    /// the allocation request.
268    ///
269    /// # Safety
270    ///
271    /// The behavior is _undefined_ if `size == 0`.
272    #[cfg_attr(prefixed, link_name = "_rjem_mallocx")]
273    pub fn mallocx(size: size_t, flags: c_int) -> *mut c_void;
274
275    /// Resizes the previously-allocated memory region referenced by `ptr` to be
276    /// at least `size` bytes.
277    ///
278    /// Deallocates the old object pointed to by `ptr` and returns a pointer to
279    /// a new object that has the size specified by `size`. The contents of the
280    /// new object are the same as that of the old object prior to deallocation,
281    /// up to the lesser of the new and old sizes.
282    ///
283    /// The the memory in the new object beyond the size of the old object is
284    /// obtained according to `flags` (it might be uninitialized).
285    ///
286    /// The returned pointer to a new object may have the same value as a
287    /// pointer to the old object, but [`rallocx`] may move the memory
288    /// allocation, resulting in a different return value than `ptr`.
289    ///
290    /// # Errors
291    ///
292    /// On success it returns a non-null pointer. A null pointer return value
293    /// indicates that insufficient contiguous memory was available to service
294    /// the allocation request. In this case, the old object is not
295    /// deallocated, and its value is unchanged.
296    ///
297    /// # Safety
298    ///
299    /// The behavior is _undefiend_ if:
300    ///
301    /// * `size == 0`, or
302    /// * `ptr` does not match a pointer earlier returned by
303    ///   the memory allocation functions of this crate, or
304    /// * the memory region referenced by `ptr` has been deallocated.
305    #[cfg_attr(prefixed, link_name = "_rjem_rallocx")]
306    pub fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
307
308    /// Resizes the previously-allocated memory region referenced by `ptr` _in
309    /// place_ to be at least `size` bytes, returning the real size of the
310    /// allocation.
311    ///
312    /// Deallocates the old object pointed to by `ptr` and sets `ptr` to a new
313    /// object that has the size returned; the old a new objects share the same
314    /// base address. The contents of the new object are the same as that of the
315    /// old object prior to deallocation, up to the lesser of the new and old
316    /// sizes.
317    ///
318    /// If `extra` is non-zero, an attempt is made to resize the allocation to
319    /// be at least `size + extra` bytes. Inability to allocate the `extra`
320    /// bytes will not by itself result in failure to resize.
321    ///
322    /// The memory in the new object beyond the size of the old object is
323    /// obtained according to `flags` (it might be uninitialized).
324    ///
325    /// # Errors
326    ///
327    /// If the allocation cannot be adequately grown in place up to `size`, the
328    /// size returned is smaller than `size`.
329    ///
330    /// Note:
331    ///
332    /// * the size value returned can be larger than the size requested during
333    ///   allocation
334    /// * when shrinking an allocation, use the size returned to determine
335    ///   whether the allocation was shrunk sufficiently or not.
336    ///
337    /// # Safety
338    ///
339    /// The behavior is _undefined_ if:
340    ///
341    /// * `size == 0`, or
342    /// * `size + extra > size_t::max_value()`, or
343    /// * `ptr` does not match a pointer earlier returned by the memory
344    ///   allocation functions of this crate, or
345    /// * the memory region referenced by `ptr` has been deallocated.
346    #[cfg_attr(prefixed, link_name = "_rjem_xallocx")]
347    pub fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
348
349    /// Returns the real size of the previously-allocated memory region
350    /// referenced by `ptr`.
351    ///
352    /// The value may be larger than the size requested on allocation.
353    ///
354    /// # Safety
355    ///
356    /// The behavior is _undefined_ if:
357    ///
358    /// * `ptr` does not match a pointer earlier returned by the memory
359    ///   allocation functions of this crate, or
360    /// * the memory region referenced by `ptr` has been deallocated.
361    #[cfg_attr(prefixed, link_name = "_rjem_sallocx")]
362    pub fn sallocx(ptr: *const c_void, flags: c_int) -> size_t;
363
364    /// Deallocates previously-allocated memory region referenced by `ptr`.
365    ///
366    /// This makes the space available for future allocations.
367    ///
368    /// # Safety
369    ///
370    /// The behavior is _undefined_ if:
371    ///
372    /// * `ptr` does not match a pointer earlier returned by the memory
373    ///   allocation functions of this crate, or
374    /// * `ptr` is null, or
375    /// * the memory region referenced by `ptr` has been deallocated.
376    #[cfg_attr(prefixed, link_name = "_rjem_dallocx")]
377    pub fn dallocx(ptr: *mut c_void, flags: c_int);
378
379    /// Deallocates previously-allocated memory region referenced by `ptr` with
380    /// `size` hint.
381    ///
382    /// This makes the space available for future allocations.
383    ///
384    /// # Safety
385    ///
386    /// The behavior is _undefined_ if:
387    ///
388    /// * `size` is not in range `[req_size, alloc_size]`, where `req_size` is
389    ///   the size requested when performing the allocation, and `alloc_size` is
390    ///   the allocation size returned by [`nallocx`], [`sallocx`], or
391    ///   [`xallocx`],
392    /// * `ptr` does not match a pointer earlier returned by the memory
393    ///   allocation functions of this crate, or
394    /// * `ptr` is null, or
395    /// * the memory region referenced by `ptr` has been deallocated.
396    #[cfg_attr(prefixed, link_name = "_rjem_sdallocx")]
397    pub fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
398
399    /// Returns the real size of the allocation that would result from a
400    /// [`mallocx`] function call with the same arguments.
401    ///
402    /// # Errors
403    ///
404    /// If the inputs exceed the maximum supported size class and/or alignment
405    /// it returns zero.
406    ///
407    /// # Safety
408    ///
409    /// The behavior is _undefined_ if `size == 0`.
410    #[cfg_attr(prefixed, link_name = "_rjem_nallocx")]
411    pub fn nallocx(size: size_t, flags: c_int) -> size_t;
412
413    /// Returns the real size of the previously-allocated memory region
414    /// referenced by `ptr`.
415    ///
416    /// The value may be larger than the size requested on allocation.
417    ///
418    /// Although the excess bytes can be overwritten by the application without
419    /// ill effects, this is not good programming practice: the number of excess
420    /// bytes in an allocation depends on the underlying implementation.
421    ///
422    /// The main use of this function is for debugging and introspection.
423    ///
424    /// # Errors
425    ///
426    /// If `ptr` is null, 0 is returned.
427    ///
428    /// # Safety
429    ///
430    /// The behavior is _undefined_ if:
431    ///
432    /// * `ptr` does not match a pointer earlier returned by the memory
433    ///   allocation functions of this crate, or
434    /// * the memory region referenced by `ptr` has been deallocated.
435    #[cfg_attr(prefixed, link_name = "_rjem_malloc_usable_size")]
436    pub fn malloc_usable_size(ptr: *const c_void) -> size_t;
437
438    /// General interface for introspecting the memory allocator, as well as
439    /// setting modifiable parameters and triggering actions.
440    ///
441    /// The period-separated name argument specifies a location in a
442    /// tree-structured namespace ([see jemalloc's `MALLCTL`
443    /// documentation][jemalloc_mallctl]).
444    ///
445    /// To read a value, pass a pointer via `oldp` to adequate space to contain
446    /// the value, and a pointer to its length via `oldlenp``; otherwise pass
447    /// null and null. Similarly, to write a value, pass a pointer to the value
448    /// via `newp`, and its length via `newlen`; otherwise pass null and 0.
449    ///
450    /// # Errors
451    ///
452    /// Returns `0` on success, otherwise returns:
453    ///
454    /// * `EINVAL`: if `newp` is not null, and `newlen` is too large or too
455    ///   small. Alternatively, `*oldlenp` is too large or too small; in this case
456    ///   as much data as possible are read despite the error.
457    ///
458    /// * `ENOENT`: `name` or mib specifies an unknown/invalid value.
459    ///
460    /// * `EPERM`: Attempt to read or write void value, or attempt to write read-only value.
461    ///
462    /// * `EAGAIN`: A memory allocation failure occurred.
463    ///
464    /// * `EFAULT`: An interface with side effects failed in some way not
465    ///   directly related to `mallctl` read/write processing.
466    ///
467    /// [jemalloc_mallctl]: http://jemalloc.net/jemalloc.3.html#mallctl_namespace
468    #[cfg_attr(prefixed, link_name = "_rjem_mallctl")]
469    pub fn mallctl(
470        name: *const c_char,
471        oldp: *mut c_void,
472        oldlenp: *mut size_t,
473        newp: *mut c_void,
474        newlen: size_t,
475    ) -> c_int;
476    /// Translates a name to a “Management Information Base” (MIB) that can be
477    /// passed repeatedly to [`mallctlbymib`].
478    ///
479    /// This avoids repeated name lookups for applications that repeatedly query
480    /// the same portion of the namespace.
481    ///
482    /// On success, `mibp` contains an array of `*miblenp` integers, where
483    /// `*miblenp` is the lesser of the number of components in name and the
484    /// input value of `*miblenp`. Thus it is possible to pass a `*miblenp` that is
485    /// smaller than the number of period-separated name components, which
486    /// results in a partial MIB that can be used as the basis for constructing
487    /// a complete MIB. For name components that are integers (e.g. the 2 in
488    /// arenas.bin.2.size), the corresponding MIB component will always be that
489    /// integer.
490    #[cfg_attr(prefixed, link_name = "_rjem_mallctlnametomib")]
491    pub fn mallctlnametomib(name: *const c_char, mibp: *mut size_t, miblenp: *mut size_t) -> c_int;
492
493    /// Like [`mallctl`] but taking a `mib` as input instead of a name.
494    #[cfg_attr(prefixed, link_name = "_rjem_mallctlbymib")]
495    pub fn mallctlbymib(
496        mib: *const size_t,
497        miblen: size_t,
498        oldp: *mut c_void,
499        oldpenp: *mut size_t,
500        newp: *mut c_void,
501        newlen: size_t,
502    ) -> c_int;
503
504    /// Writes summary statistics via the `write_cb` callback function pointer
505    /// and `cbopaque` data passed to `write_cb`, or [`malloc_message`] if `write_cb`
506    /// is null.
507    ///
508    /// The statistics are presented in human-readable form unless “J”
509    /// is specified as a character within the opts string, in which case the
510    /// statistics are presented in JSON format.
511    ///
512    /// This function can be called repeatedly.
513    ///
514    /// General information that never changes during execution can be omitted
515    /// by specifying `g` as a character within the opts string.
516    ///
517    /// Note that [`malloc_message`] uses the `mallctl*` functions internally,
518    /// so inconsistent statistics can be reported if multiple threads use these
519    /// functions simultaneously.
520    ///
521    /// If the Cargo feature `stats` is enabled, `m`, `d`, and `a` can be
522    /// specified to omit merged arena, destroyed merged arena, and per arena
523    /// statistics, respectively; `b` and `l` can be specified to omit per size
524    /// class statistics for bins and large objects, respectively; `x` can be
525    /// specified to omit all mutex statistics. Unrecognized characters are
526    /// silently ignored.
527    ///
528    /// Note that thread caching may prevent some statistics from being
529    /// completely up to date, since extra locking would be required to merge
530    /// counters that track thread cache operations.
531    #[cfg_attr(prefixed, link_name = "_rjem_malloc_stats_print")]
532    pub fn malloc_stats_print(
533        write_cb: Option<unsafe extern "C" fn(*mut c_void, *const c_char)>,
534        cbopaque: *mut c_void,
535        opts: *const c_char,
536    );
537
538    /// Allows overriding the function which emits the text strings forming the
539    /// errors and warnings if for some reason the `STDERR_FILENO` file descriptor
540    /// is not suitable for this.
541    ///
542    /// [`malloc_message`] takes the `cbopaque` pointer argument that is null,
543    /// unless overridden by the arguments in a call to [`malloc_stats_print`],
544    /// followed by a string pointer.
545    ///
546    /// Please note that doing anything which tries to allocate memory in this
547    /// function is likely to result in a crash or deadlock.
548    #[cfg_attr(prefixed, link_name = "_rjem_malloc_message")]
549    pub static mut malloc_message:
550    Option<unsafe extern "C" fn(cbopaque: *mut c_void, s: *const c_char)>;
551
552    /// Compile-time string of configuration options.
553    ///
554    /// Once, when the first call is made to one of the memory allocation
555    /// routines, the allocator initializes its internals based in part on
556    /// various options that can be specified at compile- or run-time.
557    ///
558    /// The string specified via `--with-malloc-conf`, the string pointed to by
559    /// the global variable `malloc_conf`, the “name” of the file referenced by
560    /// the symbolic link named `/etc/malloc.conf`, and the value of the
561    /// environment variable `MALLOC_CONF`, will be interpreted, in that order,
562    /// from left to right as options. Note that `malloc_conf` may be read
563    /// before `main()` is entered, so the declaration of `malloc_conf` should
564    /// specify an initializer that contains the final value to be read by
565    /// `jemalloc`.
566    ///
567    /// `--with-malloc-conf` and `malloc_conf` are compile-time mechanisms, whereas
568    /// `/etc/malloc.conf` and `MALLOC_CONF` can be safely set any time prior to
569    /// program invocation.
570    ///
571    /// An options string is a comma-separated list of `option:value` pairs.
572    /// There is one key corresponding to each `opt.* mallctl` (see the `MALLCTL
573    /// NAMESPACE` section for options documentation). For example,
574    /// `abort:true,narenas:1` sets the `opt.abort` and `opt.narenas` options.
575    /// Some options have boolean values (`true`/`false`), others have integer
576    /// values (base `8`, `10`, or `16`, depending on prefix), and yet others
577    /// have raw string values.
578    #[cfg_attr(prefixed, link_name = "_rjem_malloc_conf")]
579    pub static malloc_conf: Option<&'static c_char>;
580}
581
582/// Extent lifetime management functions.
583pub type extent_hooks_t = extent_hooks_s;
584
585// note: there are two structs here, one is used when compiling the crate normally,
586// and the other one is behind the `--cfg jemallocator_docs` flag and used only
587// when generating docs.
588//
589// For the docs we want to use type aliases here, but `ctest` does see through
590// them when generating the code to verify the FFI bindings, and it needs to
591// be able to tell that these are `fn` types so that `Option<fn>` gets lowered
592// to C function pointers.
593
594#[repr(C)]
595#[cfg(not(jemallocator_docs))]
596#[derive(Copy, Clone, Default)]
597#[doc(hidden)]
598#[allow(missing_docs)]
599pub struct extent_hooks_s {
600    pub alloc: Option<
601        unsafe extern "C" fn(
602            *mut extent_hooks_t,
603            *mut c_void,
604            size_t,
605            size_t,
606            *mut c_bool,
607            *mut c_bool,
608            c_uint,
609        ) -> *mut c_void,
610    >,
611    pub dalloc: Option<
612        unsafe extern "C" fn(*mut extent_hooks_t, *mut c_void, size_t, c_bool, c_uint) -> c_bool,
613    >,
614    pub destroy:
615        Option<unsafe extern "C" fn(*mut extent_hooks_t, *mut c_void, size_t, c_bool, c_uint)>,
616    pub commit: Option<
617        unsafe extern "C" fn(
618            *mut extent_hooks_t,
619            *mut c_void,
620            size_t,
621            size_t,
622            size_t,
623            c_uint,
624        ) -> c_bool,
625    >,
626    pub decommit: Option<
627        unsafe extern "C" fn(
628            *mut extent_hooks_t,
629            *mut c_void,
630            size_t,
631            size_t,
632            size_t,
633            c_uint,
634        ) -> c_bool,
635    >,
636    pub purge_lazy: Option<
637        unsafe extern "C" fn(
638            *mut extent_hooks_t,
639            *mut c_void,
640            size_t,
641            size_t,
642            size_t,
643            c_uint,
644        ) -> c_bool,
645    >,
646    pub purge_forced: Option<
647        unsafe extern "C" fn(
648            *mut extent_hooks_t,
649            *mut c_void,
650            size_t,
651            size_t,
652            size_t,
653            c_uint,
654        ) -> c_bool,
655    >,
656    pub split: Option<
657        unsafe extern "C" fn(
658            *mut extent_hooks_t,
659            *mut c_void,
660            size_t,
661            size_t,
662            size_t,
663            c_bool,
664            c_uint,
665        ) -> c_bool,
666    >,
667    pub merge: Option<
668        unsafe extern "C" fn(
669            *mut extent_hooks_t,
670            *mut c_void,
671            size_t,
672            *mut c_void,
673            size_t,
674            c_bool,
675            c_uint,
676        ) -> c_bool,
677    >,
678}
679
680/// Extent lifetime management functions.
681///
682/// The extent_hooks_t structure comprises function pointers which are described
683/// individually below. `jemalloc` uses these functions to manage extent lifetime,
684/// which starts off with allocation of mapped committed memory, in the simplest
685/// case followed by deallocation. However, there are performance and platform
686/// reasons to retain extents for later reuse. Cleanup attempts cascade from
687/// deallocation to decommit to forced purging to lazy purging, which gives the
688/// extent management functions opportunities to reject the most permanent
689/// cleanup operations in favor of less permanent (and often less costly)
690/// operations. All operations except allocation can be universally opted out of
691/// by setting the hook pointers to `NULL`, or selectively opted out of by
692/// returning failure. Note that once the extent hook is set, the structure is
693/// accessed directly by the associated arenas, so it must remain valid for the
694/// entire lifetime of the arenas.
695#[repr(C)]
696#[cfg(jemallocator_docs)]
697#[derive(Copy, Clone, Default)]
698pub struct extent_hooks_s {
699    #[allow(missing_docs)]
700    pub alloc: Option<extent_alloc_t>,
701    #[allow(missing_docs)]
702    pub dalloc: Option<extent_dalloc_t>,
703    #[allow(missing_docs)]
704    pub destroy: Option<extent_destroy_t>,
705    #[allow(missing_docs)]
706    pub commit: Option<extent_commit_t>,
707    #[allow(missing_docs)]
708    pub decommit: Option<extent_decommit_t>,
709    #[allow(missing_docs)]
710    pub purge_lazy: Option<extent_purge_t>,
711    #[allow(missing_docs)]
712    pub purge_forced: Option<extent_purge_t>,
713    #[allow(missing_docs)]
714    pub split: Option<extent_split_t>,
715    #[allow(missing_docs)]
716    pub merge: Option<extent_merge_t>,
717}
718
719/// Extent allocation function.
720///
721/// On success returns a pointer to `size` bytes of mapped memory on behalf of
722/// arena `arena_ind` such that the extent's base address is a multiple of
723/// `alignment`, as well as setting `*zero` to indicate whether the extent is
724/// zeroed and `*commit` to indicate whether the extent is committed.
725///
726/// Zeroing is mandatory if `*zero` is `true` upon function entry. Committing is mandatory if
727/// `*commit` is true upon function entry. If `new_addr` is not null, the returned
728/// pointer must be `new_addr` on success or null on error.
729///
730/// Committed memory may be committed in absolute terms as on a system that does
731/// not overcommit, or in implicit terms as on a system that overcommits and
732/// satisfies physical memory needs on demand via soft page faults. Note that
733/// replacing the default extent allocation function makes the arena's
734/// `arena.<i>.dss` setting irrelevant.
735///
736/// # Errors
737///
738/// On error the function returns null and leaves `*zero` and `*commit` unmodified.
739///
740/// # Safety
741///
742/// The behavior is _undefined_ if:
743///
744/// * the `size` parameter is not a multiple of the page size
745/// * the `alignment` parameter is not a power of two at least as large as the page size
746pub type extent_alloc_t = unsafe extern "C" fn(
747    extent_hooks: *mut extent_hooks_t,
748    new_addr: *mut c_void,
749    size: size_t,
750    alignment: size_t,
751    zero: *mut c_bool,
752    commit: *mut c_bool,
753    arena_ind: c_uint,
754) -> *mut c_void;
755
756/// Extent deallocation function.
757///
758/// Deallocates an extent at given `addr` and `size` with `committed`/decommited
759/// memory as indicated, on behalf of arena `arena_ind`, returning `false` upon
760/// success.
761///
762/// If the function returns `true`, this indicates opt-out from deallocation;
763/// the virtual memory mapping associated with the extent remains mapped, in the
764/// same commit state, and available for future use, in which case it will be
765/// automatically retained for later reuse.
766pub type extent_dalloc_t = unsafe extern "C" fn(
767    extent_hooks: *mut extent_hooks_t,
768    addr: *mut c_void,
769    size: size_t,
770    committed: c_bool,
771    arena_ind: c_uint,
772) -> c_bool;
773
774/// Extent destruction function.
775///
776/// Unconditionally destroys an extent at given `addr` and `size` with
777/// `committed`/decommited memory as indicated, on behalf of arena `arena_ind`.
778///
779/// This function may be called to destroy retained extents during arena
780/// destruction (see `arena.<i>.destroy`).
781pub type extent_destroy_t = unsafe extern "C" fn(
782    extent_hooks: *mut extent_hooks_t,
783    addr: *mut c_void,
784    size: size_t,
785    committed: c_bool,
786    arena_ind: c_uint,
787);
788
789/// Extent commit function.
790///
791/// Commits zeroed physical memory to back pages within an extent at given
792/// `addr` and `size` at `offset` bytes, extending for `length` on behalf of
793/// arena `arena_ind`, returning `false` upon success.
794///
795/// Committed memory may be committed in absolute terms as on a system that does
796/// not overcommit, or in implicit terms as on a system that overcommits and
797/// satisfies physical memory needs on demand via soft page faults. If the
798/// function returns `true`, this indicates insufficient physical memory to
799/// satisfy the request.
800pub type extent_commit_t = unsafe extern "C" fn(
801    extent_hooks: *mut extent_hooks_t,
802    addr: *mut c_void,
803    size: size_t,
804    offset: size_t,
805    length: size_t,
806    arena_ind: c_uint,
807) -> c_bool;
808
809/// Extent decommit function.
810///
811/// Decommits any physical memory that is backing pages within an extent at
812/// given `addr` and `size` at `offset` bytes, extending for `length` on behalf of arena
813/// `arena_ind`, returning `false` upon success, in which case the pages will be
814/// committed via the extent commit function before being reused.
815///
816/// If the function returns `true`, this indicates opt-out from decommit; the
817/// memory remains committed and available for future use, in which case it will
818/// be automatically retained for later reuse.
819pub type extent_decommit_t = unsafe extern "C" fn(
820    extent_hooks: *mut extent_hooks_t,
821    addr: *mut c_void,
822    size: size_t,
823    offset: size_t,
824    length: size_t,
825    arena_ind: c_uint,
826) -> c_bool;
827
828/// Extent purge function.
829///
830/// Discards physical pages within the virtual memory mapping associated with an
831/// extent at given `addr` and `size` at `offset` bytes, extending for `length` on
832/// behalf of arena `arena_ind`.
833///
834/// A lazy extent purge function (e.g. implemented via `madvise(...MADV_FREE)`)
835/// can delay purging indefinitely and leave the pages within the purged virtual
836/// memory range in an indeterminite state, whereas a forced extent purge
837/// function immediately purges, and the pages within the virtual memory range
838/// will be zero-filled the next time they are accessed. If the function returns
839/// `true`, this indicates failure to purge.
840pub type extent_purge_t = unsafe extern "C" fn(
841    extent_hooks: *mut extent_hooks_t,
842    addr: *mut c_void,
843    size: size_t,
844    offset: size_t,
845    length: size_t,
846    arena_ind: c_uint,
847) -> c_bool;
848
849/// Extent split function.
850///
851/// Optionally splits an extent at given `addr` and `size` into two adjacent
852/// extents, the first of `size_a` bytes, and the second of `size_b` bytes,
853/// operating on `committed`/decommitted memory as indicated, on behalf of arena
854/// `arena_ind`, returning `false` upon success.
855///
856/// If the function returns `true`, this indicates that the extent remains
857/// unsplit and therefore should continue to be operated on as a whole.
858pub type extent_split_t = unsafe extern "C" fn(
859    extent_hooks: *mut extent_hooks_t,
860    addr: *mut c_void,
861    size: size_t,
862    size_a: size_t,
863    size_b: size_t,
864    committed: c_bool,
865    arena_ind: c_uint,
866) -> c_bool;
867
868/// Extent merge function.
869///
870/// Optionally merges adjacent extents, at given `addr_a` and `size_a` with given
871/// `addr_b` and `size_b` into one contiguous extent, operating on
872/// `committed`/decommitted memory as indicated, on behalf of arena `arena_ind`,
873/// returning `false` upon success.
874///
875/// If the function returns `true`, this indicates that the extents remain
876/// distinct mappings and therefore should continue to be operated on
877/// independently.
878pub type extent_merge_t = unsafe extern "C" fn(
879    extent_hooks: *mut extent_hooks_t,
880    addr_a: *mut c_void,
881    size_a: size_t,
882    addr_b: *mut c_void,
883    size_b: size_t,
884    committed: c_bool,
885    arena_ind: c_uint,
886) -> c_bool;
887
888#[allow(missing_docs)]
889mod env;
890
891pub use env::*;