Merge branch 'issue-699' into 'master'
[glib.git] / tests / timeloop-basic.c
blobd2bc41eec54965b3feb3040ac380589d1a518c60
1 #undef G_DISABLE_ASSERT
2 #undef G_LOG_DOMAIN
4 #include <errno.h>
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <sys/resource.h>
10 #include <sys/time.h>
11 #include <poll.h>
13 #define TRUE 1
14 #define FALSE 0
16 static int n_children = 3;
17 static int n_active_children;
18 static int n_iters = 10000;
20 static int write_fds[1024];
21 static struct pollfd poll_fds[1024];
23 void
24 my_pipe (int *fds)
26 if (pipe(fds) < 0)
28 int errsv = errno;
29 fprintf (stderr, "Cannot create pipe %s\n", strerror (errsv));
30 exit (1);
34 int
35 read_all (int fd, char *buf, int len)
37 size_t bytes_read = 0;
38 gssize count;
40 while (bytes_read < len)
42 count = read (fd, buf + bytes_read, len - bytes_read);
43 if (count < 0)
45 if (errno != EAGAIN)
46 return FALSE;
48 else if (count == 0)
49 return FALSE;
51 bytes_read += count;
54 return TRUE;
57 int
58 write_all (int fd, char *buf, int len)
60 size_t bytes_written = 0;
61 gssize count;
63 while (bytes_written < len)
65 count = write (fd, buf + bytes_written, len - bytes_written);
66 if (count < 0)
68 if (errno != EAGAIN)
69 return FALSE;
72 bytes_written += count;
75 return TRUE;
78 void
79 run_child (int in_fd, int out_fd)
81 int i;
82 int val = 1;
84 for (i = 0; i < n_iters; i++)
86 write_all (out_fd, (char *)&val, sizeof (val));
87 read_all (in_fd, (char *)&val, sizeof (val));
90 val = 0;
91 write_all (out_fd, (char *)&val, sizeof (val));
93 exit (0);
96 int
97 input_callback (int source, int dest)
99 int val;
101 if (!read_all (source, (char *)&val, sizeof(val)))
103 fprintf (stderr,"Unexpected EOF\n");
104 exit (1);
107 if (val)
109 write_all (dest, (char *)&val, sizeof(val));
110 return TRUE;
112 else
114 close (source);
115 close (dest);
117 n_active_children--;
118 return FALSE;
122 void
123 create_child (int pos)
125 int pid, errsv;
126 int in_fds[2];
127 int out_fds[2];
129 my_pipe (in_fds);
130 my_pipe (out_fds);
132 pid = fork ();
133 errsv = errno;
135 if (pid > 0) /* Parent */
137 close (in_fds[0]);
138 close (out_fds[1]);
140 write_fds[pos] = in_fds[1];
141 poll_fds[pos].fd = out_fds[0];
142 poll_fds[pos].events = POLLIN;
144 else if (pid == 0) /* Child */
146 close (in_fds[1]);
147 close (out_fds[0]);
149 setsid ();
151 run_child (in_fds[0], out_fds[1]);
153 else /* Error */
155 fprintf (stderr,"Cannot fork: %s\n", strerror (errsv));
156 exit (1);
160 static double
161 difftimeval (struct timeval *old, struct timeval *new)
163 return
164 (new->tv_sec - old->tv_sec) * 1000. + (new->tv_usec - old->tv_usec) / 1000;
167 int
168 main (int argc, char **argv)
170 int i, j;
171 struct rusage old_usage;
172 struct rusage new_usage;
174 if (argc > 1)
175 n_children = atoi(argv[1]);
177 if (argc > 2)
178 n_iters = atoi(argv[2]);
180 printf ("Children: %d Iters: %d\n", n_children, n_iters);
182 n_active_children = n_children;
183 for (i = 0; i < n_children; i++)
184 create_child (i);
186 getrusage (RUSAGE_SELF, &old_usage);
188 while (n_active_children > 0)
190 int old_n_active_children = n_active_children;
192 poll (poll_fds, n_active_children, -1);
194 for (i=0; i<n_active_children; i++)
196 if (poll_fds[i].events & (POLLIN | POLLHUP))
198 if (!input_callback (poll_fds[i].fd, write_fds[i]))
199 write_fds[i] = -1;
203 if (old_n_active_children > n_active_children)
205 j = 0;
206 for (i=0; i<old_n_active_children; i++)
208 if (write_fds[i] != -1)
210 if (j < i)
212 poll_fds[j] = poll_fds[i];
213 write_fds[j] = write_fds[i];
215 j++;
221 getrusage (RUSAGE_SELF, &new_usage);
223 printf ("Elapsed user: %g\n",
224 difftimeval (&old_usage.ru_utime, &new_usage.ru_utime));
225 printf ("Elapsed system: %g\n",
226 difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
227 printf ("Elapsed total: %g\n",
228 difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +
229 difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
230 printf ("total / iteration: %g\n",
231 (difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +
232 difftimeval (&old_usage.ru_stime, &new_usage.ru_stime)) /
233 (n_iters * n_children));
235 return 0;