1 /* asyn_wait() - wait for asynch operations Author: Kees J. Bot 2 * 7 Jul 1997 3 */ 4 #define DEBUG 0 5 6 #include "asyn.h" 7 #include <time.h> 8 #if DEBUG 9 #include <stdio.h> 10 #endif 11 12 #define TBOUND_MIN 1 13 #define TBOUND_MAX 16 14 15 int asyn_wait(asynchio_t *asyn, int flags, struct timeval *to) 16 /* Wait for one or more nonblocking operations to return a result. */ 17 { 18 int r; 19 static struct timeval zero_time; 20 struct timeval t; 21 static time_t tbound= TBOUND_MIN; 22 23 /* Are there more things to do before we can block? */ 24 if (asyn->asyn_more > 0) { asyn->asyn_more= 0; return 0; } 25 26 if (flags & ASYN_NONBLOCK) { 27 /* Don't block by using a zero second timeout. */ 28 to= &zero_time; 29 } else 30 if (to != nil) { 31 /* asyn_wait() uses an absolute time. */ 32 if (to->tv_usec >= 1000000L) { 33 to->tv_sec+= to->tv_usec / 1000000L; 34 to->tv_usec%= 1000000L; 35 } 36 (void) gettimeofday(&t, nil); 37 if (t.tv_sec > to->tv_sec || (t.tv_sec == to->tv_sec 38 && t.tv_usec >= to->tv_usec)) { 39 to= &zero_time; 40 } else { 41 t.tv_sec= to->tv_sec - t.tv_sec; 42 t.tv_usec= to->tv_usec - t.tv_usec; 43 if (t.tv_usec < 0) { 44 t.tv_sec--; 45 t.tv_usec+= 1000000L; 46 } 47 to= &t; 48 } 49 50 /* Don't sleep too long, we don't trust select(). */ 51 if (to->tv_sec > tbound) goto bound; 52 } else { 53 bound: 54 /* No timeout? Don't hang in (buggy?) select() forever. */ 55 to= &t; 56 t.tv_sec= tbound; 57 t.tv_usec= 0; 58 } 59 60 #if DEBUG 61 { 62 int op; 63 64 fprintf(stderr, "select: "); 65 for (op= 0; op < SEL_NR; op++) { 66 fd_set *fdsetp= &asyn->asyn_fdset[op]; 67 int fd; 68 69 for (fd= 0; fd < FD_SETSIZE; fd++) { 70 if (FD_ISSET(fd, fdsetp)) { 71 asyn->asyn_afd[fd].afd_state[op]= 72 PENDING; 73 fprintf(stderr, "%d%c", fd, "rwx"[op]); 74 } 75 } 76 } 77 fflush(stderr); 78 } 79 #endif 80 r= select(FD_SETSIZE, &asyn->asyn_fdset[SEL_READ], 81 &asyn->asyn_fdset[SEL_WRITE], 82 &asyn->asyn_fdset[SEL_EXCEPT], to); 83 #if DEBUG 84 fprintf(stderr, " (%d) ", r); 85 #endif 86 if (r > 0) { 87 /* An event occurred on one or more file descriptors. */ 88 int op; 89 90 for (op= 0; op < SEL_NR; op++) { 91 fd_set *fdsetp= &asyn->asyn_fdset[op]; 92 int fd; 93 94 for (fd= 0; fd < FD_SETSIZE; fd++) { 95 if (FD_ISSET(fd, fdsetp)) { 96 asyn->asyn_afd[fd].afd_state[op]= 97 PENDING; 98 #if DEBUG 99 fprintf(stderr, "%d%c", fd, "rwx"[op]); 100 #endif 101 } 102 } 103 } 104 tbound= TBOUND_MIN; 105 } else 106 if (r == 0) { 107 /* If nothing happened then let the time boundary slip a bit. */ 108 if (tbound < TBOUND_MAX) tbound <<= 1; 109 } 110 #if DEBUG 111 fputc('\n', stderr); 112 #endif 113 114 FD_ZERO(&asyn->asyn_fdset[SEL_READ]); 115 FD_ZERO(&asyn->asyn_fdset[SEL_WRITE]); 116 FD_ZERO(&asyn->asyn_fdset[SEL_EXCEPT]); 117 118 return r == 0 ? (errno= EINTR, -1) : r; 119 } 120