mirror of https://github.com/xzeldon/htop.git
Scan threads for process state information.
Based on: http://stackoverflow.com/questions/6788274/ios-mac-cpu-usage-for-thread
and e86692e869/ProcessList.c
This should be a fix for #361.
This commit is contained in:
parent
c18309466d
commit
5ee6715843
|
@ -13,6 +13,8 @@ in the source distribution for its full text.
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <mach/mach.h>
|
||||||
|
|
||||||
/*{
|
/*{
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "DarwinProcessList.h"
|
#include "DarwinProcessList.h"
|
||||||
|
@ -296,15 +298,7 @@ void DarwinProcess_setFromKInfoProc(Process *proc, struct kinfo_proc *ps, time_t
|
||||||
proc->nice = ep->p_nice;
|
proc->nice = ep->p_nice;
|
||||||
proc->priority = ep->p_priority;
|
proc->priority = ep->p_priority;
|
||||||
|
|
||||||
/* Set the state */
|
proc->state = (ep->p_stat == SZOMB) ? 'Z' : '?';
|
||||||
switch(ep->p_stat) {
|
|
||||||
case SIDL: proc->state = 'I'; break;
|
|
||||||
case SRUN: proc->state = 'R'; break;
|
|
||||||
case SSLEEP: proc->state = 'S'; break;
|
|
||||||
case SSTOP: proc->state = 'T'; break;
|
|
||||||
case SZOMB: proc->state = 'Z'; break;
|
|
||||||
default: proc->state = '?'; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure the updated flag is set */
|
/* Make sure the updated flag is set */
|
||||||
proc->updated = true;
|
proc->updated = true;
|
||||||
|
@ -343,3 +337,64 @@ void DarwinProcess_setFromLibprocPidinfo(DarwinProcess *proc, DarwinProcessList
|
||||||
dpl->super.runningTasks += pti.pti_numrunning;
|
dpl->super.runningTasks += pti.pti_numrunning;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scan threads for process state information.
|
||||||
|
* Based on: http://stackoverflow.com/questions/6788274/ios-mac-cpu-usage-for-thread
|
||||||
|
* and https://github.com/max-horvath/htop-osx/blob/e86692e869e30b0bc7264b3675d2a4014866ef46/ProcessList.c
|
||||||
|
*/
|
||||||
|
void DarwinProcess_scanThreads(DarwinProcess *dp) {
|
||||||
|
Process* proc = (Process*) dp;
|
||||||
|
kern_return_t ret;
|
||||||
|
|
||||||
|
if (proc->state == 'Z') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
task_t port;
|
||||||
|
ret = task_for_pid(mach_task_self(), proc->pid, &port);
|
||||||
|
if (ret != KERN_SUCCESS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
task_info_data_t tinfo;
|
||||||
|
mach_msg_type_number_t task_info_count = TASK_INFO_MAX;
|
||||||
|
ret = task_info(port, TASK_BASIC_INFO, (task_info_t) tinfo, &task_info_count);
|
||||||
|
if (ret != KERN_SUCCESS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_array_t thread_list;
|
||||||
|
mach_msg_type_number_t thread_count;
|
||||||
|
ret = task_threads(port, &thread_list, &thread_count);
|
||||||
|
if (ret != KERN_SUCCESS) {
|
||||||
|
mach_port_deallocate(mach_task_self(), port);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
integer_t run_state = 999;
|
||||||
|
for (unsigned int i = 0; i < thread_count; i++) {
|
||||||
|
thread_info_data_t thinfo;
|
||||||
|
mach_msg_type_number_t thread_info_count = THREAD_BASIC_INFO_COUNT;
|
||||||
|
ret = thread_info(thread_list[i], THREAD_BASIC_INFO, (thread_info_t)thinfo, &thread_info_count);
|
||||||
|
if (ret == KERN_SUCCESS) {
|
||||||
|
thread_basic_info_t basic_info_th = (thread_basic_info_t) thinfo;
|
||||||
|
if (basic_info_th->run_state < run_state) {
|
||||||
|
run_state = basic_info_th->run_state;
|
||||||
|
}
|
||||||
|
mach_port_deallocate(mach_task_self(), thread_list[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vm_deallocate(mach_task_self(), (vm_address_t) thread_list, sizeof(thread_port_array_t) * thread_count);
|
||||||
|
mach_port_deallocate(mach_task_self(), port);
|
||||||
|
|
||||||
|
char state = '?';
|
||||||
|
switch (run_state) {
|
||||||
|
case TH_STATE_RUNNING: state = 'R'; break;
|
||||||
|
case TH_STATE_STOPPED: state = 'S'; break;
|
||||||
|
case TH_STATE_WAITING: state = 'W'; break;
|
||||||
|
case TH_STATE_UNINTERRUPTIBLE: state = 'U'; break;
|
||||||
|
case TH_STATE_HALTED: state = 'H'; break;
|
||||||
|
}
|
||||||
|
proc->state = state;
|
||||||
|
}
|
||||||
|
|
|
@ -38,4 +38,6 @@ void DarwinProcess_setFromKInfoProc(Process *proc, struct kinfo_proc *ps, time_t
|
||||||
|
|
||||||
void DarwinProcess_setFromLibprocPidinfo(DarwinProcess *proc, DarwinProcessList *dpl);
|
void DarwinProcess_setFromLibprocPidinfo(DarwinProcess *proc, DarwinProcessList *dpl);
|
||||||
|
|
||||||
|
void DarwinProcess_scanThreads(DarwinProcess *dp);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -168,8 +168,10 @@ void ProcessList_goThroughEntries(ProcessList* super) {
|
||||||
for(size_t i = 0; i < count; ++i) {
|
for(size_t i = 0; i < count; ++i) {
|
||||||
proc = (DarwinProcess *)ProcessList_getProcess(super, ps[i].kp_proc.p_pid, &preExisting, (Process_New)DarwinProcess_new);
|
proc = (DarwinProcess *)ProcessList_getProcess(super, ps[i].kp_proc.p_pid, &preExisting, (Process_New)DarwinProcess_new);
|
||||||
|
|
||||||
DarwinProcess_setFromKInfoProc(&proc->super, ps + i, tv.tv_sec, preExisting);
|
DarwinProcess_setFromKInfoProc(&proc->super, &ps[i], tv.tv_sec, preExisting);
|
||||||
DarwinProcess_setFromLibprocPidinfo(proc, dpl);
|
DarwinProcess_setFromLibprocPidinfo(proc, dpl);
|
||||||
|
|
||||||
|
DarwinProcess_scanThreads(proc);
|
||||||
|
|
||||||
super->totalTasks += 1;
|
super->totalTasks += 1;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue