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     sleep(20);
 349     rand_next += 1;
 350   }
 351 }

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