1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
/** @file 410user/progs/actual_wait.c
* @author de0u
* @brief Exercises wait() and vanish().
* @public yes
* @for p2 p3
* @covers wait vanish fork yield set_status
* @status done
*/
#include <syscall.h>
#include <stdlib.h>
#include <stdio.h>
#include <simics.h>
#include "410_tests.h"
DEF_TEST_NAME("actual_wait:");
#define NCHILD 40 /* must be < 255 */
#define PRESERVE (1024*1024)
void child(int);
int main(void)
{
char buf[4096];
int pid, pids[NCHILD];
int c, preserve;
char msg[128];
buf[0] = buf[sizeof (buf) - 1] = 'q';
REPORT_START_CMPLT;
for (c = 0; c < NCHILD; ++c)
switch(((pid = fork()) < 0) ? -1 : pid) {
case -1:
REPORT_MISC("cannot fork");
goto fail;
case 0:
child(c);
break;
default:
pids[c] = pid;
snprintf(msg, sizeof (msg), "slot %d pid %d", c, pid);
printf("%s\n", msg);
REPORT_MISC(msg);
if (c & 1)
yield(-1);
break;
}
for (c = 0; c < NCHILD; ++c) {
int slot;
char msg[128];
if ((c & 8) == 8)
yield(-1);
pid = wait(&slot);
snprintf(msg, sizeof (msg), "slot %d pid %d", slot, pid);
printf("%s\n", msg);
REPORT_MISC(msg);
if ((slot < 0) || (slot >= NCHILD)) {
REPORT_MISC("invalid slot");
goto fail;
}
if (pids[slot] != pid) {
REPORT_MISC("pid/slot mismatch");
goto fail;
}
pids[slot] = -1;
}
preserve = PRESERVE;
pid = wait(&preserve);
if (pid >= 0) {
REPORT_MISC("phantom menace");
goto fail;
}
if (preserve != PRESERVE) {
REPORT_MISC("obliteration");
goto fail;
}
REPORT_END_SUCCESS;
exit(0);
fail:
REPORT_END_FAIL;
exit(9);
}
void
child(int which)
{
int wpid, gpid;
char msg[128];
snprintf(msg, sizeof (msg), "child %d", which);
printf("%s\n", msg);
REPORT_MISC(msg);
switch(((gpid = fork()) < 0) ? -1 : gpid) {
case -1:
REPORT_MISC("child cannot fork");
goto fail;
break;
case 0:
if (which & 1) {
yield(-1);
yield(-1);
}
exit(0);
default:
if ((which & 4) != 4) {
if ((wpid = wait(0)) != gpid) {
REPORT_MISC("grandchild??");
goto fail;
}
}
exit(which);
break;
}
fail:
exit(-1);
}
|