use core::ops::BitAnd;
use self::{
error::Result,
global::{free_pages_to_freelist, get_page_from_freelist},
};
use crate::{println, space::mm::pgtabledef::PAGE_SHIFT};
mod global;
mod page;
mod slab;
pub(crate) use global::kalloc_init;
use global::{global_nr_free_pages, global_nr_reserved_pages, global_nr_total_pages};
pub use page::Page;
pub use slab::vaddr_name;
pub(crate) use slab::{kfree, kmalloc};
use super::addr::Vaddr;
pub mod error;
#[derive(Clone, Copy)]
#[repr(usize)]
pub enum GfpFlags {
Normal = 0b0000000,
Clean = 0b0000001,
}
impl BitAnd for GfpFlags {
type Output = usize;
#[inline(always)]
fn bitand(self, rhs: Self) -> Self::Output {
self as usize & rhs as usize
}
}
impl GfpFlags {
#[inline(always)]
pub(crate) fn clear(self) -> bool {
self & GfpFlags::Clean != 0
}
}
pub fn alloc_pages(flags: GfpFlags, order: usize) -> Result<Vaddr> {
get_page_from_freelist(flags, order)
}
pub fn free_pages(vaddr: Vaddr, order: usize) {
free_pages_to_freelist(vaddr, order);
}
#[inline]
pub fn alloc_page(flags: GfpFlags) -> Result<Vaddr> {
alloc_pages(flags, 0)
}
#[inline]
pub fn free_page(vaddr: Vaddr) {
free_pages(vaddr, 0);
}
pub fn nr_total_pages() -> usize {
global_nr_total_pages()
}
pub fn nr_free_pages() -> usize {
global_nr_free_pages()
}
pub fn nr_reserved_pages() -> usize {
global_nr_reserved_pages()
}
pub fn kalloc_dump() {
println!(
"Mem total: {}M, reserved: {}M, free {}M",
(nr_total_pages() << (PAGE_SHIFT - 10)) / 1024,
(nr_reserved_pages() << (PAGE_SHIFT - 10)) / 1024,
(nr_free_pages() << (PAGE_SHIFT - 10)) / 1024
);
}
#[cfg(not(test))]
mod alloc {
use core::alloc::GlobalAlloc;
use super::{
super::addr::Vaddr,
GfpFlags,
slab::{kfree, kmalloc},
};
struct GAlloc;
#[global_allocator]
static GLOBAL_ALLOC: GAlloc = GAlloc;
unsafe impl GlobalAlloc for GAlloc {
unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 {
let mut size = layout.size();
let align = layout.align();
size = (size + align - 1) & !(align - 1);
let vaddr = kmalloc(size, GfpFlags::Normal).unwrap().to_value();
vaddr as *mut u8
}
unsafe fn dealloc(&self, ptr: *mut u8, _: core::alloc::Layout) {
let vaddr = Vaddr::from(ptr as usize);
kfree(vaddr);
}
}
}