diff options
Diffstat (limited to 'proc/info.c')
-rw-r--r-- | proc/info.c | 100 |
1 files changed, 54 insertions, 46 deletions
diff --git a/proc/info.c b/proc/info.c index 56e462a6..85b398f6 100644 --- a/proc/info.c +++ b/proc/info.c @@ -302,6 +302,7 @@ S_proc_getprocenv (struct proc *callerp, kern_return_t S_proc_getprocinfo (struct proc *callerp, pid_t pid, + int flags, int **piarray, u_int *piarraylen) { @@ -311,7 +312,7 @@ S_proc_getprocinfo (struct proc *callerp, thread_t *thds; error_t err; size_t structsize; - int i, j; + int i; int didalloc = 0; u_int tkcount, thcount; struct proc *tp; @@ -319,11 +320,20 @@ S_proc_getprocinfo (struct proc *callerp, if (!p) return ESRCH; - err = task_threads (p->p_task, &thds, &nthreads); - if (err == MACH_SEND_INVALID_DEST) - err = ESRCH; - if (err) - return err; + if (flags & (PI_FETCH_THREAD_SCHED | PI_FETCH_THREAD_BASIC + | PI_FETCH_THREAD_WAITS)) + flags |= PI_FETCH_THREADS; + + if (flags & PI_FETCH_THREADS) + { + err = task_threads (p->p_task, &thds, &nthreads); + if (err == MACH_SEND_INVALID_DEST) + err = ESRCH; + if (err) + return err; + } + else + nthreads = 0; structsize = (sizeof (struct procinfo) + nthreads * sizeof (struct thread_basic_info) @@ -354,65 +364,63 @@ S_proc_getprocinfo (struct proc *callerp, pi->nthreads = nthreads; - tkcount = TASK_BASIC_INFO_COUNT; - err = task_info (p->p_task, TASK_BASIC_INFO, (int *)&pi->taskinfo, - &tkcount); + if (flags & PI_FETCH_TASKINFO) + { + tkcount = TASK_BASIC_INFO_COUNT; + err = task_info (p->p_task, TASK_BASIC_INFO, (int *)&pi->taskinfo, + &tkcount); - if (err == MACH_SEND_INVALID_DEST) - err = ESRCH; - if (err) - for (i = 0; i < nthreads; i++) - mach_port_deallocate (mach_task_self (), thds[i]); - else + if (err == MACH_SEND_INVALID_DEST) + err = ESRCH; + } + + for (i = 0; i < nthreads; i++) { - j = 0; - for (i = 0; i < nthreads; i++) + pi->threadinfos[i].dead = 0; + if (flags & PI_FETCH_THREAD_BASIC) { thcount = THREAD_BASIC_INFO_COUNT; err = thread_info (thds[i], THREAD_BASIC_INFO, - (int *)&pi->threadinfos[j].pis_bi, + (int *)&pi->threadinfos[i].pis_bi, &thcount); if (err == MACH_SEND_INVALID_DEST) - err = ESRCH; - if (err && err != ESRCH) + { + pi->threadinfos[i].dead = 1; + continue; + } + if (err && err != MACH_SEND_INVALID_DEST) break; + } + if (flags & PI_FETCH_THREAD_SCHED) + { thcount = THREAD_SCHED_INFO_COUNT; if (!err) err = thread_info (thds[i], THREAD_SCHED_INFO, - (int *)&pi->threadinfos[j].pis_si, + (int *)&pi->threadinfos[i].pis_si, &thcount); if (err == MACH_SEND_INVALID_DEST) - err = ESRCH; - if (err && err != ESRCH) - break; - - if (!err) - j++; - else { - /* Don't count this one */ - /* XXX This is buggy if *piarraylen drops enough to - reduce the number of pages in structsize, because - the message send won't deallocate all that we allocated. */ - *piarraylen -= sizeof pi->threadinfos[j] / sizeof (int); - pi->nthreads--; + pi->threadinfos[i].dead = 1; + continue; } - - /* XXX If a thread has died, then its stats are now in - the TASK_BASIC_INFO struct, but our copy might have been fetched - from before the thread's death. */ - - mach_port_deallocate (mach_task_self (), thds[i]); + if (err && err != ESRCH) + break; } - /* If we got an error (other than ESRCH); clean the rest - of the thds */ - for (; i < nthreads; i++) - mach_port_deallocate (mach_task_self (), thds[i]); + + if (flags & PI_FETCH_THREAD_WAITS) + /* Errors are not significant here. */ + msg_report_wait (p->p_msgport, thds[i], + &pi->threadinfos[i].rpc_block); + + mach_port_deallocate (mach_task_self (), thds[i]); } - vm_deallocate (mach_task_self (), (u_int )thds, - nthreads * sizeof (thread_t)); + if (flags & PI_FETCH_THREADS) + { + vm_deallocate (mach_task_self (), (u_int )thds, + nthreads * sizeof (thread_t)); + } if (err && didalloc) vm_deallocate (mach_task_self (), (u_int) *piarray, structsize); |