summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--proc/info.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/proc/info.c b/proc/info.c
index f7af9d33..7fe056c4 100644
--- a/proc/info.c
+++ b/proc/info.c
@@ -359,12 +359,17 @@ S_proc_getprocinfo (struct proc *callerp,
mach_msg_type_number_t waits_used = 0;
u_int tkcount, thcount;
struct proc *tp;
+ task_t task; /* P's task port. */
+ mach_port_t msgport; /* P's msgport, or MACH_PORT_NULL if none. */
/* No need to check CALLERP here; we don't use it. */
if (!p)
return ESRCH;
+ task = p->p_task;
+ msgport = p->p_deadmsg ? MACH_PORT_NULL : p->p_msgport;
+
if (flags & (PI_FETCH_THREAD_SCHED | PI_FETCH_THREAD_BASIC
| PI_FETCH_THREAD_WAITS))
flags |= PI_FETCH_THREADS;
@@ -413,12 +418,14 @@ S_proc_getprocinfo (struct proc *callerp,
pi->nthreads = nthreads;
+ /* Release GLOBAL_LOCK around time consuming bits, and more importatantly,
+ potential calls to P's msgport, which can block. */
+ mutex_unlock (&global_lock);
+
if (flags & PI_FETCH_TASKINFO)
{
tkcount = TASK_BASIC_INFO_COUNT;
- err = task_info (p->p_task, TASK_BASIC_INFO, (int *)&pi->taskinfo,
- &tkcount);
-
+ err = task_info (task, TASK_BASIC_INFO, (int *)&pi->taskinfo, &tkcount);
if (err == MACH_SEND_INVALID_DEST)
err = ESRCH;
}
@@ -460,14 +467,14 @@ S_proc_getprocinfo (struct proc *callerp,
if (flags & PI_FETCH_THREAD_WAITS)
{
/* See what thread I is waiting on. */
- if (p->p_msgport == MACH_PORT_NULL || p->p_deadmsg)
+ if (msgport == MACH_PORT_NULL)
flags &= ~PI_FETCH_THREAD_WAITS; /* Can't return much... */
else
{
string_t desc;
size_t desc_len;
- if (msg_report_wait (p->p_msgport, thds[i],
+ if (msg_report_wait (msgport, thds[i],
desc, &pi->threadinfos[i].rpc_block))
desc[0] = '\0'; /* Don't know. */
@@ -503,7 +510,7 @@ S_proc_getprocinfo (struct proc *callerp,
}
}
- if (waits_used + desc_len + 1 > *waits_len)
+ if (waits_used + desc_len + 1 <= *waits_len)
/* Append DESC to WAITS. */
{
bcopy (desc, *waits + waits_used, desc_len);
@@ -528,6 +535,9 @@ S_proc_getprocinfo (struct proc *callerp,
else
*waits_len = waits_used;
+ /* Reacquire GLOBAL_LOCK to make the central locking code happy. */
+ mutex_lock (&global_lock);
+
return err;
}