use alloc::{string::ToString, vec::Vec};
use core::{
    fmt::{self, Debug, Error, Formatter},
    marker::PhantomData,
    mem,
    ops::Add,
    sync::atomic::{compiler_fence, Ordering},
};
use system_error::SystemError;
use unified_init::macros::unified_init;

use alloc::sync::{Arc, Weak};
use hashbrown::{HashMap, HashSet};
use log::{error, info};
use lru::LruCache;

use crate::{
    arch::{mm::LockedFrameAllocator, MMArch},
    filesystem::{
        page_cache::{
            async_writeback_progress_snapshot, list_page_caches, wait_for_async_writeback_progress,
            PageCache,
        },
        vfs::FilePrivateData,
    },
    init::initcall::INITCALL_CORE,
    libs::{
        mutex::{Mutex, MutexGuard},
        rwsem::{RwSem, RwSemReadGuard, RwSemUpgradeableGuard, RwSemWriteGuard},
    },
    mm::page_cache_stats as pc_stats,
    process::{ProcessControlBlock, ProcessManager},
    time::{sleep::nanosleep, PosixTimeSpec},
};

use super::{
    allocator::page_frame::{
        deallocate_page_frames, FrameAllocator, PageFrameCount, PhysPageFrame,
    },
    syscall::ProtFlags,
    ucontext::LockedVMA,
    MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
};

pub const PAGE_4K_SHIFT: usize = 12;
#[allow(dead_code)]
pub const PAGE_2M_SHIFT: usize = 21;
pub const PAGE_1G_SHIFT: usize = 30;

pub const PAGE_4K_SIZE: usize = 1 << PAGE_4K_SHIFT;
pub const PAGE_2M_SIZE: usize = 1 << PAGE_2M_SHIFT;

/// 全局物理页信息管理器
pub static mut PAGE_MANAGER: Option<Mutex<PageManager>> = None;

/// 初始化PAGE_MANAGER
pub fn page_manager_init() {
    info!("page_manager_init");
    let page_manager = Mutex::new(PageManager::new());

    compiler_fence(Ordering::SeqCst);
    unsafe { PAGE_MANAGER = Some(page_manager) };
    compiler_fence(Ordering::SeqCst);

    info!("page_manager_init done");
}

pub fn page_manager_lock() -> MutexGuard<'static, PageManager> {
    unsafe { PAGE_MANAGER.as_ref().unwrap().lock() }
}

/// Maximum number of page identities changed while holding a global page
/// registry lock. This bounds work by element count; HashMap growth itself is
/// not a hard real-time operation.
const PAGE_MANAGER_BULK_BATCH: usize = 64;

/// Release an allocator-owned physical range as aligned buddy blocks.
///
/// The range may be a non-power-of-two suffix of a larger allocation. Splitting
/// it into the largest aligned blocks avoids both invalid buddy frees and an
/// O(n) one-frame-at-a-time teardown.
unsafe fn free_aligned_frame_range(mut start: PhysAddr, mut pages: usize) {
    while pages != 0 {
        let pfn = start.data() / MMArch::PAGE_SIZE;
        let alignment_pages = if pfn == 0 {
            usize::MAX
        } else {
            1usize << pfn.trailing_zeros()
        };
        let length_pages = 1usize << (usize::BITS - 1 - pages.leading_zeros());
        let block_pages = alignment_pages.min(length_pages);
        LockedFrameAllocator.free(start, PageFrameCount::new(block_pages));
        start = PhysAddr::new(start.data() + block_pages * MMArch::PAGE_SIZE);
        pages -= block_pages;
    }
}

/// Owns the part of a raw buddy allocation not yet transferred to `Page`.
struct RawFrameExtent {
    next: PhysAddr,
    remaining: usize,
}

impl RawFrameExtent {
    fn trim_to(&mut self, requested: usize) {
        debug_assert!(requested <= self.remaining);
        let tail = self.remaining - requested;
        if tail != 0 {
            let tail_start = PhysAddr::new(self.next.data() + requested * MMArch::PAGE_SIZE);
            unsafe { free_aligned_frame_range(tail_start, tail) };
            self.remaining = requested;
        }
    }

    fn transfer_to_extent_owner(&mut self) {
        self.remaining = 0;
    }
}

impl Drop for RawFrameExtent {
    fn drop(&mut self) {
        if self.remaining != 0 {
            unsafe { free_aligned_frame_range(self.next, self.remaining) };
        }
    }
}

/// Owns one exact physically-contiguous allocation after raw construction.
///
/// Every `Page` created from the run pins this object. The final pin returns
/// the run as aligned buddy blocks, avoiding one global allocator lock per
/// 4-KiB page while still delaying reuse until all transient page references
/// have disappeared.
#[derive(Debug)]
struct ContiguousFrameOwner {
    start: PhysAddr,
    pages: usize,
}

impl Drop for ContiguousFrameOwner {
    fn drop(&mut self) {
        unsafe { free_aligned_frame_range(self.start, self.pages) };
    }
}

/// Registered, zeroed, intrinsically unevictable pages awaiting adoption by a
/// private PageCache. Until `commit`, this guard owns PageManager membership
/// and rolls it back by page identity on every failure path.
pub struct ManagedPageBatch {
    start_paddr: PhysAddr,
    pages: Vec<Arc<Page>>,
    registered: usize,
    committed: bool,
}

impl ManagedPageBatch {
    pub fn start_paddr(&self) -> PhysAddr {
        self.start_paddr
    }

    pub fn pages(&self) -> &[Arc<Page>] {
        &self.pages
    }

    pub(crate) fn commit(mut self) {
        self.committed = true;
    }
}

impl Drop for ManagedPageBatch {
    fn drop(&mut self) {
        if !self.committed && self.registered != 0 {
            detach_pages_from_manager_batched(self.pages[..self.registered].iter());
            self.registered = 0;
        }
    }
}

/// Allocate an exact user-visible run of zeroed Normal/PG_UNEVICTABLE pages.
/// Slow allocation, zeroing, and `Arc<Page>` construction happen outside the
/// global PageManager lock; only identity registration is performed there in
/// bounded batches.
pub fn allocate_registered_intrinsic_unevictable_pages_exact(
    requested: PageFrameCount,
) -> Result<ManagedPageBatch, SystemError> {
    let requested_pages = requested.data();
    if requested_pages == 0 {
        return Err(SystemError::EINVAL);
    }
    let allocator_pages = requested_pages
        .checked_next_power_of_two()
        .ok_or(SystemError::ENOMEM)?;

    let (start_paddr, actual) = unsafe {
        LockedFrameAllocator
            .allocate(PageFrameCount::new(allocator_pages))
            .ok_or(SystemError::ENOMEM)?
    };
    let mut raw = RawFrameExtent {
        next: start_paddr,
        remaining: actual.data(),
    };
    // FrameAllocator does not promise that an implementation returns at least
    // the requested extent. Validate before zeroing or trimming so a short
    // allocation cannot become an out-of-bounds write or arithmetic underflow.
    if raw.remaining < requested_pages {
        return Err(SystemError::ENOMEM);
    }
    let mut pages = Vec::new();
    pages
        .try_reserve_exact(requested_pages)
        .map_err(|_| SystemError::ENOMEM)?;
    let bytes = requested_pages
        .checked_mul(MMArch::PAGE_SIZE)
        .ok_or(SystemError::ENOMEM)?;
    let vaddr = unsafe { MMArch::phys_2_virt(start_paddr) }.ok_or(SystemError::EFAULT)?;

    // Zero before PageManager/PageCache publication so recycled kernel data is
    // never observable through a userspace mapping.
    unsafe { MMArch::write_bytes(vaddr, 0, bytes) };
    raw.trim_to(requested_pages);

    let extent_owner = Arc::try_new(ContiguousFrameOwner {
        start: start_paddr,
        pages: requested_pages,
    })
    .map_err(|_| SystemError::ENOMEM)?;
    raw.transfer_to_extent_owner();

    for index in 0..requested_pages {
        let paddr = PhysAddr::new(start_paddr.data() + index * MMArch::PAGE_SIZE);
        pages.push(Page::try_new_with_contiguous_owner(
            paddr,
            PageType::Normal,
            PageFlags::PG_UNEVICTABLE,
            extent_owner.clone(),
        )?);
    }

    let mut batch = ManagedPageBatch {
        start_paddr,
        pages,
        registered: 0,
        committed: false,
    };
    while batch.registered < batch.pages.len() {
        let end = (batch.registered + PAGE_MANAGER_BULK_BATCH).min(batch.pages.len());
        let chunk = &batch.pages[batch.registered..end];
        {
            let mut manager = page_manager_lock();
            manager
                .phys2page
                .try_reserve(chunk.len())
                .map_err(|_| SystemError::ENOMEM)?;
            if chunk
                .iter()
                .any(|page| manager.phys2page.contains_key(&page.phys_address()))
            {
                return Err(SystemError::EEXIST);
            }
            for page in chunk {
                manager.phys2page.insert(page.phys_address(), page.clone());
            }
        }
        batch.registered = end;
    }
    Ok(batch)
}

/// Remove pinned pages from PageManager only when the registered identity is
/// the expected `Arc<Page>`. Removed manager references are released after the
/// global lock; callers retain their own page references for the whole call.
pub fn detach_pages_from_manager_batched<'a>(pages: impl IntoIterator<Item = &'a Arc<Page>>) {
    let mut pages = pages.into_iter();
    let mut removed: [Option<Arc<Page>>; PAGE_MANAGER_BULK_BATCH] = core::array::from_fn(|_| None);
    loop {
        let mut count = 0;
        let mut exhausted = false;
        {
            let mut manager = page_manager_lock();
            while count < PAGE_MANAGER_BULK_BATCH {
                let Some(page) = pages.next() else {
                    exhausted = true;
                    break;
                };
                removed[count] = manager.remove_page_if_same(page);
                count += 1;
            }
        }
        for slot in &mut removed[..count] {
            drop(slot.take());
        }
        if exhausted {
            break;
        }
    }
}

/// Identity-safe, bounded counterpart for the global page reclaimer registry.
pub fn detach_pages_from_reclaimer_batched<'a>(pages: impl IntoIterator<Item = &'a Arc<Page>>) {
    let mut pages = pages.into_iter();
    let mut removed: [Option<Arc<Page>>; PAGE_MANAGER_BULK_BATCH] = core::array::from_fn(|_| None);
    loop {
        let mut count = 0;
        let mut exhausted = false;
        {
            let mut reclaimer = page_reclaimer_lock();
            while count < PAGE_MANAGER_BULK_BATCH {
                let Some(page) = pages.next() else {
                    exhausted = true;
                    break;
                };
                removed[count] = reclaimer.remove_page_if_same(page);
                count += 1;
            }
        }
        for slot in &mut removed[..count] {
            drop(slot.take());
        }
        if exhausted {
            break;
        }
    }
}

// 物理页管理器
pub struct PageManager {
    phys2page: HashMap<PhysAddr, Arc<Page>>,
}

impl PageManager {
    pub fn new() -> Self {
        Self {
            phys2page: HashMap::new(),
        }
    }

    #[allow(dead_code)]
    pub fn contains(&self, paddr: &PhysAddr) -> bool {
        self.phys2page.contains_key(paddr)
    }

    pub fn get(&mut self, paddr: &PhysAddr) -> Option<Arc<Page>> {
        if let Some(p) = page_reclaimer_lock().get(paddr) {
            return Some(p);
        }
        self.phys2page.get(paddr).cloned()
    }

    pub fn get_unwrap(&mut self, paddr: &PhysAddr) -> Arc<Page> {
        if let Some(p) = page_reclaimer_lock().get(paddr) {
            return p;
        }
        self.phys2page
            .get(paddr)
            .unwrap_or_else(|| panic!("Phys Page not found, {:?}", paddr))
            .clone()
    }

    fn insert(&mut self, page: &Arc<Page>) -> Result<Arc<Page>, SystemError> {
        let phys = page.phys_address();
        if !self.phys2page.contains_key(&phys) {
            self.phys2page.insert(phys, page.clone());
            Ok(page.clone())
        } else {
            log::error!("phys page: {phys:?} already exists.");
            Err(SystemError::EINVAL)
        }
    }

    pub fn remove_page(&mut self, paddr: &PhysAddr) -> Option<Arc<Page>> {
        self.phys2page.remove(paddr)
    }

    pub(crate) fn remove_page_if_same(&mut self, expected: &Arc<Page>) -> Option<Arc<Page>> {
        let paddr = expected.phys_address();
        let current = self.phys2page.get(&paddr)?;
        if !Arc::ptr_eq(current, expected) {
            return None;
        }
        self.phys2page.remove(&paddr)
    }

    /// # 创建一个新页面并加入管理器
    ///
    /// ## 参数
    ///
    /// - `shared`: 是否共享
    /// - `page_type`: 页面类型
    /// - `flags`: 页面标志
    /// - `allocator`: 物理页帧分配器
    ///
    /// ## 返回值
    ///
    /// - `Ok(Arc<Page>)`: 新页面
    /// - `Err(SystemError)`: 错误码
    pub fn create_one_page(
        &mut self,
        page_type: PageType,
        flags: PageFlags,
        allocator: &mut dyn FrameAllocator,
    ) -> Result<Arc<Page>, SystemError> {
        self.create_pages(page_type, flags, allocator, PageFrameCount::ONE)?
            .1
            .first()
            .ok_or(SystemError::ENOMEM)
            .cloned()
    }

    /// # 创建新页面并加入管理器
    ///
    /// ## 参数
    ///
    /// - `shared`: 是否共享
    /// - `page_type`: 页面类型
    /// - `flags`: 页面标志
    /// - `allocator`: 物理页帧分配器
    /// - `count`: 页面数量
    ///
    /// ## 返回值
    ///
    /// - `Ok((PhysAddr, Vec<Arc<Page>>))`: 页面起始物理地址，新页面集合
    /// - `Err(SystemError)`: 错误码
    pub fn create_pages(
        &mut self,
        page_type: PageType,
        flags: PageFlags,
        allocator: &mut dyn FrameAllocator,
        count: PageFrameCount,
    ) -> Result<(PhysAddr, Vec<Arc<Page>>), SystemError> {
        compiler_fence(Ordering::SeqCst);
        let (start_paddr, count) = unsafe { allocator.allocate(count).ok_or(SystemError::ENOMEM)? };
        compiler_fence(Ordering::SeqCst);

        let mut ret: Vec<Arc<Page>> = Vec::new();
        if ret.try_reserve_exact(count.data()).is_err()
            || self.phys2page.try_reserve(count.data()).is_err()
        {
            // No Page object exists yet, so the allocator still owns this
            // extent as one unit. Reserve both metadata containers before
            // publishing any Page, then return exactly what allocate() supplied
            // if either reservation fails.
            unsafe { allocator.free(start_paddr, count) };
            return Err(SystemError::ENOMEM);
        }

        unsafe {
            let vaddr = MMArch::phys_2_virt(start_paddr).unwrap();
            MMArch::write_bytes(vaddr, 0, MMArch::PAGE_SIZE * count.data());
        }

        let mut cur_phys = PhysPageFrame::new(start_paddr);
        for created in 0..count.data() {
            let page = match Page::try_new(cur_phys.phys_address(), page_type.clone(), flags) {
                Ok(page) => page,
                Err(err) => {
                    // Arc::try_new drops the just-constructed InnerPage on
                    // failure, which releases the current frame. Published
                    // prefix pages release individually after detaching from
                    // PageManager; the untouched suffix still belongs to the
                    // original extent and is returned as one range.
                    for insert_page in ret {
                        self.remove_page(&insert_page.read().phys_addr);
                    }
                    let remaining = count.data() - created - 1;
                    let mut suffix = cur_phys.next();
                    for _ in 0..remaining {
                        // A failed Arc construction splits the original buddy
                        // extent into individually owned/freed prefix pages.
                        // Return the untouched suffix one page at a time so
                        // arbitrary non-power-of-two tails coalesce safely.
                        unsafe { allocator.free(suffix.phys_address(), PageFrameCount::ONE) };
                        suffix = suffix.next();
                    }
                    return Err(err);
                }
            };
            if let Err(e) = self.insert(&page) {
                for insert_page in ret {
                    self.remove_page(&insert_page.read().phys_addr);
                }
                return Err(e);
            }
            ret.push(page);
            cur_phys = cur_phys.next();
        }
        Ok((start_paddr, ret))
    }

    /// # 拷贝管理器中原有页面并加入管理器，同时拷贝原页面内容
    ///
    /// ## 参数
    ///
    /// - `old_phys`: 原页面的物理地址
    /// - `allocator`: 物理页帧分配器
    ///
    /// ## 返回值
    ///
    /// - `Ok(Arc<Page>)`: 新页面
    /// - `Err(SystemError)`: 错误码
    pub fn copy_page(
        &mut self,
        old_phys: &PhysAddr,
        allocator: &mut dyn FrameAllocator,
    ) -> Result<Arc<Page>, SystemError> {
        self.copy_page_with_type(old_phys, allocator, None)
    }

    pub fn copy_page_as_normal(
        &mut self,
        old_phys: &PhysAddr,
        allocator: &mut dyn FrameAllocator,
    ) -> Result<Arc<Page>, SystemError> {
        self.copy_page_with_type(old_phys, allocator, Some(PageType::Normal))
    }

    fn copy_page_with_type(
        &mut self,
        old_phys: &PhysAddr,
        allocator: &mut dyn FrameAllocator,
        page_type: Option<PageType>,
    ) -> Result<Arc<Page>, SystemError> {
        let old_page = self.get(old_phys).ok_or(SystemError::EINVAL)?;
        let paddr = unsafe { allocator.allocate_one().ok_or(SystemError::ENOMEM)? };

        assert!(!self.contains(&paddr), "phys page: {paddr:?} already exist");

        let page = Page::copy(old_page.read(), paddr)
            .inspect_err(|_| unsafe { allocator.free_one(paddr) })?;
        if let Some(page_type) = page_type {
            let mut guard = page.write();
            guard.set_page_type(page_type);
            guard.clear_mapping_unevictable_source_for_cow();
        }

        self.insert(&page)?;

        Ok(page)
    }
}

pub static mut PAGE_RECLAIMER: Option<Mutex<PageReclaimer>> = None;

pub fn page_reclaimer_init() {
    info!("page_reclaimer_init");
    let page_reclaimer = Mutex::new(PageReclaimer::new());

    compiler_fence(Ordering::SeqCst);
    unsafe { PAGE_RECLAIMER = Some(page_reclaimer) };
    compiler_fence(Ordering::SeqCst);

    info!("page_reclaimer_init done");
}

/// 页面回收线程
static mut PAGE_RECLAIMER_THREAD: Option<Arc<ProcessControlBlock>> = None;

/// 页面回收线程初始化函数
#[unified_init(INITCALL_CORE)]
fn page_reclaimer_thread_init() -> Result<(), SystemError> {
    let closure = crate::process::kthread::KernelThreadClosure::StaticEmptyClosure((
        &(page_reclaim_thread as fn() -> i32),
        (),
    ));
    let pcb = crate::process::kthread::KernelThreadMechanism::create_and_run(
        closure,
        "page_reclaim".to_string(),
    )
    .ok_or("")
    .expect("create tty_refresh thread failed");
    unsafe {
        PAGE_RECLAIMER_THREAD = Some(pcb);
    }
    Ok(())
}

/// 页面回收线程执行的函数
fn page_reclaim_thread() -> i32 {
    loop {
        let usage = unsafe { LockedFrameAllocator.usage() };
        // log::info!("usage{:?}", usage);

        // 保留4096个页面，总计16MB的空闲空间
        if usage.free().data() < 4096 {
            let page_to_free = 4096;
            let writeback_generation = async_writeback_progress_snapshot();
            // 分离选择和回收阶段，避免长时间持有页面回收器锁导致与
            // page_manager/page_cache 的锁顺序反转。
            let progress = PageReclaimer::shrink_list(PageFrameCount::new(page_to_free));
            if progress.reclaimed == 0 {
                // Any no-progress pass must yield: dirty pages may need an
                // asynchronous writeback completion, while mapped,
                // unevictable, or otherwise busy pages cannot be reclaimed by
                // immediately draining the same LRU again.  If there is no
                // writeback to wait for, use a bounded retry backoff.
                if progress.dirty_seen == 0
                    || !wait_for_async_writeback_progress(writeback_generation)
                {
                    let _ = nanosleep(PosixTimeSpec::new(0, 1_000_000));
                }
            }
        } else {
            //TODO Temporarily let page reclaim thread handle dirty page writeback; should be separated later.
            PageReclaimer::flush_dirty_pages();

            // Sleep 5 seconds, matching the Linux dirty_writeback_centisecs default.
            // Metadata writeback is handled by the VFS writeback thread. Keeping
            // sync_fs out of reclaim avoids coupling page reclaim to umount_lock.
            let _ = nanosleep(PosixTimeSpec::new(5, 0));
        }
    }
}

/// 获取页面回收器
pub fn page_reclaimer_lock() -> MutexGuard<'static, PageReclaimer> {
    unsafe { PAGE_RECLAIMER.as_ref().unwrap().lock() }
}

/// 页面回收器
pub struct PageReclaimer {
    lru: LruCache<PhysAddr, Arc<Page>>,
    writeback_cursor: usize,
}

#[derive(Clone, Copy, Debug, Default)]
pub struct ReclaimProgress {
    pub reclaimed: usize,
    pub dirty_seen: usize,
    pub writeback_scheduled: usize,
}

impl PageReclaimer {
    pub fn new() -> Self {
        Self {
            lru: LruCache::unbounded(),
            writeback_cursor: 0,
        }
    }

    pub fn get(&mut self, paddr: &PhysAddr) -> Option<Arc<Page>> {
        self.lru.get(paddr).cloned()
    }

    pub fn insert_page(&mut self, paddr: PhysAddr, page: &Arc<Page>) {
        self.lru.put(paddr, page.clone());
    }

    pub fn remove_page(&mut self, paddr: &PhysAddr) -> Option<Arc<Page>> {
        self.lru.pop(paddr)
    }

    fn remove_page_if_same(&mut self, expected: &Arc<Page>) -> Option<Arc<Page>> {
        let paddr = expected.phys_address();
        let current = self.lru.peek(&paddr)?;
        if !Arc::ptr_eq(current, expected) {
            return None;
        }
        self.lru.pop(&paddr)
    }

    /// lru链表缩减（对外接口，内部自行获取/释放回收器锁）
    /// 分两阶段：
    /// 1) 持有回收器锁，从 LRU 中摘下目标页面列表；
    /// 2) 释放回收器锁后，逐个执行写回与回收，避免锁顺序反转。
    pub fn shrink_list(count: PageFrameCount) -> ReclaimProgress {
        // 阶段1：仅持有回收器锁，摘取受害者
        let victims = {
            let mut reclaimer = page_reclaimer_lock();
            reclaimer.drain_lru(count)
        };

        // 阶段2：不持有回收器锁，安全地回收页面
        Self::evict_pages(victims)
    }

    /// 从 LRU 中批量弹出页面，不做任何回收操作。
    fn drain_lru(&mut self, count: PageFrameCount) -> Vec<Arc<Page>> {
        let mut victims = Vec::new();
        for _ in 0..count.data() {
            match self.lru.pop_lru() {
                Some((_paddr, page)) => victims.push(page),
                None => break,
            }
        }
        victims
    }

    /// 在不持有回收器锁的情况下，完成页面写回与回收。
    fn evict_pages(victims: Vec<Arc<Page>>) -> ReclaimProgress {
        let mut progress = ReclaimProgress::default();
        for page in victims {
            let guard = page.write();
            if let PageType::File(info) = guard.page_type().clone() {
                if guard.flags().contains(PageFlags::PG_UNEVICTABLE) {
                    continue;
                }

                // Never evict a file-backed page that is still mapped into any VMA.
                // Our eviction path removes the page from page_cache/page_manager; dropping a
                // still-mapped page will trip InnerPage::drop assertions and can crash userland.
                if guard.map_count() != 0 {
                    drop(guard);
                    page_reclaimer_lock().insert_page(page.phys_address(), &page);
                    continue;
                }

                let page_index = info.index;
                let paddr = guard.phys_address();

                if guard.flags().contains(PageFlags::PG_DIRTY) {
                    progress.dirty_seen += 1;
                    const MAX_RECLAIMER_PAGES_PER_BATCH: usize = 64;
                    let writeback_target = match guard.page_type() {
                        PageType::File(info) => info
                            .page_cache
                            .upgrade()
                            .map(|page_cache| (page_cache, info.index)),
                        _ => None,
                    };
                    drop(guard);

                    if let Some((page_cache, page_index)) = writeback_target {
                        // Reclaim must never synchronously enter a filesystem
                        // or FUSE daemon. Schedule the same bounded, try-only
                        // worker used by background writeback and keep the
                        // victim on the LRU until a later pass observes it
                        // clean. This also lets adjacent victims coalesce.
                        let end = page_index.saturating_add(MAX_RECLAIMER_PAGES_PER_BATCH - 1);
                        if page_cache
                            .manager()
                            .try_start_reclaimer_writeback_range(page_index, end)
                            .unwrap_or(false)
                        {
                            progress.writeback_scheduled += 1;
                        }
                        page_reclaimer_lock().insert_page(paddr, &page);
                        continue;
                    } else {
                        let mut guard = page.write();
                        guard.remove_flags(PageFlags::PG_DIRTY | PageFlags::PG_WRITEBACK);
                        drop(guard);
                        if page_manager_lock().remove_page(&paddr).is_some() {
                            progress.reclaimed += 1;
                        }
                        continue;
                    }
                }

                // 删除页面：顺序为 page_cache -> page_manager，避免原有的 reclaimer 锁参与死锁
                //
                // FileMapInfo 内保存 Weak<PageCache> 以避免 PageCache <-> Page 的强引用环。
                // 如果此时 PageCache 已被释放（upgrade 失败），说明其 pages 映射也已销毁，无需再 remove。
                let page_cache = info.page_cache.upgrade();
                drop(guard);

                if let Some(page_cache) = page_cache {
                    if !page_cache.manager().supports_clean_reclaim() {
                        continue;
                    }
                    let removed = page_cache
                        .manager()
                        .remove_clean_page_for_reclaim(page_index, &page)
                        .ok()
                        .flatten();
                    if removed.is_none() {
                        page_reclaimer_lock().insert_page(paddr, &page);
                        continue;
                    }
                }
                if page_manager_lock().remove_page(&paddr).is_some() {
                    progress.reclaimed += 1;
                }
            }
        }
        progress
    }

    /// Drop clean pagecache pages only, matching Linux drop_caches semantics.
    pub fn drop_pagecache(clean_only: bool) -> usize {
        if !clean_only {
            return 0;
        }

        let mut dropped = 0;
        for cache in list_page_caches() {
            dropped += cache.drop_clean_pages();
        }

        dropped
    }

    /// 唤醒页面回收线程
    pub fn wakeup_claim_thread() {
        // log::info!("wakeup_claim_thread");
        let _ = ProcessManager::wakeup(unsafe { PAGE_RECLAIMER_THREAD.as_ref().unwrap() });
    }

    /// 脏页回写函数
    /// ## 参数
    ///
    /// - `guard`: 需要回写的脏页
    /// - `unmap`: 是否取消映射
    ///
    /// ## 返回值
    /// - VmFaultReason: 页面错误处理信息标志
    pub fn page_writeback(guard: &mut RwSemWriteGuard<'_, InnerPage>, unmap: bool) {
        // log::debug!("page writeback: {:?}", guard.phys_addr);

        let (page_cache, page_index) = match guard.page_type() {
            PageType::File(info) => match info.page_cache.upgrade() {
                Some(page_cache) => (page_cache, info.index),
                None => {
                    log::warn!("try to writeback a file page but page_cache already dropped");
                    return;
                }
            },
            _ => {
                log::warn!("try to writeback a non-file page");
                return;
            }
        };
        let paddr = guard.phys_address();
        let inode = page_cache.inode().clone().unwrap().upgrade().unwrap();
        let backend = page_cache.backend();

        if let Ok(unmapped_vmas) = page_cache.mkclean_page(page_index, unmap) {
            for vma in unmapped_vmas {
                guard.remove_vma(vma.as_ref());
            }
            if guard.flags().contains(PageFlags::PG_UNEVICTABLE) && !guard.has_unevictable_source()
            {
                guard.remove_flags(PageFlags::PG_UNEVICTABLE);
            }
        }

        let page_start = page_index * MMArch::PAGE_SIZE;
        let len = if let Ok(metadata) = inode.metadata() {
            let file_size = metadata.size.max(0) as usize;
            if file_size <= page_start {
                0
            } else {
                core::cmp::min(MMArch::PAGE_SIZE, file_size - page_start)
            }
        } else {
            MMArch::PAGE_SIZE
        };

        if len > 0 {
            if !page_cache.try_mark_page_writeback(page_index, paddr) {
                return;
            }
            guard.remove_flags(PageFlags::PG_DIRTY);
            let data = unsafe {
                core::slice::from_raw_parts(
                    MMArch::phys_2_virt(paddr).unwrap().data() as *const u8,
                    len,
                )
            };
            let r = if let Some(backend) = backend {
                backend.write_page(page_index, data)
            } else {
                inode.write_direct(
                    page_start,
                    len,
                    data,
                    Mutex::new(FilePrivateData::Unused).lock(),
                )
            };
            if let Err(e) = r {
                log::error!(
                    "page writeback failed: offset={}, len={}, err={:?}",
                    page_start,
                    len,
                    e
                );
                guard.add_flags(PageFlags::PG_ERROR | PageFlags::PG_DIRTY);
                page_cache.mark_page_error(page_index, e);
                return;
            }
        }

        guard.remove_flags(PageFlags::PG_ERROR);
        if guard.flags().contains(PageFlags::PG_DIRTY) {
            let _ = page_cache.mark_page_dirty_page_locked(page_index, guard);
        } else {
            page_cache.mark_page_uptodate(page_index);
        }
    }

    /// Take a bounded, rotating LRU snapshot without acquiring any page lock
    /// while the global reclaimer lock is held.
    fn writeback_scan_snapshot(&mut self) -> Vec<Arc<Page>> {
        const MAX_RECLAIMER_SCAN_PAGES: usize = 512;
        const RECLAIMER_SCAN_STRIDE: usize = 8;
        let total = self.lru.len();
        if total == 0 {
            self.writeback_cursor = 0;
            return Vec::new();
        }

        let start = self.writeback_cursor % total;
        let count = total.min(MAX_RECLAIMER_SCAN_PAGES);
        let mut pages = Vec::new();
        if pages.try_reserve_exact(count).is_err() {
            return pages;
        }
        pages.extend(
            self.lru
                .iter()
                .skip(start)
                .chain(self.lru.iter().take(start))
                .take(count)
                .map(|(_paddr, page)| page.clone()),
        );
        // Large LRUs advance by the whole sampled window so every region is
        // visited before windows overlap. When the entire LRU fits, retain a
        // small stride to rotate which hot cache gets the first scheduling
        // slots without skipping any page from the snapshot.
        let advance = if total > count {
            count
        } else {
            RECLAIMER_SCAN_STRIDE.min(total)
        };
        self.writeback_cursor = if advance >= total - start {
            advance - (total - start)
        } else {
            start + advance
        };
        pages
    }

    pub fn flush_dirty_pages() {
        let pages = {
            let mut reclaimer = page_reclaimer_lock();
            reclaimer.writeback_scan_snapshot()
        };
        Self::flush_dirty_pages_snapshot(pages);
    }

    fn flush_dirty_pages_snapshot(pages: Vec<Arc<Page>>) {
        const MAX_RECLAIMER_RUNNERS: usize = 8;
        const MAX_RECLAIMER_PAGES_PER_RUN: usize = 512;
        let mut scheduled_runners = 0;
        for page in pages {
            let Some(guard) = page.try_read() else {
                continue;
            };
            if guard.flags().contains(PageFlags::PG_DIRTY) {
                let writeback_target = match guard.page_type() {
                    PageType::File(info) => info
                        .page_cache
                        .upgrade()
                        .map(|page_cache| (page_cache, info.index)),
                    _ => None,
                };
                if let Some((page_cache, page_index)) = writeback_target {
                    drop(guard);
                    if scheduled_runners < MAX_RECLAIMER_RUNNERS {
                        // Anchor every attempt at a page from the LRU snapshot,
                        // then let one cache runner drain the same bounded
                        // 512-page window as multiple backend-sized batches.
                        // A contended cache is skipped immediately and later
                        // snapshot candidates are still considered.
                        let end = page_index.saturating_add(MAX_RECLAIMER_PAGES_PER_RUN - 1);
                        if page_cache
                            .manager()
                            .try_start_reclaimer_writeback_range(page_index, end)
                            .unwrap_or(false)
                        {
                            scheduled_runners += 1;
                        }
                    }
                } else {
                    drop(guard);
                    if let Some(mut guard) = page.try_write() {
                        if guard.flags().contains(PageFlags::PG_DIRTY) {
                            Self::page_writeback(&mut guard, false);
                        }
                    }
                }
            }
        }
    }
}

bitflags! {
    pub struct PageFlags: u64 {
        const PG_LOCKED = 1 << 0;
        const PG_WRITEBACK = 1 << 1;
        const PG_REFERENCED = 1 << 2;
        const PG_UPTODATE = 1 << 3;
        const PG_DIRTY = 1 << 4;
        const PG_LRU = 1 << 5;
        const PG_HEAD = 1 << 6;
        const PG_WAITERS = 1 << 7;
        const PG_ACTIVE = 1 << 8;
        const PG_WORKINGSET = 1 << 9;
        const PG_ERROR = 1 << 10;
        const PG_SLAB = 1 << 11;
        const PG_RESERVED = 1 << 14;
        const PG_PRIVATE = 1 << 15;
        const PG_RECLAIM = 1 << 18;
        const PG_SWAPBACKED = 1 << 19;
        const PG_UNEVICTABLE = 1 << 20;
        const PG_READAHEAD = 1 << 21;
    }
}

#[derive(Debug)]
pub struct Page {
    inner: RwSem<InnerPage>,
    /// 页面所在物理地址
    phys_addr: PhysAddr,
    /// Pins a bulk allocation when this page is one member of a contiguous
    /// run. Ordinary pages own and release their frame individually.
    contiguous_owner: Option<Arc<ContiguousFrameOwner>>,
}

impl Page {
    /// # 创建新页面
    ///
    /// ## 参数
    ///
    /// - `shared`: 是否共享
    /// - `phys_addr`: 物理地址
    /// - `page_type`: 页面类型
    /// - `flags`: 页面标志
    ///
    /// ## 返回值
    ///
    /// - `Arc<Page>`: 新页面
    fn try_new(
        phys_addr: PhysAddr,
        page_type: PageType,
        flags: PageFlags,
    ) -> Result<Arc<Page>, SystemError> {
        let inner = InnerPage::new(phys_addr, page_type, flags, true);
        let page = Arc::try_new(Self {
            inner: RwSem::new(inner),
            phys_addr,
            contiguous_owner: None,
        })
        .map_err(|_| SystemError::ENOMEM)?;
        if page.read().flags == PageFlags::PG_LRU {
            page_reclaimer_lock().insert_page(phys_addr, &page);
        };
        Ok(page)
    }

    fn try_new_with_contiguous_owner(
        phys_addr: PhysAddr,
        page_type: PageType,
        flags: PageFlags,
        owner: Arc<ContiguousFrameOwner>,
    ) -> Result<Arc<Page>, SystemError> {
        let inner = InnerPage::new(phys_addr, page_type, flags, false);
        Arc::try_new(Self {
            inner: RwSem::new(inner),
            phys_addr,
            contiguous_owner: Some(owner),
        })
        .map_err(|_| SystemError::ENOMEM)
    }

    /// # 拷贝页面及内容
    ///
    /// ## 参数
    ///
    /// - `old_guard`: 源页面的读守卫
    /// - `new_phys`: 新页面的物理地址
    ///
    /// ## 返回值
    ///
    /// - `Ok(Arc<Page>)`: 新页面
    /// - `Err(SystemError)`: 错误码
    fn copy(
        old_guard: RwSemReadGuard<InnerPage>,
        new_phys: PhysAddr,
    ) -> Result<Arc<Page>, SystemError> {
        let page_type = old_guard.page_type().clone();
        let flags = *old_guard.flags();
        let inner = InnerPage::new(new_phys, page_type, flags, true);
        unsafe {
            let old_vaddr =
                MMArch::phys_2_virt(old_guard.phys_address()).ok_or(SystemError::EFAULT)?;
            let new_vaddr = MMArch::phys_2_virt(new_phys).ok_or(SystemError::EFAULT)?;
            (new_vaddr.data() as *mut u8)
                .copy_from_nonoverlapping(old_vaddr.data() as *mut u8, MMArch::PAGE_SIZE);
        }
        Ok(Arc::new(Self {
            inner: RwSem::new(inner),
            phys_addr: new_phys,
            contiguous_owner: None,
        }))
    }

    #[inline(always)]
    pub fn phys_address(&self) -> PhysAddr {
        self.phys_addr
    }

    pub fn read(&self) -> RwSemReadGuard<'_, InnerPage> {
        self.inner.read()
    }

    pub fn try_read(&self) -> Option<RwSemReadGuard<'_, InnerPage>> {
        self.inner.try_read()
    }

    pub fn upread(&self) -> RwSemUpgradeableGuard<'_, InnerPage> {
        self.inner.upread()
    }

    pub fn write(&self) -> RwSemWriteGuard<'_, InnerPage> {
        self.inner.write()
    }

    pub fn try_write(&self) -> Option<RwSemWriteGuard<'_, InnerPage>> {
        self.inner.try_write()
    }

    pub(crate) fn shares_contiguous_frame_owner(&self, other: &Self) -> bool {
        match (&self.contiguous_owner, &other.contiguous_owner) {
            (Some(left), Some(right)) => Arc::ptr_eq(left, right),
            _ => false,
        }
    }
}

#[derive(Debug)]
enum PageVmaSet {
    Empty,
    One(Arc<LockedVMA>),
    Two(Arc<LockedVMA>, Arc<LockedVMA>),
    Many(HashSet<Arc<LockedVMA>>),
}

impl PageVmaSet {
    fn new() -> Self {
        Self::Empty
    }

    fn len(&self) -> usize {
        match self {
            Self::Empty => 0,
            Self::One(_) => 1,
            Self::Two(_, _) => 2,
            Self::Many(vmas) => vmas.len(),
        }
    }

    fn contains(&self, vma: &LockedVMA) -> bool {
        match self {
            Self::Empty => false,
            Self::One(existing) => existing.as_ref() == vma,
            Self::Two(first, second) => first.as_ref() == vma || second.as_ref() == vma,
            Self::Many(vmas) => vmas.contains(vma),
        }
    }

    fn insert(&mut self, vma: Arc<LockedVMA>) -> bool {
        match self {
            Self::Empty => {
                *self = Self::One(vma);
                true
            }
            Self::One(existing) => {
                if existing.as_ref() == vma.as_ref() {
                    false
                } else {
                    let Self::One(existing) = mem::replace(self, Self::Empty) else {
                        unreachable!();
                    };
                    *self = Self::Two(existing, vma);
                    true
                }
            }
            Self::Two(first, second) => {
                if first.as_ref() == vma.as_ref() || second.as_ref() == vma.as_ref() {
                    return false;
                }

                // Allocate before taking the inline state so allocation failure cannot discard
                // either existing reverse mapping.
                let mut vmas = HashSet::with_capacity(3);
                let Self::Two(first, second) = mem::replace(self, Self::Empty) else {
                    unreachable!();
                };
                vmas.insert(first);
                vmas.insert(second);
                vmas.insert(vma);
                *self = Self::Many(vmas);
                true
            }
            Self::Many(vmas) => vmas.insert(vma),
        }
    }

    fn remove(&mut self, vma: &LockedVMA) -> bool {
        match self {
            Self::Empty => false,
            Self::One(existing) => {
                if existing.as_ref() != vma {
                    return false;
                }
                *self = Self::Empty;
                true
            }
            Self::Two(first, second) => {
                let remove_first = first.as_ref() == vma;
                let remove_second = second.as_ref() == vma;
                if !remove_first && !remove_second {
                    return false;
                }

                let Self::Two(first, second) = mem::replace(self, Self::Empty) else {
                    unreachable!();
                };
                *self = Self::One(if remove_first { second } else { first });
                true
            }
            Self::Many(vmas) => {
                let removed = vmas.remove(vma);
                if removed && vmas.is_empty() {
                    *self = Self::Empty;
                }
                removed
            }
        }
    }
}

#[derive(Debug)]
/// 物理页面信息
pub struct InnerPage {
    /// 映射到当前page的VMA
    vma_set: PageVmaSet,
    /// 当前对该页贡献 mlock/unevictable 原因的 VMA 子集。
    ///
    /// 该集合必须始终是 `vma_set` 的子集。它让 page-cache reclassify
    /// 可以 O(1) 判断页是否仍因 VMA mlock 不可回收，而不需要反向锁住所有 VMA。
    mlocked_vmas: HashSet<Arc<LockedVMA>>,
    /// 内核子系统显式创建的 non-page-cache unevictable 页。
    intrinsic_unevictable: bool,
    /// Backing object lifetime pins.
    ///
    /// 这只表达“页面仍被 backing 对象拥有，不能从 page_manager 释放”，不表达
    /// reclaim policy，也不应设置 `PG_UNEVICTABLE`。shared-anon backing 使用它
    /// 替代旧的 `PG_UNEVICTABLE` lifetime workaround。
    backing_lifetime_pins: usize,
    /// 标志
    flags: PageFlags,
    /// 页面所在物理地址
    phys_addr: PhysAddr,
    /// 页面类型
    page_type: PageType,
    /// Ordinary pages return their own frame. Bulk pages instead pin a shared
    /// contiguous owner stored by `Page`.
    individually_owns_frame: bool,
}

impl InnerPage {
    pub fn new(
        phys_addr: PhysAddr,
        page_type: PageType,
        flags: PageFlags,
        individually_owns_frame: bool,
    ) -> Self {
        let intrinsic_unevictable =
            flags.contains(PageFlags::PG_UNEVICTABLE) && !matches!(page_type, PageType::File(_));
        Self {
            vma_set: PageVmaSet::new(),
            mlocked_vmas: HashSet::new(),
            intrinsic_unevictable,
            backing_lifetime_pins: 0,
            flags,
            phys_addr,
            page_type,
            individually_owns_frame,
        }
    }

    /// 将vma加入anon_vma
    pub fn insert_vma(&mut self, vma: Arc<LockedVMA>, vma_mlocked: bool) {
        let was_mapped = self.map_count() > 0;
        let inserted = self.vma_set.insert(vma.clone());
        if inserted && vma_mlocked {
            self.mlocked_vmas.insert(vma);
            self.flags.insert(PageFlags::PG_UNEVICTABLE);
        }
        if !was_mapped && matches!(self.page_type, PageType::File(_)) {
            pc_stats::inc_file_mapped();
        }
    }

    /// 将vma从anon_vma中删去
    ///
    /// This only removes the VMA from the page-level source sets.  Callers that
    /// may have removed the last unevictable source must subsequently run
    /// `InnerAddressSpace::remove_page_unevictable_if_unneeded`.
    pub fn remove_vma(&mut self, vma: &LockedVMA) {
        let was_mapped = self.map_count() > 0;
        let removed = self.vma_set.remove(vma);
        if removed {
            self.mlocked_vmas.remove(vma);
        }
        if removed
            && was_mapped
            && self.map_count() == 0
            && matches!(self.page_type, PageType::File(_))
        {
            pc_stats::dec_file_mapped();
        }
    }

    /// 判断当前物理页是否能被回
    pub fn can_deallocate(&self) -> bool {
        self.map_count() == 0
            && !self.flags.contains(PageFlags::PG_UNEVICTABLE)
            && self.backing_lifetime_pins == 0
    }

    /// Whether a VMA unmap may release this page from the global page manager.
    ///
    /// Page-cache backed pages are owned by their address_space/PageCache.  VMA
    /// teardown only removes PTE/rmap state; the page cache eviction path is the
    /// authority that unlinks and drops those pages from page_manager.
    pub fn can_deallocate_after_vma_unmap(&self) -> bool {
        self.can_deallocate() && !matches!(self.page_type, PageType::File(_))
    }

    pub fn shared(&self) -> bool {
        self.map_count() > 1
    }

    pub fn add_mlocked_vma_ref(&mut self, vma: &Arc<LockedVMA>) {
        if self.vma_set.contains(vma.as_ref()) && self.mlocked_vmas.insert(vma.clone()) {
            self.flags.insert(PageFlags::PG_UNEVICTABLE);
        }
    }

    pub fn remove_mlocked_vma_ref(&mut self, vma: &Arc<LockedVMA>) {
        self.mlocked_vmas.remove(vma);
    }

    pub fn clear_unlinked_file_mapping_unevictable(&mut self) {
        if matches!(self.page_type, PageType::File(_))
            && self.map_count() == 0
            && !self.has_mlocked_vma_refs()
        {
            self.flags.remove(PageFlags::PG_UNEVICTABLE);
        }
    }

    #[inline(always)]
    pub fn has_mlocked_vma_refs(&self) -> bool {
        !self.mlocked_vmas.is_empty()
    }

    pub fn has_unevictable_source(&self) -> bool {
        self.intrinsic_unevictable
            || self.has_mlocked_vma_refs()
            || self
                .page_cache()
                .map(|page_cache| page_cache.mapping_unevictable())
                .unwrap_or(false)
    }

    pub(crate) fn intrinsic_unevictable(&self) -> bool {
        self.intrinsic_unevictable
    }

    pub fn clear_mapping_unevictable_source_for_cow(&mut self) {
        self.intrinsic_unevictable = false;
        if !self.has_unevictable_source() {
            self.flags.remove(PageFlags::PG_UNEVICTABLE);
        }
    }

    pub fn add_backing_lifetime_pin(&mut self) {
        self.backing_lifetime_pins = self
            .backing_lifetime_pins
            .checked_add(1)
            .expect("backing lifetime pin count overflow");
    }

    pub fn remove_backing_lifetime_pin(&mut self) {
        self.backing_lifetime_pins = self
            .backing_lifetime_pins
            .checked_sub(1)
            .expect("backing lifetime pin count underflow");
    }

    pub fn page_cache(&self) -> Option<Arc<PageCache>> {
        match &self.page_type {
            PageType::File(info) => info.page_cache.upgrade(),
            _ => None,
        }
    }

    pub fn page_type(&self) -> &PageType {
        &self.page_type
    }

    pub fn set_page_type(&mut self, page_type: PageType) {
        self.page_type = page_type;
    }

    #[inline(always)]
    pub fn map_count(&self) -> usize {
        self.vma_set.len()
    }

    #[inline(always)]
    pub fn flags(&self) -> &PageFlags {
        &self.flags
    }

    #[inline(always)]
    pub fn set_flags(&mut self, flags: PageFlags) {
        self.flags = flags
    }

    #[inline(always)]
    pub fn add_flags(&mut self, flags: PageFlags) {
        self.flags = self.flags.union(flags);
    }

    #[inline(always)]
    pub fn remove_flags(&mut self, flags: PageFlags) {
        self.flags = self.flags.difference(flags);
    }

    #[inline(always)]
    pub(crate) fn phys_address(&self) -> PhysAddr {
        self.phys_addr
    }

    pub unsafe fn as_slice(&self) -> &[u8] {
        core::slice::from_raw_parts(
            MMArch::phys_2_virt(self.phys_addr).unwrap().data() as *const u8,
            MMArch::PAGE_SIZE,
        )
    }

    pub unsafe fn as_slice_mut(&mut self) -> &mut [u8] {
        core::slice::from_raw_parts_mut(
            MMArch::phys_2_virt(self.phys_addr).unwrap().data() as *mut u8,
            MMArch::PAGE_SIZE,
        )
    }

    pub unsafe fn copy_from_slice(&mut self, slice: &[u8]) {
        assert_eq!(
            slice.len(),
            MMArch::PAGE_SIZE,
            "length of slice not match PAGE_SIZE"
        );
        core::slice::from_raw_parts_mut(
            MMArch::phys_2_virt(self.phys_addr).unwrap().data() as *mut u8,
            MMArch::PAGE_SIZE,
        )
        .copy_from_slice(slice);
    }

    pub unsafe fn truncate(&mut self, len: usize) {
        if len > MMArch::PAGE_SIZE {
            return;
        }

        let vaddr = unsafe { MMArch::phys_2_virt(self.phys_addr).unwrap() };

        unsafe {
            core::slice::from_raw_parts_mut(
                (vaddr.data() + len) as *mut u8,
                MMArch::PAGE_SIZE - len,
            )
            .fill(0)
        };
    }
}

impl Drop for InnerPage {
    fn drop(&mut self) {
        assert!(
            self.map_count() == 0,
            "page drop when map count is non-zero"
        );

        if self.individually_owns_frame {
            unsafe {
                deallocate_page_frames(PhysPageFrame::new(self.phys_addr), PageFrameCount::new(1))
            };
        }
    }
}

/// 页面类型，包含额外的页面信息
#[derive(Debug, Clone)]
pub enum PageType {
    /// 普通页面，不含额外信息
    Normal,
    /// 文件映射页，含文件映射相关信息
    File(FileMapInfo),
    /// 共享内存页，记录ShmId
    Shm,
}

#[derive(Debug, Clone)]
pub struct FileMapInfo {
    /// 指向页缓存的弱引用，避免 PageCache -> Page -> PageCache 的强引用环导致页面无法释放。
    pub page_cache: Weak<PageCache>,
    /// 在pagecache中的偏移
    pub index: usize,
}

#[derive(Debug)]
pub struct PageTable<Arch> {
    /// 当前页表表示的虚拟地址空间的起始地址
    base: VirtAddr,
    /// 当前页表所在的物理地址
    phys: PhysAddr,
    /// 当前页表的层级（请注意，最顶级页表的level为[Arch::PAGE_LEVELS - 1]）
    level: usize,
    phantom: PhantomData<Arch>,
}

#[allow(dead_code)]
impl<Arch: MemoryManagementArch> PageTable<Arch> {
    pub unsafe fn new(base: VirtAddr, phys: PhysAddr, level: usize) -> Self {
        Self {
            base,
            phys,
            level,
            phantom: PhantomData,
        }
    }

    /// 获取顶级页表
    ///
    /// ## 参数
    ///
    /// - table_kind 页表类型
    ///
    /// ## 返回值
    ///
    /// 返回顶级页表
    pub unsafe fn top_level_table(table_kind: PageTableKind) -> Self {
        return Self::new(
            VirtAddr::new(0),
            Arch::table(table_kind),
            Arch::PAGE_LEVELS - 1,
        );
    }

    /// 获取当前页表的物理地址
    #[inline(always)]
    pub fn phys(&self) -> PhysAddr {
        self.phys
    }

    /// 当前页表表示的虚拟地址空间的起始地址
    #[inline(always)]
    pub fn base(&self) -> VirtAddr {
        self.base
    }

    /// 获取当前页表的层级
    #[inline(always)]
    pub fn level(&self) -> usize {
        self.level
    }

    /// 获取当前页表自身所在的虚拟地址
    #[inline(always)]
    pub unsafe fn virt(&self) -> VirtAddr {
        return Arch::phys_2_virt(self.phys).unwrap();
    }

    /// 获取第i个页表项所表示的虚拟内存空间的起始地址
    pub fn entry_base(&self, i: usize) -> Option<VirtAddr> {
        if i < Arch::PAGE_ENTRY_NUM {
            let shift = self.level * Arch::PAGE_ENTRY_SHIFT + Arch::PAGE_SHIFT;
            return Some(self.base.add(i << shift));
        } else {
            return None;
        }
    }

    /// 获取当前页表的第i个页表项所在的虚拟地址（注意与entry_base进行区分）
    pub unsafe fn entry_virt(&self, i: usize) -> Option<VirtAddr> {
        if i < Arch::PAGE_ENTRY_NUM {
            return Some(self.virt().add(i * Arch::PAGE_ENTRY_SIZE));
        } else {
            return None;
        }
    }

    /// 获取当前页表的第i个页表项
    pub unsafe fn entry(&self, i: usize) -> Option<PageEntry<Arch>> {
        let entry_virt = self.entry_virt(i)?;
        return Some(PageEntry::from_usize(Arch::read::<usize>(entry_virt)));
    }

    /// 设置当前页表的第i个页表项
    pub unsafe fn set_entry(&self, i: usize, entry: PageEntry<Arch>) -> Option<()> {
        let entry_virt = self.entry_virt(i)?;
        Arch::write::<usize>(entry_virt, entry.data());
        return Some(());
    }

    /// 判断当前页表的第i个页表项是否已经填写了值
    ///
    /// ## 参数
    /// - Some(true) 如果已经填写了值
    /// - Some(false) 如果未填写值
    /// - None 如果i超出了页表项的范围
    pub fn entry_mapped(&self, i: usize) -> Option<bool> {
        let etv = unsafe { self.entry_virt(i) }?;
        if unsafe { Arch::read::<usize>(etv) } != 0 {
            return Some(true);
        } else {
            return Some(false);
        }
    }

    /// 根据虚拟地址，获取对应的页表项在页表中的下标
    ///
    /// ## 参数
    ///
    /// - addr: 虚拟地址
    ///
    /// ## 返回值
    ///
    /// 页表项在页表中的下标。如果addr不在当前页表所表示的虚拟地址空间中，则返回None
    pub fn index_of(&self, addr: VirtAddr) -> Option<usize> {
        let addr = VirtAddr::new(addr.data() & Arch::PAGE_ADDRESS_MASK);
        let shift = self.level * Arch::PAGE_ENTRY_SHIFT + Arch::PAGE_SHIFT;

        let mask = (MMArch::PAGE_ENTRY_NUM << shift) - 1;
        if addr < self.base || addr >= self.base.add(mask) {
            return None;
        } else {
            return Some((addr.data() >> shift) & MMArch::PAGE_ENTRY_MASK);
        }
    }

    /// 获取第i个页表项指向的下一级页表
    pub unsafe fn next_level_table(&self, index: usize) -> Option<Self> {
        if self.level == 0 {
            return None;
        }

        // 返回下一级页表
        return Some(PageTable::new(
            self.entry_base(index)?,
            self.entry(index)?.address().ok()?,
            self.level - 1,
        ));
    }

    /// 拷贝页表
    /// ## 参数
    ///
    /// - `allocator`: 物理页框分配器
    /// - `copy_on_write`: 是否写时复制
    pub unsafe fn clone(
        &self,
        allocator: &mut impl FrameAllocator,
        copy_on_write: bool,
    ) -> Option<PageTable<Arch>> {
        // 分配新页面作为新的页表
        let phys = allocator.allocate_one()?;
        let frame = MMArch::phys_2_virt(phys).unwrap();
        MMArch::write_bytes(frame, 0, MMArch::PAGE_SIZE);
        let new_table = PageTable::new(self.base, phys, self.level);
        if self.level == 0 {
            for i in 0..Arch::PAGE_ENTRY_NUM {
                if let Some(mut entry) = self.entry(i) {
                    if entry.present() {
                        if copy_on_write {
                            let mut new_flags = entry.flags().set_write(false);
                            entry.set_flags(new_flags);
                            self.set_entry(i, entry);
                            new_flags = new_flags.set_dirty(false);
                            entry.set_flags(new_flags);
                            new_table.set_entry(i, entry);
                        } else {
                            let mut page_manager_guard = page_manager_lock();
                            let old_phys = entry.address().unwrap();
                            let page = page_manager_guard.copy_page(&old_phys, allocator).ok()?;
                            new_table
                                .set_entry(i, PageEntry::new(page.phys_address(), entry.flags()));
                        }
                    }
                }
            }
        } else {
            // 非一级页表拷贝时，对每个页表项对应的页表都进行拷贝
            for i in 0..MMArch::PAGE_ENTRY_NUM {
                if let Some(next_table) = self.next_level_table(i) {
                    let table = next_table.clone(allocator, copy_on_write)?;
                    let old_entry = self.entry(i).unwrap();
                    let entry = PageEntry::new(table.phys(), old_entry.flags());
                    new_table.set_entry(i, entry);
                }
            }
        }
        Some(new_table)
    }
}

/// 页表项
#[repr(C, align(8))]
#[derive(Copy, Clone)]
pub struct PageEntry<Arch> {
    data: usize,
    phantom: PhantomData<Arch>,
}

impl<Arch> Debug for PageEntry<Arch> {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
        f.write_fmt(format_args!("PageEntry({:#x})", self.data))
    }
}

impl<Arch: MemoryManagementArch> PageEntry<Arch> {
    #[inline(always)]
    pub fn new(paddr: PhysAddr, flags: EntryFlags<Arch>) -> Self {
        Self {
            data: MMArch::make_entry(paddr, flags.data()),
            phantom: PhantomData,
        }
    }
    #[inline(always)]
    pub fn from_usize(data: usize) -> Self {
        Self {
            data,
            phantom: PhantomData,
        }
    }

    #[inline(always)]
    pub fn data(&self) -> usize {
        self.data
    }

    /// 获取当前页表项指向的物理地址
    ///
    /// ## 返回值
    ///
    /// - Ok(PhysAddr) 如果当前页面存在于物理内存中, 返回物理地址
    /// - Err(PhysAddr) 如果当前页表项不存在, 返回物理地址
    #[inline(always)]
    pub fn address(&self) -> Result<PhysAddr, PhysAddr> {
        let paddr: PhysAddr = {
            #[cfg(target_arch = "x86_64")]
            {
                PhysAddr::new(self.data & Arch::PAGE_ADDRESS_MASK)
            }

            #[cfg(target_arch = "riscv64")]
            {
                let ppn = ((self.data & (!((1 << 10) - 1))) >> 10) & ((1 << 54) - 1);
                super::allocator::page_frame::PhysPageFrame::from_ppn(ppn).phys_address()
            }

            #[cfg(target_arch = "loongarch64")]
            {
                todo!("la64: PageEntry::address")
            }
        };

        if self.present() {
            Ok(paddr)
        } else {
            Err(paddr)
        }
    }

    #[inline(always)]
    pub fn flags(&self) -> EntryFlags<Arch> {
        unsafe { EntryFlags::from_data(self.data & Arch::ENTRY_FLAGS_MASK) }
    }

    #[inline(always)]
    pub fn set_flags(&mut self, flags: EntryFlags<Arch>) {
        self.data = (self.data & !Arch::ENTRY_FLAGS_MASK) | flags.data();
    }

    #[inline(always)]
    pub fn present(&self) -> bool {
        return self.data & Arch::ENTRY_FLAG_PRESENT != 0;
    }

    #[inline(always)]
    pub fn empty(&self) -> bool {
        self.data & !(Arch::ENTRY_FLAG_DIRTY & Arch::ENTRY_FLAG_ACCESSED) == 0
    }

    #[inline(always)]
    pub fn protnone(&self) -> bool {
        return self.data & (Arch::ENTRY_FLAG_PRESENT | Arch::ENTRY_FLAG_GLOBAL)
            == Arch::ENTRY_FLAG_GLOBAL;
    }

    #[inline(always)]
    pub fn write(&self) -> bool {
        return self.data & Arch::ENTRY_FLAG_READWRITE != 0;
    }
}

/// 页表项的标志位
#[derive(Copy, Clone, Hash)]
pub struct EntryFlags<Arch> {
    data: usize,
    phantom: PhantomData<Arch>,
}

impl<Arch: MemoryManagementArch> Default for EntryFlags<Arch> {
    fn default() -> Self {
        Self::new()
    }
}

#[allow(dead_code)]
impl<Arch: MemoryManagementArch> EntryFlags<Arch> {
    #[inline(always)]
    pub fn new() -> Self {
        let mut r = unsafe {
            Self::from_data(
                Arch::ENTRY_FLAG_DEFAULT_PAGE
                    | Arch::ENTRY_FLAG_READONLY
                    | Arch::ENTRY_FLAG_NO_EXEC,
            )
        };

        #[cfg(target_arch = "x86_64")]
        {
            if crate::arch::mm::X86_64MMArch::is_xd_reserved() {
                r = r.set_execute(true);
            }
        }

        return r;
    }

    /// 根据ProtFlags生成EntryFlags
    ///
    /// ## 参数
    ///
    /// - prot_flags: 页的保护标志
    /// - user: 用户空间是否可访问
    pub fn from_prot_flags(prot_flags: ProtFlags, user: bool) -> Self {
        if Arch::PAGE_FAULT_ENABLED {
            let vm_flags = super::VmFlags::from(prot_flags);
            Arch::vm_get_page_prot(vm_flags).set_user(user)
        } else {
            EntryFlags::new()
                .set_user(user)
                .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC))
                .set_write(prot_flags.contains(ProtFlags::PROT_WRITE))
        }
    }

    #[inline(always)]
    pub fn data(&self) -> usize {
        self.data
    }

    #[inline(always)]
    pub const unsafe fn from_data(data: usize) -> Self {
        return Self {
            data,
            phantom: PhantomData,
        };
    }

    /// 为新页表的页表项设置默认值
    ///
    /// 默认值为：
    /// - present
    /// - read only
    /// - kernel space
    /// - no exec
    #[inline(always)]
    pub fn new_page_table(user: bool) -> Self {
        return unsafe {
            let r = {
                #[cfg(target_arch = "x86_64")]
                {
                    Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE | Arch::ENTRY_FLAG_READWRITE)
                }

                #[cfg(target_arch = "riscv64")]
                {
                    // riscv64指向下一级页表的页表项，不应设置R/W/X权限位
                    Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE)
                }

                #[cfg(target_arch = "loongarch64")]
                {
                    Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE)
                }
            };

            #[cfg(target_arch = "x86_64")]
            {
                if user {
                    r.set_user(true)
                } else {
                    r
                }
            }

            #[cfg(target_arch = "riscv64")]
            {
                r
            }

            #[cfg(target_arch = "loongarch64")]
            {
                todo!("loongarch64: new_page_table")
            }
        };
    }

    /// 取得当前页表项的所有权，更新当前页表项的标志位，并返回更新后的页表项。
    ///
    /// ## 参数
    /// - flag 要更新的标志位的值
    /// - value 如果为true，那么将flag对应的位设置为1，否则设置为0
    ///
    /// ## 返回值
    ///
    /// 更新后的页表项
    #[inline(always)]
    #[must_use]
    pub fn update_flags(mut self, flag: usize, value: bool) -> Self {
        if value {
            self.data |= flag;
        } else {
            self.data &= !flag;
        }
        return self;
    }

    /// 判断当前页表项是否存在指定的flag（只有全部flag都存在才返回true）
    #[inline(always)]
    pub fn has_flag(&self, flag: usize) -> bool {
        return self.data & flag == flag;
    }

    #[inline(always)]
    pub fn present(&self) -> bool {
        return self.has_flag(Arch::ENTRY_FLAG_PRESENT);
    }

    /// 设置当前页表项的权限
    ///
    /// @param value 如果为true，那么将当前页表项的权限设置为用户态可访问
    #[must_use]
    #[inline(always)]
    pub fn set_user(self, value: bool) -> Self {
        return self.update_flags(Arch::ENTRY_FLAG_USER, value);
    }

    /// 用户态是否可以访问当前页表项
    #[inline(always)]
    pub fn has_user(&self) -> bool {
        return self.has_flag(Arch::ENTRY_FLAG_USER);
    }

    /// 设置当前页表项的可写性, 如果为true，那么将当前页表项的权限设置为可写, 否则设置为只读
    ///
    /// ## 返回值
    ///
    /// 更新后的页表项.
    ///
    /// **请注意，**本函数会取得当前页表项的所有权，因此返回的页表项不是原来的页表项
    #[must_use]
    #[inline(always)]
    pub fn set_write(self, value: bool) -> Self {
        #[cfg(target_arch = "x86_64")]
        {
            // 有的架构同时具有可写和不可写的标志位，因此需要同时更新
            return self
                .update_flags(Arch::ENTRY_FLAG_READONLY, !value)
                .update_flags(Arch::ENTRY_FLAG_READWRITE, value);
        }

        #[cfg(target_arch = "riscv64")]
        {
            if value {
                return self.update_flags(Arch::ENTRY_FLAG_READWRITE, true);
            } else {
                return self
                    .update_flags(Arch::ENTRY_FLAG_READONLY, true)
                    .update_flags(Arch::ENTRY_FLAG_WRITEABLE, false);
            }
        }

        #[cfg(target_arch = "loongarch64")]
        {
            todo!("la64: set_write")
        }
    }

    /// 当前页表项是否可写
    #[inline(always)]
    pub fn has_write(&self) -> bool {
        // 有的架构同时具有可写和不可写的标志位，因此需要同时判断
        return self.data & (Arch::ENTRY_FLAG_READWRITE | Arch::ENTRY_FLAG_READONLY)
            == Arch::ENTRY_FLAG_READWRITE;
    }

    /// 设置当前页表项的可执行性, 如果为true，那么将当前页表项的权限设置为可执行, 否则设置为不可执行
    #[must_use]
    #[inline(always)]
    pub fn set_execute(self, mut value: bool) -> Self {
        #[cfg(target_arch = "x86_64")]
        {
            // 如果xd位被保留，那么将可执行性设置为true
            if crate::arch::mm::X86_64MMArch::is_xd_reserved() {
                value = true;
            }
        }

        // 有的架构同时具有可执行和不可执行的标志位，因此需要同时更新
        return self
            .update_flags(Arch::ENTRY_FLAG_NO_EXEC, !value)
            .update_flags(Arch::ENTRY_FLAG_EXEC, value);
    }

    /// 当前页表项是否可执行
    #[inline(always)]
    pub fn has_execute(&self) -> bool {
        // 有的架构同时具有可执行和不可执行的标志位，因此需要同时判断
        return self.data & (Arch::ENTRY_FLAG_EXEC | Arch::ENTRY_FLAG_NO_EXEC)
            == Arch::ENTRY_FLAG_EXEC;
    }

    /// 设置当前页表项的缓存策略
    ///
    /// ## 参数
    ///
    /// - value: 如果为true，那么将当前页表项的缓存策略设置为不缓存。
    #[inline(always)]
    pub fn set_page_cache_disable(self, value: bool) -> Self {
        return self.update_flags(Arch::ENTRY_FLAG_CACHE_DISABLE, value);
    }

    /// 获取当前页表项的缓存策略
    ///
    /// ## 返回值
    ///
    /// 如果当前页表项的缓存策略为不缓存，那么返回true，否则返回false。
    #[inline(always)]
    pub fn has_page_cache_disable(&self) -> bool {
        return self.has_flag(Arch::ENTRY_FLAG_CACHE_DISABLE);
    }

    /// 设置当前页表项的写穿策略
    ///
    /// ## 参数
    ///
    /// - value: 如果为true，那么将当前页表项的写穿策略设置为写穿。
    #[inline(always)]
    pub fn set_page_write_through(self, value: bool) -> Self {
        return self.update_flags(Arch::ENTRY_FLAG_WRITE_THROUGH, value);
    }

    #[inline(always)]
    pub fn set_page_global(self, value: bool) -> Self {
        return self.update_flags(MMArch::ENTRY_FLAG_GLOBAL, value);
    }

    /// 获取当前页表项的写穿策略
    ///
    /// ## 返回值
    ///
    /// 如果当前页表项的写穿策略为写穿，那么返回true，否则返回false。
    #[inline(always)]
    pub fn has_page_write_through(&self) -> bool {
        return self.has_flag(Arch::ENTRY_FLAG_WRITE_THROUGH);
    }

    /// 设置当前页表是否为脏页
    ///
    /// ## 参数
    ///
    /// - value: 如果为true，那么将当前页表项的写穿策略设置为写穿。
    #[inline(always)]
    pub fn set_dirty(self, value: bool) -> Self {
        return self.update_flags(Arch::ENTRY_FLAG_DIRTY, value);
    }

    /// 设置当前页表被访问
    ///
    /// ## 参数
    ///
    /// - value: 如果为true，那么将当前页表项的访问标志设置为已访问。
    #[inline(always)]
    pub fn set_access(self, value: bool) -> Self {
        return self.update_flags(Arch::ENTRY_FLAG_ACCESSED, value);
    }

    /// 设置指向的页是否为大页
    ///
    /// ## 参数
    ///
    /// - value: 如果为true，那么将当前页表项的访问标志设置为已访问。
    #[inline(always)]
    pub fn set_huge_page(self, value: bool) -> Self {
        return self.update_flags(Arch::ENTRY_FLAG_HUGE_PAGE, value);
    }

    /// MMIO内存的页表项标志
    #[inline(always)]
    pub fn mmio_flags() -> Self {
        #[cfg(target_arch = "x86_64")]
        {
            Self::new()
                .set_user(false)
                .set_write(true)
                .set_execute(true)
                .set_page_cache_disable(true)
                .set_page_write_through(true)
                .set_page_global(true)
        }

        #[cfg(target_arch = "riscv64")]
        {
            Self::new()
                .set_user(false)
                .set_write(true)
                .set_execute(true)
                .set_page_global(true)
        }

        #[cfg(target_arch = "loongarch64")]
        {
            todo!("la64: mmio_flags()")
        }
    }
}

impl<Arch: MemoryManagementArch> fmt::Debug for EntryFlags<Arch> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("EntryFlags")
            .field("bits", &format_args!("{:#0x}", self.data))
            .field("present", &self.present())
            .field("has_write", &self.has_write())
            .field("has_execute", &self.has_execute())
            .field("has_user", &self.has_user())
            .finish()
    }
}

/// 页表映射器
#[derive(Hash)]
pub struct PageMapper<Arch, F> {
    /// 页表类型
    table_kind: PageTableKind,
    /// 根页表物理地址
    table_paddr: PhysAddr,
    /// 页分配器
    frame_allocator: F,
    phantom: PhantomData<fn() -> Arch>,
}

#[derive(Clone, Copy, Debug)]
pub struct CreatedPageTable {
    parent_base: VirtAddr,
    parent_phys: PhysAddr,
    parent_level: usize,
    index: usize,
    child_phys: PhysAddr,
}

impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
    /// 创建新的页面映射器
    ///
    /// ## 参数
    /// - table_kind 页表类型
    /// - table_paddr 根页表物理地址
    /// - allocator 页分配器
    ///
    /// ## 返回值
    ///
    /// 页面映射器
    pub unsafe fn new(table_kind: PageTableKind, table_paddr: PhysAddr, allocator: F) -> Self {
        return Self {
            table_kind,
            table_paddr,
            frame_allocator: allocator,
            phantom: PhantomData,
        };
    }

    /// 创建页表，并为这个页表创建页面映射器
    pub unsafe fn create(table_kind: PageTableKind, mut allocator: F) -> Option<Self> {
        let table_paddr = allocator.allocate_one()?;
        // 清空页表
        let table_vaddr = Arch::phys_2_virt(table_paddr)?;
        Arch::write_bytes(table_vaddr, 0, Arch::PAGE_SIZE);
        return Some(Self::new(table_kind, table_paddr, allocator));
    }

    /// 获取当前页表的页面映射器
    #[inline(always)]
    pub unsafe fn current(table_kind: PageTableKind, allocator: F) -> Self {
        let table_paddr = Arch::table(table_kind);
        return Self::new(table_kind, table_paddr, allocator);
    }

    /// 判断当前页表分配器所属的页表是否是当前页表
    #[inline(always)]
    pub fn is_current(&self) -> bool {
        return unsafe { self.table().phys() == Arch::table(self.table_kind) };
    }

    /// 将当前页表分配器所属的页表设置为当前页表
    #[inline(always)]
    pub unsafe fn make_current(&self) {
        Arch::set_table(self.table_kind, self.table_paddr);
    }

    /// 获取当前页表分配器所属的根页表的结构体
    #[inline(always)]
    pub fn table(&self) -> PageTable<Arch> {
        // 由于只能通过new方法创建PageMapper，因此这里假定table_paddr是有效的
        return unsafe {
            PageTable::new(VirtAddr::new(0), self.table_paddr, Arch::PAGE_LEVELS - 1)
        };
    }

    /// 获取当前PageMapper所对应的页分配器实例的引用
    #[inline(always)]
    #[allow(dead_code)]
    pub fn allocator_ref(&self) -> &F {
        return &self.frame_allocator;
    }

    /// 获取当前PageMapper所对应的页分配器实例的可变引用
    #[inline(always)]
    pub fn allocator_mut(&mut self) -> &mut F {
        return &mut self.frame_allocator;
    }

    /// Allocate a physical page from this mapper's allocator and map it at the
    /// specified virtual address.
    ///
    /// # Safety
    ///
    /// The caller must hold the mapper's required page-table edit serialization
    /// and ensure that the target leaf entry is empty.
    pub unsafe fn map(
        &mut self,
        virt: VirtAddr,
        flags: EntryFlags<Arch>,
    ) -> Option<PageFlush<Arch>> {
        self.map_new_page(virt, flags).map(|(_, flush)| flush)
    }

    /// Allocate a managed normal page and map it into an empty leaf entry.
    ///
    /// The returned [`Arc<Page>`] is the same object registered in the global
    /// page manager. Callers can use it directly for rmap/LRU accounting
    /// instead of translating the new PTE and looking the page up again.
    ///
    /// # Safety
    ///
    /// The caller must hold the mapper's required page-table edit serialization
    /// and must have established that the target leaf entry is empty. This
    /// method deliberately does not repeat that lookup on the anonymous-fault
    /// hot path.
    pub(crate) unsafe fn map_new_page(
        &mut self,
        virt: VirtAddr,
        flags: EntryFlags<Arch>,
    ) -> Option<(Arc<Page>, PageFlush<Arch>)> {
        let mut page_manager_guard = page_manager_lock();
        let page = page_manager_guard
            .create_one_page(
                PageType::Normal,
                PageFlags::empty(),
                &mut self.frame_allocator,
            )
            .ok()?;
        drop(page_manager_guard);
        let phys = page.phys_address();
        match self.map_phys(virt, phys, flags) {
            Some(flush) => Some((page, flush)),
            None => {
                let _ = page_manager_lock().remove_page(&phys);
                None
            }
        }
    }

    /// 映射一个物理页到指定的虚拟地址
    pub unsafe fn map_phys(
        &mut self,
        virt: VirtAddr,
        phys: PhysAddr,
        flags: EntryFlags<Arch>,
    ) -> Option<PageFlush<Arch>> {
        // 验证虚拟地址和物理地址是否对齐
        if !(virt.check_aligned(Arch::PAGE_SIZE) && phys.check_aligned(Arch::PAGE_SIZE)) {
            error!(
                "Try to map unaligned page: virt={:?}, phys={:?}",
                virt, phys
            );
            return None;
        }

        let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK));

        // TODO： 验证flags是否合法

        // 创建页表项
        let entry = PageEntry::new(phys, flags);
        let mut table = self.table();
        loop {
            let i = table.index_of(virt)?;

            assert!(i < Arch::PAGE_ENTRY_NUM);
            if table.level() == 0 {
                compiler_fence(Ordering::SeqCst);

                table.set_entry(i, entry);
                compiler_fence(Ordering::SeqCst);
                return Some(PageFlush::new(virt));
            } else {
                let next_table = table.next_level_table(i);
                if let Some(next_table) = next_table {
                    table = next_table;
                    // debug!("Mapping {:?} to next level table...", virt);
                } else {
                    // 分配下一级页表
                    let frame = self.frame_allocator.allocate_one()?;

                    // 清空这个页帧
                    MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
                    // 设置页表项的flags
                    let flags: EntryFlags<Arch> =
                        EntryFlags::new_page_table(virt.kind() == PageTableKind::User);

                    // 把新分配的页表映射到当前页表
                    table.set_entry(i, PageEntry::new(frame, flags));

                    // 获取新分配的页表
                    table = table.next_level_table(i)?;
                }
            }
        }
    }

    /// Map an existing physical range at a specific page-table leaf level.
    ///
    /// The target entry must be empty. Any intermediate tables allocated by this call are appended
    /// to `created_tables`, allowing a higher-level transaction to reclaim only tables it owns.
    pub unsafe fn map_phys_at_level(
        &mut self,
        virt: VirtAddr,
        phys: PhysAddr,
        level: usize,
        flags: EntryFlags<Arch>,
        created_tables: &mut Vec<CreatedPageTable>,
    ) -> Option<PageFlush<Arch>> {
        if level >= Arch::PAGE_LEVELS {
            return None;
        }
        let shift = level
            .checked_mul(Arch::PAGE_ENTRY_SHIFT)?
            .checked_add(Arch::PAGE_SHIFT)?;
        let size = 1usize.checked_shl(shift as u32)?;
        if !virt.check_aligned(size) || !phys.check_aligned(size) {
            return None;
        }

        let virt = VirtAddr::new(virt.data() & !Arch::PAGE_NEGATIVE_MASK);
        let mut table = self.table();
        while table.level() > level {
            let index = table.index_of(virt)?;
            let entry = table.entry(index)?;
            if entry.present() {
                if Arch::entry_is_leaf(table.level(), entry.flags().data()) {
                    return None;
                }
                table = table.next_level_table(index)?;
                continue;
            }

            let child_phys = self.frame_allocator.allocate_one()?;
            Arch::write_bytes(Arch::phys_2_virt(child_phys)?, 0, Arch::PAGE_SIZE);
            let child = PageTable::new(table.entry_base(index)?, child_phys, table.level() - 1);
            table.set_entry(
                index,
                PageEntry::new(
                    child_phys,
                    EntryFlags::new_page_table(virt.kind() == PageTableKind::User),
                ),
            )?;
            created_tables.push(CreatedPageTable {
                parent_base: table.base(),
                parent_phys: table.phys(),
                parent_level: table.level(),
                index,
                child_phys,
            });
            table = child;
        }

        let index = table.index_of(virt)?;
        if !table.entry(index)?.empty() {
            return None;
        }
        let flags = if level == 0 {
            flags
        } else {
            flags.set_huge_page(true)
        };
        table.set_entry(index, PageEntry::new(phys, flags))?;
        Some(PageFlush::new(virt))
    }

    /// Return whether every top-level slot covering `[start, end)` already points at a shared
    /// kernel page-table subtree. Device-linear mappings may add lower-level entries to an existing
    /// shared subtree, but must not create a new top-level entry visible only in the current CR3.
    pub unsafe fn has_existing_top_level_subtrees(&self, start: VirtAddr, end: VirtAddr) -> bool {
        if start >= end {
            return false;
        }
        let table = self.table();
        let top_level_size_shift = (Arch::PAGE_LEVELS - 1)
            .checked_mul(Arch::PAGE_ENTRY_SHIFT)
            .and_then(|shift| shift.checked_add(Arch::PAGE_SHIFT));
        let Some(top_level_size) =
            top_level_size_shift.and_then(|shift| 1usize.checked_shl(shift as u32))
        else {
            return false;
        };
        let mut address = start.data();
        while address < end.data() {
            let vaddr = VirtAddr::new(address);
            let Some(index) = table.index_of(vaddr) else {
                return false;
            };
            let Some(entry) = table.entry(index) else {
                return false;
            };
            if !entry.present() || Arch::entry_is_leaf(table.level(), entry.flags().data()) {
                return false;
            }
            let next = (address & !(top_level_size - 1)).saturating_add(top_level_size);
            if next <= address {
                return false;
            }
            address = next.min(end.data());
        }
        true
    }

    /// Clear exactly the leaf entry at `level`, without descending through a huge mapping and
    /// without freeing intermediate page tables.
    pub unsafe fn clear_mapping_at_level(
        &mut self,
        virt: VirtAddr,
        level: usize,
    ) -> Option<(PhysAddr, EntryFlags<Arch>)> {
        let mut table = self.table();
        while table.level() > level {
            let index = table.index_of(virt)?;
            let entry = table.entry(index)?;
            if !entry.present() || Arch::entry_is_leaf(table.level(), entry.flags().data()) {
                return None;
            }
            table = table.next_level_table(index)?;
        }
        let index = table.index_of(virt)?;
        let entry = table.entry(index)?;
        if !entry.present() || !Arch::entry_is_leaf(level, entry.flags().data()) {
            return None;
        }
        table.set_entry(index, PageEntry::from_usize(0))?;
        Some((entry.address().ok()?, entry.flags()))
    }

    /// Reclaim transaction-owned page tables after a synchronous kernel TLB shootdown.
    pub unsafe fn reclaim_created_tables(&mut self, created_tables: &mut Vec<CreatedPageTable>) {
        // A lower-level table must be reclaimed before the parent that points to it. Records that
        // are still non-empty remain owned and are retried by a later device-mapping teardown.
        created_tables.sort_unstable_by_key(|owned| owned.parent_level);
        let pending = core::mem::take(created_tables);
        for owned in pending {
            let parent =
                PageTable::<Arch>::new(owned.parent_base, owned.parent_phys, owned.parent_level);
            let Some(entry) = parent.entry(owned.index) else {
                continue;
            };
            if !entry.present() || entry.address().ok() != Some(owned.child_phys) {
                continue;
            }
            if Arch::entry_is_leaf(owned.parent_level, entry.flags().data()) {
                continue;
            }
            let child = PageTable::<Arch>::new(
                parent.entry_base(owned.index).unwrap(),
                owned.child_phys,
                owned.parent_level - 1,
            );
            let empty = (0..Arch::PAGE_ENTRY_NUM)
                .all(|index| child.entry(index).is_some_and(|entry| entry.empty()));
            if empty {
                parent.set_entry(owned.index, PageEntry::from_usize(0));
                self.frame_allocator.free_one(owned.child_phys);
            } else {
                created_tables.push(owned);
            }
        }
    }

    /// 进行大页映射
    pub unsafe fn map_huge_page(
        &mut self,
        virt: VirtAddr,
        flags: EntryFlags<Arch>,
    ) -> Option<PageFlush<Arch>> {
        // 验证虚拟地址是否对齐
        if !(virt.check_aligned(Arch::PAGE_SIZE)) {
            error!("Try to map unaligned page: virt={:?}", virt);
            return None;
        }

        let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK));

        let mut table = self.table();
        loop {
            let i = table.index_of(virt)?;
            assert!(i < Arch::PAGE_ENTRY_NUM);
            let next_table = table.next_level_table(i);
            if let Some(next_table) = next_table {
                table = next_table;
            } else {
                break;
            }
        }

        // 支持2M、1G大页，即页表层级为1、2级的页表可以映射大页
        if table.level == 0 || table.level > 2 {
            return None;
        }

        let (phys, count) = self.frame_allocator.allocate(PageFrameCount::new(
            Arch::PAGE_ENTRY_NUM.pow(table.level as u32),
        ))?;

        MMArch::write_bytes(
            MMArch::phys_2_virt(phys).unwrap(),
            0,
            MMArch::PAGE_SIZE * count.data(),
        );

        table.set_entry(
            table.index_of(virt)?,
            PageEntry::new(phys, flags.set_huge_page(true)),
        )?;
        Some(PageFlush::new(virt))
    }

    /// 为虚拟地址分配指定层级的页表
    /// ## 参数
    ///
    /// - `virt`: 虚拟地址
    /// - `level`: 指定页表层级
    ///
    /// ## 返回值
    /// - Some(PageTable<Arch>): 虚拟地址对应层级的页表
    /// - None: 对应页表不存在
    pub unsafe fn allocate_table(
        &mut self,
        virt: VirtAddr,
        level: usize,
    ) -> Option<PageTable<Arch>> {
        let table = self.get_table(virt, level + 1)?;
        let i = table.index_of(virt)?;
        let frame = self.frame_allocator.allocate_one()?;

        // 清空这个页帧
        MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);

        // 设置页表项的flags
        let flags: EntryFlags<Arch> =
            EntryFlags::new_page_table(virt.kind() == PageTableKind::User);

        table.set_entry(i, PageEntry::new(frame, flags));
        table.next_level_table(i)
    }

    /// 获取虚拟地址的指定层级页表
    /// ## 参数
    ///
    /// - `virt`: 虚拟地址
    /// - `level`: 指定页表层级
    ///
    /// ## 返回值
    /// - Some(PageTable<Arch>): 虚拟地址对应层级的页表
    /// - None: 对应页表不存在
    pub fn get_table(&self, virt: VirtAddr, level: usize) -> Option<PageTable<Arch>> {
        let mut table = self.table();
        if level > Arch::PAGE_LEVELS - 1 {
            return None;
        }

        unsafe {
            loop {
                if table.level == level {
                    return Some(table);
                }
                let i = table.index_of(virt)?;
                assert!(i < Arch::PAGE_ENTRY_NUM);

                table = table.next_level_table(i)?;
            }
        }
    }

    /// 获取虚拟地址在指定层级页表的PageEntry
    /// ## 参数
    ///
    /// - `virt`: 虚拟地址
    /// - `level`: 指定页表层级
    ///
    /// ## 返回值
    /// - Some(PageEntry<Arch>): 虚拟地址在指定层级的页表的有效PageEntry
    /// - None: 无对应的有效PageEntry
    pub fn get_entry(&self, virt: VirtAddr, level: usize) -> Option<PageEntry<Arch>> {
        let table = self.get_table(virt, level)?;
        let i = table.index_of(virt)?;
        let entry = unsafe { table.entry(i) }?;

        if !entry.empty() {
            Some(entry)
        } else {
            None
        }

        // let mut table = self.table();
        // if level > Arch::PAGE_LEVELS - 1 {
        //     return None;
        // }
        // unsafe {
        //     loop {
        //         let i = table.index_of(virt)?;
        //         assert!(i < Arch::PAGE_ENTRY_NUM);

        //         if table.level == level {
        //             let entry = table.entry(i)?;
        //             if !entry.empty() {
        //                 return Some(entry);
        //             } else {
        //                 return None;
        //             }
        //         }

        //         table = table.next_level_table(i)?;
        //     }
        // }
    }

    /// 拷贝用户空间映射
    /// ## 参数
    ///
    /// - `umapper`: 要拷贝的用户空间
    /// - `copy_on_write`: 是否写时复制
    pub unsafe fn clone_user_mapping(&mut self, umapper: &mut Self, copy_on_write: bool) {
        let old_table = umapper.table();
        let new_table = self.table();
        let allocator = self.allocator_mut();
        // 顶级页表的[0, PAGE_KERNEL_INDEX)项为用户空间映射
        for entry_index in 0..Arch::PAGE_KERNEL_INDEX {
            if let Some(next_table) = old_table.next_level_table(entry_index) {
                let table = next_table.clone(allocator, copy_on_write).unwrap();
                let old_entry = old_table.entry(entry_index).unwrap();
                let entry = PageEntry::new(table.phys(), old_entry.flags());
                new_table.set_entry(entry_index, entry);
            }
        }
    }

    /// 将物理地址映射到具有线性偏移量的虚拟地址
    #[allow(dead_code)]
    pub unsafe fn map_linearly(
        &mut self,
        phys: PhysAddr,
        flags: EntryFlags<Arch>,
    ) -> Option<(VirtAddr, PageFlush<Arch>)> {
        let virt: VirtAddr = Arch::phys_2_virt(phys)?;
        return self.map_phys(virt, phys, flags).map(|flush| (virt, flush));
    }

    /// 修改虚拟地址的页表项的flags，并返回页表项刷新器
    ///
    /// 请注意，需要在修改完flags后，调用刷新器的flush方法，才能使修改生效
    ///
    /// ## 参数
    /// - virt 虚拟地址
    /// - flags 新的页表项的flags
    ///
    /// ## 返回值
    ///
    /// 如果修改成功，返回刷新器，否则返回None
    pub unsafe fn remap(
        &mut self,
        virt: VirtAddr,
        flags: EntryFlags<Arch>,
    ) -> Option<PageFlush<Arch>> {
        return self
            .visit(virt, |p1, i| {
                let mut entry = p1.entry(i)?;

                entry.set_flags(flags);
                p1.set_entry(i, entry);
                Some(PageFlush::new(virt))
            })
            .flatten();
    }

    /// Modify the leaf PTE flags of an existing mapping without allocating or freeing any page-table pages.
    ///
    /// This variant only touches an already present leaf entry and therefore works with `&self`.
    /// It is intended for reverse-mapping walkers such as `mkclean` / file truncate zap, which
    /// run under a separate page-table edit lock and must not require `&mut PageMapper`.
    pub unsafe fn remap_present(
        &self,
        virt: VirtAddr,
        flags: EntryFlags<Arch>,
    ) -> Option<PageFlush<Arch>> {
        self.visit(virt, |p1, i| {
            let mut entry = p1.entry(i)?;
            if entry.empty() {
                return None;
            }

            entry.set_flags(flags);
            p1.set_entry(i, entry);
            Some(PageFlush::new(virt))
        })
        .flatten()
    }

    /// 根据虚拟地址，查找页表，获取对应的物理地址和页表项的flags
    ///
    /// ## 参数
    ///
    /// - virt 虚拟地址
    ///
    /// ## 返回值
    ///
    /// 如果查找成功，返回物理地址和页表项的flags，否则返回None
    pub fn translate(&self, virt: VirtAddr) -> Option<(PhysAddr, EntryFlags<Arch>)> {
        let entry: PageEntry<Arch> = self.visit(virt, |p1, i| unsafe { p1.entry(i) })??;
        let paddr = entry.address().ok()?;
        let flags = entry.flags();
        return Some((paddr, flags));
    }

    /// 取消虚拟地址的映射，释放页面，并返回页表项刷新器
    ///
    /// 请注意，需要在取消映射后，调用刷新器的flush方法，才能使修改生效
    ///
    /// ## 参数
    ///
    /// - virt 虚拟地址
    /// - unmap_parents 是否在父页表内，取消空闲子页表的映射
    ///
    /// ## 返回值
    /// 如果取消成功，返回刷新器，否则返回None
    #[allow(dead_code)]
    pub unsafe fn unmap(&mut self, virt: VirtAddr, unmap_parents: bool) -> Option<PageFlush<Arch>> {
        let (paddr, _, flusher) = self.unmap_phys(virt, unmap_parents)?;
        self.frame_allocator.free_one(paddr);
        return Some(flusher);
    }

    /// 取消虚拟地址的映射，并返回物理地址和页表项的flags
    ///
    /// ## 参数
    ///
    /// - vaddr 虚拟地址
    /// - unmap_parents 是否在父页表内，取消空闲子页表的映射
    ///
    /// ## 返回值
    ///
    /// 如果取消成功，返回物理地址和页表项的flags，否则返回None
    pub unsafe fn unmap_phys(
        &mut self,
        virt: VirtAddr,
        unmap_parents: bool,
    ) -> Option<(PhysAddr, EntryFlags<Arch>, PageFlush<Arch>)> {
        self.unmap_phys_with_freed_tables(virt, unmap_parents)
            .map(|(paddr, flags, flush, _freed)| (paddr, flags, flush))
    }

    /// Same as `unmap_phys`, but also returns whether intermediate page-table pages were freed during unmapping.
    ///
    /// Freed intermediate page-table pages (i.e. this unmap caused a page table level to become empty and
    /// be returned to the allocator) means that other CPUs' TLBs may still cache intermediate-level translation
    /// entries pointing to those pages (corresponding to `tlb->freed_tables` in Linux). The caller should
    /// pass this information to [`MmuGather`] so that shootdown triggers a full-mm invalidation instead of
    /// per-page invlpg, preventing Paging-Structure Cache from retaining stale entries.
    ///
    /// [`MmuGather`]: crate::mm::mmu_gather::MmuGather
    pub unsafe fn unmap_phys_with_freed_tables(
        &mut self,
        virt: VirtAddr,
        unmap_parents: bool,
    ) -> Option<(PhysAddr, EntryFlags<Arch>, PageFlush<Arch>, bool)> {
        if !virt.check_aligned(Arch::PAGE_SIZE) {
            error!("Try to unmap unaligned page: virt={:?}", virt);
            return None;
        }

        let table = self.table();
        let mut freed_tables = false;
        unmap_phys_inner(
            virt,
            &table,
            unmap_parents,
            self.allocator_mut(),
            &mut freed_tables,
        )
        .map(|(paddr, flags)| (paddr, flags, PageFlush::<Arch>::new(virt), freed_tables))
    }

    /// Clear an existing leaf PTE without freeing intermediate page-table pages.
    ///
    /// This is the non-allocating / non-freeing counterpart used by cross-mm file-rmap walkers.
    /// Keeping parent page tables intact avoids needing access to the frame allocator and mirrors
    /// Linux's `zap_pte_range()` style leaf-only invalidation.
    pub unsafe fn unmap_phys_preserve_tables(
        &self,
        virt: VirtAddr,
    ) -> Option<(PhysAddr, EntryFlags<Arch>, PageFlush<Arch>)> {
        if !virt.check_aligned(Arch::PAGE_SIZE) {
            error!("Try to unmap unaligned page: virt={:?}", virt);
            return None;
        }

        self.visit(virt, |p1, i| {
            let entry = p1.entry(i)?;
            if entry.empty() {
                return None;
            }

            p1.set_entry(i, PageEntry::from_usize(0));
            Some((
                entry.address().ok()?,
                entry.flags(),
                PageFlush::<Arch>::new(virt),
            ))
        })
        .flatten()
    }

    /// 在页表中，访问虚拟地址对应的页表项，并调用传入的函数F
    fn visit<T>(
        &self,
        virt: VirtAddr,
        f: impl FnOnce(&mut PageTable<Arch>, usize) -> T,
    ) -> Option<T> {
        let mut table = self.table();
        unsafe {
            loop {
                let i = table.index_of(virt)?;
                if table.level() == 0 {
                    return Some(f(&mut table, i));
                } else {
                    table = table.next_level_table(i)?;
                }
            }
        }
    }
}

/// 取消页面映射，返回被取消映射的页表项的：【物理地址】和【flags】
///
/// ## 参数
///
/// - vaddr 虚拟地址
/// - table 页表
/// - unmap_parents 是否在父页表内，取消空闲子页表的映射
/// - allocator 页面分配器（如果页表从这个分配器分配，那么在取消映射时，也需要归还到这个分配器内）
///
/// ## 返回值
///
/// 如果取消成功，返回被取消映射的页表项的：【物理地址】和【flags】，否则返回None
unsafe fn unmap_phys_inner<Arch: MemoryManagementArch>(
    vaddr: VirtAddr,
    table: &PageTable<Arch>,
    unmap_parents: bool,
    allocator: &mut impl FrameAllocator,
    freed_tables: &mut bool,
) -> Option<(PhysAddr, EntryFlags<Arch>)> {
    // 获取页表项的索引
    let i = table.index_of(vaddr)?;

    // 如果当前是最后一级页表，直接取消页面映射
    if table.level() == 0 {
        let entry = table.entry(i)?;
        table.set_entry(i, PageEntry::from_usize(0));
        return Some((entry.address().ok()?, entry.flags()));
    }

    let subtable = table.next_level_table(i)?;
    // 递归地取消映射
    let result = unmap_phys_inner(vaddr, &subtable, unmap_parents, allocator, freed_tables)?;

    // TODO: This is a bad idea for architectures where the kernel mappings are done in the process tables,
    // as these mappings may become out of sync
    if unmap_parents {
        // 如果子页表已经没有映射的页面了，就取消子页表的映射

        // 检查子页表中是否还有映射的页面
        let x = (0..Arch::PAGE_ENTRY_NUM)
            .map(|k| subtable.entry(k).expect("invalid page entry"))
            .any(|e| e.present());
        if !x {
            // 如果没有，就取消子页表的映射
            table.set_entry(i, PageEntry::from_usize(0));
            // 释放子页表
            allocator.free_one(subtable.phys());
            // Mark: intermediate page-table pages were freed; upper layer needs a heavier shootdown for this mm (`freed_tables`).
            *freed_tables = true;
        }
    }

    return Some(result);
}

impl<Arch, F: Debug> Debug for PageMapper<Arch, F> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("PageMapper")
            .field("table_paddr", &self.table_paddr)
            .field("frame_allocator", &self.frame_allocator)
            .finish()
    }
}

/// 页表刷新器的trait
pub trait Flusher<Arch: MemoryManagementArch> {
    /// 取消对指定的page flusher的刷新
    fn consume(&mut self, flush: PageFlush<Arch>);
}

/// 用于刷新某个虚拟地址的刷新器。这个刷新器一经产生，就必须调用flush()方法，
/// 否则会造成对页表的更改被忽略，这是不安全的
#[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."]
pub struct PageFlush<Arch: MemoryManagementArch> {
    virt: VirtAddr,
    phantom: PhantomData<Arch>,
}

impl<Arch: MemoryManagementArch> PageFlush<Arch> {
    pub fn new(virt: VirtAddr) -> Self {
        return Self {
            virt,
            phantom: PhantomData,
        };
    }

    pub fn flush(self) {
        unsafe { Arch::invalidate_page(self.virt) };
    }

    /// 忽略掉这个刷新器
    pub unsafe fn ignore(self) {
        mem::forget(self);
    }
}

impl<Arch: MemoryManagementArch> Drop for PageFlush<Arch> {
    fn drop(&mut self) {
        unsafe {
            MMArch::invalidate_page(self.virt);
        }
    }
}

/// A flusher for the entire page table. Once created, its `flush()` method must be called;
/// otherwise, page table changes will be silently ignored, which is unsafe.
///
/// # Usage Constraints
///
/// **Only allowed for mappings not attached to any user `AddressSpace`**, for example:
///
/// - Kernel-mode fixed mappings (kernel mapper)
/// - DMA / IO remap regions that are never loaded as a user mm by another CPU
///
/// Any user-mm PTE modification must go through [`MmuGather`] + [`AddressSpace::flush_tlb_range`],
/// which perform synchronous shootdown on all `active_cpus`, preventing stale TLB hits on freed physical pages.
///
/// A flush initiated with `PageFlushAll` only takes effect on the current CPU (`invalidate_all`)
/// and does not perform cross-core shootdown; using it in a user-mm scenario would break TLB
/// consistency (risk 4).
///
/// [`MmuGather`]: crate::mm::mmu_gather::MmuGather
/// [`AddressSpace::flush_tlb_range`]: crate::mm::ucontext::AddressSpace::flush_tlb_range
#[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."]
pub struct PageFlushAll<Arch: MemoryManagementArch> {
    phantom: PhantomData<fn() -> Arch>,
}

#[allow(dead_code)]
impl<Arch: MemoryManagementArch> PageFlushAll<Arch> {
    pub fn new() -> Self {
        return Self {
            phantom: PhantomData,
        };
    }

    pub fn flush(self) {
        unsafe { Arch::invalidate_all() };
    }

    /// 忽略掉这个刷新器
    pub unsafe fn ignore(self) {
        mem::forget(self);
    }
}

impl<Arch: MemoryManagementArch> Flusher<Arch> for PageFlushAll<Arch> {
    /// 为page flush all 实现consume，消除对单个页面的刷新。（刷新整个页表了就不需要刷新单个页面了）
    fn consume(&mut self, flush: PageFlush<Arch>) {
        unsafe { flush.ignore() };
    }
}

impl<Arch: MemoryManagementArch, T: Flusher<Arch> + ?Sized> Flusher<Arch> for &mut T {
    /// 允许一个flusher consume掉另一个flusher
    fn consume(&mut self, flush: PageFlush<Arch>) {
        <T as Flusher<Arch>>::consume(self, flush);
    }
}

impl<Arch: MemoryManagementArch> Flusher<Arch> for () {
    fn consume(&mut self, _flush: PageFlush<Arch>) {}
}

/// "Deferred" flusher: silently forgets `PageFlush` on consume;
/// the caller is responsible for performing a unified mm-aware `AddressSpace::flush_tlb_range` flush later.
///
/// This kind of flusher performs no TLB invalidation; suitable for mprotect/mremap/madvise/munmap etc.
/// where the pattern is "modify PTEs + unified shootdown afterwards".
#[derive(Debug, Default)]
pub struct DeferredFlusher;

impl DeferredFlusher {
    #[inline]
    pub const fn new() -> Self {
        Self
    }
}

impl<Arch: MemoryManagementArch> Flusher<Arch> for DeferredFlusher {
    #[inline]
    fn consume(&mut self, flush: PageFlush<Arch>) {
        // SAFETY: caller guarantees that AddressSpace::flush_tlb_range will be called later for unified TLB flush.
        unsafe { flush.ignore() };
    }
}

impl<Arch: MemoryManagementArch> Drop for PageFlushAll<Arch> {
    fn drop(&mut self) {
        unsafe {
            Arch::invalidate_all();
        }
    }
}

/// # 把一个地址向下对齐到页大小
pub fn round_down_to_page_size(addr: usize) -> usize {
    addr & !(MMArch::PAGE_SIZE - 1)
}

/// # 把一个地址向上对齐到页大小
pub fn round_up_to_page_size(addr: usize) -> usize {
    round_down_to_page_size(addr + MMArch::PAGE_SIZE - 1)
}
