diff options
Diffstat (limited to 'user')
| -rw-r--r-- | user/bcachetest.c | 189 | ||||
| -rw-r--r-- | user/init.c | 1 | ||||
| -rw-r--r-- | user/kalloctest.c | 161 | ||||
| -rw-r--r-- | user/statistics.c | 24 | ||||
| -rw-r--r-- | user/stats.c | 24 | ||||
| -rw-r--r-- | user/user.h | 9 | 
6 files changed, 408 insertions, 0 deletions
| diff --git a/user/bcachetest.c b/user/bcachetest.c new file mode 100644 index 0000000..5dc46ef --- /dev/null +++ b/user/bcachetest.c @@ -0,0 +1,189 @@ +#include "kernel/fcntl.h" +#include "kernel/param.h" +#include "kernel/types.h" +#include "kernel/stat.h" +#include "kernel/riscv.h" +#include "kernel/fs.h" +#include "user/user.h" + +void test0(); +void test1(); + +#define SZ 4096 +char buf[SZ]; + +int +main(int argc, char *argv[]) +{ +  test0(); +  test1(); +  exit(0); +} + +void +createfile(char *file, int nblock) +{ +  int fd; +  char buf[BSIZE]; +  int i; +   +  fd = open(file, O_CREATE | O_RDWR); +  if(fd < 0){ +    printf("createfile %s failed\n", file); +    exit(-1); +  } +  for(i = 0; i < nblock; i++) { +    if(write(fd, buf, sizeof(buf)) != sizeof(buf)) { +      printf("write %s failed\n", file); +      exit(-1); +    } +  } +  close(fd); +} + +void +readfile(char *file, int nbytes, int inc) +{ +  char buf[BSIZE]; +  int fd; +  int i; + +  if(inc > BSIZE) { +    printf("readfile: inc too large\n"); +    exit(-1); +  } +  if ((fd = open(file, O_RDONLY)) < 0) { +    printf("readfile open %s failed\n", file); +    exit(-1); +  } +  for (i = 0; i < nbytes; i += inc) { +    if(read(fd, buf, inc) != inc) { +      printf("read %s failed for block %d (%d)\n", file, i, nbytes); +      exit(-1); +    } +  } +  close(fd); +} + +int ntas(int print) +{ +  int n; +  char *c; + +  if (statistics(buf, SZ) <= 0) { +    fprintf(2, "ntas: no stats\n"); +  } +  c = strchr(buf, '='); +  n = atoi(c+2); +  if(print) +    printf("%s", buf); +  return n; +} + +// Test reading small files concurrently +void +test0() +{ +  char file[2]; +  char dir[2]; +  enum { N = 10, NCHILD = 3 }; +  int m, n; + +  dir[0] = '0'; +  dir[1] = '\0'; +  file[0] = 'F'; +  file[1] = '\0'; + +  printf("start test0\n"); +  for(int i = 0; i < NCHILD; i++){ +    dir[0] = '0' + i; +    mkdir(dir); +    if (chdir(dir) < 0) { +      printf("chdir failed\n"); +      exit(1); +    } +    unlink(file); +    createfile(file, N); +    if (chdir("..") < 0) { +      printf("chdir failed\n"); +      exit(1); +    } +  } +  m = ntas(0); +  for(int i = 0; i < NCHILD; i++){ +    dir[0] = '0' + i; +    int pid = fork(); +    if(pid < 0){ +      printf("fork failed"); +      exit(-1); +    } +    if(pid == 0){ +      if (chdir(dir) < 0) { +        printf("chdir failed\n"); +        exit(1); +      } + +      readfile(file, N*BSIZE, 1); + +      exit(0); +    } +  } + +  for(int i = 0; i < NCHILD; i++){ +    wait(0); +  } +  printf("test0 results:\n"); +  n = ntas(1); +  if (n-m < 500) +    printf("test0: OK\n"); +  else +    printf("test0: FAIL\n"); +} + +// Test bcache evictions by reading a large file concurrently +void test1() +{ +  char file[3]; +  enum { N = 200, BIG=100, NCHILD=2 }; +   +  printf("start test1\n"); +  file[0] = 'B'; +  file[2] = '\0'; +  for(int i = 0; i < NCHILD; i++){ +    file[1] = '0' + i; +    unlink(file); +    if (i == 0) { +      createfile(file, BIG); +    } else { +      createfile(file, 1); +    } +  } +  for(int i = 0; i < NCHILD; i++){ +    file[1] = '0' + i; +    int pid = fork(); +    if(pid < 0){ +      printf("fork failed"); +      exit(-1); +    } +    if(pid == 0){ +      if (i==0) { +        for (i = 0; i < N; i++) { +          readfile(file, BIG*BSIZE, BSIZE); +        } +        unlink(file); +        exit(0); +      } else { +        for (i = 0; i < N*20; i++) { +          readfile(file, 1, BSIZE); +        } +        unlink(file); +      } +      exit(0); +    } +  } + +  for(int i = 0; i < NCHILD; i++){ +    wait(0); +  } +  printf("test1 OK\n"); +} diff --git a/user/init.c b/user/init.c index e0a5689..fc1c3db 100644 --- a/user/init.c +++ b/user/init.c @@ -18,6 +18,7 @@ main(void)    if(open("console", O_RDWR) < 0){      mknod("console", CONSOLE, 0); +    mknod("statistics", STATS, 0);      open("console", O_RDWR);    }    dup(0);  // stdout diff --git a/user/kalloctest.c b/user/kalloctest.c new file mode 100644 index 0000000..a82f1d5 --- /dev/null +++ b/user/kalloctest.c @@ -0,0 +1,161 @@ +#include "kernel/param.h" +#include "kernel/types.h" +#include "kernel/stat.h" +#include "kernel/riscv.h" +#include "kernel/memlayout.h" +#include "kernel/fcntl.h" +#include "user/user.h" + +#define NCHILD 2 +#define N 100000 +#define SZ 4096 + +void test1(void); +void test2(void); +void test3(void); +char buf[SZ]; + +int +main(int argc, char *argv[]) +{ +  test1(); +  test2(); +  test3(); +  exit(0); +} + +int ntas(int print) +{ +  int n; +  char *c; + +  if (statistics(buf, SZ) <= 0) { +    fprintf(2, "ntas: no stats\n"); +  } +  c = strchr(buf, '='); +  n = atoi(c+2); +  if(print) +    printf("%s", buf); +  return n; +} + +// Test concurrent kallocs and kfrees +void test1(void) +{ +  void *a, *a1; +  int n, m; +  printf("start test1\n");   +  m = ntas(0); +  for(int i = 0; i < NCHILD; i++){ +    int pid = fork(); +    if(pid < 0){ +      printf("fork failed"); +      exit(-1); +    } +    if(pid == 0){ +      for(i = 0; i < N; i++) { +        a = sbrk(4096); +        *(int *)(a+4) = 1; +        a1 = sbrk(-4096); +        if (a1 != a + 4096) { +          printf("wrong sbrk\n"); +          exit(-1); +        } +      } +      exit(-1); +    } +  } + +  for(int i = 0; i < NCHILD; i++){ +    wait(0); +  } +  printf("test1 results:\n"); +  n = ntas(1); +  if(n-m < 10)  +    printf("test1 OK\n"); +  else +    printf("test1 FAIL\n"); +} + +// +// countfree() from usertests.c +// +int +countfree() +{ +  uint64 sz0 = (uint64)sbrk(0); +  int n = 0; + +  while(1){ +    uint64 a = (uint64) sbrk(4096); +    if(a == 0xffffffffffffffff){ +      break; +    } +    // modify the memory to make sure it's really allocated. +    *(char *)(a + 4096 - 1) = 1; +    n += 1; +  } +  sbrk(-((uint64)sbrk(0) - sz0)); +  return n; +} + +// Test stealing +void test2() { +  int free0 = countfree(); +  int free1; +  int n = (PHYSTOP-KERNBASE)/PGSIZE; +  printf("start test2\n");   +  printf("total free number of pages: %d (out of %d)\n", free0, n); +  if(n - free0 > 1000) { +    printf("test2 FAILED: cannot allocate enough memory"); +    exit(-1); +  } +  for (int i = 0; i < 50; i++) { +    free1 = countfree(); +    if(i % 10 == 9) +      printf("."); +    if(free1 != free0) { +      printf("test2 FAIL: losing pages\n"); +      exit(-1); +    } +  } +  printf("\ntest2 OK\n");   +} + +// Test concurrent kalloc/kfree and stealing +void test3(void) +{ +  void *a, *a1; +  printf("start test3\n");   +  for(int i = 0; i < NCHILD; i++){ +    int pid = fork(); +    if(pid < 0){ +      printf("fork failed"); +      exit(-1); +    } +    if(pid == 0){ +      if (i == 0) { +        for(i = 0; i < N; i++) { +          a = sbrk(4096); +          *(int *)(a+4) = 1; +          a1 = sbrk(-4096); +          if (a1 != a + 4096) { +            printf("wrong sbrk\n"); +            exit(-1); +          } +        } +        printf("child done %d\n", i); +        exit(0); +      } else { +        countfree(); +        printf("child done %d\n", i); +        exit(0); +      } +    } +  } + +  for(int i = 0; i < NCHILD; i++){ +    wait(0); +  } +  printf("test3 OK\n"); +} diff --git a/user/statistics.c b/user/statistics.c new file mode 100644 index 0000000..e22681a --- /dev/null +++ b/user/statistics.c @@ -0,0 +1,24 @@ +#include "kernel/types.h" +#include "kernel/stat.h" +#include "kernel/fcntl.h" +#include "user/user.h" + +int +statistics(void *buf, int sz) +{ +  int fd, i, n; +   +  fd = open("statistics", O_RDONLY); +  if(fd < 0) { +      fprintf(2, "stats: open failed\n"); +      exit(1); +  } +  for (i = 0; i < sz; ) { +    if ((n = read(fd, buf+i, sz-i)) < 0) { +      break; +    } +    i += n; +  } +  close(fd); +  return i; +} diff --git a/user/stats.c b/user/stats.c new file mode 100644 index 0000000..f8c9138 --- /dev/null +++ b/user/stats.c @@ -0,0 +1,24 @@ +#include "kernel/types.h" +#include "kernel/stat.h" +#include "kernel/fcntl.h" +#include "user/user.h" + +#define SZ 4096 +char buf[SZ]; + +int +main(void) +{ +  int i, n; +   +  while (1) { +    n = statistics(buf, SZ); +    for (i = 0; i < n; i++) { +      write(1, buf+i, 1); +    } +    if (n != SZ) +      break; +  } + +  exit(0); +} diff --git a/user/user.h b/user/user.h index 4d398d5..16cf173 100644 --- a/user/user.h +++ b/user/user.h @@ -22,6 +22,14 @@ int getpid(void);  char* sbrk(int);  int sleep(int);  int uptime(void); +#ifdef LAB_NET +int connect(uint32, uint16, uint16); +#endif +#ifdef LAB_PGTBL +int pgaccess(void *base, int len, void *mask); +// usyscall region +int ugetpid(void); +#endif  // ulib.c  int stat(const char*, struct stat*); @@ -39,3 +47,4 @@ void free(void*);  int atoi(const char*);  int memcmp(const void *, const void *, uint);  void *memcpy(void *, const void *, uint); +int statistics(void*, int); | 
