summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2005-10-27 16:47:28 +0000
committerjhb <jhb@FreeBSD.org>2005-10-27 16:47:28 +0000
commit31b39202701bc7c349b94a958647fc504a1ad9a6 (patch)
tree08321a9078dbb63fde3d1973b413732023614b72
parent5e727d7ba41e2e05df29273aeacbbb74564c57fa (diff)
downloadFreeBSD-src-31b39202701bc7c349b94a958647fc504a1ad9a6.zip
FreeBSD-src-31b39202701bc7c349b94a958647fc504a1ad9a6.tar.gz
Revert most of revision 1.235 and fix the problem a different way. We
can't acquire an sx lock in ttyinfo() because ttyinfo() can be called from interrupt handlers (such as atkbd_intr()). Instead, go back to locking the process group while we pick a thread to display information for and hold that lock until after we drop sched_lock to make sure the process doesn't exit out from under us. sched_lock ensures that the specific thread from that process doesn't go away. To protect against the process exiting after we drop the proc lock but before we dereference it to lookup the pid and p_comm in the call to ttyprintf(), we now copy the pid and p_comm to local variables while holding the proc lock. This problem was found by the recently added TD_NO_SLEEPING assertions for interrupt handlers. Tested by: emaste MFC after: 1 week
-rw-r--r--sys/kern/tty.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index 825f8a0..94a3d40 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -2531,6 +2531,8 @@ ttyinfo(struct tty *tp)
const char *stateprefix, *state;
long rss;
int load, pctcpu;
+ pid_t pid;
+ char comm[MAXCOMLEN + 1];
if (ttycheckoutq(tp,0) == 0)
return;
@@ -2553,9 +2555,9 @@ ttyinfo(struct tty *tp)
tp->t_rocount = 0;
return;
}
- sx_slock(&proctree_lock);
- if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == NULL) {
- sx_sunlock(&proctree_lock);
+ PGRP_LOCK(tp->t_pgrp);
+ if (LIST_EMPTY(&tp->t_pgrp->pg_members)) {
+ PGRP_UNLOCK(tp->t_pgrp);
ttyprintf(tp, "empty foreground process group\n");
tp->t_rocount = 0;
return;
@@ -2569,8 +2571,9 @@ ttyinfo(struct tty *tp)
* copy of the state, but may increase interrupt latency
* too much.
*/
+ pick = NULL;
mtx_lock_spin(&sched_lock);
- for (pick = NULL; p != NULL; p = LIST_NEXT(p, p_pglist))
+ LIST_FOREACH(p, &tp->t_pgrp->pg_members, p_pglist)
if (proc_compare(pick, p))
pick = p;
@@ -2580,7 +2583,7 @@ ttyinfo(struct tty *tp)
#else
if (td == NULL) {
mtx_unlock_spin(&sched_lock);
- sx_sunlock(&proctree_lock);
+ PGRP_UNLOCK(tp->t_pgrp);
ttyprintf(tp, "foreground process without thread\n");
tp->t_rocount = 0;
return;
@@ -2613,18 +2616,20 @@ ttyinfo(struct tty *tp)
rss = pgtok(vmspace_resident_count(pick->p_vmspace));
mtx_unlock_spin(&sched_lock);
PROC_LOCK(pick);
+ PGRP_UNLOCK(tp->t_pgrp);
calcru(pick, &utime, &stime);
+ pid = pick->p_pid;
+ bcopy(pick->p_comm, comm, sizeof(comm));
PROC_UNLOCK(pick);
/* Print command, pid, state, utime, stime, %cpu, and rss. */
ttyprintf(tp,
" cmd: %s %d [%s%s] %ld.%02ldu %ld.%02lds %d%% %ldk\n",
- pick->p_comm, pick->p_pid, stateprefix, state,
+ comm, pid, stateprefix, state,
(long)utime.tv_sec, utime.tv_usec / 10000,
(long)stime.tv_sec, stime.tv_usec / 10000,
pctcpu / 100, rss);
tp->t_rocount = 0;
- sx_sunlock(&proctree_lock);
}
/*
OpenPOWER on IntegriCloud