nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | #undef G_DISABLE_ASSERT |
2 | #undef G_LOG_DOMAIN |
||
3 | |||
4 | #include <errno.h> |
||
5 | #include <stdlib.h> |
||
6 | #include <unistd.h> |
||
7 | #include <stdio.h> |
||
8 | #include <sys/time.h> |
||
9 | #include <sys/resource.h> |
||
10 | |||
11 | #include <glib.h> |
||
12 | |||
13 | static int n_children = 3; |
||
14 | static int n_active_children; |
||
15 | static int n_iters = 10000; |
||
16 | static GMainLoop *loop; |
||
17 | |||
18 | static void |
||
19 | io_pipe (GIOChannel **channels) |
||
20 | { |
||
21 | int fds[2]; |
||
22 | |||
23 | if (pipe(fds) < 0) |
||
24 | { |
||
25 | fprintf (stderr, "Cannot create pipe %s\n", g_strerror (errno)); |
||
26 | exit (1); |
||
27 | } |
||
28 | |||
29 | channels[0] = g_io_channel_unix_new (fds[0]); |
||
30 | channels[1] = g_io_channel_unix_new (fds[1]); |
||
31 | } |
||
32 | |||
33 | static gboolean |
||
34 | read_all (GIOChannel *channel, char *buf, int len) |
||
35 | { |
||
36 | gsize bytes_read = 0; |
||
37 | gsize count; |
||
38 | GIOError err; |
||
39 | |||
40 | while (bytes_read < len) |
||
41 | { |
||
42 | err = g_io_channel_read (channel, buf + bytes_read, len - bytes_read, &count); |
||
43 | if (err) |
||
44 | { |
||
45 | if (err != G_IO_ERROR_AGAIN) |
||
46 | return FALSE; |
||
47 | } |
||
48 | else if (count == 0) |
||
49 | return FALSE; |
||
50 | |||
51 | bytes_read += count; |
||
52 | } |
||
53 | |||
54 | return TRUE; |
||
55 | } |
||
56 | |||
57 | static gboolean |
||
58 | write_all (GIOChannel *channel, char *buf, int len) |
||
59 | { |
||
60 | gsize bytes_written = 0; |
||
61 | gsize count; |
||
62 | GIOError err; |
||
63 | |||
64 | while (bytes_written < len) |
||
65 | { |
||
66 | err = g_io_channel_write (channel, buf + bytes_written, len - bytes_written, &count); |
||
67 | if (err && err != G_IO_ERROR_AGAIN) |
||
68 | return FALSE; |
||
69 | |||
70 | bytes_written += count; |
||
71 | } |
||
72 | |||
73 | return TRUE; |
||
74 | } |
||
75 | |||
76 | static void |
||
77 | run_child (GIOChannel *in_channel, GIOChannel *out_channel) |
||
78 | { |
||
79 | int i; |
||
80 | int val = 1; |
||
81 | GTimer *timer = g_timer_new(); |
||
82 | |||
83 | for (i = 0; i < n_iters; i++) |
||
84 | { |
||
85 | write_all (out_channel, (char *)&val, sizeof (val)); |
||
86 | read_all (in_channel, (char *)&val, sizeof (val)); |
||
87 | } |
||
88 | |||
89 | val = 0; |
||
90 | write_all (out_channel, (char *)&val, sizeof (val)); |
||
91 | |||
92 | val = g_timer_elapsed (timer, NULL) * 1000; |
||
93 | |||
94 | write_all (out_channel, (char *)&val, sizeof (val)); |
||
95 | g_timer_destroy (timer); |
||
96 | |||
97 | exit (0); |
||
98 | } |
||
99 | |||
100 | static gboolean |
||
101 | input_callback (GIOChannel *source, |
||
102 | GIOCondition condition, |
||
103 | gpointer data) |
||
104 | { |
||
105 | int val; |
||
106 | GIOChannel *dest = (GIOChannel *)data; |
||
107 | |||
108 | if (!read_all (source, (char *)&val, sizeof(val))) |
||
109 | { |
||
110 | fprintf (stderr, "Unexpected EOF\n"); |
||
111 | exit (1); |
||
112 | } |
||
113 | |||
114 | if (val) |
||
115 | { |
||
116 | write_all (dest, (char *)&val, sizeof(val)); |
||
117 | |||
118 | return TRUE; |
||
119 | } |
||
120 | else |
||
121 | { |
||
122 | g_io_channel_close (source); |
||
123 | g_io_channel_close (dest); |
||
124 | |||
125 | g_io_channel_unref (source); |
||
126 | g_io_channel_unref (dest); |
||
127 | |||
128 | n_active_children--; |
||
129 | if (n_active_children == 0) |
||
130 | g_main_loop_quit (loop); |
||
131 | |||
132 | return FALSE; |
||
133 | } |
||
134 | } |
||
135 | |||
136 | static void |
||
137 | create_child (void) |
||
138 | { |
||
139 | int pid; |
||
140 | GIOChannel *in_channels[2]; |
||
141 | GIOChannel *out_channels[2]; |
||
142 | |||
143 | io_pipe (in_channels); |
||
144 | io_pipe (out_channels); |
||
145 | |||
146 | pid = fork (); |
||
147 | |||
148 | if (pid > 0) /* Parent */ |
||
149 | { |
||
150 | g_io_channel_close (in_channels[0]); |
||
151 | g_io_channel_unref (in_channels[0]); |
||
152 | g_io_channel_close (out_channels[1]); |
||
153 | g_io_channel_unref (out_channels[1]); |
||
154 | |||
155 | g_io_add_watch (out_channels[0], G_IO_IN | G_IO_HUP, |
||
156 | input_callback, in_channels[1]); |
||
157 | } |
||
158 | else if (pid == 0) /* Child */ |
||
159 | { |
||
160 | g_io_channel_close (in_channels[1]); |
||
161 | g_io_channel_close (out_channels[0]); |
||
162 | |||
163 | setsid (); |
||
164 | |||
165 | run_child (in_channels[0], out_channels[1]); |
||
166 | } |
||
167 | else /* Error */ |
||
168 | { |
||
169 | fprintf (stderr, "Cannot fork: %s\n", g_strerror (errno)); |
||
170 | exit (1); |
||
171 | } |
||
172 | } |
||
173 | |||
174 | static double |
||
175 | difftimeval (struct timeval *old, struct timeval *new) |
||
176 | { |
||
177 | return |
||
178 | (new->tv_sec - old->tv_sec) * 1000. + (new->tv_usec - old->tv_usec) / 1000; |
||
179 | } |
||
180 | |||
181 | int |
||
182 | main (int argc, char **argv) |
||
183 | { |
||
184 | int i; |
||
185 | struct rusage old_usage; |
||
186 | struct rusage new_usage; |
||
187 | |||
188 | if (argc > 1) |
||
189 | n_children = atoi(argv[1]); |
||
190 | |||
191 | if (argc > 2) |
||
192 | n_iters = atoi(argv[2]); |
||
193 | |||
194 | printf ("Children: %d Iters: %d\n", n_children, n_iters); |
||
195 | |||
196 | n_active_children = n_children; |
||
197 | for (i = 0; i < n_children; i++) |
||
198 | create_child (); |
||
199 | |||
200 | getrusage (RUSAGE_SELF, &old_usage); |
||
201 | loop = g_main_loop_new (NULL, FALSE); |
||
202 | g_main_loop_run (loop); |
||
203 | getrusage (RUSAGE_SELF, &new_usage); |
||
204 | |||
205 | printf ("Elapsed user: %g\n", |
||
206 | difftimeval (&old_usage.ru_utime, &new_usage.ru_utime)); |
||
207 | printf ("Elapsed system: %g\n", |
||
208 | difftimeval (&old_usage.ru_stime, &new_usage.ru_stime)); |
||
209 | printf ("Elapsed total: %g\n", |
||
210 | difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) + |
||
211 | difftimeval (&old_usage.ru_stime, &new_usage.ru_stime)); |
||
212 | printf ("total / iteration: %g\n", |
||
213 | (difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) + |
||
214 | difftimeval (&old_usage.ru_stime, &new_usage.ru_stime)) / |
||
215 | (n_iters * n_children)); |
||
216 | |||
217 | g_main_loop_unref (loop); |
||
218 | return 0; |
||
219 | } |