Drop main() prototype. Syncs with NetBSD-8
[minix.git] / minix / tests / test75.c
blob208398b88bceb634a1455dc7d941bc8611117be8
1 /* Test 75 - getrusage and wait4 test.
2 */
4 #include <sys/resource.h>
5 #include <sys/time.h>
6 #include <stdio.h>
7 #include <assert.h>
8 #include <sys/types.h>
9 #include <sys/wait.h>
10 #include <sys/mman.h>
11 #include <unistd.h>
13 #include "common.h"
15 #define CHECK_ZERO_FIELD(rusage, field) \
16 if (rusage.field != 0) \
17 em(1, #field " must be zero");
19 #define CHECK_NOT_ZERO_FIELD(rusage, field) \
20 if (rusage.field == 0) \
21 em(1, #field " can't be zero");
23 #define CHECK_EQUAL_FIELD(rusage1, rusage2, field) \
24 if (rusage1.field != rusage2.field) \
25 em(1, #field " of " #rusage1 " doesn't equal to " \
26 #field " of " #rusage2);
28 static void
29 spin(void)
31 struct timeval start_time;
32 struct timeval end_time;
33 unsigned int loop = 0;
34 if (gettimeofday(&start_time, NULL) == -1) e(1);
35 end_time = start_time;
36 do {
37 if ((++loop % 3000000000) == 0) {
38 if (gettimeofday(&end_time, NULL) == -1) e(1);
40 } while (start_time.tv_sec + 10 > end_time.tv_sec);
44 * Test getrusage(2).
46 static void
47 test75a(void)
49 struct rusage r_usage1;
50 struct rusage r_usage2;
51 struct rusage r_usage3;
52 pid_t child;
53 int status = 0;
55 if ((getrusage(RUSAGE_SELF + 1, &r_usage1) != -1 || errno != EINVAL) ||
56 (getrusage(RUSAGE_CHILDREN - 1, &r_usage1) != -1 ||
57 errno != EINVAL) || (getrusage(RUSAGE_SELF, NULL) != -1 ||
58 errno != EFAULT))
59 e(1);
61 spin();
62 if (getrusage(RUSAGE_SELF, &r_usage1) != 0) e(1);
63 CHECK_NOT_ZERO_FIELD(r_usage1, ru_utime.tv_sec);
64 CHECK_NOT_ZERO_FIELD(r_usage1, ru_maxrss);
65 if (getrusage(RUSAGE_CHILDREN, &r_usage2) != 0) e(1);
67 if ((child = fork()) == 0) {
69 * We cannot do this part of the test in the parent, since
70 * start() calls system() which spawns a child process.
72 if (getrusage(RUSAGE_CHILDREN, &r_usage1) != 0) e(1);
73 CHECK_ZERO_FIELD(r_usage1, ru_utime.tv_sec);
74 CHECK_ZERO_FIELD(r_usage1, ru_utime.tv_usec);
75 spin();
76 exit(errct);
77 } else {
78 if (child != waitpid(child, &status, 0)) e(1);
79 if (WEXITSTATUS(status) != 0) e(1);
80 if (getrusage(RUSAGE_CHILDREN, &r_usage3) != 0) e(1);
81 CHECK_NOT_ZERO_FIELD(r_usage3, ru_utime.tv_sec);
86 * Test the wait4 system call with good and bad rusage pointers, and with the
87 * wait4 either being satisfied immediately or blocking until the child exits:
88 * - mode 0: child has exited when parent calls wait4;
89 * - mode 1: parent blocks waiting for child, using a bad rusage pointer;
90 * - mode 2: parent blocks waiting for child, using a good rusage pointer.
92 static void
93 sub75b(int mode, void * bad_ptr)
95 struct rusage r_usage;
96 pid_t pid;
97 int status;
99 pid = fork();
101 switch (pid) {
102 case -1:
103 e(0);
104 break;
105 case 0:
106 if (mode != 0)
107 spin();
108 exit(0);
109 default:
110 if (mode == 0)
111 sleep(1);
113 if (mode != 2) {
115 * Try with a bad pointer. This call may fail only
116 * once the child has exited, but it must not clean up
117 * the child.
119 if (wait4(-1, &status, 0, bad_ptr) != -1) e(0);
120 if (errno != EFAULT) e(0);
123 r_usage.ru_nsignals = 1234; /* see if it's written at all */
125 /* Wait for the actual process. */
126 if (wait4(-1, &status, 0, &r_usage) != pid) e(0);
127 if (!WIFEXITED(status)) e(0);
128 if (WEXITSTATUS(status) != 0) e(0);
130 if (r_usage.ru_nsignals != 0) e(0);
132 /* Only check for actual time spent if the child spun. */
133 if (mode != 0)
134 CHECK_NOT_ZERO_FIELD(r_usage, ru_utime.tv_sec);
139 * Test wait4().
141 static void
142 test75b(void)
144 void *ptr;
146 if ((ptr = mmap(NULL, sizeof(struct rusage), PROT_READ,
147 MAP_PRIVATE | MAP_ANON, -1, 0)) == MAP_FAILED) e(0);
148 if (munmap(ptr, sizeof(struct rusage)) != 0) e(0);
149 /* "ptr" is now a known-bad pointer */
151 sub75b(0, ptr);
152 sub75b(1, ptr);
153 sub75b(2, NULL);
157 main(int argc, char *argv[])
160 start(75);
162 test75a();
163 test75b();
165 quit();
167 return 0;