Clean up and fix multiple bugs in select:
- Remove redundant code. - Always wait for the initial reply from an asynchronous select request, even if the select has been satisfied on another file descriptor or was canceled due to a serious error. - Restart asynchronous selects if upon reply from the driver turns out that there are deferred operations (and do not forget we're still interested in the results of the deferred operations). - Do not hang a non-blocking select when another blocking select on the same filp is still blocking. - Split blocking operations in read, write, and exceptions (i.e., blocking on read does not imply the write will block as well). - Some loops would iterate over OPEN_MAX file descriptors instead of the "highest" file descriptor. - Use proper internal error return values. - A secondary reply from a synchronous driver is essentially the same as from an asynchronous driver (the only difference being how the answer is received). Merge. - Return proper error code after a driver failure. - Auto-detect whether a driver is synchronous or asynchronous. - Remove some code duplication. - Clean up code (coding style, add missing comments, put all select related code together).
This commit is contained in:
parent
f0740680cd
commit
aba392e630
8 changed files with 646 additions and 595 deletions
|
@ -183,7 +183,7 @@ PUBLIC void dev_status(message *m)
|
||||||
revive(endpt, st.REP_STATUS);
|
revive(endpt, st.REP_STATUS);
|
||||||
break;
|
break;
|
||||||
case DEV_IO_READY:
|
case DEV_IO_READY:
|
||||||
select_notified(d, st.DEV_MINOR,
|
select_reply2(st.m_source, st.DEV_MINOR,
|
||||||
st.DEV_SEL_OPS);
|
st.DEV_SEL_OPS);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -242,3 +242,20 @@ PUBLIC void dmap_endpt_up(int proc_e)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* get_dmap *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC struct dmap *get_dmap(endpoint_t proc_e)
|
||||||
|
{
|
||||||
|
/* See if 'proc_e' endpoint belongs to a valid dmap entry. If so, return a
|
||||||
|
* pointer */
|
||||||
|
|
||||||
|
int major;
|
||||||
|
for (major = 0; major < NR_DEVICES; major++)
|
||||||
|
if (dmap_driver_match(proc_e, major))
|
||||||
|
return(&dmap[major]);
|
||||||
|
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef __VFS_DMAP_H__
|
||||||
|
#define __VFS_DMAP_H__
|
||||||
|
|
||||||
/*
|
/*
|
||||||
dmap.h
|
dmap.h
|
||||||
*/
|
*/
|
||||||
|
@ -21,3 +24,5 @@ extern struct dmap {
|
||||||
int dmap_style;
|
int dmap_style;
|
||||||
struct filp *dmap_sel_filp;
|
struct filp *dmap_sel_filp;
|
||||||
} dmap[];
|
} dmap[];
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef __VFS_FILE_H__
|
||||||
|
#define __VFS_FILE_H__
|
||||||
|
|
||||||
/* This is the filp table. It is an intermediary between file descriptors and
|
/* This is the filp table. It is an intermediary between file descriptors and
|
||||||
* inodes. A slot is free if filp_count == 0.
|
* inodes. A slot is free if filp_count == 0.
|
||||||
*/
|
*/
|
||||||
|
@ -7,10 +10,7 @@ EXTERN struct filp {
|
||||||
int filp_flags; /* flags from open and fcntl */
|
int filp_flags; /* flags from open and fcntl */
|
||||||
int filp_state; /* state for crash recovery */
|
int filp_state; /* state for crash recovery */
|
||||||
int filp_count; /* how many file descriptors share this slot?*/
|
int filp_count; /* how many file descriptors share this slot?*/
|
||||||
/* struct inode *filp_ino;*/ /* pointer to the inode */
|
struct vnode *filp_vno; /* vnode belonging to this file */
|
||||||
|
|
||||||
struct vnode *filp_vno;
|
|
||||||
|
|
||||||
u64_t filp_pos; /* file position */
|
u64_t filp_pos; /* file position */
|
||||||
|
|
||||||
/* the following fields are for select() and are owned by the generic
|
/* the following fields are for select() and are owned by the generic
|
||||||
|
@ -29,13 +29,17 @@ EXTERN struct filp {
|
||||||
#define FS_NORMAL 0 /* file descriptor can be used normally */
|
#define FS_NORMAL 0 /* file descriptor can be used normally */
|
||||||
#define FS_NEEDS_REOPEN 1 /* file descriptor needs to be re-opened */
|
#define FS_NEEDS_REOPEN 1 /* file descriptor needs to be re-opened */
|
||||||
|
|
||||||
#define FSF_UPDATE 1 /* The driver should be informed about new
|
#define FSF_UPDATE 001 /* The driver should be informed about new
|
||||||
* state.
|
* state.
|
||||||
*/
|
*/
|
||||||
#define FSF_BUSY 2 /* Select operation sent to driver but no
|
#define FSF_BUSY 002 /* Select operation sent to driver but no
|
||||||
* reply yet.
|
* reply yet.
|
||||||
*/
|
*/
|
||||||
#define FSF_BLOCK 4 /* Request is blocking, the driver should
|
#define FSF_RD_BLOCK 010 /* Read request is blocking, the driver should
|
||||||
* keep state.
|
* keep state.
|
||||||
*/
|
*/
|
||||||
|
#define FSF_WR_BLOCK 020 /* Write request is blocking */
|
||||||
|
#define FSF_ERR_BLOCK 040 /* Exception request is blocking */
|
||||||
|
#define FSF_BLOCKED 070
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -95,12 +95,12 @@ PUBLIC int main(void)
|
||||||
}
|
}
|
||||||
if (call_nr == DEV_SEL_REPL1)
|
if (call_nr == DEV_SEL_REPL1)
|
||||||
{
|
{
|
||||||
select_reply1();
|
select_reply1(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (call_nr == DEV_SEL_REPL2)
|
if (call_nr == DEV_SEL_REPL2)
|
||||||
{
|
{
|
||||||
select_reply2();
|
select_reply2(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -328,20 +328,18 @@ size_t size;
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC void unsuspend_by_endpt(endpoint_t proc_e)
|
PUBLIC void unsuspend_by_endpt(endpoint_t proc_e)
|
||||||
{
|
{
|
||||||
|
/* Revive processes waiting for drivers (SUSPENDed) that have disappeared with
|
||||||
|
* return code EAGAIN.
|
||||||
|
*/
|
||||||
struct fproc *rp;
|
struct fproc *rp;
|
||||||
|
|
||||||
/* Revive processes waiting for drivers (SUSPENDed) that have
|
for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++) {
|
||||||
* disappeared with return code EAGAIN.
|
if (rp->fp_pid == PID_FREE) continue;
|
||||||
*/
|
if (rp->fp_blocked_on == FP_BLOCKED_ON_OTHER && rp->fp_task == proc_e)
|
||||||
for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++)
|
|
||||||
if(rp->fp_pid != PID_FREE &&
|
|
||||||
rp->fp_blocked_on == FP_BLOCKED_ON_OTHER && rp->fp_task == proc_e) {
|
|
||||||
revive(rp->fp_endpoint, EAGAIN);
|
revive(rp->fp_endpoint, EAGAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Revive processes waiting in drivers on select()s
|
/* Revive processes waiting in drivers on select()s with EAGAIN too */
|
||||||
* with EAGAIN too.
|
|
||||||
*/
|
|
||||||
select_unsuspend_by_endpt(proc_e);
|
select_unsuspend_by_endpt(proc_e);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -36,14 +36,15 @@ _PROTOTYPE( endpoint_t suspended_ep, (endpoint_t driver,
|
||||||
_PROTOTYPE( void reopen_reply, (void) );
|
_PROTOTYPE( void reopen_reply, (void) );
|
||||||
|
|
||||||
/* dmap.c */
|
/* dmap.c */
|
||||||
_PROTOTYPE( int do_mapdriver, (void) );
|
|
||||||
_PROTOTYPE( int map_service, (struct rprocpub *rpub) );
|
|
||||||
_PROTOTYPE( void build_dmap, (void) );
|
_PROTOTYPE( void build_dmap, (void) );
|
||||||
|
_PROTOTYPE( int do_mapdriver, (void) );
|
||||||
|
_PROTOTYPE( int dmap_driver_match, (endpoint_t proc, int major) );
|
||||||
|
_PROTOTYPE( void dmap_endpt_up, (int proc_nr) );
|
||||||
|
_PROTOTYPE( void dmap_unmap_by_endpt, (int proc_nr) );
|
||||||
|
_PROTOTYPE( struct dmap *get_dmap, (endpoint_t proc_e) );
|
||||||
_PROTOTYPE( int map_driver, (const char *label, int major, endpoint_t proc_nr,
|
_PROTOTYPE( int map_driver, (const char *label, int major, endpoint_t proc_nr,
|
||||||
int dev_style, int flags) );
|
int dev_style, int flags) );
|
||||||
_PROTOTYPE( int dmap_driver_match, (endpoint_t proc, int major) );
|
_PROTOTYPE( int map_service, (struct rprocpub *rpub) );
|
||||||
_PROTOTYPE( void dmap_unmap_by_endpt, (int proc_nr) );
|
|
||||||
_PROTOTYPE( void dmap_endpt_up, (int proc_nr) );
|
|
||||||
|
|
||||||
/* exec.c */
|
/* exec.c */
|
||||||
_PROTOTYPE( int pm_exec, (int proc_e, char *path, vir_bytes path_len,
|
_PROTOTYPE( int pm_exec, (int proc_e, char *path, vir_bytes path_len,
|
||||||
|
@ -150,11 +151,7 @@ _PROTOTYPE( void revive, (int proc_nr, int bytes) );
|
||||||
_PROTOTYPE( void suspend, (int task) );
|
_PROTOTYPE( void suspend, (int task) );
|
||||||
_PROTOTYPE( void pipe_suspend, (int rw_flag, int fd_nr, char *buf,
|
_PROTOTYPE( void pipe_suspend, (int rw_flag, int fd_nr, char *buf,
|
||||||
size_t size) );
|
size_t size) );
|
||||||
_PROTOTYPE( int select_request_pipe, (struct filp *f, int *ops, int bl) );
|
|
||||||
_PROTOTYPE( int select_match_pipe, (struct filp *f) );
|
|
||||||
_PROTOTYPE( void unsuspend_by_endpt, (endpoint_t) );
|
_PROTOTYPE( void unsuspend_by_endpt, (endpoint_t) );
|
||||||
_PROTOTYPE( void select_reply1, (void) );
|
|
||||||
_PROTOTYPE( void select_reply2, (void) );
|
|
||||||
_PROTOTYPE( void wait_for, (endpoint_t) );
|
_PROTOTYPE( void wait_for, (endpoint_t) );
|
||||||
#if DO_SANITYCHECKS
|
#if DO_SANITYCHECKS
|
||||||
_PROTOTYPE( int check_pipe, (void) );
|
_PROTOTYPE( int check_pipe, (void) );
|
||||||
|
@ -288,9 +285,10 @@ _PROTOTYPE( int do_gcov_flush, (void) );
|
||||||
|
|
||||||
/* select.c */
|
/* select.c */
|
||||||
_PROTOTYPE( int do_select, (void) );
|
_PROTOTYPE( int do_select, (void) );
|
||||||
_PROTOTYPE( int select_callback, (struct filp *, int ops) );
|
|
||||||
_PROTOTYPE( void select_forget, (int fproc) );
|
|
||||||
_PROTOTYPE( void select_timeout_check, (timer_t *) );
|
|
||||||
_PROTOTYPE( void init_select, (void) );
|
_PROTOTYPE( void init_select, (void) );
|
||||||
|
_PROTOTYPE( void select_callback, (struct filp *, int ops) );
|
||||||
|
_PROTOTYPE( void select_forget, (endpoint_t proc_e) );
|
||||||
|
_PROTOTYPE( void select_reply1, (endpoint_t driver_e, int minor, int status));
|
||||||
|
_PROTOTYPE( void select_reply2, (endpoint_t driver_e, int minor, int status));
|
||||||
|
_PROTOTYPE( void select_timeout_check, (timer_t *) );
|
||||||
_PROTOTYPE( void select_unsuspend_by_endpt, (endpoint_t proc) );
|
_PROTOTYPE( void select_unsuspend_by_endpt, (endpoint_t proc) );
|
||||||
_PROTOTYPE( int select_notified, (int major, int minor, int ops) );
|
|
||||||
|
|
1049
servers/vfs/select.c
1049
servers/vfs/select.c
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue