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
, fd_setsize
;
93 struct timeval timeout
;
94 struct selectentry
*se
;
98 /* Sane amount of file descriptors? */
99 if (nfds
< 0 || nfds
> OPEN_MAX
) return(EINVAL
);
100 fd_setsize
= _FDSETWORDS(nfds
) * _FDSETBITSPERWORD
/8;
102 /* Find a slot to store this select request */
103 for (s
= 0; s
< MAXSELECTS
; s
++)
104 if (selecttab
[s
].requestor
== NULL
) /* Unused slot */
106 if (s
>= MAXSELECTS
) return(ENOSPC
);
109 wipe_select(se
); /* Clear results of previous usage.*/
110 se
->req_endpt
= who_e
;
111 se
->vir_readfds
= (fd_set
*) m_in
.SEL_READFDS
;
112 se
->vir_writefds
= (fd_set
*) m_in
.SEL_WRITEFDS
;
113 se
->vir_errorfds
= (fd_set
*) m_in
.SEL_ERRORFDS
;
115 /* Copy fdsets from the process */
116 if ((r
= copy_fdsets(se
, nfds
, FROM_PROC
)) != OK
) return(r
);
118 /* Did the process set a timeout value? If so, retrieve it. */
119 if (m_in
.SEL_TIMEOUT
!= NULL
) {
121 r
= sys_vircopy(who_e
, D
, (vir_bytes
) m_in
.SEL_TIMEOUT
, SELF
, D
,
122 (vir_bytes
) &timeout
, sizeof(timeout
));
123 if (r
!= OK
) return(r
);
126 /* No nonsense in the timeval. */
127 if(do_timeout
&& (timeout
.tv_sec
< 0 || timeout
.tv_usec
< 0)) return(EINVAL
);
129 /* If there is no timeout, we block forever. Otherwise, we block up to the
130 * specified time interval.
132 if(!do_timeout
) /* No timeout value set */
134 else if (do_timeout
&& (timeout
.tv_sec
> 0 || timeout
.tv_usec
> 0))
136 else /* timeout set as (0,0) - this effects a poll */
138 se
->expiry
= 0; /* no timer set (yet) */
140 /* Check all file descriptors in the set whether one is 'ready' now. */
141 for (fd
= 0; fd
< nfds
; fd
++) {
142 int ops
, t
, type
= -1, r
;
145 if (!(ops
= tab2ops(fd
, se
)))
146 continue; /* No operations set; nothing to do for this fd */
148 /* Get filp belonging to this fd */
149 filp
= se
->filps
[fd
] = get_filp(fd
);
150 if (filp
== NIL_FILP
) {
151 if (err_code
== EBADF
) {
152 select_cancel_all(se
);
156 /* File descriptor is 'ready' to return EIO */
157 printf("VFS do_select: EIO after driver failure\n");
158 ops2tab(SEL_RD
|SEL_WR
|SEL_ERR
, fd
, se
);
162 /* Figure out what type of file we're dealing with */
163 for(t
= 0; t
< SEL_FDS
; t
++) {
164 if (fdtypes
[t
].select_match
) {
165 if (fdtypes
[t
].select_match(filp
)) {
168 } else if (select_major_match(fdtypes
[t
].select_major
, filp
)) {
173 if (type
== -1) return(EBADF
);
176 /* Test filp for select operations if not already done so. e.g., files
177 * sharing a filp and both doing a select on that filp. */
178 if ((se
->filps
[fd
]->filp_select_ops
& ops
) != ops
) {
181 wantops
= (se
->filps
[fd
]->filp_select_ops
|= ops
);
182 r
= fdtypes
[type
].select_request(filp
, &wantops
, se
->block
);
184 if (r
== SEL_DEFERRED
) {
190 /* Error or bogus return code; cancel select. */
191 select_cancel_all(se
);
195 /* The select request above might have turned on/off some
196 * operations because they were 'ready' or not meaningful.
197 * Either way, we might have a result and we need to store them
198 * in the select table entry. */
199 if (wantops
& ops
) ops2tab(wantops
, fd
, se
);
203 se
->filps
[fd
]->filp_selectors
++;
206 if (se
->nreadyfds
> 0 || (!se
->block
&& !se
->deferred
)) {
207 /* fd's were found that were ready to go right away, and/or
208 * we were instructed not to block at all. Must return
211 r
= copy_fdsets(se
, se
->nfds
, TO_PROC
);
212 select_cancel_all(se
);
213 se
->requestor
= NULL
;
215 if (r
!= OK
) return(r
);
216 else return(se
->nreadyfds
);
219 /* Convert timeval to ticks and set the timer. If it fails, undo
225 * "If the requested timeout interval requires a finer
226 * granularity than the implementation supports, the
227 * actual timeout interval shall be rounded up to the next
230 #define USECPERSEC 1000000
231 while(timeout
.tv_usec
>= USECPERSEC
) {
232 /* this is to avoid overflow with *system_hz below */
233 timeout
.tv_usec
-= USECPERSEC
;
236 ticks
= timeout
.tv_sec
* system_hz
+
237 (timeout
.tv_usec
* system_hz
+ USECPERSEC
-1) / USECPERSEC
;
239 fs_set_timer(&se
->timer
, ticks
, select_timeout_check
, s
);
242 /* if we're blocking, the table entry is now valid. */
245 /* process now blocked */
246 suspend(FP_BLOCKED_ON_SELECT
);
251 /*===========================================================================*
252 * select_request_file *
253 *===========================================================================*/
254 PRIVATE
int select_request_file(struct filp
*f
, int *ops
, int block
)
256 /* output *ops is input *ops */
261 /*===========================================================================*
262 * select_match_file *
263 *===========================================================================*/
264 PRIVATE
int select_match_file(struct filp
*file
)
266 return(file
&& file
->filp_vno
&& (file
->filp_vno
->v_mode
& I_REGULAR
));
270 /*===========================================================================*
271 * select_request_general *
272 *===========================================================================*/
273 PRIVATE
int select_request_general(struct filp
*f
, int *ops
, int block
)
276 if (block
) rops
|= SEL_NOTIFY
;
277 *ops
= dev_io(VFS_DEV_SELECT
, f
->filp_vno
->v_sdev
, rops
, NULL
,
278 cvu64(0), 0, 0, FALSE
);
286 /*===========================================================================*
287 * select_request_asynch *
288 *===========================================================================*/
289 PRIVATE
int select_request_asynch(struct filp
*f
, int *ops
, int block
)
295 f
->filp_select_flags
|= FSF_UPDATE
;
298 f
->filp_select_flags
|= FSF_BLOCK
;
301 if (f
->filp_select_flags
& FSF_BUSY
)
302 return(SEL_DEFERRED
);
304 dp
= &dmap
[((f
->filp_vno
->v_sdev
) >> MAJOR
) & BYTE
];
305 if (dp
->dmap_sel_filp
)
306 return(SEL_DEFERRED
);
308 f
->filp_select_flags
&= ~FSF_UPDATE
;
309 r
= dev_io(VFS_DEV_SELECT
, f
->filp_vno
->v_sdev
, rops
, NULL
,
310 cvu64(0), 0, 0, FALSE
);
311 if (r
< 0 && r
!= SUSPEND
)
315 panic(__FILE__
, "select_request_asynch: expected SUSPEND got", r
);
318 dp
->dmap_sel_filp
= f
;
319 f
->filp_select_flags
|= FSF_BUSY
;
321 return(SEL_DEFERRED
);
325 /*===========================================================================*
326 * select_major_match *
327 *===========================================================================*/
328 PRIVATE
int select_major_match(int match_major
, struct filp
*file
)
331 if (!(file
&& file
->filp_vno
&&
332 (file
->filp_vno
->v_mode
& I_TYPE
) == I_CHAR_SPECIAL
))
334 major
= (file
->filp_vno
->v_sdev
>> MAJOR
) & BYTE
;
335 if (major
== match_major
) return 1;
340 /*===========================================================================*
342 *===========================================================================*/
343 PRIVATE
int tab2ops(int fd
, struct selectentry
*e
)
346 if (FD_ISSET(fd
, &e
->readfds
)) ops
|= SEL_RD
;
347 if (FD_ISSET(fd
, &e
->writefds
)) ops
|= SEL_WR
;
348 if (FD_ISSET(fd
, &e
->errorfds
)) ops
|= SEL_ERR
;
354 /*===========================================================================*
356 *===========================================================================*/
357 PRIVATE
void ops2tab(int ops
, int fd
, struct selectentry
*e
)
359 if ((ops
& SEL_RD
) && e
->vir_readfds
&& FD_ISSET(fd
, &e
->readfds
) &&
360 !FD_ISSET(fd
, &e
->ready_readfds
)) {
361 FD_SET(fd
, &e
->ready_readfds
);
365 if ((ops
& SEL_WR
) && e
->vir_writefds
&& FD_ISSET(fd
, &e
->writefds
) &&
366 !FD_ISSET(fd
, &e
->ready_writefds
)) {
367 FD_SET(fd
, &e
->ready_writefds
);
371 if ((ops
& SEL_ERR
) && e
->vir_errorfds
&& FD_ISSET(fd
, &e
->errorfds
) &&
372 !FD_ISSET(fd
, &e
->ready_errorfds
)) {
373 FD_SET(fd
, &e
->ready_errorfds
);
379 /*===========================================================================*
381 *===========================================================================*/
382 PRIVATE
int copy_fdsets(struct selectentry
*se
, int nfds
, int direction
)
385 endpoint_t src_e
, dst_e
;
386 fd_set
*src_fds
, *dst_fds
;
388 if(nfds
< 0 || nfds
> OPEN_MAX
)
389 panic(__FILE__
, "select copy_fdsets: nfds wrong", nfds
);
391 /* Only copy back as many bits as the user expects. */
392 fd_setsize
= _FDSETWORDS(nfds
) * _FDSETBITSPERWORD
/8;
394 /* Set source and destination endpoints */
395 src_e
= (direction
== FROM_PROC
) ? se
->req_endpt
: SELF
;
396 dst_e
= (direction
== FROM_PROC
) ? SELF
: se
->req_endpt
;
399 src_fds
= (direction
== FROM_PROC
) ? se
->vir_readfds
: &se
->ready_readfds
;
400 dst_fds
= (direction
== FROM_PROC
) ? &se
->readfds
: se
->vir_readfds
;
401 if (se
->vir_readfds
) {
402 r
= sys_vircopy(src_e
, D
, (vir_bytes
) src_fds
, dst_e
, D
,
403 (vir_bytes
) dst_fds
, fd_setsize
);
404 if (r
!= OK
) return(r
);
408 src_fds
= (direction
== FROM_PROC
) ? se
->vir_writefds
: &se
->ready_writefds
;
409 dst_fds
= (direction
== FROM_PROC
) ? &se
->writefds
: se
->vir_writefds
;
410 if (se
->vir_writefds
) {
411 r
= sys_vircopy(src_e
, D
, (vir_bytes
) src_fds
, dst_e
, D
,
412 (vir_bytes
) dst_fds
, fd_setsize
);
413 if (r
!= OK
) return(r
);
417 src_fds
= (direction
== FROM_PROC
) ? se
->vir_errorfds
: &se
->ready_errorfds
;
418 dst_fds
= (direction
== FROM_PROC
) ? &se
->errorfds
: se
->vir_errorfds
;
419 if (se
->vir_errorfds
) {
420 r
= sys_vircopy(src_e
, D
, (vir_bytes
) src_fds
, dst_e
, D
,
421 (vir_bytes
) dst_fds
, fd_setsize
);
422 if (r
!= OK
) return(r
);
429 /*===========================================================================*
430 * select_cancel_all *
431 *===========================================================================*/
432 PRIVATE
void select_cancel_all(struct selectentry
*e
)
436 for(fd
= 0; fd
< e
->nfds
; fd
++) {
441 printf("[ fd %d/%d NULL ] ", fd
, e
->nfds
);
445 if (fp
->filp_selectors
< 1) {
447 printf("select: %d selectors?!\n", fp
->filp_selectors
);
451 fp
->filp_selectors
--;
453 select_reevaluate(fp
);
458 printf("cancelling timer %d\n", e
- selecttab
);
460 fs_cancel_timer(&e
->timer
);
468 /*===========================================================================*
470 *===========================================================================*/
471 PRIVATE
void select_wakeup(struct selectentry
*e
, int r
)
473 revive(e
->req_endpt
, r
);
477 /*===========================================================================*
478 * select_reevaluate *
479 *===========================================================================*/
480 PRIVATE
int select_reevaluate(struct filp
*fp
)
482 int s
, remain_ops
= 0, fd
, type
= -1;
485 printf("fs: select: reevalute NULL fp\n");
489 for(s
= 0; s
< MAXSELECTS
; s
++) {
490 if (selecttab
[s
].requestor
!= NULL
) continue;
492 for(fd
= 0; fd
< selecttab
[s
].nfds
; fd
++)
493 if (fp
== selecttab
[s
].filps
[fd
]) {
494 remain_ops
|= tab2ops(fd
, &selecttab
[s
]);
495 type
= selecttab
[s
].type
[fd
];
499 /* If there are any select()s open that want any operations on
500 * this fd that haven't been satisfied by this callback, then we're
501 * still in the market for it.
503 fp
->filp_select_ops
= remain_ops
;
505 printf("remaining operations on fp are %d\n", fp
->filp_select_ops
);
512 /*===========================================================================*
514 *===========================================================================*/
515 PRIVATE
void select_return(struct selectentry
*se
, int r
)
517 select_cancel_all(se
);
518 copy_fdsets(se
, se
->nfds
, TO_PROC
); /* FIXME, return error status */
519 select_wakeup(se
, r
? r
: se
->nreadyfds
);
520 se
->requestor
= NULL
;
524 /*===========================================================================*
526 *===========================================================================*/
527 PUBLIC
int select_callback(struct filp
*fp
, int ops
)
529 int s
, fd
, want_ops
, type
;
531 /* We are being notified that file pointer fp is available for
532 * operations 'ops'. We must re-register the select for
533 * operations that we are still interested in, if any.
538 for(s
= 0; s
< MAXSELECTS
; s
++) {
540 if (selecttab
[s
].requestor
== NULL
) continue;
542 for(fd
= 0; fd
< selecttab
[s
].nfds
; fd
++) {
543 if (!selecttab
[s
].filps
[fd
])
545 if (selecttab
[s
].filps
[fd
] == fp
) {
547 this_want_ops
= tab2ops(fd
, &selecttab
[s
]);
548 want_ops
|= this_want_ops
;
549 if (this_want_ops
& ops
) {
550 /* this select() has been satisfied. */
551 ops2tab(ops
, fd
, &selecttab
[s
]);
554 type
= selecttab
[s
].type
[fd
];
558 select_return(&selecttab
[s
], 0);
565 /*===========================================================================*
567 *===========================================================================*/
568 PUBLIC
int select_notified(int major
, int minor
, int selected_ops
)
573 printf("select callback: %d, %d: %d\n", major
, minor
, selected_ops
);
576 for(t
= 0; t
< SEL_FDS
; t
++)
577 if (!fdtypes
[t
].select_match
&& fdtypes
[t
].select_major
== major
)
582 printf("select callback: no fdtype found for device %d\n", major
);
587 /* We have a select callback from major device no.
588 * d, which corresponds to our select type t.
591 for(s
= 0; s
< MAXSELECTS
; s
++) {
593 if (selecttab
[s
].requestor
== NULL
) continue;
594 for(f
= 0; f
< selecttab
[s
].nfds
; f
++) {
595 if (!selecttab
[s
].filps
[f
] ||
596 !select_major_match(major
, selecttab
[s
].filps
[f
]))
598 ops
= tab2ops(f
, &selecttab
[s
]);
600 (selecttab
[s
].filps
[f
]->filp_vno
->v_sdev
>> MINOR
)
602 if ((s_minor
== minor
) &&
603 (selected_ops
& ops
)) {
604 select_callback(selecttab
[s
].filps
[f
], (selected_ops
& ops
));
613 /*===========================================================================*
615 *===========================================================================*/
616 PUBLIC
void init_select(void)
620 for(s
= 0; s
< MAXSELECTS
; s
++)
621 fs_init_timer(&selecttab
[s
].timer
);
625 /*===========================================================================*
627 *===========================================================================*/
628 PUBLIC
void select_forget(int proc_e
)
630 /* something has happened (e.g. signal delivered that interrupts
631 * select()). totally forget about the select().
635 for(s
= 0; s
< MAXSELECTS
; s
++) {
636 if (selecttab
[s
].requestor
!= NULL
&&
637 selecttab
[s
].req_endpt
== proc_e
) {
642 if (s
>= MAXSELECTS
) {
644 printf("select: cancelled select() not found");
649 select_cancel_all(&selecttab
[s
]);
650 selecttab
[s
].requestor
= NULL
;
656 /*===========================================================================*
657 * select_timeout_check *
658 *===========================================================================*/
659 PUBLIC
void select_timeout_check(timer_t
*timer
)
662 struct selectentry
*se
;
664 s
= tmr_arg(timer
)->ta_int
;
665 if (s
< 0 || s
>= MAXSELECTS
) {
667 printf("select: bogus slot arg to watchdog %d\n", s
);
671 se
= &selecttab
[s
]; /* Point to select table entry */
673 if (se
->requestor
== NULL
) {
675 printf("select: no requestor in watchdog\n");
680 if (se
->expiry
<= 0) {
682 printf("select: strange expiry value in watchdog\n", s
);
688 select_return(se
, 0);
693 /*===========================================================================*
694 * select_unsuspend_by_endpt *
695 *===========================================================================*/
696 PUBLIC
void select_unsuspend_by_endpt(endpoint_t proc_e
)
700 for(s
= 0; s
< MAXSELECTS
; s
++) {
701 if (selecttab
[s
].requestor
== NULL
) continue;
703 for(fd
= 0; fd
< selecttab
[s
].nfds
; fd
++) {
704 if (selecttab
[s
].filps
[fd
] == NIL_FILP
||
705 selecttab
[s
].filps
[fd
]->filp_vno
== NIL_VNODE
) {
709 maj
= (selecttab
[s
].filps
[fd
]->filp_vno
->v_sdev
>> MAJOR
)&BYTE
;
710 if (dmap_driver_match(proc_e
, maj
))
711 select_return(&selecttab
[s
], EAGAIN
);
718 /*===========================================================================*
720 *===========================================================================*/
721 PUBLIC
void select_reply1()
723 int i
, s
, minor
, status
;
730 driver_e
= m_in
.m_source
;
731 minor
= m_in
.DEV_MINOR
;
732 status
= m_in
.DEV_SEL_OPS
;
734 /* Locate dmap entry */
735 for (i
= 0, dp
= dmap
; i
<NR_DEVICES
; i
++, dp
++)
737 if (dp
->dmap_driver
== driver_e
)
742 printf("select_reply1: proc %d is not a recoqnized driver\n",
746 dev
= (i
<< MAJOR
) | (minor
& BYTE
);
748 fp
= dp
->dmap_sel_filp
;
751 printf("select_reply1: strange, no dmap_sel_filp\n");
755 if (!(fp
->filp_select_flags
& FSF_BUSY
))
756 panic(__FILE__
, "select_reply1: strange, not FSF_BUSY", NO_NUM
);
760 panic(__FILE__
, "select_reply1: FSF_BUSY but no vp", NO_NUM
);
762 if ((vp
->v_mode
& I_TYPE
) != I_CHAR_SPECIAL
)
764 panic(__FILE__
, "select_reply1: FSF_BUSY but not char special",
768 if (vp
->v_sdev
!= dev
)
770 printf("select_reply1: strange, reply from wrong dev\n");
774 dp
->dmap_sel_filp
= NULL
;
775 fp
->filp_select_flags
&= ~FSF_BUSY
;
776 if (!(fp
->filp_select_flags
& (FSF_UPDATE
|FSF_BLOCK
)))
777 fp
->filp_select_ops
= 0;
782 /* Clear the replied bits from the request mask unless
785 if (!(fp
->filp_select_flags
& FSF_UPDATE
))
786 fp
->filp_select_ops
&= ~status
;
788 filp_status(fp
, status
);
790 if (fp
->filp_count
> 1)
794 if (fp
->filp_count
!= 1)
796 panic(__FILE__
, "select_reply1: bad filp_count",
805 /*===========================================================================*
807 *===========================================================================*/
808 PUBLIC
void select_reply2()
810 int i
, s
, minor
, status
;
817 driver_e
= m_in
.m_source
;
818 minor
= m_in
.DEV_MINOR
;
819 status
= m_in
.DEV_SEL_OPS
;
821 /* Locate dmap entry */
822 for (i
= 0, dp
= dmap
; i
<NR_DEVICES
; i
++, dp
++)
824 if (dp
->dmap_driver
== driver_e
)
829 printf("select_reply2: proc %d is not a recognized driver\n",
833 dev
= (i
<< MAJOR
) | (minor
& BYTE
);
835 /* Find filedescriptors for this device */
836 for (s
= 0; s
<MAXSELECTS
; s
++)
838 if (selecttab
[s
].requestor
== NULL
)
839 continue; /* empty slot */
841 for (i
= 0; i
<OPEN_MAX
; i
++)
843 fp
= selecttab
[s
].filps
[i
];
849 if ((vp
->v_mode
& I_TYPE
) != I_CHAR_SPECIAL
)
852 if (vp
->v_sdev
!= dev
)
857 printf("select_reply2: should handle error\n");
861 /* Clear the replied bits from the request
862 * mask unless FSF_UPDATE is set.
864 if (!(fp
->filp_select_flags
& FSF_UPDATE
))
865 fp
->filp_select_ops
&= ~status
;
866 ops2tab(status
, i
, &selecttab
[s
]);
869 if (selecttab
[s
].nreadyfds
> 0)
875 PRIVATE
void sel_restart_dev()
882 /* Locate filps that can be restarted */
883 for (s
= 0; s
<MAXSELECTS
; s
++)
885 if (selecttab
[s
].requestor
== NULL
)
886 continue; /* empty slot */
887 if (!selecttab
[s
].deferred
)
888 continue; /* process is not waiting for an
891 for (i
= 0; i
<OPEN_MAX
; i
++)
893 fp
= selecttab
[s
].filps
[i
];
896 if (fp
->filp_select_flags
& FSF_BUSY
)
898 if (!(fp
->filp_select_flags
& FSF_UPDATE
))
905 "sel_restart_dev: FSF_UPDATE but no vp",
908 if ((vp
->v_mode
& I_TYPE
) != I_CHAR_SPECIAL
)
911 "sel_restart_dev: FSF_UPDATE but not char special",
915 dp
= &dmap
[((vp
->v_sdev
) >> MAJOR
) & BYTE
];
916 if (dp
->dmap_sel_filp
)
920 "sel_restart_dev: should consider fd %d in slot %d\n",
927 PRIVATE
void filp_status(fp
, status
)
933 /* Locate processes that need to know about this result */
934 for (s
= 0; s
<MAXSELECTS
; s
++)
936 if (selecttab
[s
].requestor
== NULL
) continue; /* empty slot */
938 for (i
= 0; i
<OPEN_MAX
; i
++)
940 if (selecttab
[s
].filps
[i
] != fp
)
945 printf("filp_status: should handle error\n");
948 ops2tab(status
, i
, &selecttab
[s
]);
956 PRIVATE
void restart_proc(slot
)
960 struct selectentry
*se
;
963 se
= &selecttab
[slot
];
966 for (fd
= se
->deferred_fd
; fd
< OPEN_MAX
; fd
++)
971 if (fp
->filp_select_flags
& (FSF_UPDATE
|FSF_BUSY
))
981 if (se
->nreadyfds
> 0 || !se
->block
) {
982 copy_fdsets(se
, se
->nfds
, TO_PROC
); /* FIXME, return error */
983 select_wakeup(se
, se
->nreadyfds
);
984 se
->requestor
= NULL
;
988 /*===========================================================================*
990 *===========================================================================*/
991 PRIVATE
void wipe_select(struct selectentry
*se
)
993 se
->deferred
= FALSE
;
996 /* memset(se->filps, 0, OPEN_MAX * sizeof(struct filp *)); */
997 memset(se
->filps
, 0, sizeof(se
->filps
));
999 FD_ZERO(&se
->readfds
);
1000 FD_ZERO(&se
->writefds
);
1001 FD_ZERO(&se
->errorfds
);
1002 FD_ZERO(&se
->ready_readfds
);
1003 FD_ZERO(&se
->ready_writefds
);
1004 FD_ZERO(&se
->ready_errorfds
);