root/user/grind.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. do_rand
  2. rand
  3. go
  4. iter
  5. main

   1 //
   2 // run random system calls in parallel forever.
   3 //
   4 
   5 #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"
  14 
  15 // from FreeBSD.
  16 int
  17 do_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) + 2836
  23    * 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;
  28 
  29   /* 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 }
  41 
  42 unsigned long rand_next = 1;
  43 
  44 int
  45 rand(void)
  46 {
  47   return (do_rand(&rand_next));
  48 }
  49 
  50 void
  51 go(int which_child)
  52 {
  53   int fd = -1;
  54   static char buf[999];
  55   char *break0 = sbrk(0);
  56   uint64 iters = 0;
  57 
  58   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 | cat
 225       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 }
 295 
 296 void
 297 iter()
 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   }
 312 
 313   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   }
 323 
 324   int st1 = -1;
 325   wait(&st1);
 326   if (st1 != 0) {
 327     kill(pid1);
 328     kill(pid2);
 329   }
 330   int st2 = -1;
 331   wait(&st2);
 332 
 333   exit(0);
 334 }
 335 
 336 int
 337 main()
 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 }

/* [<][>][^][v][top][bottom][index][help] */