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.
This commit is contained in:
parent
cbd276e4ce
commit
18924ea563
|
@ -315,7 +315,7 @@ PRIVATE void ser_debug(int c)
|
||||||
PRIVATE void printslot(struct proc *pp, int level)
|
PRIVATE void printslot(struct proc *pp, int level)
|
||||||
{
|
{
|
||||||
struct proc *depproc = NULL;
|
struct proc *depproc = NULL;
|
||||||
int dep = NONE;
|
endpoint_t dep;
|
||||||
#define COL { int i; for(i = 0; i < level; i++) printf("> "); }
|
#define COL { int i; for(i = 0; i < level; i++) printf("> "); }
|
||||||
|
|
||||||
if(level >= NR_PROCS) {
|
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,
|
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));
|
rtsflagstr(pp->p_rts_flags), miscflagstr(pp->p_misc_flags));
|
||||||
|
|
||||||
if(pp->p_rts_flags & RTS_SENDING) {
|
if((dep = P_BLOCKEDON(pp)) != NONE) {
|
||||||
dep = pp->p_sendto_e;
|
kprintf(" blocked on: ");
|
||||||
kprintf(" to: ");
|
|
||||||
} else if(pp->p_rts_flags & RTS_RECEIVING) {
|
|
||||||
dep = pp->p_getfrom_e;
|
|
||||||
kprintf(" from: ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(dep != NONE) {
|
|
||||||
if(dep == ANY) {
|
if(dep == ANY) {
|
||||||
kprintf(" ANY\n");
|
kprintf(" ANY\n");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -511,6 +511,7 @@ proc_nr_t src_dst; /* src or dst process */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (src_dst != ANY) { /* check while process nr */
|
while (src_dst != ANY) { /* check while process nr */
|
||||||
|
endpoint_t dep;
|
||||||
xp = proc_addr(src_dst); /* follow chain of processes */
|
xp = proc_addr(src_dst); /* follow chain of processes */
|
||||||
#if DEBUG_ENABLE_IPC_WARNINGS
|
#if DEBUG_ENABLE_IPC_WARNINGS
|
||||||
processes[group_size] = xp;
|
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
|
/* Check whether the last process in the chain has a dependency. If it
|
||||||
* has not, the cycle cannot be closed and we are done.
|
* has not, the cycle cannot be closed and we are done.
|
||||||
*/
|
*/
|
||||||
if (RTS_ISSET(xp, RTS_RECEIVING)) { /* xp has dependency */
|
if((dep = P_BLOCKEDON(xp)) == NONE)
|
||||||
if(xp->p_getfrom_e == ANY) src_dst = ANY;
|
return 0;
|
||||||
else okendpt(xp->p_getfrom_e, &src_dst);
|
|
||||||
} else if (RTS_ISSET(xp, RTS_SENDING)) { /* xp has dependency */
|
if(dep == ANY)
|
||||||
okendpt(xp->p_sendto_e, &src_dst);
|
src_dst = ANY;
|
||||||
} else {
|
else
|
||||||
return(0); /* not a deadlock */
|
okendpt(dep, &src_dst);
|
||||||
}
|
|
||||||
|
|
||||||
/* Now check if there is a cyclic dependency. For group sizes of two,
|
/* 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
|
* 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))
|
if (RTS_ISSET(dst_ptr, RTS_NO_ENDPOINT))
|
||||||
{
|
{
|
||||||
return EDSTDIED;
|
return EDEADSRCDST;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if 'dst' is blocked waiting for this message. The destination's
|
/* Check if 'dst' is blocked waiting for this message. The destination's
|
||||||
|
@ -661,7 +661,7 @@ int flags;
|
||||||
okendpt(src_e, &src_p);
|
okendpt(src_e, &src_p);
|
||||||
if (RTS_ISSET(proc_addr(src_p), RTS_NO_ENDPOINT))
|
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 */
|
/* RTS_NO_ENDPOINT should be removed */
|
||||||
if (dst_ptr->p_rts_flags & RTS_NO_ENDPOINT)
|
if (dst_ptr->p_rts_flags & RTS_NO_ENDPOINT)
|
||||||
{
|
{
|
||||||
tabent.result= EDSTDIED;
|
tabent.result= EDEADSRCDST;
|
||||||
A_INSERT(i, result);
|
A_INSERT(i, result);
|
||||||
tabent.flags= flags | AMF_DONE;
|
tabent.flags= flags | AMF_DONE;
|
||||||
A_INSERT(i, flags);
|
A_INSERT(i, flags);
|
||||||
|
|
|
@ -157,6 +157,25 @@ struct proc {
|
||||||
#define proc_is_preempted(p) ((p)->p_rts_flags & RTS_PREEMPTED)
|
#define proc_is_preempted(p) ((p)->p_rts_flags & RTS_PREEMPTED)
|
||||||
#define proc_no_quantum(p) ((p)->p_rts_flags & RTS_NO_QUANTUM)
|
#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. */
|
/* These runtime flags can be tested and manipulated by these macros. */
|
||||||
|
|
||||||
#define RTS_ISSET(rp, f) (((rp)->p_rts_flags & (f)) == (f))
|
#define RTS_ISSET(rp, f) (((rp)->p_rts_flags & (f)) == (f))
|
||||||
|
|
|
@ -519,21 +519,12 @@ register struct proc *rc; /* slot of process to clean up */
|
||||||
/* Unset pending notification bits. */
|
/* Unset pending notification bits. */
|
||||||
unset_sys_bit(priv(rp)->s_notify_pending, priv(rc)->s_id);
|
unset_sys_bit(priv(rp)->s_notify_pending, priv(rc)->s_id);
|
||||||
|
|
||||||
/* Check if process is receiving from exiting process. */
|
/* Check if process is depends on exiting process. */
|
||||||
if (RTS_ISSET(rp, RTS_RECEIVING) && rp->p_getfrom_e == rc->p_endpoint) {
|
if (P_BLOCKEDON(rp) == rc->p_endpoint) {
|
||||||
rp->p_reg.retreg = ESRCDIED; /* report source died */
|
rp->p_reg.retreg = EDEADSRCDST; /* report source died */
|
||||||
RTS_UNSET(rp, RTS_RECEIVING); /* no longer receiving */
|
RTS_UNSET(rp, (RTS_RECEIVING|RTS_SENDING)); /* no longer blocking */
|
||||||
#if DEBUG_ENABLE_IPC_WARNINGS
|
#if DEBUG_ENABLE_IPC_WARNINGS
|
||||||
kprintf("endpoint %d / %s receiving from dead src 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
|
|
||||||
}
|
|
||||||
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",
|
|
||||||
rp->p_endpoint, rp->p_name, rc->p_endpoint, rc->p_name);
|
rp->p_endpoint, rp->p_name, rc->p_endpoint, rc->p_name);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue