PRIVATE void printslot(struct proc *pp, int level)
{
struct proc *depproc = NULL;
- int dep = NONE;
+ endpoint_t dep;
#define COL { int i; for(i = 0; i < level; i++) printf("> "); }
if(level >= NR_PROCS) {
pp->p_sys_time, pp->p_cycles.hi, pp->p_cycles.lo, pp->p_seg.p_cr3,
rtsflagstr(pp->p_rts_flags), miscflagstr(pp->p_misc_flags));
- if(pp->p_rts_flags & RTS_SENDING) {
- dep = pp->p_sendto_e;
- kprintf(" to: ");
- } else if(pp->p_rts_flags & RTS_RECEIVING) {
- dep = pp->p_getfrom_e;
- kprintf(" from: ");
- }
-
- if(dep != NONE) {
+ if((dep = P_BLOCKEDON(pp)) != NONE) {
+ kprintf(" blocked on: ");
if(dep == ANY) {
kprintf(" ANY\n");
} else {
#endif
while (src_dst != ANY) { /* check while process nr */
+ endpoint_t dep;
xp = proc_addr(src_dst); /* follow chain of processes */
#if DEBUG_ENABLE_IPC_WARNINGS
processes[group_size] = xp;
/* Check whether the last process in the chain has a dependency. If it
* has not, the cycle cannot be closed and we are done.
*/
- if (RTS_ISSET(xp, RTS_RECEIVING)) { /* xp has dependency */
- if(xp->p_getfrom_e == ANY) src_dst = ANY;
- else okendpt(xp->p_getfrom_e, &src_dst);
- } else if (RTS_ISSET(xp, RTS_SENDING)) { /* xp has dependency */
- okendpt(xp->p_sendto_e, &src_dst);
- } else {
- return(0); /* not a deadlock */
- }
+ if((dep = P_BLOCKEDON(xp)) == NONE)
+ return 0;
+
+ if(dep == ANY)
+ src_dst = ANY;
+ else
+ okendpt(dep, &src_dst);
/* Now check if there is a cyclic dependency. For group sizes of two,
* a combination of SEND(REC) and RECEIVE is not fatal. Larger groups
if (RTS_ISSET(dst_ptr, RTS_NO_ENDPOINT))
{
- return EDSTDIED;
+ return EDEADSRCDST;
}
/* Check if 'dst' is blocked waiting for this message. The destination's
okendpt(src_e, &src_p);
if (RTS_ISSET(proc_addr(src_p), RTS_NO_ENDPOINT))
{
- return ESRCDIED;
+ return EDEADSRCDST;
}
}
/* RTS_NO_ENDPOINT should be removed */
if (dst_ptr->p_rts_flags & RTS_NO_ENDPOINT)
{
- tabent.result= EDSTDIED;
+ tabent.result= EDEADSRCDST;
A_INSERT(i, result);
tabent.flags= flags | AMF_DONE;
A_INSERT(i, flags);
#define proc_is_preempted(p) ((p)->p_rts_flags & RTS_PREEMPTED)
#define proc_no_quantum(p) ((p)->p_rts_flags & RTS_NO_QUANTUM)
+/* Macro to return: on which process is a certain process blocked?
+ * return endpoint number (can be ANY) or NONE. It's important to
+ * check RTS_SENDING first, and then RTS_RECEIVING, as they could
+ * both be on (if a sendrec() blocks on sending), and p_getfrom_e
+ * could be nonsense even though RTS_RECEIVING is on.
+ */
+#define P_BLOCKEDON(p) \
+ ( \
+ ((p)->p_rts_flags & RTS_SENDING) ? \
+ (p)->p_sendto_e : \
+ ( \
+ ( \
+ ((p)->p_rts_flags & RTS_RECEIVING) ? \
+ (p)->p_getfrom_e : \
+ NONE \
+ ) \
+ ) \
+ )
+
/* These runtime flags can be tested and manipulated by these macros. */
#define RTS_ISSET(rp, f) (((rp)->p_rts_flags & (f)) == (f))
/* Unset pending notification bits. */
unset_sys_bit(priv(rp)->s_notify_pending, priv(rc)->s_id);
- /* Check if process is receiving from exiting process. */
- if (RTS_ISSET(rp, RTS_RECEIVING) && rp->p_getfrom_e == rc->p_endpoint) {
- rp->p_reg.retreg = ESRCDIED; /* report source died */
- RTS_UNSET(rp, RTS_RECEIVING); /* no longer receiving */
+ /* Check if process is depends on exiting process. */
+ if (P_BLOCKEDON(rp) == rc->p_endpoint) {
+ rp->p_reg.retreg = EDEADSRCDST; /* report source died */
+ RTS_UNSET(rp, (RTS_RECEIVING|RTS_SENDING)); /* no longer blocking */
#if DEBUG_ENABLE_IPC_WARNINGS
- kprintf("endpoint %d / %s receiving from dead src ep %d / %s\n",
- rp->p_endpoint, rp->p_name, rc->p_endpoint, rc->p_name);
-#endif
- }
- if (RTS_ISSET(rp, RTS_SENDING) &&
- rp->p_sendto_e == rc->p_endpoint) {
- rp->p_reg.retreg = EDSTDIED; /* report destination died */
- RTS_UNSET(rp, RTS_SENDING);
-#if DEBUG_ENABLE_IPC_WARNINGS
- kprintf("endpoint %d / %s send to dying dst ep %d (%s)\n",
+ kprintf("endpoint %d / %s blocked on dead src ep %d / %s\n",
rp->p_endpoint, rp->p_name, rc->p_endpoint, rc->p_name);
#endif
}