diff options
author | Robert Morris <[email protected]> | 2010-08-10 17:08:41 -0400 |
---|---|---|
committer | Robert Morris <[email protected]> | 2010-08-10 17:08:41 -0400 |
commit | 83d2db91f75460e1275d67847adec0fca5a9800b (patch) | |
tree | cc8df8349ca1981e85d8e343dbf365b59f5eabd7 /vm.c | |
parent | c4cc10da7ef6d65f0f654445e0af35b8309f16c2 (diff) | |
download | xv6-labs-83d2db91f75460e1275d67847adec0fca5a9800b.tar.gz xv6-labs-83d2db91f75460e1275d67847adec0fca5a9800b.tar.bz2 xv6-labs-83d2db91f75460e1275d67847adec0fca5a9800b.zip |
allow sbrk(-x) to de-allocate user memory
Diffstat (limited to 'vm.c')
-rw-r--r-- | vm.c | 26 |
1 files changed, 25 insertions, 1 deletions
@@ -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 |