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_unsuspend_by_endpt: cancel a blocking select on exiting driver
8 * The select code uses minimal locking, so that the replies from character
9 * drivers can be processed without blocking. Filps are locked only for pipes.
10 * We make the assumption that any other structures and fields are safe to
11 * check (and possibly change) as long as we know that a process is blocked on
12 * a select(2) call, meaning that all involved filps are guaranteed to stay
13 * open until either we finish the select call, it the process gets interrupted
18 #include <sys/fcntl.h>
20 #include <sys/select.h>
22 #include <minix/callnr.h>
23 #include <minix/u64.h>
30 /* max. number of simultaneously pending select() calls */
35 static struct selectentry
{
36 struct fproc
*requestor
; /* slot is free iff this is NULL */
38 fd_set readfds
, writefds
, errorfds
;
39 fd_set ready_readfds
, ready_writefds
, ready_errorfds
;
40 fd_set
*vir_readfds
, *vir_writefds
, *vir_errorfds
;
41 struct filp
*filps
[OPEN_MAX
];
48 minix_timer_t timer
; /* if expiry > 0 */
49 } selecttab
[MAXSELECTS
];
51 static int copy_fdsets(struct selectentry
*se
, int nfds
, int direction
);
52 static void filp_status(struct filp
*fp
, int status
);
53 static int is_deferred(struct selectentry
*se
);
54 static void restart_proc(struct selectentry
*se
);
55 static void ops2tab(int ops
, int fd
, struct selectentry
*e
);
56 static int is_regular_file(struct filp
*f
);
57 static int is_pipe(struct filp
*f
);
58 static int is_char_device(struct filp
*f
);
59 static void select_lock_filp(struct filp
*f
, int ops
);
60 static int select_request_file(struct filp
*f
, int *ops
, int block
,
62 static int select_request_char(struct filp
*f
, int *ops
, int block
,
64 static int select_request_pipe(struct filp
*f
, int *ops
, int block
,
66 static void select_cancel_all(struct selectentry
*e
);
67 static void select_cancel_filp(struct filp
*f
);
68 static void select_return(struct selectentry
*);
69 static void select_restart_filps(void);
70 static int tab2ops(int fd
, struct selectentry
*e
);
71 static void wipe_select(struct selectentry
*s
);
73 static struct fdtype
{
74 int (*select_request
)(struct filp
*, int *ops
, int block
,
76 int (*type_match
)(struct filp
*f
);
78 { select_request_char
, is_char_device
},
79 { select_request_file
, is_regular_file
},
80 { select_request_pipe
, is_pipe
},
82 #define SEL_FDS (sizeof(fdtypes) / sizeof(fdtypes[0]))
84 /*===========================================================================*
86 *===========================================================================*/
89 /* Implement the select(nfds, readfds, writefds, errorfds, timeout) system
90 * call. First we copy the arguments and verify their sanity. Then we check
91 * whether there are file descriptors that satisfy the select call right off
92 * the bat. If so, or if there are no ready file descriptors but the process
93 * requested to return immediately, we return the result. Otherwise we set a
94 * timeout and wait for either the file descriptors to become ready or the
95 * timer to go off. If no timeout value was provided, we wait indefinitely.
97 int r
, nfds
, do_timeout
= 0, fd
, s
;
99 unsigned int type
, ops
;
100 struct timeval timeout
;
101 struct selectentry
*se
;
104 nfds
= job_m_in
.m_lc_vfs_select
.nfds
;
105 vtimeout
= job_m_in
.m_lc_vfs_select
.timeout
;
107 /* Sane amount of file descriptors? */
108 if (nfds
< 0 || nfds
> OPEN_MAX
) return(EINVAL
);
110 /* Find a slot to store this select request */
111 for (s
= 0; s
< MAXSELECTS
; s
++)
112 if (selecttab
[s
].requestor
== NULL
) /* Unused slot */
114 if (s
>= MAXSELECTS
) return(ENOSPC
);
117 wipe_select(se
); /* Clear results of previous usage */
119 se
->req_endpt
= who_e
;
120 se
->vir_readfds
= job_m_in
.m_lc_vfs_select
.readfds
;
121 se
->vir_writefds
= job_m_in
.m_lc_vfs_select
.writefds
;
122 se
->vir_errorfds
= job_m_in
.m_lc_vfs_select
.errorfds
;
124 /* Copy fdsets from the process */
125 if ((r
= copy_fdsets(se
, nfds
, FROM_PROC
)) != OK
) {
126 se
->requestor
= NULL
;
130 /* Did the process set a timeout value? If so, retrieve it. */
133 r
= sys_datacopy_wrapper(who_e
, vtimeout
, SELF
, (vir_bytes
) &timeout
,
136 se
->requestor
= NULL
;
141 /* No nonsense in the timeval */
142 if (do_timeout
&& (timeout
.tv_sec
< 0 || timeout
.tv_usec
< 0)) {
143 se
->requestor
= NULL
;
147 /* If there is no timeout, we block forever. Otherwise, we block up to the
148 * specified time interval.
150 if (!do_timeout
) /* No timeout value set */
152 else if (do_timeout
&& (timeout
.tv_sec
> 0 || timeout
.tv_usec
> 0))
154 else /* timeout set as (0,0) - this effects a poll */
156 se
->expiry
= 0; /* no timer set (yet) */
158 /* We are going to lock filps, and that means that while locking a second
159 * filp, we might already get the results for the first one. In that case,
160 * the incoming results must not cause the select call to finish prematurely.
164 /* Verify that file descriptors are okay to select on */
165 for (fd
= 0; fd
< nfds
; fd
++) {
166 /* Because the select() interface implicitly includes file descriptors
167 * you might not want to select on, we have to figure out whether we're
168 * interested in them. Typically, these file descriptors include fd's
169 * inherited from the parent proc and file descriptors that have been
170 * close()d, but had a lower fd than one in the current set.
172 if (!(ops
= tab2ops(fd
, se
)))
173 continue; /* No operations set; nothing to do for this fd */
175 /* Get filp belonging to this fd */
176 f
= se
->filps
[fd
] = get_filp(fd
, VNODE_READ
);
178 if (err_code
== EBADF
)
180 else /* File descriptor is 'ready' to return EIO */
183 se
->requestor
= NULL
;
187 /* Check file types. According to POSIX 2008:
188 * "The pselect() and select() functions shall support regular files,
189 * terminal and pseudo-terminal devices, FIFOs, pipes, and sockets. The
190 * behavior of pselect() and select() on file descriptors that refer to
191 * other types of file is unspecified."
193 * In our case, terminal and pseudo-terminal devices are handled by the
194 * TTY major and sockets by either INET major (socket type AF_INET) or
195 * UDS major (socket type AF_UNIX). Additionally, we give other
196 * character drivers the chance to handle select for any of their
197 * device nodes. Some may not implement support for select and let
198 * libchardriver return EBADF, which we then pass to the calling
199 * process once we receive the reply.
202 for (type
= 0; type
< SEL_FDS
; type
++) {
203 if (fdtypes
[type
].type_match(f
)) {
206 se
->filps
[fd
]->filp_selectors
++;
211 if (se
->type
[fd
] == -1) { /* Type not found */
212 se
->requestor
= NULL
;
217 /* Check all file descriptors in the set whether one is 'ready' now */
218 for (fd
= 0; fd
< nfds
; fd
++) {
219 /* Again, check for involuntarily selected fd's */
220 if (!(ops
= tab2ops(fd
, se
)))
221 continue; /* No operations set; nothing to do for this fd */
223 /* File descriptors selected for reading that are not opened for
224 * reading should be marked as readable, as read calls would fail
225 * immediately. The same applies to writing.
228 if ((ops
& SEL_RD
) && !(f
->filp_mode
& R_BIT
)) {
229 ops2tab(SEL_RD
, fd
, se
);
232 if ((ops
& SEL_WR
) && !(f
->filp_mode
& W_BIT
)) {
233 ops2tab(SEL_WR
, fd
, se
);
236 /* Test filp for select operations if not already done so. e.g.,
237 * processes sharing a filp and both doing a select on that filp. */
238 if ((f
->filp_select_ops
& ops
) != ops
) {
241 wantops
= (f
->filp_select_ops
|= ops
);
243 select_lock_filp(f
, wantops
);
244 r
= fdtypes
[type
].select_request(f
, &wantops
, se
->block
, fp
);
246 if (r
!= OK
&& r
!= SUSPEND
) {
248 break; /* Error or bogus return code; abort */
251 /* The select request above might have turned on/off some
252 * operations because they were 'ready' or not meaningful.
253 * Either way, we might have a result and we need to store them
254 * in the select table entry. */
255 if (wantops
& ops
) ops2tab(wantops
, fd
, se
);
259 /* At this point there won't be any blocking calls anymore. */
260 se
->starting
= FALSE
;
262 if ((se
->nreadyfds
> 0 || se
->error
!= OK
|| !se
->block
) &&
264 /* An error occurred, or fd's were found that were ready to go right
265 * away, and/or we were instructed not to block at all. Must return
266 * immediately. Do not copy FD sets if an error occurred.
271 r
= copy_fdsets(se
, se
->nfds
, TO_PROC
);
272 select_cancel_all(se
);
273 se
->requestor
= NULL
;
277 return(se
->nreadyfds
);
280 /* Convert timeval to ticks and set the timer. If it fails, undo
286 * "If the requested timeout interval requires a finer
287 * granularity than the implementation supports, the
288 * actual timeout interval shall be rounded up to the next
291 #define USECPERSEC 1000000
292 while(timeout
.tv_usec
>= USECPERSEC
) {
293 /* this is to avoid overflow with *system_hz below */
294 timeout
.tv_usec
-= USECPERSEC
;
297 ticks
= timeout
.tv_sec
* system_hz
+
298 (timeout
.tv_usec
* system_hz
+ USECPERSEC
-1) / USECPERSEC
;
300 set_timer(&se
->timer
, ticks
, select_timeout_check
, s
);
303 /* process now blocked */
304 suspend(FP_BLOCKED_ON_SELECT
);
308 /*===========================================================================*
310 *===========================================================================*/
311 static int is_deferred(struct selectentry
*se
)
313 /* Find out whether this select has pending initial replies */
318 /* The select call must have finished its initialization at all. */
319 if (se
->starting
) return(TRUE
);
321 for (fd
= 0; fd
< se
->nfds
; fd
++) {
322 if ((f
= se
->filps
[fd
]) == NULL
) continue;
323 if (f
->filp_select_flags
& (FSF_UPDATE
|FSF_BUSY
)) return(TRUE
);
330 /*===========================================================================*
332 *===========================================================================*/
333 static int is_regular_file(struct filp
*f
)
335 return(f
&& f
->filp_vno
&& S_ISREG(f
->filp_vno
->v_mode
));
338 /*===========================================================================*
340 *===========================================================================*/
341 static int is_pipe(struct filp
*f
)
343 /* Recognize either anonymous pipe or named pipe (FIFO) */
344 return(f
&& f
->filp_vno
&& S_ISFIFO(f
->filp_vno
->v_mode
));
347 /*===========================================================================*
349 *===========================================================================*/
350 static int is_char_device(struct filp
*f
)
352 /* See if this filp is a handle on a character device. This function MUST NOT
353 * block its calling thread. The given filp may or may not be locked.
356 return (f
&& f
->filp_vno
&& S_ISCHR(f
->filp_vno
->v_mode
));
359 /*===========================================================================*
360 * select_request_char *
361 *===========================================================================*/
362 static int select_request_char(struct filp
*f
, int *ops
, int block
,
365 /* Check readiness status on a character device. Unless suitable results are
366 * available right now, this will only initiate the polling process, causing
367 * result processing to be deferred. This function MUST NOT block its calling
368 * thread. The given filp may or may not be locked.
374 /* Start by remapping the device node number to a "real" device number. Those
375 * two are different only for CTTY_MAJOR aka /dev/tty, but that one single
376 * exception requires quite some extra effort here: the select code matches
377 * character driver replies to their requests based on the device number, so
378 * it needs to be aware that device numbers may be mapped. The idea is to
379 * perform the mapping once and store the result in the filp object, so that
380 * at least we don't run into problems when a process loses its controlling
381 * terminal while doing a select (see also free_proc). It should be noted
382 * that it is possible that multiple processes share the same /dev/tty filp,
383 * and they may not all have a controlling terminal. The ctty-less processes
384 * should never pass the mapping; a more problematic case is checked below.
386 * The cdev_map call also checks the major number for rough validity, so that
387 * we can use it to index the dmap array safely a bit later.
389 if ((dev
= cdev_map(f
->filp_vno
->v_sdev
, rfp
)) == NO_DEV
)
392 if (f
->filp_char_select_dev
!= NO_DEV
&& f
->filp_char_select_dev
!= dev
) {
393 /* Currently, this case can occur as follows: a process with a
394 * controlling terminal opens /dev/tty and forks, the new child starts
395 * a new session, opens a new controlling terminal, and both parent and
396 * child call select on the /dev/tty file descriptor. If this case ever
397 * becomes real, a better solution may be to force-close a filp for
398 * /dev/tty when a new controlling terminal is opened.
400 printf("VFS: file pointer has multiple controlling TTYs!\n");
403 f
->filp_char_select_dev
= dev
; /* set before possibly suspending */
407 /* By default, nothing to do */
410 if (!block
&& (f
->filp_select_flags
& FSF_BLOCKED
)) {
411 /* This filp is blocked waiting for a reply, but we don't want to
412 * block ourselves. Unless we're awaiting the initial reply, these
413 * operations won't be ready */
414 if (!(f
->filp_select_flags
& FSF_BUSY
)) {
415 if ((rops
& SEL_RD
) && (f
->filp_select_flags
& FSF_RD_BLOCK
))
417 if ((rops
& SEL_WR
) && (f
->filp_select_flags
& FSF_WR_BLOCK
))
419 if ((rops
& SEL_ERR
) && (f
->filp_select_flags
& FSF_ERR_BLOCK
))
421 if (!(rops
& (SEL_RD
|SEL_WR
|SEL_ERR
)))
426 f
->filp_select_flags
|= FSF_UPDATE
;
429 if (rops
& SEL_RD
) f
->filp_select_flags
|= FSF_RD_BLOCK
;
430 if (rops
& SEL_WR
) f
->filp_select_flags
|= FSF_WR_BLOCK
;
431 if (rops
& SEL_ERR
) f
->filp_select_flags
|= FSF_ERR_BLOCK
;
434 if (f
->filp_select_flags
& FSF_BUSY
)
437 dp
= &dmap
[major(dev
)];
438 if (dp
->dmap_sel_busy
)
441 f
->filp_select_flags
&= ~FSF_UPDATE
;
442 r
= cdev_select(dev
, rops
);
446 dp
->dmap_sel_busy
= TRUE
;
447 dp
->dmap_sel_filp
= f
;
448 f
->filp_select_flags
|= FSF_BUSY
;
453 /*===========================================================================*
454 * select_request_file *
455 *===========================================================================*/
456 static int select_request_file(struct filp
*UNUSED(f
), int *UNUSED(ops
),
457 int UNUSED(block
), struct fproc
*UNUSED(rfp
))
459 /* Files are always ready, so output *ops is input *ops */
463 /*===========================================================================*
464 * select_request_pipe *
465 *===========================================================================*/
466 static int select_request_pipe(struct filp
*f
, int *ops
, int block
,
467 struct fproc
*UNUSED(rfp
))
469 /* Check readiness status on a pipe. The given filp is locked. This function
470 * may block its calling thread if necessary.
472 int orig_ops
, r
= 0, err
;
476 if ((*ops
& (SEL_RD
|SEL_ERR
))) {
477 /* Check if we can read 1 byte */
478 err
= pipe_check(f
, READING
, f
->filp_flags
& ~O_NONBLOCK
, 1,
483 if (err
< 0 && err
!= SUSPEND
)
487 if ((*ops
& (SEL_WR
|SEL_ERR
))) {
488 /* Check if we can write 1 byte */
489 err
= pipe_check(f
, WRITING
, f
->filp_flags
& ~O_NONBLOCK
, 1,
494 if (err
< 0 && err
!= SUSPEND
)
498 /* Some options we collected might not be requested. */
502 f
->filp_pipe_select_ops
|= orig_ops
;
507 /*===========================================================================*
509 *===========================================================================*/
510 static int tab2ops(int fd
, struct selectentry
*e
)
513 if (FD_ISSET(fd
, &e
->readfds
)) ops
|= SEL_RD
;
514 if (FD_ISSET(fd
, &e
->writefds
)) ops
|= SEL_WR
;
515 if (FD_ISSET(fd
, &e
->errorfds
)) ops
|= SEL_ERR
;
521 /*===========================================================================*
523 *===========================================================================*/
524 static void ops2tab(int ops
, int fd
, struct selectentry
*e
)
526 if ((ops
& SEL_RD
) && e
->vir_readfds
&& FD_ISSET(fd
, &e
->readfds
) &&
527 !FD_ISSET(fd
, &e
->ready_readfds
)) {
528 FD_SET(fd
, &e
->ready_readfds
);
532 if ((ops
& SEL_WR
) && e
->vir_writefds
&& FD_ISSET(fd
, &e
->writefds
) &&
533 !FD_ISSET(fd
, &e
->ready_writefds
)) {
534 FD_SET(fd
, &e
->ready_writefds
);
538 if ((ops
& SEL_ERR
) && e
->vir_errorfds
&& FD_ISSET(fd
, &e
->errorfds
) &&
539 !FD_ISSET(fd
, &e
->ready_errorfds
)) {
540 FD_SET(fd
, &e
->ready_errorfds
);
546 /*===========================================================================*
548 *===========================================================================*/
549 static int copy_fdsets(struct selectentry
*se
, int nfds
, int direction
)
551 /* Copy FD sets from or to the user process calling select(2). This function
552 * MUST NOT block the calling thread.
556 endpoint_t src_e
, dst_e
;
557 fd_set
*src_fds
, *dst_fds
;
559 if (nfds
< 0 || nfds
> OPEN_MAX
)
560 panic("select copy_fdsets: nfds wrong: %d", nfds
);
562 /* Only copy back as many bits as the user expects. */
563 fd_setsize
= (size_t) (howmany(nfds
, __NFDBITS
) * sizeof(__fd_mask
));
565 /* Set source and destination endpoints */
566 src_e
= (direction
== FROM_PROC
) ? se
->req_endpt
: SELF
;
567 dst_e
= (direction
== FROM_PROC
) ? SELF
: se
->req_endpt
;
570 src_fds
= (direction
== FROM_PROC
) ? se
->vir_readfds
: &se
->ready_readfds
;
571 dst_fds
= (direction
== FROM_PROC
) ? &se
->readfds
: se
->vir_readfds
;
572 if (se
->vir_readfds
) {
573 r
= sys_datacopy_wrapper(src_e
, (vir_bytes
) src_fds
, dst_e
,
574 (vir_bytes
) dst_fds
, fd_setsize
);
575 if (r
!= OK
) return(r
);
579 src_fds
= (direction
== FROM_PROC
) ? se
->vir_writefds
: &se
->ready_writefds
;
580 dst_fds
= (direction
== FROM_PROC
) ? &se
->writefds
: se
->vir_writefds
;
581 if (se
->vir_writefds
) {
582 r
= sys_datacopy_wrapper(src_e
, (vir_bytes
) src_fds
, dst_e
,
583 (vir_bytes
) dst_fds
, fd_setsize
);
584 if (r
!= OK
) return(r
);
588 src_fds
= (direction
== FROM_PROC
) ? se
->vir_errorfds
: &se
->ready_errorfds
;
589 dst_fds
= (direction
== FROM_PROC
) ? &se
->errorfds
: se
->vir_errorfds
;
590 if (se
->vir_errorfds
) {
591 r
= sys_datacopy_wrapper(src_e
, (vir_bytes
) src_fds
, dst_e
,
592 (vir_bytes
) dst_fds
, fd_setsize
);
593 if (r
!= OK
) return(r
);
600 /*===========================================================================*
601 * select_cancel_all *
602 *===========================================================================*/
603 static void select_cancel_all(struct selectentry
*se
)
605 /* Cancel select, possibly on success. Decrease select usage and cancel timer.
606 * This function MUST NOT block its calling thread.
612 for (fd
= 0; fd
< se
->nfds
; fd
++) {
613 if ((f
= se
->filps
[fd
]) == NULL
) continue;
614 se
->filps
[fd
] = NULL
;
615 select_cancel_filp(f
);
618 if (se
->expiry
> 0) {
619 cancel_timer(&se
->timer
);
623 se
->requestor
= NULL
;
626 /*===========================================================================*
627 * select_cancel_filp *
628 *===========================================================================*/
629 static void select_cancel_filp(struct filp
*f
)
631 /* Reduce the number of select users of this filp. This function MUST NOT block
632 * its calling thread.
637 assert(f
->filp_selectors
> 0);
638 assert(f
->filp_count
> 0);
641 if (f
->filp_selectors
== 0) {
642 /* No one selecting on this filp anymore, forget about select state */
643 f
->filp_select_ops
= 0;
644 f
->filp_select_flags
= 0;
645 f
->filp_pipe_select_ops
= 0;
647 /* If this filp is the subject of an ongoing select query to a
648 * character device, mark the query as stale, so that this filp will
649 * not be checked when the result arrives. The filp select device may
650 * still be NO_DEV if do_select fails on the initial fd check.
652 if (is_char_device(f
) && f
->filp_char_select_dev
!= NO_DEV
) {
653 major
= major(f
->filp_char_select_dev
);
654 if (dmap
[major
].dmap_sel_busy
&&
655 dmap
[major
].dmap_sel_filp
== f
)
656 dmap
[major
].dmap_sel_filp
= NULL
; /* leave _busy set */
657 f
->filp_char_select_dev
= NO_DEV
;
662 /*===========================================================================*
664 *===========================================================================*/
665 static void select_return(struct selectentry
*se
)
667 /* Return the results of a select call to the user process and revive the
668 * process. This function MUST NOT block its calling thread.
672 assert(!is_deferred(se
)); /* Not done yet, first wait for async reply */
674 select_cancel_all(se
);
679 r
= copy_fdsets(se
, se
->nfds
, TO_PROC
);
683 revive(se
->req_endpt
, r
);
687 /*===========================================================================*
689 *===========================================================================*/
690 void select_callback(struct filp
*f
, int status
)
692 /* The status of a filp has changed, with the given ready operations or error.
693 * This function is currently called only for pipes, and holds the lock to
697 filp_status(f
, status
);
700 /*===========================================================================*
702 *===========================================================================*/
703 void init_select(void)
707 for (s
= 0; s
< MAXSELECTS
; s
++)
708 init_timer(&selecttab
[s
].timer
);
712 /*===========================================================================*
714 *===========================================================================*/
715 void select_forget(void)
717 /* The calling thread's associated process is expected to be unpaused, due to
718 * a signal that is supposed to interrupt the current system call. Totally
719 * forget about the select(). This function may block its calling thread if
720 * necessary (but it doesn't).
723 struct selectentry
*se
;
725 for (slot
= 0; slot
< MAXSELECTS
; slot
++) {
726 se
= &selecttab
[slot
];
727 if (se
->requestor
== fp
)
731 if (slot
>= MAXSELECTS
) return; /* Entry not found */
733 assert(se
->starting
== FALSE
);
735 /* Do NOT test on is_deferred here. We can safely cancel ongoing queries. */
736 select_cancel_all(se
);
740 /*===========================================================================*
741 * select_timeout_check *
742 *===========================================================================*/
743 void select_timeout_check(minix_timer_t
*timer
)
745 /* An alarm has gone off for one of the select queries. This function MUST NOT
746 * block its calling thread.
749 struct selectentry
*se
;
751 s
= tmr_arg(timer
)->ta_int
;
752 if (s
< 0 || s
>= MAXSELECTS
) return; /* Entry does not exist */
755 if (se
->requestor
== NULL
) return;
756 if (se
->expiry
<= 0) return; /* Strange, did we even ask for a timeout? */
758 if (is_deferred(se
)) return; /* Wait for initial replies to CDEV_SELECT */
763 /*===========================================================================*
764 * select_unsuspend_by_endpt *
765 *===========================================================================*/
766 void select_unsuspend_by_endpt(endpoint_t proc_e
)
768 /* Revive blocked processes when a driver has disappeared */
771 struct selectentry
*se
;
774 for (s
= 0; s
< MAXSELECTS
; s
++) {
777 if (se
->requestor
== NULL
) continue;
778 if (se
->requestor
->fp_endpoint
== proc_e
) {
779 assert(se
->requestor
->fp_flags
& FP_EXITING
);
780 select_cancel_all(se
);
784 for (fd
= 0; fd
< se
->nfds
; fd
++) {
785 if ((f
= se
->filps
[fd
]) == NULL
|| !is_char_device(f
))
788 assert(f
->filp_char_select_dev
!= NO_DEV
);
789 major
= major(f
->filp_char_select_dev
);
790 if (dmap_driver_match(proc_e
, major
)) {
791 se
->filps
[fd
] = NULL
;
793 select_cancel_filp(f
);
798 if (wakehim
&& !is_deferred(se
))
803 /*===========================================================================*
805 *===========================================================================*/
806 void select_reply1(endpoint_t driver_e
, devminor_t minor
, int status
)
808 /* Handle the initial reply to CDEV_SELECT request. This function MUST NOT
809 * block its calling thread.
816 /* Figure out which device is replying */
817 if ((dp
= get_dmap(driver_e
)) == NULL
) return;
820 dev
= makedev(major
, minor
);
822 /* Get filp belonging to character special file */
823 if (!dp
->dmap_sel_busy
) {
824 printf("VFS (%s:%d): major %d was not expecting a CDEV_SELECT reply\n",
825 __FILE__
, __LINE__
, major
);
829 /* The select filp may have been set to NULL if the requestor has been
830 * unpaused in the meantime. In that case, we ignore the result, but we do
831 * look for other filps to restart later.
833 if ((f
= dp
->dmap_sel_filp
) != NULL
) {
834 /* Find vnode and check we got a reply from the device we expected */
835 assert(is_char_device(f
));
836 assert(f
->filp_char_select_dev
!= NO_DEV
);
837 if (f
->filp_char_select_dev
!= dev
) {
838 /* This should never happen. The driver may be misbehaving.
839 * For now we assume that the reply we want will arrive later..
841 printf("VFS (%s:%d): expected reply from dev %llx not %llx\n",
842 __FILE__
, __LINE__
, f
->filp_char_select_dev
, dev
);
847 /* No longer waiting for a reply from this device */
848 dp
->dmap_sel_busy
= FALSE
;
849 dp
->dmap_sel_filp
= NULL
;
851 /* Process the select result only if the filp is valid. */
853 assert(f
->filp_count
>= 1);
854 assert(f
->filp_select_flags
& FSF_BUSY
);
856 f
->filp_select_flags
&= ~FSF_BUSY
;
858 /* The select call is done now, except when
859 * - another process started a select on the same filp with possibly a
860 * different set of operations.
861 * - a process does a select on the same filp but using different file
863 * - the select has a timeout. Upon receiving this reply the operations
864 * might not be ready yet, so we want to wait for that to ultimately
866 * Therefore we need to keep remembering what the operations are.
868 if (!(f
->filp_select_flags
& (FSF_UPDATE
|FSF_BLOCKED
)))
869 f
->filp_select_ops
= 0; /* done selecting */
870 else if (status
> 0 && !(f
->filp_select_flags
& FSF_UPDATE
))
871 /* there may be operations pending */
872 f
->filp_select_ops
&= ~status
;
874 /* Record new filp status */
875 if (!(status
== 0 && (f
->filp_select_flags
& FSF_BLOCKED
))) {
876 if (status
> 0) { /* operations ready */
878 f
->filp_select_flags
&= ~FSF_RD_BLOCK
;
880 f
->filp_select_flags
&= ~FSF_WR_BLOCK
;
881 if (status
& SEL_ERR
)
882 f
->filp_select_flags
&= ~FSF_ERR_BLOCK
;
883 } else if (status
< 0) { /* error */
884 /* Always unblock upon error */
885 f
->filp_select_flags
&= ~FSF_BLOCKED
;
889 filp_status(f
, status
); /* Tell filp owners about the results */
892 select_restart_filps();
896 /*===========================================================================*
898 *===========================================================================*/
899 void select_reply2(endpoint_t driver_e
, devminor_t minor
, int status
)
901 /* Handle secondary reply to DEV_SELECT request. A secondary reply occurs when
902 * the select request is 'blocking' until an operation becomes ready. This
903 * function MUST NOT block its calling thread.
910 struct selectentry
*se
;
913 printf("VFS (%s:%d): weird status (%d) to report\n",
914 __FILE__
, __LINE__
, status
);
918 /* Figure out which device is replying */
919 if ((dp
= get_dmap(driver_e
)) == NULL
) {
920 printf("VFS (%s:%d): endpoint %d is not a known driver endpoint\n",
921 __FILE__
, __LINE__
, driver_e
);
925 dev
= makedev(major
, minor
);
927 /* Find all file descriptors selecting for this device */
928 for (slot
= 0; slot
< MAXSELECTS
; slot
++) {
929 se
= &selecttab
[slot
];
930 if (se
->requestor
== NULL
) continue; /* empty slot */
933 for (fd
= 0; fd
< se
->nfds
; fd
++) {
934 if ((f
= se
->filps
[fd
]) == NULL
) continue;
935 if (!is_char_device(f
)) continue;
936 assert(f
->filp_char_select_dev
!= NO_DEV
);
937 if (f
->filp_char_select_dev
!= dev
) continue;
939 if (status
> 0) { /* Operations ready */
940 /* Clear the replied bits from the request
941 * mask unless FSF_UPDATE is set.
943 if (!(f
->filp_select_flags
& FSF_UPDATE
))
944 f
->filp_select_ops
&= ~status
;
946 f
->filp_select_flags
&= ~FSF_RD_BLOCK
;
948 f
->filp_select_flags
&= ~FSF_WR_BLOCK
;
949 if (status
& SEL_ERR
)
950 f
->filp_select_flags
&= ~FSF_ERR_BLOCK
;
952 ops2tab(status
, fd
, se
);
954 f
->filp_select_flags
&= ~FSF_BLOCKED
;
959 /* Even if 'found' is set now, nothing may have changed for this call,
960 * as it may not have been interested in the operations that were
961 * reported as ready. Let restart_proc check.
967 select_restart_filps();
970 /*===========================================================================*
971 * select_restart_filps *
972 *===========================================================================*/
973 static void select_restart_filps(void)
975 /* We got a result from a character driver, and now we need to check if we can
976 * restart deferred polling operations. This function MUST NOT block its
981 struct selectentry
*se
;
983 /* Locate filps that can be restarted */
984 for (slot
= 0; slot
< MAXSELECTS
; slot
++) {
985 se
= &selecttab
[slot
];
986 if (se
->requestor
== NULL
) continue; /* empty slot */
988 /* Only 'deferred' processes are eligible to restart */
989 if (!is_deferred(se
)) continue;
991 /* Find filps that are not waiting for a reply, but have an updated
992 * status (i.e., another select on the same filp with possibly a
993 * different set of operations is to be done), and thus requires the
994 * select request to be sent again).
996 for (fd
= 0; fd
< se
->nfds
; fd
++) {
998 if ((f
= se
->filps
[fd
]) == NULL
) continue;
999 if (f
->filp_select_flags
& FSF_BUSY
) /* Still waiting for */
1000 continue; /* initial reply */
1001 if (!(f
->filp_select_flags
& FSF_UPDATE
)) /* Must be in */
1002 continue; /* 'update' state */
1004 /* This function is suitable only for character devices. In
1005 * particular, checking pipes the same way would introduce a
1006 * serious locking problem.
1008 assert(is_char_device(f
));
1010 wantops
= ops
= f
->filp_select_ops
;
1011 r
= select_request_char(f
, &wantops
, se
->block
, se
->requestor
);
1012 if (r
!= OK
&& r
!= SUSPEND
) {
1015 break; /* Error or bogus return code; abort */
1017 if (wantops
& ops
) ops2tab(wantops
, fd
, se
);
1022 /*===========================================================================*
1024 *===========================================================================*/
1025 static void filp_status(f
, status
)
1029 /* Tell processes that need to know about the status of this filp. This
1030 * function MUST NOT block its calling thread.
1032 int fd
, slot
, found
;
1033 struct selectentry
*se
;
1035 for (slot
= 0; slot
< MAXSELECTS
; slot
++) {
1036 se
= &selecttab
[slot
];
1037 if (se
->requestor
== NULL
) continue; /* empty slot */
1040 for (fd
= 0; fd
< se
->nfds
; fd
++) {
1041 if (se
->filps
[fd
] != f
) continue;
1045 ops2tab(status
, fd
, se
);
1053 /*===========================================================================*
1055 *===========================================================================*/
1056 static void restart_proc(se
)
1057 struct selectentry
*se
;
1059 /* Tell process about select results (if any) unless there are still results
1060 * pending. This function MUST NOT block its calling thread.
1063 if ((se
->nreadyfds
> 0 || se
->error
!= OK
|| !se
->block
) && !is_deferred(se
))
1067 /*===========================================================================*
1069 *===========================================================================*/
1070 static void wipe_select(struct selectentry
*se
)
1076 memset(se
->filps
, 0, sizeof(se
->filps
));
1078 FD_ZERO(&se
->readfds
);
1079 FD_ZERO(&se
->writefds
);
1080 FD_ZERO(&se
->errorfds
);
1081 FD_ZERO(&se
->ready_readfds
);
1082 FD_ZERO(&se
->ready_writefds
);
1083 FD_ZERO(&se
->ready_errorfds
);
1086 /*===========================================================================*
1087 * select_lock_filp *
1088 *===========================================================================*/
1089 static void select_lock_filp(struct filp
*f
, int ops
)
1091 /* Lock a filp and vnode based on which operations are requested. This function
1092 * may block its calling thread, obviously.
1094 tll_access_t locktype
;
1096 locktype
= VNODE_READ
; /* By default */
1098 if (ops
& (SEL_WR
|SEL_ERR
))
1099 /* Selecting for error or writing requires exclusive access */
1100 locktype
= VNODE_WRITE
;
1102 lock_filp(f
, locktype
);