2019-11-06 16:18:43 +00:00
|
|
|
//
|
|
|
|
// run random system calls in parallel forever.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "kernel/param.h"
|
|
|
|
#include "kernel/types.h"
|
|
|
|
#include "kernel/stat.h"
|
|
|
|
#include "user/user.h"
|
|
|
|
#include "kernel/fs.h"
|
|
|
|
#include "kernel/fcntl.h"
|
|
|
|
#include "kernel/syscall.h"
|
|
|
|
#include "kernel/memlayout.h"
|
|
|
|
#include "kernel/riscv.h"
|
|
|
|
|
|
|
|
// from FreeBSD.
|
|
|
|
int
|
|
|
|
do_rand(unsigned long *ctx)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Compute x = (7^5 * x) mod (2^31 - 1)
|
|
|
|
* without overflowing 31 bits:
|
|
|
|
* (2^31 - 1) = 127773 * (7^5) + 2836
|
|
|
|
* From "Random number generators: good ones are hard to find",
|
|
|
|
* Park and Miller, Communications of the ACM, vol. 31, no. 10,
|
|
|
|
* October 1988, p. 1195.
|
|
|
|
*/
|
|
|
|
long hi, lo, x;
|
|
|
|
|
|
|
|
/* Transform to [1, 0x7ffffffe] range. */
|
|
|
|
x = (*ctx % 0x7ffffffe) + 1;
|
|
|
|
hi = x / 127773;
|
|
|
|
lo = x % 127773;
|
|
|
|
x = 16807 * lo - 2836 * hi;
|
|
|
|
if (x < 0)
|
|
|
|
x += 0x7fffffff;
|
|
|
|
/* Transform to [0, 0x7ffffffd] range. */
|
|
|
|
x--;
|
|
|
|
*ctx = x;
|
|
|
|
return (x);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned long rand_next = 1;
|
|
|
|
|
|
|
|
int
|
|
|
|
rand(void)
|
|
|
|
{
|
|
|
|
return (do_rand(&rand_next));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-11-07 11:44:23 +00:00
|
|
|
go(int which_child)
|
2019-11-06 16:18:43 +00:00
|
|
|
{
|
|
|
|
int fd = -1;
|
|
|
|
static char buf[999];
|
|
|
|
char *break0 = sbrk(0);
|
2019-11-07 11:44:23 +00:00
|
|
|
uint64 iters = 0;
|
2019-11-07 14:46:20 +00:00
|
|
|
|
|
|
|
mkdir("grindir");
|
|
|
|
if(chdir("grindir") != 0){
|
|
|
|
printf("chdir grindir failed\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
chdir("/");
|
2019-11-06 16:18:43 +00:00
|
|
|
|
|
|
|
while(1){
|
2019-11-07 11:44:23 +00:00
|
|
|
iters++;
|
|
|
|
if((iters % 500) == 0)
|
|
|
|
write(1, which_child?"B":"A", 1);
|
2019-11-07 14:46:20 +00:00
|
|
|
int what = rand() % 23;
|
2019-11-06 16:18:43 +00:00
|
|
|
if(what == 1){
|
2019-11-07 14:46:20 +00:00
|
|
|
close(open("grindir/../a", O_CREATE|O_RDWR));
|
2019-11-06 16:18:43 +00:00
|
|
|
} else if(what == 2){
|
2019-11-07 14:46:20 +00:00
|
|
|
close(open("grindir/../grindir/../b", O_CREATE|O_RDWR));
|
2019-11-06 16:18:43 +00:00
|
|
|
} else if(what == 3){
|
2019-11-07 14:46:20 +00:00
|
|
|
unlink("grindir/../a");
|
2019-11-06 16:18:43 +00:00
|
|
|
} else if(what == 4){
|
2019-11-07 14:46:20 +00:00
|
|
|
if(chdir("grindir") != 0){
|
|
|
|
printf("chdir grindir failed\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
unlink("../b");
|
|
|
|
chdir("/");
|
2019-11-06 16:18:43 +00:00
|
|
|
} else if(what == 5){
|
|
|
|
close(fd);
|
2019-11-07 14:46:20 +00:00
|
|
|
fd = open("/grindir/../a", O_CREATE|O_RDWR);
|
2019-11-06 16:18:43 +00:00
|
|
|
} else if(what == 6){
|
|
|
|
close(fd);
|
2019-11-07 14:46:20 +00:00
|
|
|
fd = open("/./grindir/./../b", O_CREATE|O_RDWR);
|
2019-11-06 16:18:43 +00:00
|
|
|
} else if(what == 7){
|
|
|
|
write(fd, buf, sizeof(buf));
|
|
|
|
} else if(what == 8){
|
|
|
|
read(fd, buf, sizeof(buf));
|
|
|
|
} else if(what == 9){
|
2019-11-07 14:46:20 +00:00
|
|
|
mkdir("grindir/../a");
|
|
|
|
close(open("a/../a/./a", O_CREATE|O_RDWR));
|
2019-11-07 11:44:23 +00:00
|
|
|
unlink("a/a");
|
2019-11-06 16:18:43 +00:00
|
|
|
} else if(what == 10){
|
2019-11-07 14:46:20 +00:00
|
|
|
mkdir("/../b");
|
|
|
|
close(open("grindir/../b/b", O_CREATE|O_RDWR));
|
2019-11-07 11:44:23 +00:00
|
|
|
unlink("b/b");
|
2019-11-06 16:18:43 +00:00
|
|
|
} else if(what == 11){
|
|
|
|
unlink("b");
|
2019-11-07 14:46:20 +00:00
|
|
|
link("../grindir/./../a", "../b");
|
2019-11-06 16:18:43 +00:00
|
|
|
} else if(what == 12){
|
2019-11-07 14:46:20 +00:00
|
|
|
unlink("../grindir/../a");
|
|
|
|
link(".././b", "/grindir/../a");
|
2019-11-06 16:18:43 +00:00
|
|
|
} else if(what == 13){
|
|
|
|
int pid = fork();
|
|
|
|
if(pid == 0){
|
|
|
|
exit(0);
|
2019-11-07 11:44:23 +00:00
|
|
|
} else if(pid < 0){
|
|
|
|
printf("grind: fork failed\n");
|
|
|
|
exit(1);
|
2019-11-06 16:18:43 +00:00
|
|
|
}
|
|
|
|
wait(0);
|
|
|
|
} else if(what == 14){
|
|
|
|
int pid = fork();
|
|
|
|
if(pid == 0){
|
|
|
|
fork();
|
|
|
|
fork();
|
|
|
|
exit(0);
|
2019-11-07 11:44:23 +00:00
|
|
|
} else if(pid < 0){
|
|
|
|
printf("grind: fork failed\n");
|
|
|
|
exit(1);
|
2019-11-06 16:18:43 +00:00
|
|
|
}
|
|
|
|
wait(0);
|
|
|
|
} else if(what == 15){
|
|
|
|
sbrk(6011);
|
|
|
|
} else if(what == 16){
|
|
|
|
if(sbrk(0) > break0)
|
|
|
|
sbrk(-(sbrk(0) - break0));
|
|
|
|
} else if(what == 17){
|
|
|
|
int pid = fork();
|
|
|
|
if(pid == 0){
|
|
|
|
close(open("a", O_CREATE|O_RDWR));
|
|
|
|
exit(0);
|
2019-11-07 11:44:23 +00:00
|
|
|
} else if(pid < 0){
|
|
|
|
printf("grind: fork failed\n");
|
|
|
|
exit(1);
|
2019-11-06 16:18:43 +00:00
|
|
|
}
|
2019-11-07 14:46:20 +00:00
|
|
|
if(chdir("../grindir/..") != 0){
|
|
|
|
printf("chdir failed\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
2019-11-06 16:18:43 +00:00
|
|
|
kill(pid);
|
|
|
|
wait(0);
|
|
|
|
} else if(what == 18){
|
|
|
|
int pid = fork();
|
|
|
|
if(pid == 0){
|
|
|
|
kill(getpid());
|
|
|
|
exit(0);
|
2019-11-07 11:44:23 +00:00
|
|
|
} else if(pid < 0){
|
|
|
|
printf("grind: fork failed\n");
|
|
|
|
exit(1);
|
2019-11-06 16:18:43 +00:00
|
|
|
}
|
|
|
|
wait(0);
|
2019-11-07 11:44:23 +00:00
|
|
|
} else if(what == 19){
|
|
|
|
int fds[2];
|
|
|
|
if(pipe(fds) < 0){
|
|
|
|
printf("grind: pipe failed\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
int pid = fork();
|
|
|
|
if(pid == 0){
|
|
|
|
fork();
|
|
|
|
fork();
|
|
|
|
if(write(fds[1], "x", 1) != 1)
|
|
|
|
printf("grind: pipe write failed\n");
|
|
|
|
char c;
|
|
|
|
if(read(fds[0], &c, 1) != 1)
|
|
|
|
printf("grind: pipe read failed\n");
|
|
|
|
exit(0);
|
|
|
|
} else if(pid < 0){
|
|
|
|
printf("grind: fork failed\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
close(fds[0]);
|
|
|
|
close(fds[1]);
|
|
|
|
wait(0);
|
2019-11-07 14:46:20 +00:00
|
|
|
} else if(what == 20){
|
|
|
|
int pid = fork();
|
|
|
|
if(pid == 0){
|
|
|
|
unlink("a");
|
|
|
|
mkdir("a");
|
|
|
|
chdir("a");
|
|
|
|
unlink("../a");
|
|
|
|
fd = open("x", O_CREATE|O_RDWR);
|
|
|
|
unlink("x");
|
|
|
|
exit(0);
|
|
|
|
} else if(pid < 0){
|
|
|
|
printf("fork failed\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
wait(0);
|
|
|
|
} else if(what == 21){
|
|
|
|
unlink("c");
|
|
|
|
// should always succeed. check that there are free i-nodes,
|
|
|
|
// file descriptors, blocks.
|
|
|
|
int fd1 = open("c", O_CREATE|O_RDWR);
|
|
|
|
if(fd1 < 0){
|
|
|
|
printf("create c failed\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if(write(fd1, "x", 1) != 1){
|
|
|
|
printf("write c failed\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
struct stat st;
|
|
|
|
if(fstat(fd1, &st) != 0){
|
|
|
|
printf("fstat failed\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if(st.size != 1){
|
|
|
|
printf("fstat reports wrong size %d\n", (int)st.size);
|
|
|
|
exit(1);
|
|
|
|
}
|
2019-11-08 18:21:06 +00:00
|
|
|
if(st.ino > 200){
|
2019-11-07 14:46:20 +00:00
|
|
|
printf("fstat reports crazy i-number %d\n", st.ino);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
close(fd1);
|
|
|
|
unlink("c");
|
|
|
|
} else if(what == 22){
|
|
|
|
// echo hi | cat
|
|
|
|
int aa[2], bb[2];
|
|
|
|
if(pipe(aa) < 0){
|
|
|
|
fprintf(2, "pipe failed\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if(pipe(bb) < 0){
|
|
|
|
fprintf(2, "pipe failed\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
int pid1 = fork();
|
|
|
|
if(pid1 == 0){
|
|
|
|
close(bb[0]);
|
|
|
|
close(bb[1]);
|
|
|
|
close(aa[0]);
|
|
|
|
close(1);
|
|
|
|
if(dup(aa[1]) != 1){
|
|
|
|
fprintf(2, "dup failed\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
close(aa[1]);
|
|
|
|
char *args[3] = { "echo", "hi", 0 };
|
|
|
|
exec("grindir/../echo", args);
|
|
|
|
fprintf(2, "echo: not found\n");
|
|
|
|
exit(2);
|
|
|
|
} else if(pid1 < 0){
|
|
|
|
fprintf(2, "fork failed\n");
|
|
|
|
exit(3);
|
|
|
|
}
|
|
|
|
int pid2 = fork();
|
|
|
|
if(pid2 == 0){
|
|
|
|
close(aa[1]);
|
|
|
|
close(bb[0]);
|
|
|
|
close(0);
|
|
|
|
if(dup(aa[0]) != 0){
|
|
|
|
fprintf(2, "dup failed\n");
|
|
|
|
exit(4);
|
|
|
|
}
|
|
|
|
close(aa[0]);
|
|
|
|
close(1);
|
|
|
|
if(dup(bb[1]) != 1){
|
|
|
|
fprintf(2, "dup failed\n");
|
|
|
|
exit(5);
|
|
|
|
}
|
|
|
|
close(bb[1]);
|
|
|
|
char *args[2] = { "cat", 0 };
|
|
|
|
exec("/cat", args);
|
|
|
|
fprintf(2, "cat: not found\n");
|
|
|
|
exit(6);
|
|
|
|
} else if(pid2 < 0){
|
|
|
|
fprintf(2, "fork failed\n");
|
|
|
|
exit(7);
|
|
|
|
}
|
|
|
|
close(aa[0]);
|
|
|
|
close(aa[1]);
|
|
|
|
close(bb[1]);
|
|
|
|
char buf[3] = { 0, 0, 0 };
|
|
|
|
read(bb[0], buf+0, 1);
|
|
|
|
read(bb[0], buf+1, 1);
|
|
|
|
close(bb[0]);
|
|
|
|
int st1, st2;
|
|
|
|
wait(&st1);
|
|
|
|
wait(&st2);
|
|
|
|
if(st1 != 0 || st2 != 0 || strcmp(buf, "hi") != 0){
|
|
|
|
printf("exec pipeline failed %d %d \"%s\"\n", st1, st2, buf);
|
|
|
|
exit(1);
|
|
|
|
}
|
2019-11-06 16:18:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main()
|
|
|
|
{
|
2019-11-07 11:44:23 +00:00
|
|
|
unlink("a");
|
|
|
|
unlink("b");
|
|
|
|
|
2019-11-06 16:18:43 +00:00
|
|
|
int pid1 = fork();
|
|
|
|
if(pid1 < 0){
|
|
|
|
printf("grind: fork failed\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if(pid1 == 0){
|
|
|
|
rand_next = 31;
|
2019-11-07 11:44:23 +00:00
|
|
|
go(0);
|
2019-11-06 16:18:43 +00:00
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pid2 = fork();
|
|
|
|
if(pid2 < 0){
|
|
|
|
printf("grind: fork failed\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if(pid2 == 0){
|
|
|
|
rand_next = 7177;
|
2019-11-07 11:44:23 +00:00
|
|
|
go(1);
|
2019-11-06 16:18:43 +00:00
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int st1 = -1;
|
|
|
|
wait(&st1);
|
|
|
|
if(st1 != 0){
|
|
|
|
kill(pid1);
|
|
|
|
kill(pid2);
|
|
|
|
}
|
|
|
|
int st2 = -1;
|
|
|
|
wait(&st2);
|
|
|
|
|
|
|
|
exit(0);
|
|
|
|
}
|