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 $
33 * $DragonFly: src/usr.bin/doscmd/AsyncIO.c,v 1.2 2003/06/17 04:29:25 dillon Exp $
36 #include <sys/param.h>
37 #include <sys/types.h>
49 #define FD_ISZERO(p) ((p)->fds_bits[0] == 0)
52 * Set or Clear the Async nature of an FD
55 #define SETASYNC(fd) fcntl(fd, F_SETFL, handlers[fd].flag | FASYNC)
56 #define CLRASYNC(fd) fcntl(fd, F_SETFL, handlers[fd].flag & ~FASYNC)
59 * Request that ``func'' be called everytime data is available on ``fd''
62 static fd_set fdset
; /* File Descriptors to select on */
65 void (*func
)(int, int, void *, regcontext_t
*);
66 /* Function to call on data arrival */
67 void (*failure
)(void *); /* Function to call on failure */
68 void *arg
; /* Argument to above functions */
69 int lockcnt
; /* Nested level of lock */
70 fd_set members
; /* Set of FD's to disable on SIGIO */
71 int flag
; /* The flag from F_GETFL (we own it) */
74 static Async handlers
[OPEN_MAX
];
76 static void CleanIO(void);
77 static void HandleIO(struct sigframe
*sf
);
80 _RegisterIO(int fd
, void (*func
)(int, int, void *, regcontext_t
*),
81 void *arg
, void (*failure
)(void *))
83 static int firsttime
= 1;
86 if (fd
< 0 || fd
> OPEN_MAX
) {
87 printf("%d: Invalid FD\n", fd
);
93 if ((as
->flag
= fcntl(fd
, F_GETFL
, 0)) == -1) {
95 /*@*/ perror("get fcntl");
103 setsignal(SIGIO
, HandleIO
);
106 if ((handlers
[fd
].func
= func
) != 0) {
109 as
->failure
= failure
;
112 FD_ZERO(&handlers
[fd
].members
);
113 FD_SET(fd
, &handlers
[fd
].members
);
114 if (fcntl(fd
, F_SETOWN
, getpid()) < 0) {
115 /*@*/ perror("SETOWN");
132 static struct timeval tv
;
135 * For every file des in fd_set, we check to see if it
136 * causes a fault on select(). If so, we unregister it
139 for (x
= 0; x
< OPEN_MAX
; ++x
) {
142 if (!FD_ISSET(x
, &fdset
))
148 if (select(FD_SETSIZE
, &set
, 0, 0, &tv
) < 0 &&
152 printf("Closed file descriptor %d\n", x
);
154 f
= handlers
[x
].failure
;
156 handlers
[x
].failure
= 0;
157 handlers
[x
].func
= 0;
159 handlers
[x
].lockcnt
= 0;
168 HandleIO(struct sigframe
*sf
)
170 static struct timeval tv
;
171 fd_set readset
, writeset
;
175 readset
= writeset
= fdset
;
176 if ((x
= select(FD_SETSIZE
, &readset
, &writeset
, 0, &tv
)) < 0) {
178 * If we failed because of a BADFiledes, go find
179 * which one(s), fail them out and then try a
180 * new select to see if any of the good ones are
183 if (errno
== EBADF
) {
185 if (FD_ISZERO(&fdset
))
194 * If we run out of fds to look at, break out of the loop
195 * and exit the handler.
201 * If there is at least 1 fd saying it has something for
202 * us, then loop through the sets looking for those
203 * bits, stopping when we have handleed the number it has
206 for (fd
= 0; x
&& fd
< OPEN_MAX
; fd
++) {
212 if (FD_ISSET(fd
, &readset
)) {
216 if (FD_ISSET(fd
, &writeset
)) {
225 * Is suppose it is possible that one of the previous
226 * I/O requests changed the fdset.
227 * We do know that SIGIO is turned off right now,
228 * so it is safe to checkit.
230 if (!FD_ISSET(fd
, &fdset
)) {
236 * as in above, maybe someone locked us...
237 * we are in dangerous water now if we are
241 fprintf(stderr
, "Selected IO on locked %d\n",fd
);
245 * Okay, now if there exists a handler, we should
246 * call it. We must turn back on SIGIO if there
247 * are possibly other people waiting for it.
250 (*handlers
[fd
].func
)(fd
, cond
, handlers
[fd
].arg
,
251 (regcontext_t
*)&sf
->sf_uc
.uc_mcontext
);
254 * Otherwise deregister this guy.
256 _RegisterIO(fd
, 0, 0, 0);
260 * If we did not process all the fd's, then we should
261 * break out of the probable infinite loop.