extern crate alloc as crate_alloc;
extern crate object_alloc;
use self::object_alloc::UntypedObjectAlloc;
pub trait BackingAlloc {
type Aligned: UntypedObjectAlloc;
type Large: UntypedObjectAlloc;
}
pub mod alloc {
extern crate alloc;
extern crate object_alloc;
use self::alloc::allocator::{Alloc, AllocErr, Layout};
use self::object_alloc::{Exhausted, UntypedObjectAlloc};
#[derive(Clone)]
pub struct AllocObjectAlloc<A: Alloc> {
alloc: A,
layout: Layout,
}
impl<A: Alloc> AllocObjectAlloc<A> {
pub fn new(alloc: A, layout: Layout) -> AllocObjectAlloc<A> {
AllocObjectAlloc { alloc, layout }
}
}
unsafe impl<A: Alloc> UntypedObjectAlloc for AllocObjectAlloc<A> {
fn layout(&self) -> Layout {
self.layout.clone()
}
unsafe fn alloc(&mut self) -> Result<*mut u8, Exhausted> {
match self.alloc.alloc(self.layout.clone()) {
Ok(ptr) => Ok(ptr),
Err(AllocErr::Exhausted { .. }) => Err(Exhausted),
Err(AllocErr::Unsupported { details }) => {
unreachable!("unexpected unsupported alloc: {}", details)
}
}
}
unsafe fn dealloc(&mut self, ptr: *mut u8) {
self.alloc.dealloc(ptr, self.layout.clone());
}
}
}
#[cfg(feature = "std")]
pub mod heap {
extern crate alloc;
use self::alloc::heap::{Heap, Layout};
use super::alloc::AllocObjectAlloc;
use super::BackingAlloc;
use PAGE_SIZE;
pub struct HeapBackingAlloc;
impl BackingAlloc for HeapBackingAlloc {
type Aligned = AllocObjectAlloc<Heap>;
type Large = AllocObjectAlloc<Heap>;
}
pub fn get_aligned(layout: Layout) -> Option<AllocObjectAlloc<Heap>> {
if layout.size() > *PAGE_SIZE {
None
} else {
Some(AllocObjectAlloc::new(Heap, layout))
}
}
pub fn get_large(layout: Layout) -> AllocObjectAlloc<Heap> {
AllocObjectAlloc::new(Heap, layout)
}
}
#[cfg(feature = "os")]
pub mod mmap {
extern crate alloc;
extern crate mmap_alloc;
extern crate sysconf;
use self::alloc::allocator::Layout;
#[cfg(target_os = "linux")]
use self::mmap_alloc::{MapAlloc, MapAllocBuilder};
#[cfg(not(target_os = "linux"))]
use self::mmap_alloc::MapAlloc;
use super::alloc::AllocObjectAlloc;
use super::BackingAlloc;
use PAGE_SIZE;
pub struct MmapBackingAlloc;
impl BackingAlloc for MmapBackingAlloc {
type Aligned = AllocObjectAlloc<MapAlloc>;
type Large = AllocObjectAlloc<MapAlloc>;
}
pub fn get_aligned(layout: Layout) -> Option<AllocObjectAlloc<MapAlloc>> {
debug_assert_eq!(layout.size(), layout.align());
if layout.size() != *PAGE_SIZE {
#[cfg(target_os = "linux")]
{
if self::sysconf::page::hugepage_supported(layout.size()) {
let map = MapAllocBuilder::default()
.huge_pagesize(layout.size())
.build();
Some(AllocObjectAlloc::new(map, layout))
} else {
None
}
}
#[cfg(not(target_os = "linux"))]
None
} else {
Some(AllocObjectAlloc::new(MapAlloc::default(), layout))
}
}
pub fn get_large(layout: Layout) -> AllocObjectAlloc<MapAlloc> {
debug_assert!(layout.align() <= *PAGE_SIZE);
AllocObjectAlloc::new(MapAlloc::default(), layout)
}
}