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