• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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