/*===========================================================================* * do_pending_pipe * *===========================================================================*/ static void do_pending_pipe(void) { int r, op; struct filp *f; tll_access_t locktype; f = fp->fp_filp[fp->fp_fd]; assert(f != NULL); locktype = (job_call_nr == VFS_READ) ? VNODE_READ : VNODE_WRITE; op = (job_call_nr == VFS_READ) ? READING : WRITING; lock_filp(f, locktype); r = rw_pipe(op, who_e, f, fp->fp_io_buffer, fp->fp_io_nbytes); if (r != SUSPEND) { /* Do we have results to report? */ /* Process is writing, but there is no reader. Send a SIGPIPE signal. * This should match the corresponding code in read_write(). */ if (r == EPIPE && op == WRITING) { if (!(f->filp_flags & O_NOSIGPIPE)) sys_kill(fp->fp_endpoint, SIGPIPE); } replycode(fp->fp_endpoint, r); } unlock_filp(f); }
/*===========================================================================* * handle_work * *===========================================================================*/ static void handle_work(void (*func)(void)) { /* Handle asynchronous device replies and new system calls. If the originating * endpoint is an FS endpoint, take extra care not to get in deadlock. */ struct vmnt *vmp = NULL; endpoint_t proc_e; int use_spare = FALSE; proc_e = m_in.m_source; if (fp->fp_flags & FP_SRV_PROC) { vmp = find_vmnt(proc_e); if (vmp != NULL) { /* A callback from an FS endpoint. Can do only one at once. */ if (vmp->m_flags & VMNT_CALLBACK) { replycode(proc_e, EAGAIN); return; } /* Already trying to resolve a deadlock? Can't handle more. */ if (worker_available() == 0) { replycode(proc_e, EAGAIN); return; } /* A thread is available. Set callback flag. */ vmp->m_flags |= VMNT_CALLBACK; if (vmp->m_flags & VMNT_MOUNTING) { vmp->m_flags |= VMNT_FORCEROOTBSF; } } /* Use the spare thread to handle this request if needed. */ use_spare = TRUE; } worker_start(fp, func, &m_in, use_spare); }
/*===========================================================================* * do_pending_pipe * *===========================================================================*/ static void do_pending_pipe(void) { vir_bytes buf; size_t nbytes, cum_io; int r, op, fd; struct filp *f; tll_access_t locktype; assert(fp->fp_blocked_on == FP_BLOCKED_ON_NONE); /* * We take all our needed resumption state from the m_in message, which is * filled by unblock(). Since this is an internal resumption, there is no * need to perform extensive checks on the message fields. */ fd = job_m_in.m_lc_vfs_readwrite.fd; buf = job_m_in.m_lc_vfs_readwrite.buf; nbytes = job_m_in.m_lc_vfs_readwrite.len; cum_io = job_m_in.m_lc_vfs_readwrite.cum_io; f = fp->fp_filp[fd]; assert(f != NULL); locktype = (job_call_nr == VFS_READ) ? VNODE_READ : VNODE_WRITE; op = (job_call_nr == VFS_READ) ? READING : WRITING; lock_filp(f, locktype); r = rw_pipe(op, who_e, f, job_call_nr, fd, buf, nbytes, cum_io); if (r != SUSPEND) { /* Do we have results to report? */ /* Process is writing, but there is no reader. Send a SIGPIPE signal. * This should match the corresponding code in read_write(). */ if (r == EPIPE && op == WRITING) { if (!(f->filp_flags & O_NOSIGPIPE)) sys_kill(fp->fp_endpoint, SIGPIPE); } replycode(fp->fp_endpoint, r); } unlock_filp(f); }