forked from M-Labs/artiq
1
0
Fork 0

alloc_list: support alloc w/ large align

Signed-off-by: Oi Chee Cheung <dc@m-labs.hk>
This commit is contained in:
occheung 2021-10-07 11:17:02 +08:00 committed by Sébastien Bourdeauducq
parent 1894f0f626
commit 59065c4663
1 changed files with 40 additions and 19 deletions

View File

@ -3,9 +3,6 @@
use core::{ptr, mem, fmt}; use core::{ptr, mem, fmt};
use core::alloc::{GlobalAlloc, Layout}; use core::alloc::{GlobalAlloc, Layout};
// The minimum alignment guaranteed by the architecture.
const MIN_ALIGN: usize = 16;
const MAGIC_FREE: usize = 0xDEADDEAD; const MAGIC_FREE: usize = 0xDEADDEAD;
const MAGIC_BUSY: usize = 0xFEEDFEED; const MAGIC_BUSY: usize = 0xFEEDFEED;
@ -13,7 +10,6 @@ const MAGIC_BUSY: usize = 0xFEEDFEED;
struct Header { struct Header {
magic: usize, magic: usize,
size: usize, size: usize,
_pad: usize,
next: *mut Header next: *mut Header
} }
@ -42,10 +38,6 @@ impl ListAlloc {
unsafe impl GlobalAlloc for ListAlloc { unsafe impl GlobalAlloc for ListAlloc {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 { unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
if layout.align() > MIN_ALIGN {
panic!("cannot allocate with alignment {}", layout.align())
}
let header_size = mem::size_of::<Header>(); let header_size = mem::size_of::<Header>();
let size; let size;
if layout.size() % header_size != 0 { if layout.size() % header_size != 0 {
@ -53,6 +45,7 @@ unsafe impl GlobalAlloc for ListAlloc {
} else { } else {
size = layout.size() size = layout.size()
} }
let align = layout.align();
let mut curr = self.root; let mut curr = self.root;
while !curr.is_null() { while !curr.is_null() {
@ -68,21 +61,49 @@ unsafe impl GlobalAlloc for ListAlloc {
next = (*curr).next; next = (*curr).next;
} }
if (*curr).size > size + header_size * 2 { unsafe fn split(header: *mut Header, split_size: usize) {
// Split let offset = mem::size_of::<Header>() + split_size;
let offset = header_size + size; let next = (header as *mut u8).offset(offset as isize) as *mut Header;
let next = (curr as *mut u8).offset(offset as isize) as *mut Header;
(*next).magic = MAGIC_FREE; (*next).magic = MAGIC_FREE;
(*next).size = (*curr).size - offset; (*next).size = (*header).size - offset;
(*next).next = (*curr).next; (*next).next = (*header).next;
(*curr).next = next; (*header).next = next;
(*curr).size = size; (*header).size = split_size;
}
// Case 1: Memory can be allocated straight from the current chunk
if (curr.offset(1) as usize) % align == 0 {
// Check available space
if (*curr).size > size + header_size * 2 {
split(curr, size);
} }
if (*curr).size >= size { if (*curr).size >= size {
(*curr).magic = MAGIC_BUSY; (*curr).magic = MAGIC_BUSY;
return curr.offset(1) as *mut u8 return curr.offset(1) as *mut u8
} }
}
// Case 2: Padding is needed to satisfy the alignment
else {
let alloc_addr = curr.offset(2) as usize;
let padding_size = align - (alloc_addr % align);
if (*curr).size >= size + padding_size + header_size {
// Create a padding region
split(curr, padding_size);
curr = (*curr).next;
// Check if a padding is needed at the rear
if (*curr).size > size + header_size * 2 {
split(curr, size);
}
(*curr).magic = MAGIC_BUSY;
return curr.offset(1) as *mut u8
}
}
}, },
_ => panic!("heap corruption detected at {:p}", curr) _ => panic!("heap corruption detected at {:p}", curr)
} }