Home | History | Annotate | Download | only in tools
      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 
     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 
     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 
     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 
     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 
     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 
     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 
     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 }
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 }
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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