mmtk/util/malloc/
malloc_ms_util.rs

1use crate::util::constants::BYTES_IN_ADDRESS;
2use crate::util::malloc::library::*;
3use crate::util::Address;
4use crate::vm::VMBinding;
5
6/// Allocate with alignment. This also guarantees the memory is zero initialized.
7pub fn align_alloc(size: usize, align: usize) -> Address {
8    let mut ptr = std::ptr::null_mut::<libc::c_void>();
9    let ptr_ptr = std::ptr::addr_of_mut!(ptr);
10    let result = unsafe { posix_memalign(ptr_ptr, align, size) };
11    if result != 0 {
12        return Address::ZERO;
13    }
14    let address = Address::from_mut_ptr(ptr);
15    crate::util::memory::zero(address, size);
16    address
17}
18
19/// Allocate with alignment and offset.
20/// Beside returning the allocation result, this will store the malloc result at (result - BYTES_IN_ADDRESS)
21/// so we know the original malloc result.
22pub fn align_offset_alloc<VM: VMBinding>(size: usize, align: usize, offset: usize) -> Address {
23    // we allocate extra `align` bytes here, so we are able to handle offset
24    let actual_size = size + align + BYTES_IN_ADDRESS;
25    let raw = unsafe { calloc(1, actual_size) };
26    let address = Address::from_mut_ptr(raw);
27    if address.is_zero() {
28        return address;
29    }
30    let mod_offset = offset % align;
31    let mut result =
32        crate::util::alloc::allocator::align_allocation_no_fill::<VM>(address, align, mod_offset);
33    if result - BYTES_IN_ADDRESS < address {
34        result += align;
35    }
36    let malloc_res_ptr: *mut usize = (result - BYTES_IN_ADDRESS).to_mut_ptr();
37    unsafe { malloc_res_ptr.write_unaligned(address.as_usize()) };
38    result
39}
40
41/// Get the malloc usable size for an address that is returned by [`crate::util::malloc::malloc_ms_util::align_offset_alloc`].
42pub fn offset_malloc_usable_size(address: Address) -> usize {
43    let malloc_res_ptr: *mut usize = (address - BYTES_IN_ADDRESS).to_mut_ptr();
44    let malloc_res = unsafe { malloc_res_ptr.read_unaligned() } as *mut libc::c_void;
45    unsafe { malloc_usable_size(malloc_res) }
46}
47
48/// Free an address that is allocated with an offset (returned by [`crate::util::malloc::malloc_ms_util::align_offset_alloc`]).
49pub fn offset_free(address: Address) {
50    let malloc_res_ptr: *mut usize = (address - BYTES_IN_ADDRESS).to_mut_ptr();
51    let malloc_res = unsafe { malloc_res_ptr.read_unaligned() } as *mut libc::c_void;
52    unsafe { free(malloc_res) };
53}
54
55pub use crate::util::malloc::library::free;
56
57/// get malloc usable size of an address
58/// is_offset_malloc: whether the address is allocated with some offset
59pub fn get_malloc_usable_size(address: Address, is_offset_malloc: bool) -> usize {
60    if is_offset_malloc {
61        offset_malloc_usable_size(address)
62    } else {
63        unsafe { malloc_usable_size(address.to_mut_ptr()) }
64    }
65}
66
67/// allocate `size` bytes, which is aligned to `align` at `offset`
68/// return the address, and whether it is an offset allocation
69pub fn alloc<VM: VMBinding>(size: usize, align: usize, offset: usize) -> (Address, bool) {
70    let address: Address;
71    let mut is_offset_malloc = false;
72    // malloc returns 16 bytes aligned address.
73    // So if the alignment is smaller than 16 bytes, we do not need to align.
74    if align <= 16 && offset == 0 {
75        let raw = unsafe { calloc(1, size) };
76        address = Address::from_mut_ptr(raw);
77        debug_assert!(address.is_aligned_to(align));
78    } else if align > 16 && offset == 0 {
79        address = align_alloc(size, align);
80        debug_assert!(
81            address.is_aligned_to(align),
82            "Address: {:x} is not aligned to the given alignment: {}",
83            address,
84            align
85        );
86    } else {
87        address = align_offset_alloc::<VM>(size, align, offset);
88        is_offset_malloc = true;
89        debug_assert!(
90            (address + offset).is_aligned_to(align),
91            "Address: {:x} is not aligned to the given alignment: {} at offset: {}",
92            address,
93            align,
94            offset
95        );
96    }
97    (address, is_offset_malloc)
98}