From 83d2db91f75460e1275d67847adec0fca5a9800b Mon Sep 17 00:00:00 2001
From: Robert Morris <rtm@nephron.lcs.mit.edu>
Date: Tue, 10 Aug 2010 17:08:41 -0400
Subject: allow sbrk(-x) to de-allocate user memory

---
 vm.c | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

(limited to 'vm.c')

diff --git a/vm.c b/vm.c
index 6914dd3..8755b82 100644
--- a/vm.c
+++ b/vm.c
@@ -198,7 +198,7 @@ uva2ka(pde_t *pgdir, char *uva)
 int
 allocuvm(pde_t *pgdir, char *addr, uint sz)
 {
-  if (addr + sz >= (char*)USERTOP)
+  if (addr + sz > (char*)USERTOP)
     return 0;
   char *first = PGROUNDDOWN(addr);
   char *last = PGROUNDDOWN(addr + sz - 1);
@@ -218,6 +218,30 @@ allocuvm(pde_t *pgdir, char *addr, uint sz)
   return 1;
 }
 
+// deallocate some of the user pages, in response to sbrk()
+// with a negative argument. if addr is not page-aligned,
+// then only deallocates starting at the next page boundary.
+int
+deallocuvm(pde_t *pgdir, char *addr, uint sz)
+{
+  if (addr + sz > (char*)USERTOP)
+    return 0;
+  char *first = (char*) PGROUNDUP((uint)addr);
+  char *last = PGROUNDDOWN(addr + sz - 1);
+  char *a;
+  for(a = first; a <= last; a += PGSIZE){
+    pte_t *pte = walkpgdir(pgdir, a, 0);
+    if(pte && (*pte & PTE_P) != 0){
+      uint pa = PTE_ADDR(*pte);
+      if(pa == 0)
+        panic("deallocuvm");
+      kfree((void *) pa, PGSIZE);
+      *pte = 0;
+    }
+  }
+  return 1;
+}
+
 // free a page table and all the physical memory pages
 // in the user part.
 void
-- 
cgit v1.2.3