From: Ben Gras Date: Wed, 3 Mar 2010 15:32:26 +0000 (+0000) Subject: New P_BLOCKEDON for kernel - a macro that encodes the "who is this X-Git-Tag: v3.1.7~260 X-Git-Url: http://zhaoyanbai.com/repos/?a=commitdiff_plain;h=18924ea5633c3aef7f548ca056b962e360b6a32b;p=minix.git New P_BLOCKEDON for kernel - a macro that encodes the "who is this process waiting for" logic, which is duplicated a few times in the kernel. (For a new feature for top.) Introducing it and throwing out ESRCDIED and EDSTDIED (replaced by EDEADSRCDST - so we don't have to care which part of the blocking is failing in system.c) simplifies some code in the kernel and callers that check for E{DEADSRCDST,ESRCDIED,EDSTDIED}, but don't care about the difference, a fair bit, and more significantly doesn't duplicate the 'blocked-on' logic. --- diff --git a/kernel/arch/i386/system.c b/kernel/arch/i386/system.c index d54dc63a4..af7f4bcae 100644 --- a/kernel/arch/i386/system.c +++ b/kernel/arch/i386/system.c @@ -315,7 +315,7 @@ PRIVATE void ser_debug(int c) 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) { @@ -331,15 +331,8 @@ PRIVATE void printslot(struct proc *pp, int level) 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 { diff --git a/kernel/proc.c b/kernel/proc.c index 612736b7b..92d39d2b5 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -511,6 +511,7 @@ proc_nr_t src_dst; /* src or dst process */ #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; @@ -520,14 +521,13 @@ proc_nr_t src_dst; /* src or dst process */ /* 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 @@ -585,7 +585,7 @@ int flags; if (RTS_ISSET(dst_ptr, RTS_NO_ENDPOINT)) { - return EDSTDIED; + return EDEADSRCDST; } /* Check if 'dst' is blocked waiting for this message. The destination's @@ -661,7 +661,7 @@ int flags; okendpt(src_e, &src_p); if (RTS_ISSET(proc_addr(src_p), RTS_NO_ENDPOINT)) { - return ESRCDIED; + return EDEADSRCDST; } } @@ -958,7 +958,7 @@ PRIVATE int mini_senda(struct proc *caller_ptr, asynmsg_t *table, size_t size) /* 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); diff --git a/kernel/proc.h b/kernel/proc.h index a144a4cb0..c2f05ea20 100644 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -157,6 +157,25 @@ struct proc { #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)) diff --git a/kernel/system.c b/kernel/system.c index 04a57d7b1..653906662 100644 --- a/kernel/system.c +++ b/kernel/system.c @@ -519,21 +519,12 @@ register struct proc *rc; /* slot of process to clean up */ /* 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 }