pipetest.c revision 47653588a022190d4b3e20194ef643dfb7b90632
15afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich/*
25afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich * Copyright 2009 The Android Open Source Project
35afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich *
45afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich * Licensed under the Apache License, Version 2.0 (the "License");
55afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich * you may not use this file except in compliance with the License.
65afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich * You may obtain a copy of the License at
75afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich *
85afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich *     http://www.apache.org/licenses/LICENSE-2.0
95afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich *
105afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich * Unless required by applicable law or agreed to in writing, software
115afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich * distributed under the License is distributed on an "AS IS" BASIS,
125afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich * See the License for the specific language governing permissions and
145afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich * limitations under the License.
155afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich */
165afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich
175afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich/* Helper to test linux pipe's */
185afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich
195afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich#include <pthread.h>
205afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich#include <stdlib.h>
215afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich#include <stdio.h>
225afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich#include <errno.h>
235afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich#include <unistd.h>
245afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich#include <sys/poll.h>
255afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich#include <sys/socket.h>
265afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich
275afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevichstatic void print_events(int events) {
285afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich    if (events & POLLIN) printf("POLLIN ");
295afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich    if (events & POLLPRI) printf("POLLPRI ");
305afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich    if (events & POLLOUT) printf("POLLOUT ");
315afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich    if (events & POLLERR) printf("POLLERR ");
325afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich    if (events & POLLHUP) printf("POLLHUP ");
335afdc87704f82cb6c3576695dd157b65ae6f3d33Jack Palevich    if (events & POLLNVAL) printf("POLLNVAL ");
3462d08f5bc3f975e10a593b428d88fe8977cb3bfcJack Palevich    printf("\n");
3562d08f5bc3f975e10a593b428d88fe8977cb3bfcJack Palevich}
3662d08f5bc3f975e10a593b428d88fe8977cb3bfcJack Palevich
3762d08f5bc3f975e10a593b428d88fe8977cb3bfcJack Palevichstatic int _socketpair(int fd[2]) {
3862d08f5bc3f975e10a593b428d88fe8977cb3bfcJack Palevich    int ret;
3962d08f5bc3f975e10a593b428d88fe8977cb3bfcJack Palevich    printf("%d: socketpair()\n", gettid());
4062d08f5bc3f975e10a593b428d88fe8977cb3bfcJack Palevich    ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
4162d08f5bc3f975e10a593b428d88fe8977cb3bfcJack Palevich    printf("%d: socketpair() = %d\n", gettid(), ret);
4262d08f5bc3f975e10a593b428d88fe8977cb3bfcJack Palevich    if (ret) printf("\terr %d (%s)\n", errno, strerror(errno));
43    return ret;
44}
45
46static 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
55static 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
72static 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
83static 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
95static 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}
105static 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
115static 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
125static 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
137static 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
144static 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
151static 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
171static 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
192static 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
213static 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
230static 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
251static 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}
267static 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
290static 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
315static 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
337static int THREADS = 100;
338
339static 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
357static 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
370static 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
386struct {
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
405static 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
414int 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