1 /*
2 * Copyright 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /* Helper to test linux pipe's */
18
19 #include <pthread.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <errno.h>
23 #include <unistd.h>
24 #include <sys/poll.h>
25 #include <sys/socket.h>
26
print_events(int events)27 static void print_events(int events) {
28 if (events & POLLIN) printf("POLLIN ");
29 if (events & POLLPRI) printf("POLLPRI ");
30 if (events & POLLOUT) printf("POLLOUT ");
31 if (events & POLLERR) printf("POLLERR ");
32 if (events & POLLHUP) printf("POLLHUP ");
33 if (events & POLLNVAL) printf("POLLNVAL ");
34 printf("\n");
35 }
36
_socketpair(int fd[2])37 static int _socketpair(int fd[2]) {
38 int ret;
39 printf("%d: socketpair()\n", gettid());
40 ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
41 printf("%d: socketpair() = %d\n", gettid(), ret);
42 if (ret) printf("\terr %d (%s)\n", errno, strerror(errno));
43 return ret;
44 }
45
_close(int fd)46 static int _close(int fd) {
47 int ret;
48 printf("%d: close(%d)\n", gettid(), fd);
49 ret = close(fd);
50 printf("%d: close(%d) = %d\n", gettid(), fd, ret);
51 if (ret) printf("\terr %d (%s)\n", errno, strerror(errno));
52 return ret;
53 }
54
_poll(struct pollfd * ufds,nfds_t nfds,int timeout)55 static int _poll(struct pollfd *ufds, nfds_t nfds, int timeout) {
56 int ret;
57 unsigned int i;
58 printf("%d: poll()\n", gettid());
59 ret = poll(ufds, nfds, timeout);
60 printf("%d: poll() = %d\n", gettid(), ret);
61 if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
62 if (ret > 0) {
63 for (i=0; i<nfds; i++) {
64 if (ufds[i].revents) {
65 printf("\tfd %d ", ufds[i].fd); print_events(ufds[i].revents);
66 }
67 }
68 }
69 return ret;
70 }
71
_write(int fd,char * buf,int len)72 static int _write(int fd, char *buf, int len) {
73 int ret;
74
75 printf("%d: write(%d)\n", gettid(), fd);
76 ret = write(fd, buf, len);
77 printf("%d: write(%d) = %d\n", gettid(), fd, ret);
78 if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
79
80 return ret;
81 }
82
_read(int fd)83 static int _read(int fd) {
84 int ret;
85 char buf;
86
87 printf("%d: read(%d)\n", gettid(), fd);
88 ret = read(fd, &buf, 1);
89 printf("%d: read(%d) = %d [%d]\n", gettid(), fd, ret, (int)buf);
90 if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
91
92 return ret;
93 }
94
_shutdown(int fd,int how)95 static int _shutdown(int fd, int how) {
96 int ret;
97
98 printf("%d: shutdown(%d)\n", gettid(), fd);
99 ret = shutdown(fd, how);
100 printf("%d: shutdown(%d) = %d\n", gettid(), fd, ret);
101 if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
102
103 return ret;
104 }
thread_poll(void * args)105 static void thread_poll(void *args) {
106 int fd = (int)args;
107 struct pollfd pfd;
108 printf("%d: START\n", gettid());
109 pfd.fd = fd;
110 pfd.events = 0;
111 _poll(&pfd, 1, -1);
112 printf("%d: END\n", gettid());
113 }
114
thread_pollin(void * args)115 static void thread_pollin(void *args) {
116 int fd = (int)args;
117 struct pollfd pfd;
118 printf("%d: START\n", gettid());
119 pfd.fd = fd;
120 pfd.events = POLLIN;
121 _poll(&pfd, 1, -1);
122 printf("%d: END\n", gettid());
123 }
124
thread_pollin_rand_delay(void * args)125 static void thread_pollin_rand_delay(void *args) {
126 int fd = (int)args;
127 struct pollfd pfd;
128 int delay = (int)((double)random() * (10000000.0 / 2147483647.0));
129 printf("%d: START (delay = %d)\n", gettid(), delay);
130 pfd.fd = fd;
131 pfd.events = POLLIN;
132 usleep(delay);
133 _poll(&pfd, 1, -1);
134 printf("%d: END\n", gettid());
135 }
136
thread_read(void * args)137 static void thread_read(void *args) {
138 int fd = (int)args;
139 printf("%d: START\n", gettid());
140 _read(fd);
141 printf("%d: END\n", gettid());
142 }
143
thread_close(void * args)144 static void thread_close(void *args) {
145 int fd = (int)args;
146 printf("%d: START\n", gettid());
147 _close(fd);
148 printf("%d: END\n", gettid());
149 }
150
do_poll_poll_close()151 static int do_poll_poll_close() {
152 pthread_t t1;
153 pthread_t t2;
154 int fd[2];
155
156 if (pipe(fd)) return -1;
157
158 pthread_create(&t1, NULL, (void *)thread_poll, NULL);
159 pthread_create(&t2, NULL, (void *)thread_poll, NULL);
160
161 sleep(1);
162
163 _close(fd[1]);
164
165 pthread_join(t1, NULL);
166 pthread_join(t2, NULL);
167
168 return 0;
169 }
170
do_socketpair_poll1_shutdown2()171 static int do_socketpair_poll1_shutdown2() {
172 int fd[2];
173 pthread_t t;
174
175 if (_socketpair(fd)) return -1;
176
177 pthread_create(&t, NULL, (void *)thread_poll, (void *)fd[1]);
178
179 sleep(1);
180
181 _shutdown(fd[0], SHUT_RDWR);
182
183 sleep(1);
184
185 _close(fd[0]);
186
187 pthread_join(t, NULL);
188
189 return 0;
190 }
191
do_socketpair_poll1_shutdown1()192 static int do_socketpair_poll1_shutdown1() {
193 int fd[2];
194 pthread_t t;
195
196 if (_socketpair(fd)) return -1;
197
198 pthread_create(&t, NULL, (void *)thread_poll, (void *)fd[0]);
199
200 sleep(1);
201
202 _shutdown(fd[0], SHUT_RDWR);
203
204 sleep(1);
205
206 _close(fd[0]);
207
208 pthread_join(t, NULL);
209
210 return 0;
211 }
212
do_socketpair_poll1_close1()213 static int do_socketpair_poll1_close1() {
214 int fd[2];
215 pthread_t t;
216
217 if (_socketpair(fd)) return -1;
218
219 pthread_create(&t, NULL, (void *)thread_poll, (void *)fd[0]);
220
221 sleep(1);
222
223 _close(fd[0]);
224
225 pthread_join(t, NULL);
226
227 return 0;
228 }
229
do_socketpair_read1_shutdown1()230 static int do_socketpair_read1_shutdown1() {
231 int fd[2];
232 pthread_t t;
233
234 if (_socketpair(fd)) return -1;
235
236 pthread_create(&t, NULL, (void *)thread_read, (void *)fd[0]);
237
238 sleep(1);
239
240 _shutdown(fd[0], SHUT_RDWR);
241
242 sleep(1);
243
244 _close(fd[0]);
245
246 pthread_join(t, NULL);
247
248 return 0;
249 }
250
do_pipe_pipe_pipe()251 static int do_pipe_pipe_pipe() {
252 int fd[2];
253 int i;
254
255 while (1) {
256 if (pipe(fd)) {
257 printf("pipe: %s\n", strerror(errno));
258 return -1;
259 }
260 printf("%d %d\n", fd[0], fd[1]);
261 close(fd[0]);
262 close(fd[1]);
263 }
264
265 return 0;
266 }
do_pollin_pollin_write()267 static int do_pollin_pollin_write() {
268 pthread_t t1;
269 pthread_t t2;
270 int fd[2];
271 char buf = 'a';
272 int i;
273
274 if (pipe(fd)) return -1;
275
276 pthread_create(&t1, NULL, (void *)thread_pollin, (void *)fd[0]);
277 pthread_create(&t2, NULL, (void *)thread_pollin, (void *)fd[0]);
278
279 sleep(1);
280
281 for (i = 0; i < 100; i++)
282 _write(fd[1], &buf, 1);
283
284 pthread_join(t1, NULL);
285 pthread_join(t2, NULL);
286
287 return 0;
288 }
289
do_pollin_pollin_pollin_write_pollin_pollin_pollin()290 static int do_pollin_pollin_pollin_write_pollin_pollin_pollin() {
291 const int MAX_T = 10;
292 pthread_t t[MAX_T];
293 int fd[2];
294 char buf = 'a';
295 int i;
296
297 if (pipe(fd)) return -1;
298
299 for (i=0; i<MAX_T; i++)
300 pthread_create(&t[i], NULL, (void *)thread_pollin_rand_delay, (void *)fd[0]);
301
302 sleep(5);
303
304 _write(fd[1], &buf, 1);
305
306 for (i=0; i<MAX_T; i++)
307 pthread_join(t[i], NULL);
308
309 _close(fd[0]);
310 _close(fd[1]);
311
312 return 0;
313 }
314
do_poll_poll_shutdown()315 static int do_poll_poll_shutdown() {
316 #if 0
317 pthread_t t1;
318 pthread_t t2;
319 int fd[2];
320
321 if (pipe(fd)) return -1;
322
323 pthread_create(&t1, NULL, (void *)thread_poll, (void *)fd[0]);
324 pthread_create(&t2, NULL, (void *)thread_poll, (void *)fd[0]);
325
326 sleep(1);
327
328 _shutdown(fd[1], SHUT_RDWR);
329
330 pthread_join(t1, NULL);
331 pthread_join(t2, NULL);
332 #endif
333
334 return -1;
335 }
336
337 static int THREADS = 100;
338
do_close_poll_poll_poll()339 static int do_close_poll_poll_poll() {
340 pthread_t t[THREADS];
341 int i;
342 int fd[2];
343
344 if (pipe(fd)) return -1;
345
346 _close(fd[1]);
347
348 for (i = 0; i < THREADS; i++)
349 pthread_create(&t[i], NULL, (void *)thread_poll, (void *)fd[0]);
350
351 for (i = 0; i < THREADS; i++)
352 pthread_join(t[i], NULL);
353
354 return 0;
355 }
356
do_close_close_close()357 static int do_close_close_close() {
358 pthread_t t[THREADS];
359 int i;
360 int fd[2];
361
362 if (pipe(fd)) return -1;
363
364 for (i = 0; i < THREADS; i++)
365 pthread_create(&t[i], NULL, (void *)thread_close, (void *)fd[i%2]);
366
367 return 0;
368 }
369
pipe_close_w_close_r_repeat()370 static int pipe_close_w_close_r_repeat() {
371 int fd[2];
372 pthread_t t;
373 int i;
374
375 for (i = 0; i < THREADS; i++) {
376 if (pipe(fd)) return -1;
377 pthread_create(&t, NULL, (void *)thread_poll, (void *)fd[0]);
378 _close(fd[1]);
379 _close(fd[0]);
380 pthread_join(t, NULL);
381 }
382
383 return 0;
384 }
385
386 struct {
387 char *name;
388 int (*ptr)();
389 } function_table[] = {
390 {"socketpair_poll1_shutdown2", do_socketpair_poll1_shutdown2},
391 {"socketpair_poll1_shutdown1", do_socketpair_poll1_shutdown1},
392 {"socketpair_poll1_close1", do_socketpair_poll1_close1},
393 {"socketpair_read1_shutdown1", do_socketpair_read1_shutdown1},
394 {"pipe_pipe_pipe", do_pipe_pipe_pipe},
395 {"poll_poll_close", do_poll_poll_close},
396 {"pollin_pollin_write", do_pollin_pollin_write},
397 {"pollin_pollin_pollin_write_pollin_pollin_pollin", do_pollin_pollin_pollin_write_pollin_pollin_pollin},
398 {"poll_poll_shutdown", do_poll_poll_shutdown},
399 {"close_poll_poll_poll", do_close_poll_poll_poll},
400 {"close_close_close", do_close_close_close},
401 {"pipe_close_w_close_w_repeat", pipe_close_w_close_r_repeat},
402 {NULL, NULL},
403 };
404
usage()405 static void usage() {
406 int i;
407
408 printf("Usage:\n");
409 for (i = 0; function_table[i].name; i++) {
410 printf("\tpipetest %s\n", function_table[i].name);
411 }
412 }
413
main(int argc,char ** argv)414 int main(int argc, char **argv) {
415 int i;
416
417 if (argc != 2) {
418 usage();
419 return -1;
420 }
421 for (i = 0; function_table[i].name; i++) {
422 if (!strcmp(argv[1], function_table[i].name)) {
423 printf("%s\n", function_table[i].name);
424 return (*function_table[i].ptr)();
425 }
426 }
427 usage();
428 return -1;
429 }
430