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:
Thomas Veerman 2011-04-13 13:25:34 +00:00
parent f0740680cd
commit aba392e630
8 changed files with 646 additions and 595 deletions

View file

@ -183,8 +183,8 @@ PUBLIC void dev_status(message *m)
revive(endpt, st.REP_STATUS);
break;
case DEV_IO_READY:
select_notified(d, st.DEV_MINOR,
st.DEV_SEL_OPS);
select_reply2(st.m_source, st.DEV_MINOR,
st.DEV_SEL_OPS);
break;
default:
printf("FS: unrecognized reply %d to "

View file

@ -242,3 +242,20 @@ PUBLIC void dmap_endpt_up(int proc_e)
}
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);
}

View file

@ -1,3 +1,6 @@
#ifndef __VFS_DMAP_H__
#define __VFS_DMAP_H__
/*
dmap.h
*/
@ -21,3 +24,5 @@ extern struct dmap {
int dmap_style;
struct filp *dmap_sel_filp;
} dmap[];
#endif

View file

@ -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
* 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_state; /* state for crash recovery */
int filp_count; /* how many file descriptors share this slot?*/
/* struct inode *filp_ino;*/ /* pointer to the inode */
struct vnode *filp_vno;
struct vnode *filp_vno; /* vnode belonging to this file */
u64_t filp_pos; /* file position */
/* 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_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.
*/
#define FSF_BUSY 2 /* Select operation sent to driver but no
#define FSF_BUSY 002 /* Select operation sent to driver but no
* 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.
*/
#define FSF_WR_BLOCK 020 /* Write request is blocking */
#define FSF_ERR_BLOCK 040 /* Exception request is blocking */
#define FSF_BLOCKED 070
#endif

View file

@ -95,12 +95,12 @@ PUBLIC int main(void)
}
if (call_nr == DEV_SEL_REPL1)
{
select_reply1();
select_reply1(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS);
continue;
}
if (call_nr == DEV_SEL_REPL2)
{
select_reply2();
select_reply2(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS);
continue;
}

View file

@ -328,20 +328,18 @@ size_t size;
*===========================================================================*/
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;
/* Revive processes waiting for drivers (SUSPENDed) that have
* disappeared with return code EAGAIN.
*/
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) {
for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++) {
if (rp->fp_pid == PID_FREE) continue;
if (rp->fp_blocked_on == FP_BLOCKED_ON_OTHER && rp->fp_task == proc_e)
revive(rp->fp_endpoint, EAGAIN);
}
}
/* Revive processes waiting in drivers on select()s
* with EAGAIN too.
*/
/* Revive processes waiting in drivers on select()s with EAGAIN too */
select_unsuspend_by_endpt(proc_e);
return;

View file

@ -36,14 +36,15 @@ _PROTOTYPE( endpoint_t suspended_ep, (endpoint_t driver,
_PROTOTYPE( void reopen_reply, (void) );
/* dmap.c */
_PROTOTYPE( int do_mapdriver, (void) );
_PROTOTYPE( int map_service, (struct rprocpub *rpub) );
_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,
int dev_style, int flags) );
_PROTOTYPE( int dmap_driver_match, (endpoint_t proc, int major) );
_PROTOTYPE( void dmap_unmap_by_endpt, (int proc_nr) );
_PROTOTYPE( void dmap_endpt_up, (int proc_nr) );
_PROTOTYPE( int map_service, (struct rprocpub *rpub) );
/* exec.c */
_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 pipe_suspend, (int rw_flag, int fd_nr, char *buf,
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 select_reply1, (void) );
_PROTOTYPE( void select_reply2, (void) );
_PROTOTYPE( void wait_for, (endpoint_t) );
#if DO_SANITYCHECKS
_PROTOTYPE( int check_pipe, (void) );
@ -288,9 +285,10 @@ _PROTOTYPE( int do_gcov_flush, (void) );
/* select.c */
_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 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( int select_notified, (int major, int minor, int ops) );

File diff suppressed because it is too large Load diff