コード例 #1
0
  void print_lcd_menu()
  {
    if (!global->lcd_output_possible())
      return;

    // dir
    std::string dir = "/";
    if (folders.size() != 1) {
      std::stack<std::pair<std::list<std::string>, int > > tmp_folders = folders;

      std::string name = tmp_folders.top().first.front();

      for (int number_of_slashes = tmp_folders.size(); number_of_slashes > 0; --number_of_slashes) {
	int p = name.rfind('/');
	if (p != std::string::npos) {
	  if (number_of_slashes != tmp_folders.size())
	    dir = name.substr(p) + dir;
	  name = name.substr(0, p);
	} else
	  break;
      }
    }

    // current
    std::string cur_name = "> " + get_name_from_file(vector_lookup(files, folders.top().second));

    std::string prev_name = "";

    if (files.size() > 2) {
      // prev
      int prev_pos = folders.top().second - 1;
      if (prev_pos == -1)
	prev_pos = files.size()-1;

      prev_name = get_name_from_file(vector_lookup(files, prev_pos));
    }

    std::string next_name = "";

    if (files.size() > 1) {
      // next
      int next_pos = folders.top().second + 1;
      if (next_pos == files.size())
	next_pos = 0;

      next_name = get_name_from_file(vector_lookup(files, next_pos));
    }

    if (global->lcd_rows() > 1) global->lcd_add_output(string_format::pretty_print_string_copy(dir,global->lcd_pixels()));
    if (global->lcd_rows() > 2) global->lcd_add_output(string_format::pretty_print_string_copy(prev_name,global->lcd_pixels()));
    global->lcd_add_output(cur_name);
    if (global->lcd_rows() > 3) global->lcd_add_output(string_format::pretty_print_string_copy(next_name,global->lcd_pixels()));

    global->lcd_print();
  }
コード例 #2
0
ファイル: kerext_page.c プロジェクト: vocho/openqnx
static void
kerext_page_wait_info(void *data) {
    struct kerargs_page_wait_info	*kap = data;
    int								id;
    unsigned						index;
    pid_t							pid;
    PROCESS							*prp;
    THREAD							*thp;
    unsigned						pt_info;

    pt_info = kap->value;
    id = SYNC_PINDEX(pt_info);
    if(id < process_vector.nentries  &&
            (prp = VECP(prp, &process_vector, id))  &&
            id == PINDEX(prp->pid) &&
            (thp = vector_lookup(&prp->threads, SYNC_TID(pt_info))) &&
            (thp->state == STATE_WAITPAGE)) {
        kap->vaddr = (uintptr_t)thp->next.thread;
        *kap->ppid = prp->pid;
        *kap->ptid = thp->tid + 1;
        *kap->pflags = (unsigned)thp->status;

        pid = (unsigned)thp->prev.thread;
        index = PINDEX(pid);
        if((index >= process_vector.nentries)
                || ((prp = VECP(prp, &process_vector, index)) == NULL)
                || (prp->pid != pid)) {
            pid = 0;
        }
        *kap->paspace_pid = pid;
    } else {
        kap->vaddr = ~0;
    }
}
コード例 #3
0
ファイル: apmgr_event.c プロジェクト: vocho/openqnx
static void ker_deliver_event(void *data)
{
	THREAD	*thp;
	struct kerargs_deliver_event *kap = data;
	PROCESS *prp = lookup_pid(kap->evtdest->pid);
	
	kap->err = ESRCH;
	if ((prp != NULL) && 
		((thp = vector_lookup(&prp->threads, MTINDEX(kap->evtdest->rcvid))) != NULL))
	{
		KerextLock();
		kap->evtdest->in_progress = bool_t_TRUE;

		// Since this is a user request for an event and can handle
		// an error return, we shouldn't delve into the critical list
		// for any pulse that we need to allocate for the event - save
		// the critical heap for important pulses like hwintrs and
		// CPU exception fault delivery
		pulse_souls.flags &= ~SOUL_CRITICAL;
		kap->err = sigevent_exe(kap->event, thp, 1);
		pulse_souls.flags |= SOUL_CRITICAL;
		
		kap->evtdest->in_progress = bool_t_FALSE;
	}
}
コード例 #4
0
 // commands
 void action_play()
 {
   Multifile e = vector_lookup(files, folders.top().second);
   int nfiles = e.filenames.size();
   if (nfiles > 0)
     playmovie(e);
   else
     DialogWaitPrint pdialog(dgettext("mms-movie", "Folder is empty"), 1000);
 }
コード例 #5
0
ファイル: main.c プロジェクト: hzsunzixiang/programming
int main ()
{
		int *x1=(int*)malloc(sizeof(int));
		int *x2=(int*)malloc(sizeof(int));
		*x1=8;
		*x2=9;
		vector vec=vector_init(3);
		vector_set(vec,x1);
		vector_set(vec,x2);
		printf("size:%d\n",vector_count(vec));
		int * find=vector_lookup(vec,1);
		printf("value:%d\n",*find);
		return 0;
}
コード例 #6
0
ファイル: kerext_page.c プロジェクト: vocho/openqnx
static void
kerext_page_cont(void *data) {
    struct kerargs_page_cont *kap = data;
    PROCESS	*prp;
    THREAD	*act = actives[KERNCPU], *thp;

    // Verify the target process and thread exists.
    if((prp = lookup_pid(kap->pid)) == NULL  ||
            (thp = vector_lookup(&prp->threads, kap->tid-1)) == NULL  ||
            (thp->state != STATE_WAITPAGE)) {
        kererr(act, ESRCH);
        return;
    }

    lock_kernel();
    if(kap->err != EOK) {
        kererr(thp, kap->err);
    } else if(kap->code_signo) {
        if(kap->code_signo & SIGCODE_KERNEL) {
            if((kap->code_signo & SIGCODE_INXFER) == 0) {
                // Fault occured while we were in a kernel call. Unwind properly
                if(!(kap->code_signo & SIGCODE_KEREXIT)) {
                    // Fixup ip
                    SETKIP(thp,KIP(thp) + KER_ENTRY_SIZE);
                }
                if(thp->flags & _NTO_TF_WAAA) {
                    thp->status = (void *)EAGAIN;
                    thp->flags |= (_NTO_TF_KILLSELF | _NTO_TF_ONLYME);
                } else {
                    kererr(thp, EFAULT);
                }
            } else {
                // Else we just restart kernel call, this time it will unwind properly
            }
        } else {
            // Make sure that the signal will be delivered by
            // knocking down all higher priority specret flags,
            // except for KILLSELF and TO_BE_STOPPED
            thp->flags &= ~(_NTO_TF_SIG_ACTIVE - 1) | (_NTO_TF_KILLSELF|_NTO_TF_TO_BE_STOPPED);

            // Deliver the signal
            // PageWait() stored the faulting address in "thp->next"
            usr_fault(kap->code_signo, thp, (uintptr_t)thp->next.thread);
        }
    }

    ready(thp);
    SETKSTATUS(act, EOK);
}
コード例 #7
0
ファイル: kerext_process.c プロジェクト: vocho/openqnx
static void
kerext_process_swap(void *data) {
	struct kerargs_process_swap		*kap = data;
	PROCESS							*parent = kap->parent;
	PROCESS							*child = kap->child;
	CONNECT							*proc_cop;
	pid_t							pid;
	int								i;
	DEBUG							*swap;

	lock_kernel();
	
	/* Swap process containers */
	process_vector.vector[PINDEX(parent->pid)] = child;
	process_vector.vector[PINDEX(child->pid)] = parent;

	if(child->parent != parent) crash();
	process_swap(child);

	pid = parent->pid;
	parent->pid = child->pid;
	child->pid = pid;

	if(parent->ocb_list || child->ocb_list) {
		void 		*ocb_list;

		ocb_list = parent->ocb_list;
		parent->ocb_list = child->ocb_list;
		child->ocb_list = ocb_list;
	}

	if(parent->alarm) {
		TIMER	*alarm = parent->alarm;

		parent->alarm = 0;
		alarm->thread = child->valid_thp;
		child->alarm = alarm;
	}

	/* Flags to inherit */
#define FLAGS	(_NTO_PF_WAITINFO | \
				_NTO_PF_WAITDONE | \
				_NTO_PF_SLEADER | \
				_NTO_PF_ORPHAN_PGRP | \
				_NTO_PF_NOCLDSTOP | \
				_NTO_PF_PTRACED | \
				_NTO_PF_NOZOMBIE)
	i = parent->flags;
    parent->flags = (parent->flags & ~FLAGS) | (child->flags & FLAGS);
    child->flags = (child->flags & ~FLAGS) | (i & FLAGS);
#undef FLAGS

	// Find the child's connection to proc (It's always the first chancon entry)
	proc_cop = vector_lookup(&child->chancons, SYSMGR_COID & ~_NTO_SIDE_CHANNEL);

#ifndef NDEBUG
	// There should be two links, One from the Send() and one from the ConnectAttach()
	if(!proc_cop || !proc_cop->channel || proc_cop->links != 2) crash();
	if(proc_cop->un.lcl.pid != SYSMGR_PID || proc_cop->un.lcl.chid != SYSMGR_CHID) crash();
	if(parent->chancons.nentries != parent->chancons.nfree) crash();
	if(child->chancons.nentries != child->chancons.nfree + 1) crash();
	if(child->fdcons.nentries != child->fdcons.nfree) crash();
#endif

	for(i = 0 ; i < parent->fdcons.nentries ; ++i) {
		CONNECT							*cop;

		if((cop = vector_rem(&parent->fdcons, i))) {
			if(vector_add(&child->fdcons, cop, i) != i) {
				crash();
			}

			parent->nfds--;
			child->nfds++;

			cop->process = child;

			// Check if this connects to proc's channel, if so, share it...
			if(proc_cop && cop->channel == proc_cop->channel) {
				vector_rem(&child->chancons, SYSMGR_COID & ~_NTO_SIDE_CHANNEL);
				vector_add(&child->chancons, cop, SYSMGR_COID & ~_NTO_SIDE_CHANNEL);
				cop->links++;
				proc_cop->links--;
				proc_cop = 0;
			}
		}
	}

	swap = child->debugger;
	if((swap != NULL) && (swap->process == child)) {
		swap->process = parent;
	}
	swap = parent->debugger;
	if((swap != NULL) && (swap->process == parent)) {
		swap->process = child;
	}
	parent->debugger = child->debugger;
	child->debugger = swap;

	SETKSTATUS(actives[KERNCPU], 0);
}
コード例 #8
0
ファイル: kerext_process.c プロジェクト: vocho/openqnx
static void
kerext_process_destroy(void *data) {
	PROCESS		*prp, *parent, *child;
	pid_t		pid = (pid_t)data;
	THREAD		*act = actives[KERNCPU];

	lock_kernel();

	if(!(prp = vector_lookup(&process_vector, PINDEX(pid)))) {
		kererr(act, ESRCH);
		return;
	}

	if(prp->querying) {
		// Some proc thread is looking at the process fields
		// (a QueryOject() has been done on it). We have to wait
		// before we can destroy the process and free the memory
		SETKSTATUS(act, 0);
		return;
	}

	_TRACE_PR_EMIT_DESTROY(prp, pid);

	// retarget all children to PROC
	if((child = prp->child)) {
		PROCESS		*proc = sysmgr_prp;

		do {
			//Loop might take a while - give intr queue a chance to drain.
			KEREXT_PREEMPT(act);

			prp->child = child->sibling;
			if(procmgr.process_threads_destroyed) {
				if (((child->flags & (_NTO_PF_LOADING | _NTO_PF_TERMING | _NTO_PF_ZOMBIE)) == _NTO_PF_ZOMBIE) || (child->flags & _NTO_PF_NOZOMBIE)) {
				struct sigevent		ev;

				child->flags &= ~(_NTO_PF_ZOMBIE | _NTO_PF_WAITINFO);
				(*procmgr.process_threads_destroyed)(child, &ev);
				sigevent_proc(&ev);
				}
			}
			child->parent = proc;
			child->sibling = proc->child;
			proc->child = child;
			--prp->num_processes; ++proc->num_processes;
		} while((child = prp->child));
	}

	vector_rem(&process_vector, PINDEX(pid));

	// Remove the thread vector
	if(prp->threads.nentries && prp->threads.nentries == prp->threads.nfree)
		vector_free(&prp->threads);

	// Remove the timer vector
	if(prp->timers.nentries && prp->timers.nentries == prp->timers.nfree)
		vector_free(&prp->timers);

	// Remove the fd vector
	if(prp->fdcons.nentries && prp->fdcons.nentries == prp->fdcons.nfree)
		vector_free(&prp->fdcons);

	// Remove the channel vector
	if(prp->chancons.nentries && prp->chancons.nentries == prp->chancons.nfree)
		vector_free(&prp->chancons);

	// Unlink the credential
	if(prp->cred) {
		cred_set(&prp->cred, NULL);
	}

	// undo all session stuff
	if(prp->session && atomic_sub_value(&prp->session->links, 1) == 1) {
		_sfree(prp->session, sizeof *prp->session);
	}
	prp->session = 0;

	// Unlink the limits
	if(prp->limits  &&  --prp->limits->links == 0) {
		LINK1_REM(limits_list, prp->limits, LIMITS);
		object_free(NULL, &limits_souls, prp->limits);
	}

	if(prp->limits  &&  prp->limits->links == ~0U) crash();
	if(prp->pid)				crash();
	if(prp->cred)				crash();
	if(prp->alarm)				crash();
	if(pril_first(&prp->sig_pending))		crash();
	if(prp->sig_table)			crash();
	if(prp->nfds)				crash();
	if(prp->chancons.vector)	crash();
	if(prp->fdcons.vector)		crash();
	if(prp->threads.vector)		crash();
	if(prp->timers.vector)		crash();
	if(prp->memory)				crash();
	if(prp->join_queue)			crash();
//	if(prp->session)			crash();
	if(prp->debugger)			crash();
	if(prp->lock)				crash();
	if(prp->num_active_threads)	crash();
	if(prp->vfork_info)			crash();
// FIX ME - this is not NULL now ... why?	if(prp->rsrc_list)			crash();
	if(prp->conf_table)			crash();

	// Unlink from parent
	parent = prp->parent;
	--parent->num_processes;
	if(prp == parent->child) {
		parent->child = prp->sibling;
	} else {
		for(parent = parent->child ; parent ; parent = parent->sibling) {
			if(parent->sibling == prp) {
				parent->sibling = prp->sibling;
				break;
			}
		}
	}

	//Keep pids as positive numbers
	pid_unique = (pid_unique + (PID_MASK + 1)) & INT_MAX;

	/* diassociate prp from all partitions */
/*
	apparently prp->pid gets looked at even though we are about to
	object_free(prp).
	prp->pid = pid;	// stick it back in so we have the info for the disassociate event
*/
	(void)SCHEDPART_DISASSOCIATE(prp, part_id_t_INVALID);
	(void)MEMPART_DISASSOCIATE(prp, part_id_t_INVALID);
	(void)MUTEX_DESTROY(prp, &prp->mpartlist_lock);
	(void)MUTEX_DESTROY(prp, &prp->spartlist_lock);
		
	CRASHCHECK(prp->mpart_list.vector != NULL);
	CRASHCHECK(prp->spart_list != NULL);	// no vector for sched partitions since only 1

	object_free(NULL, &process_souls, prp);
	SETKSTATUS(act, 1);
}
コード例 #9
0
ファイル: procmgr_init.c プロジェクト: vocho/openqnx
static int proc_start(PROCESS *prp, uintptr_t *start_ip) {
	THREAD						*thp;
	struct loader_context		*lcp = prp->lcp;

	if(!(thp = vector_lookup(&prp->threads, lcp->tid - 1)) || thp->state != STATE_REPLY) {
		return EL3HLT;
	}

	if((lcp->state & LC_STATE_MASK) == LC_FORK) {
		THREAD							*pthp;
		int								tid;
		struct _thread_local_storage	*tsp;
		char							buff[0x100];
		struct _thread_local_storage	tls;
		unsigned						size = 0;
		uintptr_t						sp;

		if(!(lookup_rcvid(0, lcp->rcvid, &pthp)) || pthp->state != STATE_REPLY) {
			return EL3HLT;
		}
		sp = GetSp(pthp);

		tid = thp->un.lcl.tls->__tid;
		tsp = thp->un.lcl.tls = pthp->un.lcl.tls;
		thp->un.lcl.stacksize = pthp->un.lcl.stacksize; 
		if(!(lcp->flags & _FORK_ASPACE)) {
			memcpy(&tls, tsp, sizeof(tls));
#ifdef STACK_GROWS_UP
			if ((size = sp - lcp->start.stackaddr) >= sizeof(buff)) return ENOMEM;
			memcpy(buff, (void *)lcp->start.stackaddr, size);
#else
			if ((size = lcp->start.stackaddr - sp) >= sizeof(buff)) return ENOMEM;
			memcpy(buff, (void *)sp, size);
#endif
		}

		KerextLock();

		tsp->__pid = prp->pid;
		tsp->__tid = tid;
		tsp->__owner = ((tsp->__pid << 16) | tsp->__tid) & ~_NTO_SYNC_WAITING;

		thp->reg = pthp->reg;
		thp->runmask = thp->default_runmask = pthp->default_runmask;

		prp->flags |= _NTO_PF_FORKED;

		if(!(lcp->flags & _FORK_ASPACE)) {
			struct vfork_info				*vip;

			if(size > sizeof buff || !(vip = prp->vfork_info = malloc(offsetof(struct vfork_info, frame) + size))) {
				return ENOMEM;
			}
			vip->rcvid = lcp->rcvid;
			vip->tls = tls;
#ifdef STACK_GROWS_UP
			vip->frame_base = (void *)lcp->start.stackaddr;
#else
			vip->frame_base = (void *)sp;
#endif
			vip->frame_size = size;
			memcpy(vip->frame, buff, size);
		}

		if(!(lcp->flags & _FORK_NOZOMBIE)) {
			prp->flags &= ~_NTO_PF_NOZOMBIE;
		}

		// Don't allow anything to change the IP
		thp->flags |= _NTO_TF_KERERR_SET;
		return EOK;
	}
コード例 #10
0
ファイル: apmgr_event.c プロジェクト: vocho/openqnx
int apm_deliver_event(evtdest_t *evtdest, struct sigevent *se)
{

	int r;
	/*
	 * in the process of sending an event, we may cause memory to be allocated
	 * (ex. growing the pulse soul list) which could trigger an event (in the
	 * case where the heap needed growing to accomodate the soul list grow).
	 * This mechanism breaks the recursion
	*/
	if (evtdest->in_progress) return EINPROGRESS;

	if (!KerextAmInKernel())
	{
		struct kerargs_deliver_event data;
		data.err = EOK;
		data.evtdest = evtdest;
		data.event = se;

		__Ring0(ker_deliver_event, &data);
		r = data.err;

#ifndef NDEBUG

		if (r != EOK) {
			if ((++evt_delivery_fail_cnt % 100) == 0) {
/*				kprintf("%u event delivery failures @ %d, err = %d\n",
						evt_delivery_fail_cnt, __LINE__, r);*/
			}
		}
#endif	/* NDEBUG */
	}
	else
	{
		/*
		 * in the case we are already in the kernel,it may be a procnto thread
		 * or a user thread that is triggering the event delivery. Because there
		 * are many places in the kernel which are not re-entrant we will not
		 * deliver the event now but instead, add it to the event queue for
		 * delivery at kernel exit. Because the 'evtdest->rcvid' relates to the
		 * connection established with 'procnto', we cannot lookup the connection
		 * and instead must know the process to deliver the event to as recorded
		 * in the 'evtdest' structure at registration time. We use this info to
		 * find a thread to deliver to.
		*/
		THREAD  *thp = NULL;
		PROCESS *prp = lookup_pid(evtdest->pid);

		r = ESRCH;
		if (prp != NULL) {
			thp = vector_lookup(&prp->threads, MTINDEX(evtdest->rcvid));
		}

		if (thp != NULL) {
			evtdest->in_progress = bool_t_TRUE;
			r = event_add(se, thp);
			evtdest->in_progress = bool_t_FALSE;
		}
#ifndef NDEBUG
		if ((thp == NULL) || (r != EOK)) {
			if ((++inker_evt_delivery_fail_cnt % 100) == 0) {
				kprintf("%u inkernel event delivery failures @ %d, err = %d\n",
						inker_evt_delivery_fail_cnt, __LINE__, r);
			}
		}
#endif	/* NDEBUG */
	}

#ifndef NDEBUG
	if (r == EOK) ++delivered_events;
	else ++undelivered_events;
#endif	/* NDEBUG */

	return r;
}
コード例 #11
0
ファイル: ker_fastmsg.c プロジェクト: vocho/openqnx
int kdecl
ker_msg_receivev(THREAD *act, struct kerargs_msg_receivev *kap) {
	CHANNEL		*chp;
	CONNECT		*cop;
	THREAD		*thp;
	THREAD		**owner;
	int			 tid, chid;
	unsigned	 tls_flags;
	VECTOR		*chvec;

	chid = act->last_chid = kap->chid;		// Used for priority boost
	chvec = &act->process->chancons;

	if(chid & _NTO_GLOBAL_CHANNEL) {
		chid &= ~_NTO_GLOBAL_CHANNEL;
		chvec = &chgbl_vector;
	}
	if((chp = vector_lookup(chvec, chid)) == NULL  ||
	   chp->type != TYPE_CHANNEL) {
	   	lock_kernel();
		return ESRCH;
	}

	if(kap->info) {
		WR_VERIFY_PTR(act, kap->info, sizeof(*kap->info));
		// NOTE:
		// Make sure the receive info pointer is valid. Note that we need some
		// extra checks in the mainline when filling in the rcvinfo (this is no
		// longer done in specret).
		//
		// Note: we don't probe the whole buffer, rather touch start and end,
		// which is faster and sufficient
		//
		WR_PROBE_INT(act, kap->info, 1);
		WR_PROBE_INT(act, &kap->info->reserved, 1);
	}

	if(chp->flags & (_NTO_CHF_ASYNC | _NTO_CHF_GLOBAL)) {
		if(chp->flags & _NTO_CHF_GLOBAL) {
			cop = NULL;
			if(kap->coid) {
				if((cop = lookup_connect(kap->coid)) == NULL  ||  cop->type != TYPE_CONNECTION) {
					return EBADF;
				}
			}

			return msgreceive_gbl(act, (CHANNELGBL*) chp, kap->rmsg, -kap->rparts, kap->info, cop, kap->coid);
		} else {
			return msgreceive_async(act, (CHANNELASYNC*) chp, kap->rmsg, kap->rparts);
		}
	}

	/*
	 * Validate incoming IOVs and calculate receive length
	 */
 	if(kap->rparts >= 0) {
		int len = 0;
		int len_last = 0;
		IOV *iov = kap->rmsg;
		int rparts = kap->rparts;

		if (kap->rparts != 0) {
			if (!WITHIN_BOUNDRY((uintptr_t)iov, (uintptr_t)(&iov[rparts]), act->process->boundry_addr)) {
				return EFAULT;
			}
		}

		// Calculate receive length -- even if not requested, we use it for msginfo
		// Do boundary check
		while(rparts) {
			uintptr_t base, last;

			len += GETIOVLEN(iov);
			if (len <len_last ) {
				/*overflow. excessively long user IOV, possibly overlayed. pr62575 */
				return EOVERFLOW;
			}
			len_last = len;
			base = (uintptr_t)GETIOVBASE(iov);
			last = base + GETIOVLEN(iov) - 1;
			if(((base > last) || !WITHIN_BOUNDRY(base, last, act->process->boundry_addr)) && (GETIOVLEN(iov) != 0)) {
				return EFAULT;
			}
			++iov;
			--rparts;
		}
		act->args.ms.srcmsglen = len;
	} else {
		// Single part -- validate receive address
		uintptr_t base, last;
		base = (uintptr_t) kap->rmsg;
		last = base + (-kap->rparts) - 1;
		if((base > last) || !WITHIN_BOUNDRY(base, last, act->process->boundry_addr)) {
			// We know length is non-zero from test above
			return EFAULT;
		}
		act->args.ms.srcmsglen = -kap->rparts;
	}


restart:
	// Was there was a waiting thread or pulse on the channel?
	thp = pril_first(&chp->send_queue);
restart2:
	if(thp) {
		int xferstat;
		unsigned	type = TYPE_MASK(thp->type);

		// Yes. There is a waiting message.
		if((type == TYPE_PULSE) || (type == TYPE_VPULSE)) {
			PULSE *pup = (PULSE *)(void *)thp;

			act->restart = NULL;
			xferstat = xferpulse(act, kap->rmsg, kap->rparts, pup->code, pup->value, pup->id);

			if(type == TYPE_VPULSE) {
				thp = (THREAD *)pup->id;
				get_rcvinfo(thp, -1, thp->blocked_on, kap->info);
			}

			lock_kernel();
			act->timeout_flags = 0;

			// By default the receiver runs with message driven priority.
			// RUSH: Fix for partition inheritance
			if(act->priority != pup->priority  &&  (chp->flags & _NTO_CHF_FIXED_PRIORITY) == 0) {
				adjust_priority(act, pup->priority, act->process->default_dpp, 1);
				act->real_priority = act->priority;
			} else if(act->dpp != act->process->default_dpp) {
				adjust_priority(act, act->priority, act->process->default_dpp, 1);
			}

			pulse_remove(chp->process, &chp->send_queue, pup);

			if((thp = act->client) != 0) {
				/* need to clear client's server field */
				act->client = 0;
				thp->args.ms.server = 0;
			}

			if(xferstat) {
				return EFAULT;
			}
			_TRACE_COMM_IPC_RET(act);

			return EOK;
		}

		// If the receive request was for a pulse only, keep checking the list..
		if(KTYPE(act) == __KER_MSG_RECEIVEPULSEV) {
			thp = thp->next.thread;
			goto restart2;
		}

#if defined(VARIANT_smp) && defined(SMP_MSGOPT)
		// If thp is in the xfer status in another CPU, try next one
		if(thp->internal_flags & _NTO_ITF_MSG_DELIVERY) {
			thp = thp->next.thread;
			goto restart2;
		}
#endif

		// If an immediate timeout was specified we unblock the sender.
		if(IMTO(thp, STATE_REPLY)) {
			lock_kernel();
			force_ready(thp, ETIMEDOUT);
			unlock_kernel();
			KER_PREEMPT(act, ENOERROR);
			goto restart;
		}

		if(thp->flags & _NTO_TF_BUFF_MSG) {
			xferstat = xfer_cpy_diov(act, kap->rmsg, thp->args.msbuff.buff, kap->rparts, thp->args.msbuff.msglen);
		} else {
			act->args.ri.rmsg = kap->rmsg;
			act->args.ri.rparts = kap->rparts;

			START_SMP_XFER(act, thp);

			xferstat = xfermsg(act, thp, 0, 0);

			lock_kernel();
			END_SMP_XFER(act, thp);

#if defined(VARIANT_smp) && defined(SMP_MSGOPT)
			if(thp->internal_flags & _NTO_ITF_MSG_FORCE_RDY) {
				force_ready(thp,KSTATUS(thp));
				thp->internal_flags &= ~_NTO_ITF_MSG_FORCE_RDY;
				KERCALL_RESTART(act);
				act->restart = 0;
				return ENOERROR;
			}
			if(act->flags & (_NTO_TF_SIG_ACTIVE | _NTO_TF_CANCELSELF)) {
				KERCALL_RESTART(act);
				act->restart = 0;
				return ENOERROR;
			}
#endif
		}

		if(xferstat) {
			lock_kernel();

			// Only a send fault will unblock the sender.
			if(xferstat & XFER_SRC_FAULT) {
				// Let sender know it faulted and restart receive.
				force_ready(thp, EFAULT);
				unlock_kernel();
				KER_PREEMPT(act, ENOERROR);
				goto restart;
			}

			if((thp = act->client) != 0) {
				/* need to clear client's server field */
				act->client = 0;
				thp->args.ms.server = 0;
			}

			// Let receiver and sender know reason for fault.
			act->timeout_flags = 0;
			return EFAULT;
		}

		if(TYPE_MASK(thp->type) == TYPE_VTHREAD) {
			tid = thp->args.ri.rparts;
		} else {
			tid = thp->tid;
		}
		cop = thp->blocked_on;
		if(thp->args.ms.srcmsglen == ~0U) {
			// This should never occur with the new code
			crash();
			/* NOTREACHED */
			thp->args.ms.srcmsglen = thp->args.ms.msglen;
		}

		// If the receive specified an info buffer stuff it as well.
		// thp->args.ms.msglen was set by xfermsg
		if(kap->info) {
		//	get_rcvinfo(thp, -1, cop, kap->info);
			STUFF_RCVINFO(thp, cop, kap->info);
			if(thp->flags & _NTO_TF_BUFF_MSG) {
				if(kap->info->msglen > act->args.ms.srcmsglen) kap->info->msglen = act->args.ms.srcmsglen;
			}
		}

		lock_kernel();
		_TRACE_COMM_IPC_RET(act);
		act->timeout_flags = 0;
		act->restart = NULL;

		// Because _NTO_TF_RCVINFO and _NTO_TF_SHORT_MSG will not be set, set this to NULL
		thp->restart = NULL;

		if(act->client != 0) {
			/* need to clear client's server field */
			act->client->args.ms.server = 0;
		}
		thp->args.ms.server = act;
		act->client = thp;

		pril_rem(&chp->send_queue, thp);
		if(thp->state == STATE_SEND) {
			thp->state = STATE_REPLY;
			snap_time(&thp->timestamp_last_block,0);
			_TRACE_TH_EMIT_STATE(thp, REPLY);
			SETKSTATUS(act, (tid << 16) | cop->scoid);
		} else {
			thp->state = STATE_NET_REPLY;
			_TRACE_TH_EMIT_STATE(thp, NET_REPLY);
			SETKSTATUS(act, -((tid << 16) | cop->scoid));
		}
		LINKPRIL_BEG(chp->reply_queue, thp, THREAD);

		// By default the receiver runs with message driven priority.
		// RUSH: Fix for partition inheritance
		if((act->priority != thp->priority || act->dpp != thp->dpp) &&  (chp->flags & _NTO_CHF_FIXED_PRIORITY) == 0) {
			AP_INHERIT_CRIT(act, thp);
			adjust_priority(act, thp->priority, thp->dpp, 1);
			if(act->real_priority != act->priority) act->real_priority = act->priority;
		} else {
			AP_CLEAR_CRIT(act);
		}

		return ENOERROR;
	}

	// No-one waiting for a msg so block
	tls_flags = act->un.lcl.tls->__flags;
	lock_kernel();
	_TRACE_COMM_IPC_RET(act);

	if((thp = act->client) != 0) {
		/* need to clear client's server field */
		act->client = 0;
		thp->args.ms.server = 0;
	}

	if(IMTO(act, STATE_RECEIVE)) {
		return ETIMEDOUT;
	}

	if(PENDCAN(tls_flags)) {
		SETKIP_FUNC(act, act->process->canstub);
		return ENOERROR;
	}

	// Can't call block() here, because act may not be actives[KERNCPU]
	// anymore - if the sender faulted, we call force_ready() above and
	// that might change actives[KERNCPU]
	unready(act, STATE_RECEIVE);

	// End inheritance of partition and critical state. This must be after block() so that we microbill
	// the partition we where running in before we reset to the original partition. PR26990
	act->dpp = act->orig_dpp;
	AP_CLEAR_CRIT(act);

	act->blocked_on = chp;
	act->args.ri.rmsg = kap->rmsg;
	act->args.ri.rparts = kap->rparts;
	act->args.ri.info = kap->info;

	// Add to the receive queue, put pulse only receives at the end of
	// the list so the ker_msg_send() only has to check the head of the list
	owner = &chp->receive_queue;
	if(KTYPE(act) == __KER_MSG_RECEIVEPULSEV) {
		act->internal_flags |= _NTO_ITF_RCVPULSE;
		for( ;; ) {
			thp = *owner;
			if(thp == NULL) break;
			if(thp->internal_flags & _NTO_ITF_RCVPULSE) break;
			owner = &thp->next.thread;
		}
	}
	LINKPRIL_BEG(*owner, act, THREAD);
	return ENOERROR;
}