Esempio n. 1
0
/*===========================================================================*
 *				blockdriver_reply			     *
 *===========================================================================*/
void blockdriver_reply(message *m_ptr, int ipc_status, int reply)
{
/* Reply to a block request sent to the driver. */
  endpoint_t caller_e;
  long id;
  int r;

  if (reply == EDONTREPLY)
	return;

  caller_e = m_ptr->m_source;
  id = m_ptr->BDEV_ID;

  memset(m_ptr, 0, sizeof(*m_ptr));

  m_ptr->m_type = BDEV_REPLY;
  m_ptr->BDEV_STATUS = reply;
  m_ptr->BDEV_ID = id;

  /* If we would block sending the message, send it asynchronously. The NOREPLY
   * flag is set because the caller may also issue a SENDREC (mixing sync and
   * async comm), and the asynchronous reply could otherwise end up satisfying
   * the SENDREC's receive part, after which our next SENDNB call would fail.
   */
  if (IPC_STATUS_CALL(ipc_status) == SENDREC)
	r = sendnb(caller_e, m_ptr);
  else
	r = asynsend3(caller_e, m_ptr, AMF_NOREPLY);

  if (r != OK)
	printf("blockdriver_reply: unable to send reply to %d: %d\n",
		caller_e, r);
}
Esempio n. 2
0
File: main.c Progetto: mwilbur/minix
/*===========================================================================*
 *		            sef_cb_signal_manager                            *
 *===========================================================================*/
PRIVATE int sef_cb_signal_manager(endpoint_t target, int signo)
{
/* Process system signal on behalf of the kernel. */
  int target_p;
  struct rproc *rp;
  struct rprocpub *rpub;
  message m;

  /* Lookup slot. */
  if(rs_isokendpt(target, &target_p) != OK || rproc_ptr[target_p] == NULL) {
      if(rs_verbose)
          printf("RS: ignoring spurious signal %d for process %d\n",
              signo, target);
      return OK; /* clear the signal */
  }
  rp = rproc_ptr[target_p];
  rpub = rp->r_pub;

  /* Don't bother if a termination signal has already been processed. */
  if((rp->r_flags & RS_TERMINATED) && !(rp->r_flags & RS_EXITING)) {
      return EDEADEPT; /* process is gone */
  }

  /* Ignore external signals for inactive service instances. */
  if( !(rp->r_flags & RS_ACTIVE) && !(rp->r_flags & RS_EXITING)) {
      if(rs_verbose)
          printf("RS: ignoring signal %d for inactive %s\n",
              signo, srv_to_string(rp));
      return OK; /* clear the signal */
  }

  if(rs_verbose)
      printf("RS: %s got %s signal %d\n", srv_to_string(rp),
          SIGS_IS_TERMINATION(signo) ? "termination" : "non-termination",signo);

  /* Print stacktrace if necessary. */
  if(SIGS_IS_STACKTRACE(signo)) {
       sys_sysctl_stacktrace(target);
  }

  /* In case of termination signal handle the event. */
  if(SIGS_IS_TERMINATION(signo)) {
      rp->r_flags |= RS_TERMINATED;
      terminate_service(rp);

      return EDEADEPT; /* process is now gone */
  }

  /* Translate every non-termination signal into a message. */
  m.m_type = SIGS_SIGNAL_RECEIVED;
  m.SIGS_SIG_NUM = signo;
  asynsend3(rpub->endpoint, &m, AMF_NOREPLY);

  return OK; /* signal has been delivered */
}
Esempio n. 3
0
static void activate(void)
{
	assert(!active);
	assert(first_queued);

	active = first_queued;
	first_queued = first_queued->next;

	if(asynsend3(VFS_PROC_NR, &active->reqmsg, AMF_NOREPLY) != OK)
		panic("VM: asynsend to VFS failed");
}
Esempio n. 4
0
/*
 * For the current event of the given process, as determined by its flags, send
 * a process event message to the next subscriber, or resume handling the
 * event itself if there are no more subscribers to notify.
 */
static void
resume_event(struct mproc * rmp)
{
	message m;
	unsigned int i, event;
	int r;

	assert(rmp->mp_flags & IN_USE);
	assert(rmp->mp_flags & EVENT_CALL);
	assert(rmp->mp_eventsub != NO_EVENTSUB);

	/* Which event should we be concerned about? */
	if (rmp->mp_flags & EXITING)
		event = PROC_EVENT_EXIT;
	else if (rmp->mp_flags & UNPAUSED)
		event = PROC_EVENT_SIGNAL;
	else
		panic("unknown event for flags %x", rmp->mp_flags);

	/*
	 * If there are additional services interested in this event, send a
	 * message to the next one.
	 */
	for (i = rmp->mp_eventsub; i < nsubs; i++, rmp->mp_eventsub++) {
		if (subs[i].mask & event) {
			memset(&m, 0, sizeof(m));
			m.m_type = PROC_EVENT;
			m.m_pm_lsys_proc_event.endpt = rmp->mp_endpoint;
			m.m_pm_lsys_proc_event.event = event;

			r = asynsend3(subs[i].endpt, &m, AMF_NOREPLY);
			if (r != OK)
				panic("asynsend failed: %d", r);

			assert(subs[i].waiting < NR_PROCS);
			subs[i].waiting++;

			return;
		}
	}

	/* No more subscribers to be notified, resume the actual event. */
	rmp->mp_flags &= ~EVENT_CALL;
	rmp->mp_eventsub = NO_EVENTSUB;

	if (event == PROC_EVENT_EXIT)
		exit_restart(rmp);
	else if (event == PROC_EVENT_SIGNAL)
		restart_sigs(rmp);
}
Esempio n. 5
0
/*===========================================================================*
 *				send_reply				     *
 *===========================================================================*/
static void send_reply(endpoint_t endpt, message *m_ptr, int ipc_status)
{
/* Send a reply message to a request. */
  int r;

  /* If we would block sending the message, send it asynchronously. The NOREPLY
   * flag is set because the caller may also issue a SENDREC (mixing sync and
   * async comm), and the asynchronous reply could otherwise end up satisfying
   * the SENDREC's receive part, after which our next SENDNB call would fail.
   */
  if (IPC_STATUS_CALL(ipc_status) == SENDREC)
	r = ipc_sendnb(endpt, m_ptr);
  else
	r = asynsend3(endpt, m_ptr, AMF_NOREPLY);

  if (r != OK)
	printf("blockdriver: unable to send reply to %d: %d\n", endpt, r);
}
Esempio n. 6
0
File: comm.c Progetto: Hooman3/minix
/*===========================================================================*
 *				sendmsg					     *
 *===========================================================================*/
static int sendmsg(struct vmnt *vmp, endpoint_t dst, struct worker_thread *wp)
{
/* This is the low level function that sends requests.
 * Currently to FSes or VM.
 */
  int r, transid;

  if(vmp) vmp->m_comm.c_cur_reqs++;	/* One more request awaiting a reply */
  transid = wp->w_tid + VFS_TRANSID;
  wp->w_sendrec->m_type = TRNS_ADD_ID(wp->w_sendrec->m_type, transid);
  wp->w_task = dst;
  if ((r = asynsend3(dst, wp->w_sendrec, AMF_NOREPLY)) != OK) {
	printf("VFS: sendmsg: error sending message. "
		"dest: %d req_nr: %d err: %d\n", dst,
			wp->w_sendrec->m_type, r);
	util_stacktrace();
	return(r);
  }

  return(r);
}
Esempio n. 7
0
File: comm.c Progetto: Hooman3/minix
/*===========================================================================*
 *				drv_sendrec				     *
 *===========================================================================*/
int drv_sendrec(endpoint_t drv_e, message *reqmp)
{
	int r;
	struct dmap *dp;

	/* For the CTTY_MAJOR case, we would actually have to lock the device
	 * entry being redirected to.  However, the CTTY major only hosts a
	 * character device while this function is used only for block devices.
	 * Thus, we can simply deny the request immediately.
	 */
	if (drv_e == CTTY_ENDPT) {
		printf("VFS: /dev/tty is not a block device!\n");
		return EIO;
	}

	if ((dp = get_dmap(drv_e)) == NULL)
		panic("driver endpoint %d invalid", drv_e);

	lock_dmap(dp);
	if (dp->dmap_servicing != INVALID_THREAD)
		panic("driver locking inconsistency");
	dp->dmap_servicing = self->w_tid;
	self->w_task = drv_e;
	self->w_drv_sendrec = reqmp;

	if ((r = asynsend3(drv_e, self->w_drv_sendrec, AMF_NOREPLY)) == OK) {
		/* Yield execution until we've received the reply */
		worker_wait();
	} else {
		printf("VFS: drv_sendrec: error sending msg to driver %d: %d\n",
			drv_e, r);
		util_stacktrace();
	}

	dp->dmap_servicing = INVALID_THREAD;
	self->w_task = NONE;
	self->w_drv_sendrec = NULL;
	unlock_dmap(dp);
	return(OK);
}
Esempio n. 8
0
File: misc.c Progetto: Hooman3/minix
/*===========================================================================*
 *				do_vm_call				     *
 *===========================================================================*/
int do_vm_call(void)
{
/* A call that VM does to VFS.
 * We must reply with the fixed type VM_VFS_REPLY (and put our result info
 * in the rest of the message) so VM can tell the difference between a
 * request from VFS and a reply to this call.
 */
	int req = job_m_in.VFS_VMCALL_REQ;
	int req_fd = job_m_in.VFS_VMCALL_FD;
	u32_t req_id = job_m_in.VFS_VMCALL_REQID;
	endpoint_t ep = job_m_in.VFS_VMCALL_ENDPOINT;
	u64_t offset = job_m_in.VFS_VMCALL_OFFSET;
	u32_t length = job_m_in.VFS_VMCALL_LENGTH;
	int result = OK;
	int slot;
	struct fproc *rfp, *vmf;
	struct filp *f = NULL;
	int r;

	if(job_m_in.m_source != VM_PROC_NR)
		return ENOSYS;

	if(isokendpt(ep, &slot) != OK) rfp = NULL;
	else rfp = &fproc[slot];

	vmf = fproc_addr(VM_PROC_NR);
	assert(fp == vmf);
	assert(rfp != vmf);

	switch(req) {
		case VMVFSREQ_FDLOOKUP:
		{
			int procfd;

			/* Lookup fd in referenced process. */

			if(!rfp) {
				printf("VFS: why isn't ep %d here?!\n", ep);
				result = ESRCH;
				goto reqdone;
			}

			if((result = dupvm(rfp, req_fd, &procfd, &f)) != OK) {
#if 0   /* Noisy diagnostic for mmap() by ld.so */
				printf("vfs: dupvm failed\n");
#endif
				goto reqdone;
			}

			if(S_ISBLK(f->filp_vno->v_mode)) {
				assert(f->filp_vno->v_sdev != NO_DEV);
				job_m_out.VMV_DEV = f->filp_vno->v_sdev;
				job_m_out.VMV_INO = VMC_NO_INODE;
				job_m_out.VMV_SIZE_PAGES = LONG_MAX;
			} else {
				job_m_out.VMV_DEV = f->filp_vno->v_dev;
				job_m_out.VMV_INO = f->filp_vno->v_inode_nr;
				job_m_out.VMV_SIZE_PAGES =
					roundup(f->filp_vno->v_size,
						PAGE_SIZE)/PAGE_SIZE;
			}

			job_m_out.VMV_FD = procfd;

			result = OK;

			break;
		}
		case VMVFSREQ_FDCLOSE:
		{
			result = close_fd(fp, req_fd);
			if(result != OK) {
				printf("VFS: VM fd close for fd %d, %d (%d)\n",
					req_fd, fp->fp_endpoint, result);
			}
			break;
		}
		case VMVFSREQ_FDIO:
		{
			result = actual_lseek(fp, req_fd, SEEK_SET, offset,
				NULL);

			if(result == OK) {
				result = actual_read_write_peek(fp, PEEKING,
					req_fd, /* vir_bytes */ 0, length);
			}

			break;
		}
		default:
			panic("VFS: bad request code from VM\n");
			break;
	}

reqdone:
	if(f)
		unlock_filp(f);

	/* fp is VM still. */
	assert(fp == vmf);
	job_m_out.VMV_ENDPOINT = ep;
	job_m_out.VMV_RESULT = result;
	job_m_out.VMV_REQID = req_id;

	/* Reply asynchronously as VM may not be able to receive
	 * an ipc_sendnb() message.
	 */
	job_m_out.m_type = VM_VFS_REPLY;
	r = asynsend3(VM_PROC_NR, &job_m_out, 0);
	if(r != OK) printf("VFS: couldn't asynsend3() to VM\n");

	/* VFS does not reply any further */
	return SUSPEND;
}