user/grind.c

351 lines
1//2// run random system calls in parallel forever.3//45#include "kernel/param.h"6#include "kernel/types.h"7#include "kernel/stat.h"8#include "user/user.h"9#include "kernel/fs.h"10#include "kernel/fcntl.h"11#include "kernel/syscall.h"12#include "kernel/memlayout.h"13#include "kernel/riscv.h"1415// from FreeBSD.16int17do_rand(unsigned long *ctx)18{19/*20 * Compute x = (7^5 * x) mod (2^31 - 1)21 * without overflowing 31 bits:22 *      (2^31 - 1) = 127773 * (7^5) + 283623 * From "Random number generators: good ones are hard to find",24 * Park and Miller, Communications of the ACM, vol. 31, no. 10,25 * October 1988, p. 1195.26 */27    long hi, lo, x;2829    /* Transform to [1, 0x7ffffffe] range. */30    x = (*ctx % 0x7ffffffe) + 1;31    hi = x / 127773;32    lo = x % 127773;33    x = 16807 * lo - 2836 * hi;34    if (x < 0)35        x += 0x7fffffff;36    /* Transform to [0, 0x7ffffffd] range. */37    x--;38    *ctx = x;39    return (x);40}4142unsigned long rand_next = 1;4344int45rand(void)46{47    return (do_rand(&rand_next));48}4950void51go(int which_child)52{53  int fd = -1;54  static char buf[999];55  char *break0 = sbrk(0);56  uint64 iters = 0;5758  mkdir("grindir");59  if(chdir("grindir") != 0){60    printf("grind: chdir grindir failed\n");61    exit(1);62  }63  chdir("/");64  65  while(1){66    iters++;67    if((iters % 500) == 0)68      write(1, which_child?"B":"A", 1);69    int what = rand() % 23;70    if(what == 1){71      close(open("grindir/../a", O_CREATE|O_RDWR));72    } else if(what == 2){73      close(open("grindir/../grindir/../b", O_CREATE|O_RDWR));74    } else if(what == 3){75      unlink("grindir/../a");76    } else if(what == 4){77      if(chdir("grindir") != 0){78        printf("grind: chdir grindir failed\n");79        exit(1);80      }81      unlink("../b");82      chdir("/");83    } else if(what == 5){84      close(fd);85      fd = open("/grindir/../a", O_CREATE|O_RDWR);86    } else if(what == 6){87      close(fd);88      fd = open("/./grindir/./../b", O_CREATE|O_RDWR);89    } else if(what == 7){90      write(fd, buf, sizeof(buf));91    } else if(what == 8){92      read(fd, buf, sizeof(buf));93    } else if(what == 9){94      mkdir("grindir/../a");95      close(open("a/../a/./a", O_CREATE|O_RDWR));96      unlink("a/a");97    } else if(what == 10){98      mkdir("/../b");99      close(open("grindir/../b/b", O_CREATE|O_RDWR));100      unlink("b/b");101    } else if(what == 11){102      unlink("b");103      link("../grindir/./../a", "../b");104    } else if(what == 12){105      unlink("../grindir/../a");106      link(".././b", "/grindir/../a");107    } else if(what == 13){108      int pid = fork();109      if(pid == 0){110        exit(0);111      } else if(pid < 0){112        printf("grind: fork failed\n");113        exit(1);114      }115      wait(0);116    } else if(what == 14){117      int pid = fork();118      if(pid == 0){119        fork();120        fork();121        exit(0);122      } else if(pid < 0){123        printf("grind: fork failed\n");124        exit(1);125      }126      wait(0);127    } else if(what == 15){128      sbrk(6011);129    } else if(what == 16){130      if(sbrk(0) > break0)131        sbrk(-(sbrk(0) - break0));132    } else if(what == 17){133      int pid = fork();134      if(pid == 0){135        close(open("a", O_CREATE|O_RDWR));136        exit(0);137      } else if(pid < 0){138        printf("grind: fork failed\n");139        exit(1);140      }141      if(chdir("../grindir/..") != 0){142        printf("grind: chdir failed\n");143        exit(1);144      }145      kill(pid);146      wait(0);147    } else if(what == 18){148      int pid = fork();149      if(pid == 0){150        kill(getpid());151        exit(0);152      } else if(pid < 0){153        printf("grind: fork failed\n");154        exit(1);155      }156      wait(0);157    } else if(what == 19){158      int fds[2];159      if(pipe(fds) < 0){160        printf("grind: pipe failed\n");161        exit(1);162      }163      int pid = fork();164      if(pid == 0){165        fork();166        fork();167        if(write(fds[1], "x", 1) != 1)168          printf("grind: pipe write failed\n");169        char c;170        if(read(fds[0], &c, 1) != 1)171          printf("grind: pipe read failed\n");172        exit(0);173      } else if(pid < 0){174        printf("grind: fork failed\n");175        exit(1);176      }177      close(fds[0]);178      close(fds[1]);179      wait(0);180    } else if(what == 20){181      int pid = fork();182      if(pid == 0){183        unlink("a");184        mkdir("a");185        chdir("a");186        unlink("../a");187        fd = open("x", O_CREATE|O_RDWR);188        unlink("x");189        exit(0);190      } else if(pid < 0){191        printf("grind: fork failed\n");192        exit(1);193      }194      wait(0);195    } else if(what == 21){196      unlink("c");197      // should always succeed. check that there are free i-nodes,198      // file descriptors, blocks.199      int fd1 = open("c", O_CREATE|O_RDWR);200      if(fd1 < 0){201        printf("grind: create c failed\n");202        exit(1);203      }204      if(write(fd1, "x", 1) != 1){205        printf("grind: write c failed\n");206        exit(1);207      }208      struct stat st;209      if(fstat(fd1, &st) != 0){210        printf("grind: fstat failed\n");211        exit(1);212      }213      if(st.size != 1){214        printf("grind: fstat reports wrong size %d\n", (int)st.size);215        exit(1);216      }217      if(st.ino > 200){218        printf("grind: fstat reports crazy i-number %d\n", st.ino);219        exit(1);220      }221      close(fd1);222      unlink("c");223    } else if(what == 22){224      // echo hi | cat225      int aa[2], bb[2];226      if(pipe(aa) < 0){227        fprintf(2, "grind: pipe failed\n");228        exit(1);229      }230      if(pipe(bb) < 0){231        fprintf(2, "grind: pipe failed\n");232        exit(1);233      }234      int pid1 = fork();235      if(pid1 == 0){236        close(bb[0]);237        close(bb[1]);238        close(aa[0]);239        close(1);240        if(dup(aa[1]) != 1){241          fprintf(2, "grind: dup failed\n");242          exit(1);243        }244        close(aa[1]);245        char *args[3] = { "echo", "hi", 0 };246        exec("grindir/../echo", args);247        fprintf(2, "grind: echo: not found\n");248        exit(2);249      } else if(pid1 < 0){250        fprintf(2, "grind: fork failed\n");251        exit(3);252      }253      int pid2 = fork();254      if(pid2 == 0){255        close(aa[1]);256        close(bb[0]);257        close(0);258        if(dup(aa[0]) != 0){259          fprintf(2, "grind: dup failed\n");260          exit(4);261        }262        close(aa[0]);263        close(1);264        if(dup(bb[1]) != 1){265          fprintf(2, "grind: dup failed\n");266          exit(5);267        }268        close(bb[1]);269        char *args[2] = { "cat", 0 };270        exec("/cat", args);271        fprintf(2, "grind: cat: not found\n");272        exit(6);273      } else if(pid2 < 0){274        fprintf(2, "grind: fork failed\n");275        exit(7);276      }277      close(aa[0]);278      close(aa[1]);279      close(bb[1]);280      char buf[4] = { 0, 0, 0, 0 };281      read(bb[0], buf+0, 1);282      read(bb[0], buf+1, 1);283      read(bb[0], buf+2, 1);284      close(bb[0]);285      int st1, st2;286      wait(&st1);287      wait(&st2);288      if(st1 != 0 || st2 != 0 || strcmp(buf, "hi\n") != 0){289        printf("grind: exec pipeline failed %d %d \"%s\"\n", st1, st2, buf);290        exit(1);291      }292    }293  }294}295296void297iter()298{299  unlink("a");300  unlink("b");301  302  int pid1 = fork();303  if(pid1 < 0){304    printf("grind: fork failed\n");305    exit(1);306  }307  if(pid1 == 0){308    rand_next ^= 31;309    go(0);310    exit(0);311  }312313  int pid2 = fork();314  if(pid2 < 0){315    printf("grind: fork failed\n");316    exit(1);317  }318  if(pid2 == 0){319    rand_next ^= 7177;320    go(1);321    exit(0);322  }323324  int st1 = -1;325  wait(&st1);326  if(st1 != 0){327    kill(pid1);328    kill(pid2);329  }330  int st2 = -1;331  wait(&st2);332333  exit(0);334}335336int337main()338{339  while(1){340    int pid = fork();341    if(pid == 0){342      iter();343      exit(0);344    }345    if(pid > 0){346      wait(0);347    }348    pause(20);349    rand_next += 1;350  }351}352