Skip to content

Commit

Permalink
Merge pull request #104 from jacob-hughes/posix_memalign
Browse files Browse the repository at this point in the history
Fix broken `memalign` behaviour.
  • Loading branch information
ltratt committed Dec 7, 2023
2 parents 1cc2852 + 43b8404 commit 52fc606
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 5 deletions.
21 changes: 17 additions & 4 deletions library/alloc/src/gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,14 @@ unsafe fn gc_malloc(layout: Layout) -> *mut u8 {
if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
unsafe { boehm::GC_malloc(layout.size()) as *mut u8 }
} else {
unsafe { boehm::GC_memalign(layout.align(), layout.size()) as *mut u8 }
let mut out = ptr::null_mut();
// posix_memalign requires that the alignment be a multiple of `sizeof(void*)`.
// Since these are all powers of 2, we can just use max.
unsafe {
let align = layout.align().max(core::mem::size_of::<usize>());
let ret = boehm::GC_posix_memalign(&mut out, align, layout.size());
if ret != 0 { ptr::null_mut() } else { out as *mut u8 }
}
}
}

Expand All @@ -80,9 +87,15 @@ unsafe fn gc_realloc(ptr: *mut u8, old_layout: Layout, new_size: usize) -> *mut
}

#[inline]
unsafe fn gc_free(ptr: *mut u8, _: Layout) {
unsafe {
boehm::GC_free(ptr);
unsafe fn gc_free(ptr: *mut u8, layout: Layout) {
if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
unsafe {
boehm::GC_free(ptr);
}
} else {
unsafe {
boehm::GC_free(boehm::GC_base(ptr));
}
}
}

Expand Down
29 changes: 29 additions & 0 deletions library/alloc/tests/gc.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,41 @@
use std::gc::GcAllocator;
use std::alloc::GlobalAlloc;
use std::alloc::Layout;

#[repr(align(1024))]
struct S(u8);

#[repr(align(16))]
struct T(usize, usize, usize, usize);

#[test]
fn large_alignment() {
let x = Box::new_in(S(123), GcAllocator);
let ptr = Box::into_raw(x);
assert!(!ptr.is_null());
assert!(ptr.is_aligned());

// When this is freed, GC assertions will check if the base pointer can be
// correctly recovered.
unsafe { let _ = Box::from_raw_in(ptr, GcAllocator); }

let y = Box::new_in(T(1, 2, 3, 4), GcAllocator);
let ptr = Box::into_raw(y);
assert!(!ptr.is_null());
assert!(ptr.is_aligned());

unsafe { let _ = Box::from_raw_in(ptr, GcAllocator); }
}

#[test]
fn boehm_issue_589() {
// Test the specific size / alignment problem raised in [1].
//
// [1]: https://github.com/ivmai/bdwgc/issues/589
unsafe {
let allocator = GcAllocator;
let layout = Layout::from_size_align_unchecked(512, 64);
let raw_ptr = GlobalAlloc::alloc(&allocator, layout);
GlobalAlloc::dealloc(&allocator, raw_ptr, layout);
}
}
4 changes: 3 additions & 1 deletion library/boehm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@ pub struct ProfileStats {
extern "C" {
pub fn GC_malloc(nbytes: usize) -> *mut u8;

pub fn GC_memalign(align: usize, nbytes: usize) -> *mut u8;
pub fn GC_posix_memalign(mem_ptr: *mut *mut u8, align: usize, nbytes: usize) -> i32;

pub fn GC_realloc(old: *mut u8, new_size: usize) -> *mut u8;

pub fn GC_free(dead: *mut u8);

pub fn GC_base(mem_ptr: *mut u8) -> *mut u8;

pub fn GC_register_finalizer(
ptr: *mut u8,
finalizer: Option<unsafe extern "C" fn(*mut u8, *mut u8)>,
Expand Down

0 comments on commit 52fc606

Please sign in to comment.