Files
DragonOS/kernel/src/mm/allocator/slab.rs
LoGin b6db20c072 feature: virtio console support (#1113)
feat(virtio): add virtio console driver support

- Implement virtio console driver with TTY interface
- Add HVC device support for console output
- Update devfs to handle HVC devices
- Fix virtio driver registration and initialization
- Improve virtio net driver interrupt handling
- Clean up block device naming implementation
- Add clippy lint checks to multiple crates
- Fix slab allocator alignment issues
- Update QEMU run script for virtio consoleagonOS.org>

---------

Signed-off-by: longjin <longjin@DragonOS.org>
2025-03-27 20:48:40 +08:00

96 lines
3.0 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use core::{alloc::Layout, ptr::NonNull, sync::atomic::AtomicBool};
use alloc::boxed::Box;
use log::debug;
use slabmalloc::*;
use crate::{arch::MMArch, mm::MemoryManagementArch, KERNEL_ALLOCATOR};
// 全局slab分配器
pub(crate) static mut SLABALLOCATOR: Option<SlabAllocator> = None;
// slab初始化状态
pub(crate) static mut SLABINITSTATE: AtomicBool = AtomicBool::new(false);
static SLAB_CALLBACK: SlabCallback = SlabCallback;
/// slab分配器实际为一堆小的allocator可以在里面装4K的page
/// 利用这些allocator可以为对象分配不同大小的空间
pub(crate) struct SlabAllocator {
zone: ZoneAllocator<'static>,
}
impl SlabAllocator {
/// 创建slab分配器
pub fn new() -> SlabAllocator {
debug!("trying to new a slab_allocator");
SlabAllocator {
zone: ZoneAllocator::new(),
}
}
/// 为对象2K以内分配内存空间
pub(crate) unsafe fn allocate(&mut self, layout: Layout) -> *mut u8 {
match self.zone.allocate(layout) {
Ok(nptr) => nptr.as_ptr(),
Err(AllocationError::OutOfMemory) => {
let boxed_page = ObjectPage::new();
assert_eq!(
(boxed_page.as_ref() as *const ObjectPage as usize) & (MMArch::PAGE_SIZE - 1),
0
);
let leaked_page = Box::leak(boxed_page);
self.zone
.refill(layout, leaked_page)
.expect("Could not refill?");
self.zone
.allocate(layout)
.expect("Should succeed after refill")
.as_ptr()
}
Err(AllocationError::InvalidLayout) => panic!("Can't allocate this size"),
}
}
/// 释放内存空间
pub(crate) unsafe fn deallocate(
&mut self,
ptr: *mut u8,
layout: Layout,
) -> Result<(), AllocationError> {
if let Some(nptr) = NonNull::new(ptr) {
self.zone
.deallocate(nptr, layout, &SLAB_CALLBACK)
.expect("Couldn't deallocate");
return Ok(());
} else {
return Ok(());
}
}
}
/// 初始化slab分配器
pub unsafe fn slab_init() {
debug!("trying to init a slab_allocator");
SLABALLOCATOR = Some(SlabAllocator::new());
SLABINITSTATE = true.into();
}
pub unsafe fn slab_usage() -> SlabUsage {
if let Some(ref mut slab) = SLABALLOCATOR {
slab.zone.usage()
} else {
SlabUsage::new(0, 0)
}
}
/// 归还slab_page给buddy的回调
pub struct SlabCallback;
impl CallBack for SlabCallback {
unsafe fn free_slab_page(&self, base_addr: *mut u8, size: usize) {
assert_eq!(base_addr as usize & (MMArch::PAGE_SIZE - 1), 0); // 确认地址4k对齐
assert_eq!(size, MMArch::PAGE_SIZE); // 确认释放的slab_page大小
KERNEL_ALLOCATOR.free_in_buddy(base_addr, Layout::from_size_align_unchecked(size, 1));
}
}