From 1540c8b15ac35de9027e60804a786d23703d383d Mon Sep 17 00:00:00 2001 From: Robert Morris Date: Tue, 2 Jul 2019 11:04:35 -0400 Subject: [PATCH] COW tests --- kernel/vm.c | 2 +- user/cow.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 144 insertions(+), 2 deletions(-) diff --git a/kernel/vm.c b/kernel/vm.c index 7d67464..d5ff594 100644 --- a/kernel/vm.c +++ b/kernel/vm.c @@ -97,8 +97,8 @@ walk(pagetable_t pagetable, uint64 va, int alloc) } // Look up a virtual address, return the physical address, -// Can only be used to look up user pages. // or 0 if not mapped. +// Can only be used to look up user pages. uint64 walkaddr(pagetable_t pagetable, uint64 va) { diff --git a/user/cow.c b/user/cow.c index f770cc9..45efc98 100644 --- a/user/cow.c +++ b/user/cow.c @@ -43,12 +43,154 @@ simpletest() exit(); } - printf(1, "simple ok\n"); + printf(1, "ok\n"); +} + +// three processes all write COW memory. +// this causes more than half of physical memory +// to be allocated, so it also checks whether +// copied pages are freed. +void +threetest() +{ + uint64 phys_size = PHYSTOP - KERNBASE; + int sz = phys_size / 4; + int pid1, pid2; + + printf(1, "three: "); + + char *p = sbrk(sz); + if(p == (char*)0xffffffffffffffffL){ + printf(1, "sbrk(%d) failed\n", sz); + exit(); + } + + pid1 = fork(); + if(pid1 < 0){ + printf(1, "fork failed\n"); + exit(); + } + if(pid1 == 0){ + pid2 = fork(); + if(pid2 < 0){ + printf(1, "fork failed"); + exit(); + } + if(pid2 == 0){ + for(char *q = p; q < p + (sz/5)*4; q += 4096){ + *(int*)q = getpid(); + } + for(char *q = p; q < p + (sz/5)*4; q += 4096){ + if(*(int*)q != getpid()){ + printf(1, "wrong content\n"); + exit(); + } + } + exit(); + } + for(char *q = p; q < p + (sz/2); q += 4096){ + *(int*)q = 9999; + } + exit(); + } + + for(char *q = p; q < p + sz; q += 4096){ + *(int*)q = getpid(); + } + + wait(); + + sleep(1); + + for(char *q = p; q < p + sz; q += 4096){ + if(*(int*)q != getpid()){ + printf(1, "wrong content\n"); + exit(); + } + } + + if(sbrk(-sz) == (char*)0xffffffffffffffffL){ + printf(1, "sbrk(-%d) failed\n", sz); + exit(); + } + + printf(1, "ok\n"); +} + +char junk1[4096]; +int fds[2]; +char junk2[4096]; +char buf[4096]; +char junk3[4096]; + +// test whether copyout() simulates COW faults. +void +filetest() +{ + int parent = getpid(); + + printf(1, "file test: "); + + buf[0] = 99; + + for(int i = 0; i < 4; i++){ + if(pipe(fds) != 0){ + printf(1, "pipe() failed\n"); + exit(); + } + int pid = fork(); + if(pid < 0){ + printf(1, "fork failed\n"); + exit(); + } + if(pid == 0){ + sleep(1); + if(read(fds[0], buf, sizeof(i)) != sizeof(i)){ + printf(1, "read failed\n"); + kill(parent); + exit(); + } + sleep(1); + int j = *(int*)buf; + if(j != i){ + printf(1, "read the wrong value\n"); + kill(parent); + exit(); + } + exit(); + } + if(write(fds[1], &i, sizeof(i)) != sizeof(i)){ + printf(1, "write failed\n"); + exit(); + } + } + + for(int i = 0; i < 4; i++) + wait(); + + if(buf[0] != 99){ + printf(1, "child overwrote parent\n"); + exit(); + } + + printf(1, "ok\n"); } int main(int argc, char *argv[]) { simpletest(); + + // check that the first simpletest() freed the physical memory. + simpletest(); + + threetest(); + threetest(); + threetest(); + + filetest(); + + printf(1, "ALL COW TESTS PASSED\n"); + exit(); }