2 İşlemeler d161134335 ... 4602c4d71c

Yazar SHA1 Mesaj Tarih
  greatbridf 4602c4d71c Merge branch 'fix' 3 hafta önce
  greatbridf e6365b41be fix(page_fault): potential skipped free in page fault handler 3 hafta önce

+ 6 - 5
src/kernel/mem/mm_list/page_fault.rs

@@ -1,5 +1,4 @@
 use arch::InterruptContext;
-use bindings::kernel::mem::paging::pfn_to_page;
 use bindings::{PA_A, PA_ANON, PA_COW, PA_MMAP, PA_P, PA_RW};
 use bitflags::bitflags;
 
@@ -86,10 +85,13 @@ impl MMList {
                 attributes &= !PA_RW as usize;
             }
 
-            // TODO!!!: Change this.
-            let page = unsafe { pfn_to_page(pfn).as_mut().unwrap() };
-            if page.refcount == 1 {
+            let page = unsafe { Page::take_pfn(pfn, 0) };
+            if unsafe { page.load_refcount() } == 1 {
+                // SAFETY: This is actually safe. If we read `1` here and we have `MMList` lock
+                // held, there couldn't be neither other processes sharing the page, nor other
+                // threads making the page COW at the same time.
                 pte.set_attributes(attributes);
+                core::mem::forget(page);
                 return Ok(());
             }
 
@@ -104,7 +106,6 @@ impl MMList {
             }
 
             attributes &= !(PA_A | PA_ANON) as usize;
-            page.refcount -= 1;
 
             pfn = new_page.into_pfn();
             pte.set(pfn, attributes);

+ 5 - 0
src/kernel/mem/paging.rs

@@ -7,6 +7,7 @@ use crate::bindings::root::EFAULT;
 use crate::io::{Buffer, FillResult};
 use crate::kernel::mem::phys;
 use core::fmt;
+use core::sync::atomic::{AtomicU64, Ordering};
 
 use super::phys::PhysPtr;
 
@@ -158,6 +159,10 @@ impl Page {
             c_increase_refcount(page);
         }
     }
+
+    pub unsafe fn load_refcount(&self) -> usize {
+        AtomicU64::from_ptr(&mut (*self.page_ptr).refcount).load(Ordering::Acquire) as usize
+    }
 }
 
 impl Clone for Page {