return(NULL);
}
+ if (rfp->fp_task != who_e)
+ printf("AVFS: expected %d to reply, not %d\n", rfp->fp_task, who_e);
*rfp->fp_sendrec = m_in;
rfp->fp_task = NONE;
vmp->m_comm.c_cur_reqs--; /* We've got our reply, make room for others */
-
worker_signal(worker_get(rfp->fp_wtid));/* Continue this worker thread */
return(NULL);
}
*/
if (call_nr < 0 || call_nr >= NCALLS) {
error = ENOSYS;
- } else if (fp->fp_flags & FP_EXITING) {
- error = SUSPEND;
} else if (fp->fp_pid == PID_FREE) {
/* Process vanished before we were able to handle request.
* Replying has no use. Just drop it. */
org_m_in = m_in;
org_fp = fp;
org_self = self;
- if (mutex_lock(&rfp->fp_lock) != 0)
- panic("unable to lock fproc lock");
+ if ((r = mutex_lock(&rfp->fp_lock)) != 0)
+ panic("unable to lock fproc lock: %d", r);
m_in = org_m_in;
fp = org_fp;
self = org_self;
}
#endif
- if (rfp != NULL) unlock_proc(rfp);
+ if (rfp != NULL) {
+ rfp->fp_flags &= ~FP_DROP_WORK;
+ unlock_proc(rfp);
+ }
#if 0
mthread_exit(NULL);
if (!(fp->fp_flags & FP_PENDING) && mutex_trylock(&fp->fp_lock) == 0) {
mutex_unlock(&fp->fp_lock);
worker_start(do_dummy);
+ fp->fp_flags |= FP_DROP_WORK;
}
fp->fp_job.j_m_in = m_in;
/*===========================================================================*
* unpause *
*===========================================================================*/
-PUBLIC void unpause(proc_nr_e)
-int proc_nr_e;
+PUBLIC void unpause(endpoint_t proc_e)
{
/* A signal has been sent to a user who is paused on the file system.
* Abort the system call with the EINTR error message.
message mess;
int wasreviving = 0;
- if (isokendpt(proc_nr_e, &slot) != OK) {
- printf("VFS: ignoring unpause for bogus endpoint %d\n", proc_nr_e);
+ if (isokendpt(proc_e, &slot) != OK) {
+ printf("VFS: ignoring unpause for bogus endpoint %d\n", proc_e);
return;
}
break;
case FP_BLOCKED_ON_SELECT:/* process blocking on select() */
- select_forget(proc_nr_e);
+ select_forget(proc_e);
break;
case FP_BLOCKED_ON_POPEN: /* process trying to open a fifo */
susp_count--;
}
- reply(proc_nr_e, status); /* signal interrupted call */
+ reply(proc_e, status); /* signal interrupted call */
}
#if DO_SANITYCHECKS
int fd;
struct filp *f;
- /* Always await results of asynchronous requests */
- assert(!is_deferred(se));
-
for (fd = 0; fd < se->nfds; fd++) {
if ((f = se->filps[fd]) == NULL) continue;
se->filps[fd] = NULL;
assert(f);
assert(f->filp_selectors >= 0);
if (f->filp_selectors == 0) return;
+ if (f->filp_count == 0) return;
select_lock_filp(f, f->filp_select_ops);
assert(!is_deferred(se)); /* Not done yet, first wait for async reply */
select_cancel_all(se);
+
r1 = copy_fdsets(se, se->nfds, TO_PROC);
if (r1 != OK)
r = r1;
int wakehim = 0;
se = &selecttab[s];
if (se->requestor == NULL) continue;
+ if (se->requestor->fp_endpoint == proc_e) {
+ assert(se->requestor->fp_flags & FP_EXITING);
+ select_cancel_all(se);
+ continue;
+ }
for (fd = 0; fd < se->nfds; fd++) {
if ((f = se->filps[fd]) == NULL || f->filp_vno == NULL)
}
}
-
/*===========================================================================*
* select_reply1 *
*===========================================================================*/
}
}
- select_lock_filp(f, f->filp_select_ops);
-
/* No longer waiting for a reply from this device */
- f->filp_select_flags &= ~FSF_BUSY;
dp->dmap_sel_filp = NULL;
- /* The select call is done now, except when
- * - another process started a select on the same filp with possibly a
- * different set of operations.
- * - a process does a select on the same filp but using different file
- * descriptors.
- * - the select has a timeout. Upon receiving this reply the operations might
- * not be ready yet, so we want to wait for that to ultimately happen.
- * Therefore we need to keep remembering what the operations are. */
- if (!(f->filp_select_flags & (FSF_UPDATE|FSF_BLOCKED)))
- f->filp_select_ops = 0; /* done selecting */
- else if (!(f->filp_select_flags & FSF_UPDATE))
- f->filp_select_ops &= ~status; /* there may be operations pending */
-
- /* Tell filp owners about result unless we need to wait longer */
- if (!(status == 0 && (f->filp_select_flags & FSF_BLOCKED))) {
- if (status > 0) { /* operations ready */
- if (status & SEL_RD) f->filp_select_flags &= ~FSF_RD_BLOCK;
- if (status & SEL_WR) f->filp_select_flags &= ~FSF_WR_BLOCK;
- if (status & SEL_ERR) f->filp_select_flags &= ~FSF_ERR_BLOCK;
- } else if (status < 0) { /* error */
- f->filp_select_flags &= ~FSF_BLOCKED; /* No longer blocking */
- }
+ /* Process select result only if requestor is still around. That is, the
+ * corresponding filp is still in use.
+ */
+ if (f->filp_count >= 1) {
+ select_lock_filp(f, f->filp_select_ops);
+ f->filp_select_flags &= ~FSF_BUSY;
+
+ /* The select call is done now, except when
+ * - another process started a select on the same filp with possibly a
+ * different set of operations.
+ * - a process does a select on the same filp but using different file
+ * descriptors.
+ * - the select has a timeout. Upon receiving this reply the operations
+ * might not be ready yet, so we want to wait for that to ultimately
+ * happen.
+ * Therefore we need to keep remembering what the operations are.
+ */
+ if (!(f->filp_select_flags & (FSF_UPDATE|FSF_BLOCKED)))
+ f->filp_select_ops = 0; /* done selecting */
+ else if (!(f->filp_select_flags & FSF_UPDATE))
+ /* there may be operations pending */
+ f->filp_select_ops &= ~status;
+
+ /* Tell filp owners about result unless we need to wait longer */
+ if (!(status == 0 && (f->filp_select_flags & FSF_BLOCKED))) {
+ if (status > 0) { /* operations ready */
+ if (status & SEL_RD)
+ f->filp_select_flags &= ~FSF_RD_BLOCK;
+ if (status & SEL_WR)
+ f->filp_select_flags &= ~FSF_WR_BLOCK;
+ if (status & SEL_ERR)
+ f->filp_select_flags &= ~FSF_ERR_BLOCK;
+ } else if (status < 0) { /* error */
+ /* Always unblock upon error */
+ f->filp_select_flags &= ~FSF_BLOCKED;
+ }
- unlock_filp(f);
- filp_status(f, status); /* Tell filp owners about the results */
- } else {
- unlock_filp(f);
+ unlock_filp(f);
+ filp_status(f, status); /* Tell filp owners about the results */
+ } else {
+ unlock_filp(f);
+ }
}
select_restart_filps();