1 /* Implement entry point to select system call.
3 * The entry points into this file are
4 * do_select: perform the SELECT system call
5 * select_callback: notify select system of possible fd operation
6 * select_notified: low-level entry for device notifying select
7 * select_unsuspend_by_endpt: cancel a blocking select on exiting driver
10 #define DEBUG_SELECT 0
18 #include <sys/select.h>
19 #include <minix/com.h>
20 #include <minix/u64.h>
23 /* max. number of simultaneously pending select() calls */
28 PRIVATE
struct selectentry
{
29 struct fproc
*requestor
; /* slot is free iff this is NULL */
31 fd_set readfds
, writefds
, errorfds
;
32 fd_set ready_readfds
, ready_writefds
, ready_errorfds
;
33 fd_set
*vir_readfds
, *vir_writefds
, *vir_errorfds
;
34 struct filp
*filps
[OPEN_MAX
];
36 int deferred
; /* awaiting initial reply from driver */
37 int deferred_fd
; /* fd awaiting initial reply from driver */
41 timer_t timer
; /* if expiry > 0 */
42 } selecttab
[MAXSELECTS
];
44 FORWARD
_PROTOTYPE(int copy_fdsets
, (struct selectentry
*se
, int nfds
,
46 FORWARD
_PROTOTYPE(void filp_status
, (struct filp
*fp
, int status
) );
47 FORWARD
_PROTOTYPE(void restart_proc
, (int slot
) );
48 FORWARD
_PROTOTYPE(void ops2tab
, (int ops
, int fd
, struct selectentry
*e
));
49 FORWARD
_PROTOTYPE(int select_reevaluate
, (struct filp
*fp
) );
50 FORWARD
_PROTOTYPE(int select_request_file
, (struct filp
*f
, int *ops
,
52 FORWARD
_PROTOTYPE(int select_match_file
, (struct filp
*f
) );
53 FORWARD
_PROTOTYPE(int select_request_general
, (struct filp
*f
, int *ops
,
55 FORWARD
_PROTOTYPE(int select_request_asynch
, (struct filp
*f
, int *ops
,
57 FORWARD
_PROTOTYPE(int select_major_match
, (int match_major
,
59 FORWARD
_PROTOTYPE(void select_cancel_all
, (struct selectentry
*e
) );
60 FORWARD
_PROTOTYPE(void select_wakeup
, (struct selectentry
*e
, int r
) );
61 FORWARD
_PROTOTYPE(void select_return
, (struct selectentry
*, int) );
62 FORWARD
_PROTOTYPE(void sel_restart_dev
, (void) );
63 FORWARD
_PROTOTYPE(int tab2ops
, (int fd
, struct selectentry
*e
) );
64 FORWARD
_PROTOTYPE(void wipe_select
, (struct selectentry
*s
) );
66 PRIVATE
struct fdtype
{
67 int (*select_request
)(struct filp
*, int *ops
, int block
);
68 int (*select_match
)(struct filp
*);
71 { select_request_file
, select_match_file
, 0 },
72 { select_request_general
, NULL
, TTY_MAJOR
},
73 { select_request_general
, NULL
, INET_MAJOR
},
74 { select_request_pipe
, select_match_pipe
, 0 },
75 { select_request_asynch
, NULL
, LOG_MAJOR
},
77 #define SEL_FDS (sizeof(fdtypes) / sizeof(fdtypes[0]))
79 /*===========================================================================*
81 *===========================================================================*/
82 PUBLIC
int do_select(void)
84 /* Implement the select(nfds, readfds, writefds, errorfds, timeout) system
85 * call. First we copy the arguments and verify their sanity. Then we check
86 * whether there are file descriptors that satisfy the select call right of the
87 * bat. If so, or if there are no ready file descriptors but the process
88 * requested to return immediately, we return the result. Otherwise we set a
89 * timeout and wait for either the file descriptors to become ready or the
90 * timer to go off. If no timeout value was provided, we wait indefinitely. */
92 int r
, nfds
, do_timeout
= 0, nonzero_timeout
= 0, fd
, s
;
93 struct timeval timeout
;
94 struct selectentry
*se
;
98 /* Sane amount of file descriptors? */
99 if (nfds
< 0 || nfds
> OPEN_MAX
) return(EINVAL
);
101 /* Find a slot to store this select request */
102 for (s
= 0; s
< MAXSELECTS
; s
++)
103 if (selecttab
[s
].requestor
== NULL
) /* Unused slot */
105 if (s
>= MAXSELECTS
) return(ENOSPC
);
108 wipe_select(se
); /* Clear results of previous usage.*/
109 se
->req_endpt
= who_e
;
110 se
->vir_readfds
= (fd_set
*) m_in
.SEL_READFDS
;
111 se
->vir_writefds
= (fd_set
*) m_in
.SEL_WRITEFDS
;
112 se
->vir_errorfds
= (fd_set
*) m_in
.SEL_ERRORFDS
;
114 /* Copy fdsets from the process */
115 if ((r
= copy_fdsets(se
, nfds
, FROM_PROC
)) != OK
) return(r
);
117 /* Did the process set a timeout value? If so, retrieve it. */
118 if (m_in
.SEL_TIMEOUT
!= NULL
) {
120 r
= sys_vircopy(who_e
, D
, (vir_bytes
) m_in
.SEL_TIMEOUT
, SELF
, D
,
121 (vir_bytes
) &timeout
, sizeof(timeout
));
122 if (r
!= OK
) return(r
);
125 /* No nonsense in the timeval. */
126 if(do_timeout
&& (timeout
.tv_sec
< 0 || timeout
.tv_usec
< 0)) return(EINVAL
);
128 /* If there is no timeout, we block forever. Otherwise, we block up to the
129 * specified time interval.
131 if(!do_timeout
) /* No timeout value set */
133 else if (do_timeout
&& (timeout
.tv_sec
> 0 || timeout
.tv_usec
> 0))
135 else /* timeout set as (0,0) - this effects a poll */
137 se
->expiry
= 0; /* no timer set (yet) */
139 /* Check all file descriptors in the set whether one is 'ready' now. */
140 for (fd
= 0; fd
< nfds
; fd
++) {
141 int ops
, t
, type
= -1, r
;
144 if (!(ops
= tab2ops(fd
, se
)))
145 continue; /* No operations set; nothing to do for this fd */
147 /* Get filp belonging to this fd */
148 filp
= se
->filps
[fd
] = get_filp(fd
);
149 if (filp
== NIL_FILP
) {
150 if (err_code
== EBADF
) {
151 select_cancel_all(se
);
155 /* File descriptor is 'ready' to return EIO */
156 printf("VFS do_select: EIO after driver failure\n");
157 ops2tab(SEL_RD
|SEL_WR
|SEL_ERR
, fd
, se
);
161 /* Figure out what type of file we're dealing with */
162 for(t
= 0; t
< SEL_FDS
; t
++) {
163 if (fdtypes
[t
].select_match
) {
164 if (fdtypes
[t
].select_match(filp
)) {
167 } else if (select_major_match(fdtypes
[t
].select_major
, filp
)) {
172 if (type
== -1) return(EBADF
);
175 /* Test filp for select operations if not already done so. e.g., files
176 * sharing a filp and both doing a select on that filp. */
177 if ((se
->filps
[fd
]->filp_select_ops
& ops
) != ops
) {
180 wantops
= (se
->filps
[fd
]->filp_select_ops
|= ops
);
181 r
= fdtypes
[type
].select_request(filp
, &wantops
, se
->block
);
183 if (r
== SEL_DEFERRED
) {
189 /* Error or bogus return code; cancel select. */
190 select_cancel_all(se
);
194 /* The select request above might have turned on/off some
195 * operations because they were 'ready' or not meaningful.
196 * Either way, we might have a result and we need to store them
197 * in the select table entry. */
198 if (wantops
& ops
) ops2tab(wantops
, fd
, se
);
202 se
->filps
[fd
]->filp_selectors
++;
205 if (se
->nreadyfds
> 0 || (!se
->block
&& !se
->deferred
)) {
206 /* fd's were found that were ready to go right away, and/or
207 * we were instructed not to block at all. Must return
210 r
= copy_fdsets(se
, se
->nfds
, TO_PROC
);
211 select_cancel_all(se
);
212 se
->requestor
= NULL
;
214 if (r
!= OK
) return(r
);
215 else return(se
->nreadyfds
);
218 /* Convert timeval to ticks and set the timer. If it fails, undo
224 * "If the requested timeout interval requires a finer
225 * granularity than the implementation supports, the
226 * actual timeout interval shall be rounded up to the next
229 #define USECPERSEC 1000000
230 while(timeout
.tv_usec
>= USECPERSEC
) {
231 /* this is to avoid overflow with *system_hz below */
232 timeout
.tv_usec
-= USECPERSEC
;
235 ticks
= timeout
.tv_sec
* system_hz
+
236 (timeout
.tv_usec
* system_hz
+ USECPERSEC
-1) / USECPERSEC
;
238 fs_set_timer(&se
->timer
, ticks
, select_timeout_check
, s
);
241 /* if we're blocking, the table entry is now valid. */
244 /* process now blocked */
245 suspend(FP_BLOCKED_ON_SELECT
);
250 /*===========================================================================*
251 * select_request_file *
252 *===========================================================================*/
253 PRIVATE
int select_request_file(struct filp
*f
, int *ops
, int block
)
255 /* output *ops is input *ops */
260 /*===========================================================================*
261 * select_match_file *
262 *===========================================================================*/
263 PRIVATE
int select_match_file(struct filp
*file
)
265 return(file
&& file
->filp_vno
&& (file
->filp_vno
->v_mode
& I_REGULAR
));
269 /*===========================================================================*
270 * select_request_general *
271 *===========================================================================*/
272 PRIVATE
int select_request_general(struct filp
*f
, int *ops
, int block
)
275 if (block
) rops
|= SEL_NOTIFY
;
276 *ops
= dev_io(VFS_DEV_SELECT
, f
->filp_vno
->v_sdev
, rops
, NULL
,
277 cvu64(0), 0, 0, FALSE
);
285 /*===========================================================================*
286 * select_request_asynch *
287 *===========================================================================*/
288 PRIVATE
int select_request_asynch(struct filp
*f
, int *ops
, int block
)
294 f
->filp_select_flags
|= FSF_UPDATE
;
297 f
->filp_select_flags
|= FSF_BLOCK
;
300 if (f
->filp_select_flags
& FSF_BUSY
)
301 return(SEL_DEFERRED
);
303 dp
= &dmap
[((f
->filp_vno
->v_sdev
) >> MAJOR
) & BYTE
];
304 if (dp
->dmap_sel_filp
)
305 return(SEL_DEFERRED
);
307 f
->filp_select_flags
&= ~FSF_UPDATE
;
308 r
= dev_io(VFS_DEV_SELECT
, f
->filp_vno
->v_sdev
, rops
, NULL
,
309 cvu64(0), 0, 0, FALSE
);
310 if (r
< 0 && r
!= SUSPEND
)
314 panic(__FILE__
, "select_request_asynch: expected SUSPEND got", r
);
317 dp
->dmap_sel_filp
= f
;
318 f
->filp_select_flags
|= FSF_BUSY
;
320 return(SEL_DEFERRED
);
324 /*===========================================================================*
325 * select_major_match *
326 *===========================================================================*/
327 PRIVATE
int select_major_match(int match_major
, struct filp
*file
)
330 if (!(file
&& file
->filp_vno
&&
331 (file
->filp_vno
->v_mode
& I_TYPE
) == I_CHAR_SPECIAL
))
333 major
= (file
->filp_vno
->v_sdev
>> MAJOR
) & BYTE
;
334 if (major
== match_major
) return 1;
339 /*===========================================================================*
341 *===========================================================================*/
342 PRIVATE
int tab2ops(int fd
, struct selectentry
*e
)
345 if (FD_ISSET(fd
, &e
->readfds
)) ops
|= SEL_RD
;
346 if (FD_ISSET(fd
, &e
->writefds
)) ops
|= SEL_WR
;
347 if (FD_ISSET(fd
, &e
->errorfds
)) ops
|= SEL_ERR
;
353 /*===========================================================================*
355 *===========================================================================*/
356 PRIVATE
void ops2tab(int ops
, int fd
, struct selectentry
*e
)
358 if ((ops
& SEL_RD
) && e
->vir_readfds
&& FD_ISSET(fd
, &e
->readfds
) &&
359 !FD_ISSET(fd
, &e
->ready_readfds
)) {
360 FD_SET(fd
, &e
->ready_readfds
);
364 if ((ops
& SEL_WR
) && e
->vir_writefds
&& FD_ISSET(fd
, &e
->writefds
) &&
365 !FD_ISSET(fd
, &e
->ready_writefds
)) {
366 FD_SET(fd
, &e
->ready_writefds
);
370 if ((ops
& SEL_ERR
) && e
->vir_errorfds
&& FD_ISSET(fd
, &e
->errorfds
) &&
371 !FD_ISSET(fd
, &e
->ready_errorfds
)) {
372 FD_SET(fd
, &e
->ready_errorfds
);
378 /*===========================================================================*
380 *===========================================================================*/
381 PRIVATE
int copy_fdsets(struct selectentry
*se
, int nfds
, int direction
)
384 endpoint_t src_e
, dst_e
;
385 fd_set
*src_fds
, *dst_fds
;
387 if(nfds
< 0 || nfds
> OPEN_MAX
)
388 panic(__FILE__
, "select copy_fdsets: nfds wrong", nfds
);
390 /* Only copy back as many bits as the user expects. */
391 fd_setsize
= _FDSETWORDS(nfds
) * _FDSETBITSPERWORD
/8;
393 /* Set source and destination endpoints */
394 src_e
= (direction
== FROM_PROC
) ? se
->req_endpt
: SELF
;
395 dst_e
= (direction
== FROM_PROC
) ? SELF
: se
->req_endpt
;
398 src_fds
= (direction
== FROM_PROC
) ? se
->vir_readfds
: &se
->ready_readfds
;
399 dst_fds
= (direction
== FROM_PROC
) ? &se
->readfds
: se
->vir_readfds
;
400 if (se
->vir_readfds
) {
401 r
= sys_vircopy(src_e
, D
, (vir_bytes
) src_fds
, dst_e
, D
,
402 (vir_bytes
) dst_fds
, fd_setsize
);
403 if (r
!= OK
) return(r
);
407 src_fds
= (direction
== FROM_PROC
) ? se
->vir_writefds
: &se
->ready_writefds
;
408 dst_fds
= (direction
== FROM_PROC
) ? &se
->writefds
: se
->vir_writefds
;
409 if (se
->vir_writefds
) {
410 r
= sys_vircopy(src_e
, D
, (vir_bytes
) src_fds
, dst_e
, D
,
411 (vir_bytes
) dst_fds
, fd_setsize
);
412 if (r
!= OK
) return(r
);
416 src_fds
= (direction
== FROM_PROC
) ? se
->vir_errorfds
: &se
->ready_errorfds
;
417 dst_fds
= (direction
== FROM_PROC
) ? &se
->errorfds
: se
->vir_errorfds
;
418 if (se
->vir_errorfds
) {
419 r
= sys_vircopy(src_e
, D
, (vir_bytes
) src_fds
, dst_e
, D
,
420 (vir_bytes
) dst_fds
, fd_setsize
);
421 if (r
!= OK
) return(r
);
428 /*===========================================================================*
429 * select_cancel_all *
430 *===========================================================================*/
431 PRIVATE
void select_cancel_all(struct selectentry
*e
)
435 for(fd
= 0; fd
< e
->nfds
; fd
++) {
440 printf("[ fd %d/%d NULL ] ", fd
, e
->nfds
);
444 if (fp
->filp_selectors
< 1) {
446 printf("select: %d selectors?!\n", fp
->filp_selectors
);
450 fp
->filp_selectors
--;
452 select_reevaluate(fp
);
457 printf("cancelling timer %d\n", e
- selecttab
);
459 fs_cancel_timer(&e
->timer
);
467 /*===========================================================================*
469 *===========================================================================*/
470 PRIVATE
void select_wakeup(struct selectentry
*e
, int r
)
472 revive(e
->req_endpt
, r
);
476 /*===========================================================================*
477 * select_reevaluate *
478 *===========================================================================*/
479 PRIVATE
int select_reevaluate(struct filp
*fp
)
481 int s
, remain_ops
= 0, fd
;
484 printf("fs: select: reevalute NULL fp\n");
488 for(s
= 0; s
< MAXSELECTS
; s
++) {
489 if (selecttab
[s
].requestor
!= NULL
) continue;
491 for(fd
= 0; fd
< selecttab
[s
].nfds
; fd
++)
492 if (fp
== selecttab
[s
].filps
[fd
]) {
493 remain_ops
|= tab2ops(fd
, &selecttab
[s
]);
497 /* If there are any select()s open that want any operations on
498 * this fd that haven't been satisfied by this callback, then we're
499 * still in the market for it.
501 fp
->filp_select_ops
= remain_ops
;
503 printf("remaining operations on fp are %d\n", fp
->filp_select_ops
);
510 /*===========================================================================*
512 *===========================================================================*/
513 PRIVATE
void select_return(struct selectentry
*se
, int r
)
515 select_cancel_all(se
);
516 copy_fdsets(se
, se
->nfds
, TO_PROC
); /* FIXME, return error status */
517 select_wakeup(se
, r
? r
: se
->nreadyfds
);
518 se
->requestor
= NULL
;
522 /*===========================================================================*
524 *===========================================================================*/
525 PUBLIC
int select_callback(struct filp
*fp
, int ops
)
529 /* We are being notified that file pointer fp is available for
530 * operations 'ops'. We must re-register the select for
531 * operations that we are still interested in, if any.
534 for(s
= 0; s
< MAXSELECTS
; s
++) {
536 if (selecttab
[s
].requestor
== NULL
) continue;
538 for(fd
= 0; fd
< selecttab
[s
].nfds
; fd
++) {
539 if (!selecttab
[s
].filps
[fd
])
541 if (selecttab
[s
].filps
[fd
] == fp
) {
543 this_want_ops
= tab2ops(fd
, &selecttab
[s
]);
544 if (this_want_ops
& ops
) {
545 /* this select() has been satisfied. */
546 ops2tab(ops
, fd
, &selecttab
[s
]);
552 select_return(&selecttab
[s
], 0);
559 /*===========================================================================*
561 *===========================================================================*/
562 PUBLIC
int select_notified(int major
, int minor
, int selected_ops
)
567 printf("select callback: %d, %d: %d\n", major
, minor
, selected_ops
);
570 for(t
= 0; t
< SEL_FDS
; t
++)
571 if (!fdtypes
[t
].select_match
&& fdtypes
[t
].select_major
== major
)
576 printf("select callback: no fdtype found for device %d\n", major
);
581 /* We have a select callback from major device no.
582 * d, which corresponds to our select type t.
585 for(s
= 0; s
< MAXSELECTS
; s
++) {
587 if (selecttab
[s
].requestor
== NULL
) continue;
588 for(f
= 0; f
< selecttab
[s
].nfds
; f
++) {
589 if (!selecttab
[s
].filps
[f
] ||
590 !select_major_match(major
, selecttab
[s
].filps
[f
]))
592 ops
= tab2ops(f
, &selecttab
[s
]);
594 (selecttab
[s
].filps
[f
]->filp_vno
->v_sdev
>> MINOR
)
596 if ((s_minor
== minor
) &&
597 (selected_ops
& ops
)) {
598 select_callback(selecttab
[s
].filps
[f
], (selected_ops
& ops
));
607 /*===========================================================================*
609 *===========================================================================*/
610 PUBLIC
void init_select(void)
614 for(s
= 0; s
< MAXSELECTS
; s
++)
615 fs_init_timer(&selecttab
[s
].timer
);
619 /*===========================================================================*
621 *===========================================================================*/
622 PUBLIC
void select_forget(int proc_e
)
624 /* something has happened (e.g. signal delivered that interrupts
625 * select()). totally forget about the select().
629 for(s
= 0; s
< MAXSELECTS
; s
++) {
630 if (selecttab
[s
].requestor
!= NULL
&&
631 selecttab
[s
].req_endpt
== proc_e
) {
636 if (s
>= MAXSELECTS
) {
638 printf("select: cancelled select() not found");
643 select_cancel_all(&selecttab
[s
]);
644 selecttab
[s
].requestor
= NULL
;
650 /*===========================================================================*
651 * select_timeout_check *
652 *===========================================================================*/
653 PUBLIC
void select_timeout_check(timer_t
*timer
)
656 struct selectentry
*se
;
658 s
= tmr_arg(timer
)->ta_int
;
659 if (s
< 0 || s
>= MAXSELECTS
) {
661 printf("select: bogus slot arg to watchdog %d\n", s
);
665 se
= &selecttab
[s
]; /* Point to select table entry */
667 if (se
->requestor
== NULL
) {
669 printf("select: no requestor in watchdog\n");
674 if (se
->expiry
<= 0) {
676 printf("select: strange expiry value in watchdog\n", s
);
682 select_return(se
, 0);
687 /*===========================================================================*
688 * select_unsuspend_by_endpt *
689 *===========================================================================*/
690 PUBLIC
void select_unsuspend_by_endpt(endpoint_t proc_e
)
694 for(s
= 0; s
< MAXSELECTS
; s
++) {
695 if (selecttab
[s
].requestor
== NULL
) continue;
697 for(fd
= 0; fd
< selecttab
[s
].nfds
; fd
++) {
698 if (selecttab
[s
].filps
[fd
] == NIL_FILP
||
699 selecttab
[s
].filps
[fd
]->filp_vno
== NIL_VNODE
) {
703 maj
= (selecttab
[s
].filps
[fd
]->filp_vno
->v_sdev
>> MAJOR
)&BYTE
;
704 if (dmap_driver_match(proc_e
, maj
))
705 select_return(&selecttab
[s
], EAGAIN
);
712 /*===========================================================================*
714 *===========================================================================*/
715 PUBLIC
void select_reply1()
717 int i
, s
, minor
, status
;
724 driver_e
= m_in
.m_source
;
725 minor
= m_in
.DEV_MINOR
;
726 status
= m_in
.DEV_SEL_OPS
;
728 /* Locate dmap entry */
729 for (i
= 0, dp
= dmap
; i
<NR_DEVICES
; i
++, dp
++)
731 if (dp
->dmap_driver
== driver_e
)
736 printf("select_reply1: proc %d is not a recoqnized driver\n",
740 dev
= (i
<< MAJOR
) | (minor
& BYTE
);
742 fp
= dp
->dmap_sel_filp
;
745 printf("select_reply1: strange, no dmap_sel_filp\n");
749 if (!(fp
->filp_select_flags
& FSF_BUSY
))
750 panic(__FILE__
, "select_reply1: strange, not FSF_BUSY", NO_NUM
);
754 panic(__FILE__
, "select_reply1: FSF_BUSY but no vp", NO_NUM
);
756 if ((vp
->v_mode
& I_TYPE
) != I_CHAR_SPECIAL
)
758 panic(__FILE__
, "select_reply1: FSF_BUSY but not char special",
762 if (vp
->v_sdev
!= dev
)
764 printf("select_reply1: strange, reply from wrong dev\n");
768 dp
->dmap_sel_filp
= NULL
;
769 fp
->filp_select_flags
&= ~FSF_BUSY
;
770 if (!(fp
->filp_select_flags
& (FSF_UPDATE
|FSF_BLOCK
)))
771 fp
->filp_select_ops
= 0;
776 /* Clear the replied bits from the request mask unless
779 if (!(fp
->filp_select_flags
& FSF_UPDATE
))
780 fp
->filp_select_ops
&= ~status
;
782 filp_status(fp
, status
);
784 if (fp
->filp_count
> 1)
788 if (fp
->filp_count
!= 1)
790 panic(__FILE__
, "select_reply1: bad filp_count",
799 /*===========================================================================*
801 *===========================================================================*/
802 PUBLIC
void select_reply2()
804 int i
, s
, minor
, status
;
811 driver_e
= m_in
.m_source
;
812 minor
= m_in
.DEV_MINOR
;
813 status
= m_in
.DEV_SEL_OPS
;
815 /* Locate dmap entry */
816 for (i
= 0, dp
= dmap
; i
<NR_DEVICES
; i
++, dp
++)
818 if (dp
->dmap_driver
== driver_e
)
823 printf("select_reply2: proc %d is not a recognized driver\n",
827 dev
= (i
<< MAJOR
) | (minor
& BYTE
);
829 /* Find filedescriptors for this device */
830 for (s
= 0; s
<MAXSELECTS
; s
++)
832 if (selecttab
[s
].requestor
== NULL
)
833 continue; /* empty slot */
835 for (i
= 0; i
<OPEN_MAX
; i
++)
837 fp
= selecttab
[s
].filps
[i
];
843 if ((vp
->v_mode
& I_TYPE
) != I_CHAR_SPECIAL
)
846 if (vp
->v_sdev
!= dev
)
851 printf("select_reply2: should handle error\n");
855 /* Clear the replied bits from the request
856 * mask unless FSF_UPDATE is set.
858 if (!(fp
->filp_select_flags
& FSF_UPDATE
))
859 fp
->filp_select_ops
&= ~status
;
860 ops2tab(status
, i
, &selecttab
[s
]);
863 if (selecttab
[s
].nreadyfds
> 0)
869 PRIVATE
void sel_restart_dev()
876 /* Locate filps that can be restarted */
877 for (s
= 0; s
<MAXSELECTS
; s
++)
879 if (selecttab
[s
].requestor
== NULL
)
880 continue; /* empty slot */
881 if (!selecttab
[s
].deferred
)
882 continue; /* process is not waiting for an
885 for (i
= 0; i
<OPEN_MAX
; i
++)
887 fp
= selecttab
[s
].filps
[i
];
890 if (fp
->filp_select_flags
& FSF_BUSY
)
892 if (!(fp
->filp_select_flags
& FSF_UPDATE
))
899 "sel_restart_dev: FSF_UPDATE but no vp",
902 if ((vp
->v_mode
& I_TYPE
) != I_CHAR_SPECIAL
)
905 "sel_restart_dev: FSF_UPDATE but not char special",
909 dp
= &dmap
[((vp
->v_sdev
) >> MAJOR
) & BYTE
];
910 if (dp
->dmap_sel_filp
)
914 "sel_restart_dev: should consider fd %d in slot %d\n",
921 PRIVATE
void filp_status(fp
, status
)
927 /* Locate processes that need to know about this result */
928 for (s
= 0; s
<MAXSELECTS
; s
++)
930 if (selecttab
[s
].requestor
== NULL
) continue; /* empty slot */
932 for (i
= 0; i
<OPEN_MAX
; i
++)
934 if (selecttab
[s
].filps
[i
] != fp
)
939 printf("filp_status: should handle error\n");
942 ops2tab(status
, i
, &selecttab
[s
]);
950 PRIVATE
void restart_proc(slot
)
954 struct selectentry
*se
;
957 se
= &selecttab
[slot
];
960 for (fd
= se
->deferred_fd
; fd
< OPEN_MAX
; fd
++)
965 if (fp
->filp_select_flags
& (FSF_UPDATE
|FSF_BUSY
))
975 if (se
->nreadyfds
> 0 || !se
->block
) {
976 copy_fdsets(se
, se
->nfds
, TO_PROC
); /* FIXME, return error */
977 select_wakeup(se
, se
->nreadyfds
);
978 se
->requestor
= NULL
;
982 /*===========================================================================*
984 *===========================================================================*/
985 PRIVATE
void wipe_select(struct selectentry
*se
)
987 se
->deferred
= FALSE
;
990 /* memset(se->filps, 0, OPEN_MAX * sizeof(struct filp *)); */
991 memset(se
->filps
, 0, sizeof(se
->filps
));
993 FD_ZERO(&se
->readfds
);
994 FD_ZERO(&se
->writefds
);
995 FD_ZERO(&se
->errorfds
);
996 FD_ZERO(&se
->ready_readfds
);
997 FD_ZERO(&se
->ready_writefds
);
998 FD_ZERO(&se
->ready_errorfds
);