]> Devi Nivas Git - cs3210-lab0.git/commitdiff
Simplify allocuvm/deallocuvm to operate in a contiguous memory model. This makes...
authorAustin Clements <amdragon@mit.edu>
Thu, 2 Sep 2010 22:28:36 +0000 (18:28 -0400)
committerAustin Clements <amdragon@mit.edu>
Thu, 2 Sep 2010 22:28:36 +0000 (18:28 -0400)
defs.h
exec.c
proc.c
vm.c

diff --git a/defs.h b/defs.h
index cc3a72140244a732331242be381b87042b278258..4de95ad2ab000a63aee612f9155111c813db7f8b 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -157,8 +157,8 @@ void            kvmalloc(void);
 void            vmenable(void);
 pde_t*          setupkvm(void);
 char*           uva2ka(pde_t*, char*);
-int             allocuvm(pde_t*, char*, uint);
-int             deallocuvm(pde_t *pgdir, char *addr, uint sz);
+int             allocuvm(pde_t*, uint, uint);
+int             deallocuvm(pde_t*, uint, uint);
 void            freevm(pde_t*);
 void            inituvm(pde_t*, char*, uint);
 int             loaduvm(pde_t*, char*, struct inode *ip, uint, uint);
diff --git a/exec.c b/exec.c
index c518c04545bf7267e95224c754930b3d92d5aa94..222f64c069c2a6efd6b0737efceb364635939bfd 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -11,7 +11,7 @@ exec(char *path, char **argv)
 {
   char *mem, *s, *last;
   int i, argc, arglen, len, off;
-  uint sz, sp, spoffset, argp;
+  uint sz, sp, spbottom, argp;
   struct elfhdr elf;
   struct inode *ip;
   struct proghdr ph;
@@ -41,22 +41,18 @@ exec(char *path, char **argv)
       continue;
     if(ph.memsz < ph.filesz)
       goto bad;
-    if(!allocuvm(pgdir, (char *)ph.va, ph.memsz))
+    if(!(sz = allocuvm(pgdir, sz, ph.va + ph.memsz)))
       goto bad;
-    if(ph.va + ph.memsz > sz)
-      sz = ph.va + ph.memsz;
     if(!loaduvm(pgdir, (char *)ph.va, ip, ph.offset, ph.filesz))
       goto bad;
   }
   iunlockput(ip);
 
   // Allocate and initialize stack at sz
-  sz = PGROUNDUP(sz);
-  if(!allocuvm(pgdir, (char *)sz, PGSIZE))
+  sz = spbottom = PGROUNDUP(sz);
+  if(!(sz = allocuvm(pgdir, sz, sz + PGSIZE)))
     goto bad;
-  mem = uva2ka(pgdir, (char *)sz);
-  spoffset = sz;
-  sz += PGSIZE;
+  mem = uva2ka(pgdir, (char *)spbottom);
 
   arglen = 0;
   for(argc=0; argv[argc]; argc++)
@@ -67,22 +63,22 @@ exec(char *path, char **argv)
   argp = sz - arglen - 4*(argc+1);
 
   // Copy argv strings and pointers to stack.
-  *(uint*)(mem+argp-spoffset + 4*argc) = 0;  // argv[argc]
+  *(uint*)(mem+argp-spbottom + 4*argc) = 0;  // argv[argc]
   for(i=argc-1; i>=0; i--){
     len = strlen(argv[i]) + 1;
     sp -= len;
-    memmove(mem+sp-spoffset, argv[i], len);
-    *(uint*)(mem+argp-spoffset + 4*i) = sp;  // argv[i]
+    memmove(mem+sp-spbottom, argv[i], len);
+    *(uint*)(mem+argp-spbottom + 4*i) = sp;  // argv[i]
   }
 
   // Stack frame for main(argc, argv), below arguments.
   sp = argp;
   sp -= 4;
-  *(uint*)(mem+sp-spoffset) = argp;
+  *(uint*)(mem+sp-spbottom) = argp;
   sp -= 4;
-  *(uint*)(mem+sp-spoffset) = argc;
+  *(uint*)(mem+sp-spbottom) = argc;
   sp -= 4;
-  *(uint*)(mem+sp-spoffset) = 0xffffffff;   // fake return pc
+  *(uint*)(mem+sp-spbottom) = 0xffffffff;   // fake return pc
 
   // Save program name for debugging.
   for(last=s=path; *s; s++)
diff --git a/proc.c b/proc.c
index 853eb0a0acca27239f17443de13be67bfe11d199..6f7bdb6414128b70399884a10bf630ab38235c18 100644 (file)
--- a/proc.c
+++ b/proc.c
@@ -142,14 +142,15 @@ userinit(void)
 int
 growproc(int n)
 {
+  uint sz = proc->sz;
   if(n > 0){
-    if(!allocuvm(proc->pgdir, (char *)proc->sz, n))
+    if(!(sz = allocuvm(proc->pgdir, sz, sz + n)))
       return -1;
   } else if(n < 0){
-    if(!deallocuvm(proc->pgdir, (char *)(proc->sz + n), 0 - n))
+    if(!(sz = deallocuvm(proc->pgdir, sz, sz + n)))
       return -1;
   }
-  proc->sz += n;
+  proc->sz = sz;
   switchuvm(proc);
   return 0;
 }
diff --git a/vm.c b/vm.c
index 0104c3ecab7906a4291439efbd584549a0712b6b..5c6f943c6c2bec680c37ffb6f184f8ccf785e496 100644 (file)
--- a/vm.c
+++ b/vm.c
@@ -228,54 +228,50 @@ loaduvm(pde_t *pgdir, char *addr, struct inode *ip, uint offset, uint sz)
   return 1;
 }
 
-// Allocate sz bytes more memory for a process starting at the
-// given user address; allocates physical memory and page
-// table entries. addr and sz need not be page-aligned.
-// It is a no-op for any parts of the requested memory
-// that are already allocated.
+// Allocate memory to the process to bring its size from oldsz to
+// newsz. Allocates physical memory and page table entries. oldsz and
+// newsz need not be page-aligned, nor does newsz have to be larger
+// than oldsz.  Returns the new process size or 0 on error.
 int
-allocuvm(pde_t *pgdir, char *addr, uint sz)
+allocuvm(pde_t *pgdir, uint oldsz, uint newsz)
 {
-  if(addr + sz > (char*)USERTOP)
+  if(newsz > USERTOP)
     return 0;
-  char *a = PGROUNDDOWN(addr);
-  char *last = PGROUNDDOWN(addr + sz - 1);
-  for(; a <= last; a += PGSIZE){
-    pte_t *pte = walkpgdir(pgdir, a, 0);
-    if(pte == 0 || (*pte & PTE_P) == 0){
-      char *mem = kalloc();
-      if(mem == 0){
-        cprintf("allocuvm out of memory\n");
-        deallocuvm(pgdir, addr, sz);
-        return 0;
-      }
-      memset(mem, 0, PGSIZE);
-      mappages(pgdir, a, PGSIZE, PADDR(mem), PTE_W|PTE_U);
+  char *a = (char *)PGROUNDUP(oldsz);
+  char *last = PGROUNDDOWN(newsz - 1);
+  for (; a <= last; a += PGSIZE){
+    char *mem = kalloc();
+    if(mem == 0){
+      cprintf("allocuvm out of memory\n");
+      deallocuvm(pgdir, newsz, oldsz);
+      return 0;
     }
+    memset(mem, 0, PGSIZE);
+    mappages(pgdir, a, PGSIZE, PADDR(mem), PTE_W|PTE_U);
   }
-  return 1;
+  return newsz > oldsz ? newsz : oldsz;
 }
 
-// Deallocate some of the user pages. If addr is not page-aligned,
-// then only deallocates starting at the next page boundary.
+// Deallocate user pages to bring the process size from oldsz to
+// newsz.  oldsz and newsz need not be page-aligned, nor does newsz
+// need to be less than oldsz.  oldsz can be larger than the actual
+// process size.  Returns the new process size.
 int
-deallocuvm(pde_t *pgdir, char *addr, uint sz)
+deallocuvm(pde_t *pgdir, uint oldsz, uint newsz)
 {
-  if(addr + sz > (char*)USERTOP)
-    return 0;
-  char *a = (char *)PGROUNDUP((uint)addr);
-  char *last = PGROUNDDOWN(addr + sz - 1);
+  char *a = (char *)PGROUNDUP(newsz);
+  char *last = PGROUNDDOWN(oldsz - 1);
   for(; 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");
+        panic("kfree");
       kfree((void *) pa);
       *pte = 0;
     }
   }
-  return 1;
+  return newsz < oldsz ? newsz : oldsz;
 }
 
 // Free a page table and all the physical memory pages
@@ -287,7 +283,7 @@ freevm(pde_t *pgdir)
 
   if(!pgdir)
     panic("freevm: no pgdir");
-  deallocuvm(pgdir, 0, USERTOP);
+  deallocuvm(pgdir, USERTOP, 0);
   for(i = 0; i < NPDENTRIES; i++){
     if(pgdir[i] & PTE_P)
       kfree((void *) PTE_ADDR(pgdir[i]));