• 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