Exemplo n.º 1
0
Arquivo: main.c Projeto: Sciumo/minix
/*===========================================================================*
 *			       do_pending_pipe				     *
 *===========================================================================*/
static void *do_pending_pipe(void *arg)
{
  int r, op;
  struct job my_job;
  struct filp *f;
  tll_access_t locktype;

  my_job = *((struct job *) arg);
  fp = my_job.j_fp;

  lock_proc(fp, 1 /* force lock */);

  f = scratch(fp).file.filp;
  assert(f != NULL);
  scratch(fp).file.filp = NULL;

  locktype = (job_call_nr == READ) ? VNODE_READ : VNODE_WRITE;
  op = (job_call_nr == READ) ? READING : WRITING;
  lock_filp(f, locktype);

  r = rw_pipe(op, who_e, f, scratch(fp).io.io_buffer, scratch(fp).io.io_nbytes);

  if (r != SUSPEND)  /* Do we have results to report? */
	reply(fp->fp_endpoint, r);

  unlock_filp(f);

  thread_cleanup(fp);
  return(NULL);
}
Exemplo n.º 2
0
/*===========================================================================*
 *			       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);
}
/*===========================================================================*
 *			       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);
}
Exemplo n.º 4
0
Arquivo: main.c Projeto: bend/Minix-RC
/*===========================================================================*
 *				get_work				     *
 *===========================================================================*/
PRIVATE void get_work()
{  
  /* Normally wait for new input.  However, if 'reviving' is
   * nonzero, a suspended process must be awakened.
   */
  int r, found_one, fd_nr;
  struct filp *f;
  register struct fproc *rp;

  while (reviving != 0) {
	found_one= FALSE;

	/* Revive a suspended process. */
	for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++) 
		if (rp->fp_pid != PID_FREE && rp->fp_revived == REVIVING) {
			int blocked_on = rp->fp_blocked_on;
			found_one= TRUE;
			who_p = (int)(rp - fproc);
			who_e = rp->fp_endpoint;
			call_nr = rp->fp_block_callnr;

			m_in.fd = rp->fp_block_fd;
			m_in.buffer = rp->fp_buffer;
			m_in.nbytes = rp->fp_nbytes;
			/*no longer hanging*/
			rp->fp_blocked_on = FP_BLOCKED_ON_NONE;
			rp->fp_revived = NOT_REVIVING;
			reviving--;
			/* This should be a pipe I/O, not a device I/O.
			 * If it is, it'll 'leak' grants.
			 */
			assert(!GRANT_VALID(rp->fp_grant));

			if (blocked_on == FP_BLOCKED_ON_PIPE)
			{
				fp= rp;
				fd_nr= rp->fp_block_fd;
				f= get_filp(fd_nr);
				assert(f != NULL);
				r= rw_pipe((call_nr == READ) ? READING :
					WRITING, who_e, fd_nr, f,
					rp->fp_buffer, rp->fp_nbytes);
				if (r != SUSPEND)
					reply(who_e, r);
				continue;
			}

			return;
		}
	if (!found_one)
		panic("get_work couldn't revive anyone");
  }

  for(;;) {
    int r;
    /* Normal case.  No one to revive. */
    if ((r=sef_receive(ANY, &m_in)) != OK)
	panic("fs sef_receive error: %d", r);
    who_e = m_in.m_source;
    who_p = _ENDPOINT_P(who_e);

    /* 
     * negative who_p is never used to access the fproc array. Negative numbers
     * (kernel tasks) are treated in a special way
     */
    if(who_p >= (int)(sizeof(fproc) / sizeof(struct fproc)))
     	panic("receive process out of range: %d", who_p);
    if(who_p >= 0 && fproc[who_p].fp_endpoint == NONE) {
    	printf("FS: ignoring request from %d, endpointless slot %d (%d)\n",
		m_in.m_source, who_p, m_in.m_type);
	continue;
    }
    if(who_p >= 0 && fproc[who_p].fp_endpoint != who_e) {
	if(fproc[who_p].fp_endpoint == NONE) { 
		printf("slot unknown even\n");
	}
    	printf("FS: receive endpoint inconsistent (source %d, who_p %d, stored ep %d, who_e %d).\n",
		m_in.m_source, who_p, fproc[who_p].fp_endpoint, who_e);
#if 0
	panic("FS: inconsistent endpoint ");
#endif
	continue;
    }
    call_nr = m_in.m_type;
    return;
  }
}
Exemplo n.º 5
0
/*===========================================================================*
 *				read_write				     *
 *===========================================================================*/
int read_write(struct fproc *rfp, int rw_flag, struct filp *f,
	vir_bytes buf, size_t size, endpoint_t for_e)
{
  register struct vnode *vp;
  off_t position, res_pos;
  unsigned int cum_io, cum_io_incr, res_cum_io;
  int op, r;
  dev_t dev;

  position = f->filp_pos;
  vp = f->filp_vno;
  r = OK;
  cum_io = 0;

  assert(rw_flag == READING || rw_flag == WRITING || rw_flag == PEEKING);

  if (size > SSIZE_MAX) return(EINVAL);

  op = (rw_flag == READING ? CDEV_READ : CDEV_WRITE);

  if (S_ISFIFO(vp->v_mode)) {		/* Pipes */
	if (rfp->fp_cum_io_partial != 0) {
		panic("VFS: read_write: fp_cum_io_partial not clear");
	}
	if(rw_flag == PEEKING) {
	  	printf("read_write: peek on pipe makes no sense\n");
		return EINVAL;
	}
	r = rw_pipe(rw_flag, for_e, f, buf, size);
  } else if (S_ISCHR(vp->v_mode)) {	/* Character special files. */
	if(rw_flag == PEEKING) {
	  	printf("read_write: peek on char device makes no sense\n");
		return EINVAL;
	}

	if (vp->v_sdev == NO_DEV)
		panic("VFS: read_write tries to access char dev NO_DEV");

	dev = vp->v_sdev;

	r = cdev_io(op, dev, for_e, buf, position, size, f->filp_flags);
	if (r >= 0) {
		/* This should no longer happen: all calls are asynchronous. */
		printf("VFS: I/O to device %llx succeeded immediately!?\n", dev);
		cum_io = r;
		position += r;
		r = OK;
	} else if (r == SUSPEND) {
		/* FIXME: multiple read/write operations on a single filp
		 * should be serialized. They currently aren't; in order to
		 * achieve a similar effect, we optimistically advance the file
		 * position here. This works under the following assumptions:
		 * - character drivers that use the seek position at all,
		 *   expose a view of a statically-sized range of bytes, i.e.,
		 *   they are basically byte-granular block devices;
		 * - if short I/O or an error is returned, all subsequent calls
		 *   will return (respectively) EOF and an error;
		 * - the application never checks its own file seek position,
		 *   or does not care that it may end up having seeked beyond
		 *   the number of bytes it has actually read;
		 * - communication to the character driver is FIFO (this one
		 *   is actually true! whew).
		 * Many improvements are possible here, but in the end,
		 * anything short of queuing concurrent operations will be
		 * suboptimal - so we settle for this hack for now.
		 */
		position += size;
	}
  } else if (S_ISBLK(vp->v_mode)) {	/* Block special files. */
	if (vp->v_sdev == NO_DEV)
		panic("VFS: read_write tries to access block dev NO_DEV");

	lock_bsf();

	if(rw_flag == PEEKING) {
		r = req_bpeek(vp->v_bfs_e, vp->v_sdev, position, size);
	} else {
		r = req_breadwrite(vp->v_bfs_e, for_e, vp->v_sdev, position,
		       size, buf, rw_flag, &res_pos, &res_cum_io);
		if (r == OK) {
			position = res_pos;
			cum_io += res_cum_io;
		}
	}

	unlock_bsf();
  } else {				/* Regular files */
	if (rw_flag == WRITING) {
		/* Check for O_APPEND flag. */
		if (f->filp_flags & O_APPEND) position = vp->v_size;
	}

	/* Issue request */
	if(rw_flag == PEEKING) {
		r = req_peek(vp->v_fs_e, vp->v_inode_nr, position, size);
	} else {
		off_t new_pos;
		r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, position,
			rw_flag, for_e, buf, size, &new_pos,
			&cum_io_incr);

		if (r >= 0) {
			position = new_pos;
			cum_io += cum_io_incr;
		}
        }
  }

  /* On write, update file size and access time. */
  if (rw_flag == WRITING) {
	if (S_ISREG(vp->v_mode) || S_ISDIR(vp->v_mode)) {
		if (position > vp->v_size) {
			vp->v_size = position;
		}
	}
  }

  f->filp_pos = position;

  if (r == EPIPE && rw_flag == WRITING) {
	/* Process is writing, but there is no reader. Tell the kernel to
	 * generate s SIGPIPE signal.
	 */
	if (!(f->filp_flags & O_NOSIGPIPE)) {
		sys_kill(rfp->fp_endpoint, SIGPIPE);
	}
  }

  if (r == OK) {
	return(cum_io);
  }
  return(r);
}