2 * Copyright (c) 1992, 1993, 1996
3 * Berkeley Software Design, Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Berkeley Software
18 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * BSDI AsyncIO.c,v 2.2 1996/04/08 19:32:10 bostic Exp
32 * $FreeBSD: src/usr.bin/doscmd/AsyncIO.c,v 1.3.2.3 2002/05/21 11:49:47 tg Exp $
35 #include <sys/param.h>
36 #include <sys/types.h>
48 #define FD_ISZERO(p) ((p)->fds_bits[0] == 0)
51 * Set or Clear the Async nature of an FD
54 #define SETASYNC(fd) fcntl(fd, F_SETFL, handlers[fd].flag | FASYNC)
55 #define CLRASYNC(fd) fcntl(fd, F_SETFL, handlers[fd].flag & ~FASYNC)
58 * Request that ``func'' be called everytime data is available on ``fd''
61 static fd_set fdset; /* File Descriptors to select on */
64 void (*func)(int, int, void *, regcontext_t *);
65 /* Function to call on data arrival */
66 void (*failure)(void *); /* Function to call on failure */
67 void *arg; /* Argument to above functions */
68 int lockcnt; /* Nested level of lock */
69 fd_set members; /* Set of FD's to disable on SIGIO */
70 int flag; /* The flag from F_GETFL (we own it) */
73 static Async handlers[OPEN_MAX];
75 static void CleanIO(void);
76 static void HandleIO(struct sigframe *sf);
79 _RegisterIO(int fd, void (*func)(int, int, void *, regcontext_t *),
80 void *arg, void (*failure)(void *))
82 static int firsttime = 1;
85 if (fd < 0 || fd > OPEN_MAX) {
86 printf("%d: Invalid FD\n", fd);
92 if ((as->flag = fcntl(fd, F_GETFL, 0)) == -1) {
94 /*@*/ perror("get fcntl");
102 setsignal(SIGIO, HandleIO);
105 if ((handlers[fd].func = func) != NULL) {
108 as->failure = failure;
111 FD_ZERO(&handlers[fd].members);
112 FD_SET(fd, &handlers[fd].members);
113 if (fcntl(fd, F_SETOWN, getpid()) < 0) {
114 /*@*/ perror("SETOWN");
131 static struct timeval tv;
134 * For every file des in fd_set, we check to see if it
135 * causes a fault on select(). If so, we unregister it
138 for (x = 0; x < OPEN_MAX; ++x) {
141 if (!FD_ISSET(x, &fdset))
147 if (select(FD_SETSIZE, &set, 0, 0, &tv) < 0 &&
151 printf("Closed file descriptor %d\n", x);
153 f = handlers[x].failure;
155 handlers[x].failure = NULL;
156 handlers[x].func = NULL;
157 handlers[x].arg = NULL;
158 handlers[x].lockcnt = 0;
167 HandleIO(struct sigframe *sf)
169 static struct timeval tv;
170 fd_set readset, writeset;
174 readset = writeset = fdset;
175 if ((x = select(FD_SETSIZE, &readset, &writeset, 0, &tv)) < 0) {
177 * If we failed because of a BADFiledes, go find
178 * which one(s), fail them out and then try a
179 * new select to see if any of the good ones are
182 if (errno == EBADF) {
184 if (FD_ISZERO(&fdset))
193 * If we run out of fds to look at, break out of the loop
194 * and exit the handler.
200 * If there is at least 1 fd saying it has something for
201 * us, then loop through the sets looking for those
202 * bits, stopping when we have handleed the number it has
205 for (fd = 0; x && fd < OPEN_MAX; fd ++) {
211 if (FD_ISSET(fd, &readset)) {
215 if (FD_ISSET(fd, &writeset)) {
224 * Is suppose it is possible that one of the previous
225 * I/O requests changed the fdset.
226 * We do know that SIGIO is turned off right now,
227 * so it is safe to checkit.
229 if (!FD_ISSET(fd, &fdset)) {
235 * as in above, maybe someone locked us...
236 * we are in dangerous water now if we are
240 fprintf(stderr, "Selected IO on locked %d\n",fd);
244 * Okay, now if there exists a handler, we should
245 * call it. We must turn back on SIGIO if there
246 * are possibly other people waiting for it.
249 (*handlers[fd].func)(fd, cond, handlers[fd].arg,
250 (regcontext_t *)&sf->sf_uc.uc_mcontext);
253 * Otherwise deregister this guy.
255 _RegisterIO(fd, 0, 0, 0);
259 * If we did not process all the fd's, then we should
260 * break out of the probable infinite loop.