Переглянути джерело

使用读写锁包装Page结构体

MemoryShore 9 місяців тому
батько
коміт
2558777bba

+ 6 - 5
kernel/src/ipc/shm.rs

@@ -165,8 +165,8 @@ impl ShmManager {
         let mut page_manager_guard = page_manager_lock_irqsave();
         let mut cur_phys = PhysPageFrame::new(phys_page.0);
         for _ in 0..page_count.data() {
-            let mut page = Page::new(true, cur_phys);
-            page.set_shm_id(shm_id);
+            let page = Page::new(true, cur_phys);
+            page.write().set_shm_id(shm_id);
             let paddr = cur_phys.phys_address();
             page_manager_guard.insert(paddr, page);
             cur_phys = cur_phys.next();
@@ -324,8 +324,8 @@ impl ShmManager {
         if map_count > 0 {
             // 设置共享内存物理页当映射计数等于0时可被回收
             for _ in 0..count.data() {
-                let page = page_manager_guard.get_mut(&cur_phys.phys_address());
-                page.set_dealloc_when_zero(true);
+                let page = page_manager_guard.get_unwrap(&cur_phys.phys_address());
+                page.write().set_dealloc_when_zero(true);
 
                 cur_phys = cur_phys.next();
             }
@@ -444,7 +444,8 @@ impl KernelShm {
         for _ in 0..page_count.data() {
             let page = page_manager_guard.get(&cur_phys.phys_address()).unwrap();
             id_set.extend(
-                page.anon_vma()
+                page.read()
+                    .anon_vma()
                     .iter()
                     .map(|vma| vma.id())
                     .collect::<Vec<_>>(),

+ 4 - 3
kernel/src/ipc/syscall.rs

@@ -371,7 +371,7 @@ impl Syscall {
                 vma.unmap(&mut address_write_guard.user_mapper.utable, flusher);
 
                 // 将该虚拟内存区域映射到共享内存区域
-                let mut page_manager_guard = page_manager_lock_irqsave();
+                let page_manager_guard = page_manager_lock_irqsave();
                 let mut virt = VirtPageFrame::new(vaddr);
                 for _ in 0..count.data() {
                     let r = unsafe {
@@ -386,7 +386,8 @@ impl Syscall {
 
                     // 将vma加入到对应Page的anon_vma
                     page_manager_guard
-                        .get_mut(&phys.phys_address())
+                        .get_unwrap(&phys.phys_address())
+                        .write()
                         .insert_vma(vma.clone());
 
                     phys = phys.next();
@@ -442,7 +443,7 @@ impl Syscall {
         // 如果物理页的shm_id为None,代表不是共享页
         let page_manager_guard = page_manager_lock_irqsave();
         let page = page_manager_guard.get(&paddr).ok_or(SystemError::EINVAL)?;
-        let shm_id = page.shm_id().ok_or(SystemError::EINVAL)?;
+        let shm_id = page.read().shm_id().ok_or(SystemError::EINVAL)?;
         drop(page_manager_guard);
 
         // 获取对应共享页管理信息

+ 3 - 2
kernel/src/mm/allocator/page_frame.rs

@@ -371,8 +371,9 @@ pub unsafe fn deallocate_page_frames(
 
         if let Some(page) = page {
             // 如果page是共享页,将其共享页信息从SHM_MANAGER中删去
-            if page.shared() {
-                shm_manager_lock().free_id(&page.shm_id().unwrap());
+            let page_guard = page.read();
+            if page_guard.shared() {
+                shm_manager_lock().free_id(&page_guard.shm_id().unwrap());
             }
         }
 

+ 18 - 16
kernel/src/mm/fault.rs

@@ -259,9 +259,9 @@ impl PageFaultHandler {
                 klog_types::LogSource::Buddy,
             );
             let paddr = mapper.translate(address).unwrap().0;
-            let mut anon_vma_guard = page_manager_lock_irqsave();
-            let page = anon_vma_guard.get_mut(&paddr);
-            page.insert_vma(vma.clone());
+            let anon_vma_guard = page_manager_lock_irqsave();
+            let page = anon_vma_guard.get_unwrap(&paddr);
+            page.write().insert_vma(vma.clone());
             VmFaultReason::VM_FAULT_COMPLETED
         } else {
             VmFaultReason::VM_FAULT_OOM
@@ -434,8 +434,8 @@ impl PageFaultHandler {
         let address = pfm.address_aligned_down();
         let vma = pfm.vma.clone();
         let old_paddr = mapper.translate(address).unwrap().0;
-        let mut page_manager = page_manager_lock_irqsave();
-        let map_count = page_manager.get_mut(&old_paddr).map_count();
+        let page_manager = page_manager_lock_irqsave();
+        let map_count = page_manager.get_unwrap(&old_paddr).read().map_count();
         drop(page_manager);
 
         let mut entry = mapper.get_entry(address, 0).unwrap();
@@ -448,16 +448,16 @@ impl PageFaultHandler {
             table.set_entry(i, entry);
             VmFaultReason::VM_FAULT_COMPLETED
         } else if let Some(flush) = mapper.map(address, new_flags) {
-            let mut page_manager = page_manager_lock_irqsave();
-            let old_page = page_manager.get_mut(&old_paddr);
-            old_page.remove_vma(&vma);
+            let page_manager = page_manager_lock_irqsave();
+            let old_page = page_manager.get_unwrap(&old_paddr);
+            old_page.write().remove_vma(&vma);
             drop(page_manager);
 
             flush.flush();
             let paddr = mapper.translate(address).unwrap().0;
-            let mut anon_vma_guard = page_manager_lock_irqsave();
-            let page = anon_vma_guard.get_mut(&paddr);
-            page.insert_vma(vma.clone());
+            let anon_vma_guard = page_manager_lock_irqsave();
+            let page = anon_vma_guard.get_unwrap(&paddr);
+            page.write().insert_vma(vma.clone());
 
             (MMArch::phys_2_virt(paddr).unwrap().data() as *mut u8).copy_from_nonoverlapping(
                 MMArch::phys_2_virt(old_paddr).unwrap().data() as *mut u8,
@@ -577,8 +577,9 @@ impl PageFaultHandler {
         for pgoff in start_pgoff..=end_pgoff {
             if let Some(page_phys) = page_cache.get_page(pgoff) {
                 let page = page_manager_guard.get(&page_phys).unwrap();
-                if page.flags().contains(PageFlags::PG_UPTODATE) {
-                    let phys = page.phys_frame().phys_address();
+                let page_guard = page.read();
+                if page_guard.flags().contains(PageFlags::PG_UPTODATE) {
+                    let phys = page_guard.phys_frame().phys_address();
                     let virt = phys_2_virt(phys.data());
 
                     let address =
@@ -638,10 +639,11 @@ impl PageFaultHandler {
                 .copy_from_nonoverlapping(buf.as_mut_ptr(), MMArch::PAGE_SIZE);
 
             let page = Page::new(false, PhysPageFrame::new(new_cache_page));
-            pfm.page_phys_address = Some(page.phys_frame().phys_address());
-
-            page_cache.add_page(file_pgoff, page.phys_frame().phys_address());
+            let page_guard = page.read();
+            pfm.page_phys_address = Some(page_guard.phys_frame().phys_address());
 
+            page_cache.add_page(file_pgoff, page_guard.phys_frame().phys_address());
+            drop(page_guard);
             page_manager_guard.insert(new_cache_page, page);
 
             //     // 分配空白页并映射到缺页地址

+ 50 - 10
kernel/src/mm/page.rs

@@ -14,7 +14,10 @@ use crate::{
     arch::{interrupt::ipi::send_ipi, MMArch},
     exception::ipi::{IpiKind, IpiTarget},
     ipc::shm::ShmId,
-    libs::spinlock::{SpinLock, SpinLockGuard},
+    libs::{
+        rwlock::RwLock,
+        spinlock::{SpinLock, SpinLockGuard},
+    },
 };
 
 use super::{
@@ -53,7 +56,7 @@ pub fn page_manager_lock_irqsave() -> SpinLockGuard<'static, PageManager> {
 
 // 物理页管理器
 pub struct PageManager {
-    phys2page: HashMap<PhysAddr, Page>,
+    phys2page: HashMap<PhysAddr, Arc<Page>>,
 }
 
 impl PageManager {
@@ -67,18 +70,26 @@ impl PageManager {
         self.phys2page.contains_key(paddr)
     }
 
-    pub fn get(&self, paddr: &PhysAddr) -> Option<&Page> {
-        self.phys2page.get(paddr)
+    pub fn get(&self, paddr: &PhysAddr) -> Option<Arc<Page>> {
+        self.phys2page.get(paddr).map(|x| x.clone())
     }
 
-    pub fn get_mut(&mut self, paddr: &PhysAddr) -> &mut Page {
+    pub fn get_unwrap(&self, paddr: &PhysAddr) -> Arc<Page> {
         self.phys2page
-            .get_mut(paddr)
-            .unwrap_or_else(|| panic!("{:?}", paddr))
+            .get(paddr)
+            .unwrap_or_else(|| panic!("Phys Page not found, {:?}", paddr))
+            .clone()
     }
 
+    // pub fn get_mut(&mut self, paddr: &PhysAddr) -> RwLockWriteGuard<Page> {
+    //     self.phys2page
+    //         .get_mut(paddr)
+    //         .unwrap_or_else(|| panic!("{:?}", paddr))
+    //         .write()
+    // }
+
     pub fn insert(&mut self, paddr: PhysAddr, page: Page) {
-        self.phys2page.insert(paddr, page);
+        self.phys2page.insert(paddr, Arc::new(page));
     }
 
     pub fn remove_page(&mut self, paddr: &PhysAddr) {
@@ -106,9 +117,38 @@ bitflags! {
         const PG_SWAPBACKED = 1 << 19;
     }
 }
+
 #[derive(Debug)]
-/// 物理页面信息
 pub struct Page {
+    inner: RwLock<InnerPage>,
+}
+
+impl core::ops::Deref for Page {
+    type Target = RwLock<InnerPage>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.inner
+    }
+}
+
+impl core::ops::DerefMut for Page {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.inner
+    }
+}
+
+impl Page {
+    pub fn new(shared: bool, phys_frame: PhysPageFrame) -> Self {
+        let inner = InnerPage::new(shared, phys_frame);
+        Self {
+            inner: RwLock::new(inner),
+        }
+    }
+}
+
+#[derive(Debug)]
+/// 物理页面信息
+pub struct InnerPage {
     /// 映射计数
     map_count: usize,
     /// 是否为共享页
@@ -125,7 +165,7 @@ pub struct Page {
     phys_frame: PhysPageFrame,
 }
 
-impl Page {
+impl InnerPage {
     pub fn new(shared: bool, phys_frame: PhysPageFrame) -> Self {
         let dealloc_when_zero = !shared;
         Self {

+ 22 - 19
kernel/src/mm/ucontext.rs

@@ -187,11 +187,11 @@ impl InnerAddressSpace {
             // debug!("new vma: {:x?}", new_vma);
             let new_vma_guard = new_vma.lock();
             let new_mapper = &new_guard.user_mapper.utable;
-            let mut anon_vma_guard = page_manager_lock_irqsave();
+            let anon_vma_guard = page_manager_lock_irqsave();
             for page in new_vma_guard.pages().map(|p| p.virt_address()) {
                 if let Some((paddr, _)) = new_mapper.translate(page) {
-                    let page = anon_vma_guard.get_mut(&paddr);
-                    page.insert_vma(new_vma.clone());
+                    let page = anon_vma_guard.get_unwrap(&paddr);
+                    page.write().insert_vma(new_vma.clone());
                 }
             }
 
@@ -1177,12 +1177,13 @@ impl LockedVMA {
                 .expect("Failed to unmap, beacuse of some page is not mapped");
 
             // 从anon_vma中删除当前VMA
-            let page = page_manager_guard.get_mut(&paddr);
-            page.remove_vma(self);
+            let page = page_manager_guard.get_unwrap(&paddr);
+            page.write().remove_vma(self);
 
             // 如果物理页的anon_vma链表长度为0并且不是共享页,则释放物理页.
-            if page.can_deallocate() {
+            if page.read().can_deallocate() {
                 unsafe {
+                    drop(page);
                     deallocate_page_frames(
                         PhysPageFrame::new(paddr),
                         PageFrameCount::new(1),
@@ -1250,14 +1251,15 @@ impl LockedVMA {
         });
 
         // 重新设置before、after这两个VMA里面的物理页的anon_vma
-        let mut page_manager_guard = page_manager_lock_irqsave();
+        let page_manager_guard = page_manager_lock_irqsave();
         if let Some(before) = before.clone() {
             let virt_iter = before.lock().region.iter_pages();
             for frame in virt_iter {
                 if let Some((paddr, _)) = utable.translate(frame.virt_address()) {
-                    let page = page_manager_guard.get_mut(&paddr);
-                    page.insert_vma(before.clone());
-                    page.remove_vma(self);
+                    let page = page_manager_guard.get_unwrap(&paddr);
+                    let mut page_guard = page.write();
+                    page_guard.insert_vma(before.clone());
+                    page_guard.remove_vma(self);
                     before.lock().mapped = true;
                 }
             }
@@ -1267,9 +1269,10 @@ impl LockedVMA {
             let virt_iter = after.lock().region.iter_pages();
             for frame in virt_iter {
                 if let Some((paddr, _)) = utable.translate(frame.virt_address()) {
-                    let page = page_manager_guard.get_mut(&paddr);
-                    page.insert_vma(after.clone());
-                    page.remove_vma(self);
+                    let page = page_manager_guard.get_unwrap(&paddr);
+                    let mut page_guard = page.write();
+                    page_guard.insert_vma(after.clone());
+                    page_guard.remove_vma(self);
                     after.lock().mapped = true;
                 }
             }
@@ -1569,12 +1572,12 @@ impl VMA {
         ));
 
         // 将VMA加入到anon_vma中
-        let mut page_manager_guard = page_manager_lock_irqsave();
+        let page_manager_guard = page_manager_lock_irqsave();
         cur_phy = phys;
         for _ in 0..count.data() {
             let paddr = cur_phy.phys_address();
-            let page = page_manager_guard.get_mut(&paddr);
-            page.insert_vma(r.clone());
+            let page = page_manager_guard.get_unwrap(&paddr);
+            page.write().insert_vma(r.clone());
             cur_phy = cur_phy.next();
         }
 
@@ -1639,15 +1642,15 @@ impl VMA {
         // debug!("VMA::zeroed: flusher dropped");
 
         // 清空这些内存并将VMA加入到anon_vma中
-        let mut page_manager_guard = page_manager_lock_irqsave();
+        let page_manager_guard = page_manager_lock_irqsave();
         let virt_iter: VirtPageFrameIter =
             VirtPageFrameIter::new(destination, destination.add(page_count));
         for frame in virt_iter {
             let paddr = mapper.translate(frame.virt_address()).unwrap().0;
 
             // 将VMA加入到anon_vma
-            let page = page_manager_guard.get_mut(&paddr);
-            page.insert_vma(r.clone());
+            let page = page_manager_guard.get_unwrap(&paddr);
+            page.write().insert_vma(r.clone());
         }
         // debug!("VMA::zeroed: done");
         return Ok(r);