// codesnip-guard: HugePageAllocator #[cfg_attr(any(),rustfmt::skip)]pub use self::huge_page_allocator::HugePageAllocator;#[cfg_attr(any(),rustfmt::skip)]mod huge_page_allocator{use std::alloc::{GlobalAlloc,Layout,System};#[doc=" A system allocator that aligns allocations of at least 2 MiB for transparent huge pages"]#[doc=" on Linux x86-64. Select it with `#[global_allocator]` or `main!(huge_pages; ...)`."]#[doc=" Large allocations are rounded up to a multiple of 2 MiB; other targets use `System`."]#[doc=" The `main!` option requires the `HugePageAllocator` snippet alongside `main`."]pub struct HugePageAllocator;unsafe impl GlobalAlloc for HugePageAllocator{unsafe fn alloc(&self,layout:Layout)->*mut u8{let Some(layout)=page_layout(layout)else{return std::ptr::null_mut();};unsafe{let ptr=System.alloc(layout);#[cfg(all(target_os="linux",target_arch="x86_64"))]if!ptr.is_null()&&layout.size()>=1<<21{unsafe extern "C"{fn madvise(addr:*mut std::ffi::c_void,len:usize,advice:i32)->i32;}let _=madvise(ptr.cast(),layout.size(),14);}ptr}}unsafe fn dealloc(&self,ptr:*mut u8,layout:Layout){unsafe{System.dealloc(ptr,page_layout(layout).unwrap_unchecked())}}unsafe fn alloc_zeroed(&self,layout:Layout)->*mut u8{unsafe{if!use_huge_pages(layout.size()){return System.alloc_zeroed(layout);}let ptr=self.alloc(layout);if!ptr.is_null(){std::ptr::write_bytes(ptr,0,layout.size());}ptr}}unsafe fn realloc(&self,ptr:*mut u8,layout:Layout,new_size:usize)->*mut u8{unsafe{if!use_huge_pages(layout.size().max(new_size)){return System.realloc(ptr,layout,new_size);}let new_layout=Layout::from_size_align_unchecked(new_size,layout.align());let new_ptr=self.alloc(new_layout);if!new_ptr.is_null(){std::ptr::copy_nonoverlapping(ptr,new_ptr,layout.size().min(new_size));self.dealloc(ptr,layout);}new_ptr}}}fn page_layout(layout:Layout)->Option{if use_huge_pages(layout.size()){return layout.align_to(1<<21).ok().map(|layout|layout.pad_to_align());}Some(layout)}fn use_huge_pages(size:usize)->bool{cfg!(all(target_os="linux",target_arch="x86_64"))&&size>=1<<21}}