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