Skip to content

Commit

Permalink
Don’t assume MIN_ALIGN for small sizes
Browse files Browse the repository at this point in the history
Same as rust-lang/rust#46117

See also discussion of jemalloc’s behavior at
jemalloc/jemalloc#1072
  • Loading branch information
SimonSapin committed Nov 22, 2017
1 parent 5043bb2 commit fd99aee
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 10 deletions.
18 changes: 9 additions & 9 deletions src/lib.rs
Expand Up @@ -47,8 +47,8 @@ fn mallocx_align(a: usize) -> c_int {
a.trailing_zeros() as c_int
}

fn align_to_flags(align: usize) -> c_int {
if align <= MIN_ALIGN {
fn align_to_flags(align: usize, size: usize) -> c_int {
if align <= MIN_ALIGN && align <= size {
0
} else {
mallocx_align(align)
Expand Down Expand Up @@ -131,7 +131,7 @@ unsafe impl Alloc for Jemalloc {
unsafe impl<'a> Alloc for &'a Jemalloc {
#[inline]
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
let flags = align_to_flags(layout.align());
let flags = align_to_flags(layout.align(), layout.size());
let ptr = ffi::mallocx(layout.size(), flags);
if ptr.is_null() {
Err(AllocErr::Exhausted { request: layout })
Expand All @@ -144,10 +144,10 @@ unsafe impl<'a> Alloc for &'a Jemalloc {
unsafe fn alloc_zeroed(&mut self, layout: Layout)
-> Result<*mut u8, AllocErr>
{
let ptr = if layout.align() <= MIN_ALIGN {
let ptr = if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
ffi::calloc(1, layout.size())
} else {
let flags = align_to_flags(layout.align()) | ffi::MALLOCX_ZERO;
let flags = align_to_flags(layout.align(), layout.size()) | ffi::MALLOCX_ZERO;
ffi::mallocx(layout.size(), flags)
};
if ptr.is_null() {
Expand All @@ -159,7 +159,7 @@ unsafe impl<'a> Alloc for &'a Jemalloc {

#[inline]
unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
let flags = align_to_flags(layout.align());
let flags = align_to_flags(layout.align(), layout.size());
ffi::sdallocx(ptr as *mut c_void, layout.size(), flags)
}

Expand All @@ -171,7 +171,7 @@ unsafe impl<'a> Alloc for &'a Jemalloc {
if old_layout.align() != new_layout.align() {
return Err(AllocErr::Unsupported { details: "cannot change align" })
}
let flags = align_to_flags(new_layout.align());
let flags = align_to_flags(new_layout.align(), new_layout.size());
let ptr = ffi::rallocx(ptr as *mut c_void, new_layout.size(), flags);
if ptr.is_null() {
Err(AllocErr::Exhausted { request: new_layout })
Expand All @@ -186,7 +186,7 @@ unsafe impl<'a> Alloc for &'a Jemalloc {

#[inline]
fn usable_size(&self, layout: &Layout) -> (usize, usize) {
let flags = align_to_flags(layout.align());
let flags = align_to_flags(layout.align(), layout.size());
unsafe {
let max = ffi::nallocx(layout.size(), flags);
(layout.size(), max)
Expand All @@ -209,7 +209,7 @@ unsafe impl<'a> Alloc for &'a Jemalloc {
if old_layout.align() != new_layout.align() {
return Err(CannotReallocInPlace)
}
let flags = align_to_flags(new_layout.align());
let flags = align_to_flags(new_layout.align(), new_layout.size());
let size = ffi::xallocx(ptr as *mut c_void, new_layout.size(), 0, flags);
if size >= new_layout.size() {
Err(CannotReallocInPlace)
Expand Down
24 changes: 23 additions & 1 deletion tests/smoke.rs
@@ -1,8 +1,9 @@
#![feature(global_allocator)]
#![feature(global_allocator, allocator_api)]

extern crate jemallocator;

use jemallocator::Jemalloc;
use std::heap::{Alloc, Layout};

#[global_allocator]
static A: Jemalloc = Jemalloc;
Expand All @@ -12,3 +13,24 @@ fn smoke() {
let mut a = Vec::new();
a.push(3);
}

/// https://github.com/rust-lang/rust/issues/45955
#[test]
fn overaligned() {
let size = 8;
let align = 16; // greater than size
let iterations = 100;
unsafe {
let pointers: Vec<_> = (0..iterations).map(|_| {
Jemalloc.alloc(Layout::from_size_align(size, align).unwrap()).unwrap()
}).collect();
for &ptr in &pointers {
assert_eq!((ptr as usize) % align, 0, "Got a pointer less aligned than requested")
}

// Clean up
for &ptr in &pointers {
Jemalloc.dealloc(ptr, Layout::from_size_align(size, align).unwrap())
}
}
}

0 comments on commit fd99aee

Please sign in to comment.