pipetest.c revision 07e2e433c27fb8c0bebe2b6b2f0865f3314aaeca
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
27static 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
37static int _close(int fd) {
38    int ret;
39    printf("%d: close(%d)\n", gettid(), fd);
40    ret = close(fd);
41    printf("%d: close(%d) = %d\n", gettid(), fd, ret);
42    if (ret) printf("\terr %d (%s)\n", errno, strerror(errno));
43    return ret;
44}
45
46static int _poll(struct pollfd *ufds, nfds_t nfds, int timeout) {
47    int ret;
48    unsigned int i;
49    printf("%d: poll()\n", gettid());
50    ret = poll(ufds, nfds, timeout);
51    printf("%d: poll() = %d\n", gettid(), ret);
52    if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
53    if (ret > 0) {
54        for (i=0; i<nfds; i++) {
55            if (ufds[i].revents) {
56                printf("\tfd %d ", ufds[i].fd); print_events(ufds[i].revents);
57            }
58        }
59    }
60    return ret;
61}
62
63static int _write(int fd, char *buf, int len) {
64    int ret;
65
66    printf("%d: write(%d)\n", gettid(), fd);
67    ret = write(fd, buf, len);
68    printf("%d: write(%d) = %d\n", gettid(), fd, ret);
69    if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
70
71    return ret;
72}
73
74static int _shutdown(int fd, int how) {
75    int ret;
76
77    printf("%d: shutdown(%d)\n", gettid(), fd);
78    ret = shutdown(fd, how);
79    printf("%d: shutdown(%d) = %d\n", gettid(), fd, ret);
80    if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno));
81
82    return ret;
83}
84static void thread_poll(void *args) {
85    int fd = (int)args;
86    struct pollfd pfd;
87    printf("%d: START\n", gettid());
88    pfd.fd = fd;
89    pfd.events = 0;
90    _poll(&pfd, 1, -1);
91    printf("%d: END\n", gettid());
92}
93
94static void thread_pollin(void *args) {
95    int fd = (int)args;
96    struct pollfd pfd;
97    printf("%d: START\n", gettid());
98    pfd.fd = fd;
99    pfd.events = POLLIN;
100    _poll(&pfd, 1, -1);
101    printf("%d: END\n", gettid());
102}
103
104static void thread_close(void *args) {
105    int fd = (int)args;
106    printf("%d: START\n", gettid());
107    _close(fd);
108    printf("%d: END\n", gettid());
109}
110
111static int do_poll_poll_close() {
112    pthread_t t1;
113    pthread_t t2;
114    int fd[2];
115
116    if (pipe(fd)) return -1;
117
118    pthread_create(&t1, NULL, (void *)thread_poll, NULL);
119    pthread_create(&t2, NULL, (void *)thread_poll, NULL);
120
121    sleep(1);
122
123    _close(fd[1]);
124
125    pthread_join(t1, NULL);
126    pthread_join(t2, NULL);
127
128    return 0;
129}
130
131static int do_pipe_pipe_pipe() {
132    int fd[2];
133    int i;
134
135    while (1) {
136        if (pipe(fd)) {
137            printf("pipe: %s\n", strerror(errno));
138            return -1;
139        }
140        printf("%d %d\n", fd[0], fd[1]);
141        close(fd[0]);
142        close(fd[1]);
143    }
144
145    return 0;
146}
147static int do_pollin_pollin_write() {
148    pthread_t t1;
149    pthread_t t2;
150    int fd[2];
151    char buf = 'a';
152    int i;
153
154    if (pipe(fd)) return -1;
155
156    pthread_create(&t1, NULL, (void *)thread_pollin, (void *)fd[0]);
157    pthread_create(&t2, NULL, (void *)thread_pollin, (void *)fd[0]);
158
159    sleep(1);
160
161    for (i = 0; i < 100; i++)
162        _write(fd[1], &buf, 1);
163
164    pthread_join(t1, NULL);
165    pthread_join(t2, NULL);
166
167    return 0;
168}
169
170static int do_poll_poll_shutdown() {
171#if 0
172    pthread_t t1;
173    pthread_t t2;
174    int fd[2];
175
176    if (pipe(fd)) return -1;
177
178    pthread_create(&t1, NULL, (void *)thread_poll, (void *)fd[0]);
179    pthread_create(&t2, NULL, (void *)thread_poll, (void *)fd[0]);
180
181    sleep(1);
182
183    _shutdown(fd[1], SHUT_RDWR);
184
185    pthread_join(t1, NULL);
186    pthread_join(t2, NULL);
187#endif
188
189    return -1;
190}
191
192static int THREADS = 100;
193
194static int do_close_poll_poll_poll() {
195    pthread_t t[THREADS];
196    int i;
197    int fd[2];
198
199    if (pipe(fd)) return -1;
200
201    _close(fd[1]);
202
203    for (i = 0; i < THREADS; i++)
204        pthread_create(&t[i], NULL, (void *)thread_poll, (void *)fd[0]);
205
206    for (i = 0; i < THREADS; i++)
207        pthread_join(t[i], NULL);
208
209    return 0;
210}
211
212static int do_close_close_close() {
213    pthread_t t[THREADS];
214    int i;
215    int fd[2];
216
217    if (pipe(fd)) return -1;
218
219    for (i = 0; i < THREADS; i++)
220        pthread_create(&t[i], NULL, (void *)thread_close, (void *)fd[i%2]);
221
222    return 0;
223}
224
225static int pipe_close_w_close_r_repeat() {
226    int fd[2];
227    pthread_t t;
228    int i;
229
230    for (i = 0; i < THREADS; i++) {
231        if (pipe(fd)) return -1;
232        pthread_create(&t, NULL, (void *)thread_poll, (void *)fd[0]);
233        _close(fd[1]);
234        _close(fd[0]);
235        pthread_join(t, NULL);
236    }
237
238    return 0;
239}
240
241struct {
242    char *name;
243    int (*ptr)();
244} function_table[]  = {
245    {"pipe_pipe_pipe", do_pipe_pipe_pipe},
246    {"poll_poll_close", do_poll_poll_close},
247    {"pollin_pollin_write", do_pollin_pollin_write},
248    {"poll_poll_shutdown", do_poll_poll_shutdown},
249    {"close_poll_poll_poll", do_close_poll_poll_poll},
250    {"close_close_close", do_close_close_close},
251    {"pipe_close_w_close_w_repeat", pipe_close_w_close_r_repeat},
252    {NULL, NULL},
253};
254
255static void usage() {
256    int i;
257
258    printf("Usage:\n");
259    for (i = 0; function_table[i].name; i++) {
260        printf("\tpipetest %s\n", function_table[i].name);
261    }
262}
263
264int main(int argc, char **argv) {
265    int i;
266
267    if (argc != 2) {
268        usage();
269        return -1;
270    }
271    for (i = 0; function_table[i].name; i++) {
272        if (!strcmp(argv[1], function_table[i].name)) {
273            printf("%s\n", function_table[i].name);
274            return (*function_table[i].ptr)();
275        }
276    }
277    usage();
278    return -1;
279}
280