pkgin_all: script to auto-install all packages
[minix.git] / lib / libasyn / asyn_wait.c
blobc71e5d074a5260253b2d2efcac186618773b0f91
1 /* asyn_wait() - wait for asynch operations Author: Kees J. Bot
2 * 7 Jul 1997
3 */
4 #define DEBUG 0
6 #include "asyn.h"
7 #include <time.h>
8 #if DEBUG
9 #include <stdio.h>
10 #endif
12 #define TBOUND_MIN 1
13 #define TBOUND_MAX 16
15 int asyn_wait(asynchio_t *asyn, int flags, struct timeval *to)
16 /* Wait for one or more nonblocking operations to return a result. */
18 int r;
19 static struct timeval zero_time;
20 struct timeval t;
21 static time_t tbound= TBOUND_MIN;
23 /* Are there more things to do before we can block? */
24 if (asyn->asyn_more > 0) { asyn->asyn_more= 0; return 0; }
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;
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;
47 to= &t;
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;
60 #if DEBUG
62 int op;
64 fprintf(stderr, "select: ");
65 for (op= 0; op < SEL_NR; op++) {
66 fd_set *fdsetp= &asyn->asyn_fdset[op];
67 int fd;
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]);
77 fflush(stderr);
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;
90 for (op= 0; op < SEL_NR; op++) {
91 fd_set *fdsetp= &asyn->asyn_fdset[op];
92 int fd;
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
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;
110 #if DEBUG
111 fputc('\n', stderr);
112 #endif
114 FD_ZERO(&asyn->asyn_fdset[SEL_READ]);
115 FD_ZERO(&asyn->asyn_fdset[SEL_WRITE]);
116 FD_ZERO(&asyn->asyn_fdset[SEL_EXCEPT]);
118 return r == 0 ? (errno= EINTR, -1) : r;