mirror of https://github.com/xzeldon/htop.git
Tidy up process state handling
This commit is contained in:
parent
afa3fe4af1
commit
d8dfbbd37c
92
Process.c
92
Process.c
|
@ -415,7 +415,7 @@ void Process_makeCommandStr(Process* this) {
|
||||||
* - a user thread and showThreadNames is not set */
|
* - a user thread and showThreadNames is not set */
|
||||||
if (Process_isKernelThread(this))
|
if (Process_isKernelThread(this))
|
||||||
return;
|
return;
|
||||||
if (this->state == 'Z' && !this->mergedCommand.str)
|
if (this->state == ZOMBIE && !this->mergedCommand.str)
|
||||||
return;
|
return;
|
||||||
if (Process_isUserlandThread(this) && settings->showThreadNames && (showThreadNames == mc->prevShowThreadNames))
|
if (Process_isUserlandThread(this) && settings->showThreadNames && (showThreadNames == mc->prevShowThreadNames))
|
||||||
return;
|
return;
|
||||||
|
@ -749,6 +749,28 @@ void Process_printPercentage(float val, char* buffer, int n, int* attr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline char processStateChar(ProcessState state) {
|
||||||
|
switch (state) {
|
||||||
|
case UNKNOWN: return '?';
|
||||||
|
case RUNNABLE: return 'U';
|
||||||
|
case RUNNING: return 'R';
|
||||||
|
case QUEUED: return 'Q';
|
||||||
|
case WAITING: return 'W';
|
||||||
|
case UNINTERRUPTIBLE_WAIT: return 'D';
|
||||||
|
case BLOCKED: return 'B';
|
||||||
|
case PAGING: return 'P';
|
||||||
|
case STOPPED: return 'T';
|
||||||
|
case TRACED: return 't';
|
||||||
|
case ZOMBIE: return 'Z';
|
||||||
|
case DEFUNCT: return 'X';
|
||||||
|
case IDLE: return 'I';
|
||||||
|
case SLEEPING: return 'S';
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
return '!';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Process_writeField(const Process* this, RichString* str, ProcessField field) {
|
void Process_writeField(const Process* this, RichString* str, ProcessField field) {
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
size_t n = sizeof(buffer);
|
size_t n = sizeof(buffer);
|
||||||
|
@ -883,22 +905,32 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field
|
||||||
case SESSION: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->session); break;
|
case SESSION: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->session); break;
|
||||||
case STARTTIME: xSnprintf(buffer, n, "%s", this->starttime_show); break;
|
case STARTTIME: xSnprintf(buffer, n, "%s", this->starttime_show); break;
|
||||||
case STATE:
|
case STATE:
|
||||||
xSnprintf(buffer, n, "%c ", this->state);
|
xSnprintf(buffer, n, "%c ", processStateChar(this->state));
|
||||||
switch (this->state) {
|
switch (this->state) {
|
||||||
#ifdef HTOP_NETBSD
|
case RUNNABLE:
|
||||||
case 'P':
|
case RUNNING:
|
||||||
#else
|
case TRACED:
|
||||||
case 'R':
|
|
||||||
#endif
|
|
||||||
attr = CRT_colors[PROCESS_RUN_STATE];
|
attr = CRT_colors[PROCESS_RUN_STATE];
|
||||||
break;
|
break;
|
||||||
case 'D':
|
|
||||||
|
case BLOCKED:
|
||||||
|
case DEFUNCT:
|
||||||
|
case STOPPED:
|
||||||
|
case ZOMBIE:
|
||||||
attr = CRT_colors[PROCESS_D_STATE];
|
attr = CRT_colors[PROCESS_D_STATE];
|
||||||
break;
|
break;
|
||||||
case 'I':
|
|
||||||
case 'S':
|
case QUEUED:
|
||||||
|
case WAITING:
|
||||||
|
case UNINTERRUPTIBLE_WAIT:
|
||||||
|
case IDLE:
|
||||||
|
case SLEEPING:
|
||||||
attr = CRT_colors[PROCESS_SHADOW];
|
attr = CRT_colors[PROCESS_SHADOW];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case UNKNOWN:
|
||||||
|
case PAGING:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ST_UID: xSnprintf(buffer, n, "%*d ", Process_uidDigits, this->st_uid); break;
|
case ST_UID: xSnprintf(buffer, n, "%*d ", Process_uidDigits, this->st_uid); break;
|
||||||
|
@ -1072,44 +1104,6 @@ int Process_compare(const void* v1, const void* v2) {
|
||||||
return (Settings_getActiveDirection(settings) == 1) ? result : -result;
|
return (Settings_getActiveDirection(settings) == 1) ? result : -result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t stateCompareValue(char state) {
|
|
||||||
switch (state) {
|
|
||||||
|
|
||||||
case 'S':
|
|
||||||
return 10;
|
|
||||||
|
|
||||||
case 'I':
|
|
||||||
return 9;
|
|
||||||
|
|
||||||
case 'X':
|
|
||||||
return 8;
|
|
||||||
|
|
||||||
case 'Z':
|
|
||||||
return 7;
|
|
||||||
|
|
||||||
case 't':
|
|
||||||
return 6;
|
|
||||||
|
|
||||||
case 'T':
|
|
||||||
return 5;
|
|
||||||
|
|
||||||
case 'L':
|
|
||||||
return 4;
|
|
||||||
|
|
||||||
case 'D':
|
|
||||||
return 3;
|
|
||||||
|
|
||||||
case 'R':
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
case '?':
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int Process_compareByKey_Base(const Process* p1, const Process* p2, ProcessField key) {
|
int Process_compareByKey_Base(const Process* p1, const Process* p2, ProcessField key) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -1164,7 +1158,7 @@ int Process_compareByKey_Base(const Process* p1, const Process* p2, ProcessField
|
||||||
r = SPACESHIP_NUMBER(p1->starttime_ctime, p2->starttime_ctime);
|
r = SPACESHIP_NUMBER(p1->starttime_ctime, p2->starttime_ctime);
|
||||||
return r != 0 ? r : SPACESHIP_NUMBER(p1->pid, p2->pid);
|
return r != 0 ? r : SPACESHIP_NUMBER(p1->pid, p2->pid);
|
||||||
case STATE:
|
case STATE:
|
||||||
return SPACESHIP_NUMBER(stateCompareValue(p1->state), stateCompareValue(p2->state));
|
return SPACESHIP_NUMBER(p1->state, p2->state);
|
||||||
case ST_UID:
|
case ST_UID:
|
||||||
return SPACESHIP_NUMBER(p1->st_uid, p2->st_uid);
|
return SPACESHIP_NUMBER(p1->st_uid, p2->st_uid);
|
||||||
case TIME:
|
case TIME:
|
||||||
|
|
36
Process.h
36
Process.h
|
@ -60,6 +60,26 @@ typedef enum ProcessField_ {
|
||||||
LAST_PROCESSFIELD
|
LAST_PROCESSFIELD
|
||||||
} ProcessField;
|
} ProcessField;
|
||||||
|
|
||||||
|
/* Core process states (shared by platforms)
|
||||||
|
* NOTE: The enum has an ordering that is important!
|
||||||
|
* See processStateChar in process.c for ProcessSate -> letter mapping */
|
||||||
|
typedef enum ProcessState_ {
|
||||||
|
UNKNOWN = 1,
|
||||||
|
RUNNABLE,
|
||||||
|
RUNNING,
|
||||||
|
QUEUED,
|
||||||
|
WAITING,
|
||||||
|
UNINTERRUPTIBLE_WAIT,
|
||||||
|
BLOCKED,
|
||||||
|
PAGING,
|
||||||
|
STOPPED,
|
||||||
|
TRACED,
|
||||||
|
ZOMBIE,
|
||||||
|
DEFUNCT,
|
||||||
|
IDLE,
|
||||||
|
SLEEPING
|
||||||
|
} ProcessState;
|
||||||
|
|
||||||
struct Settings_;
|
struct Settings_;
|
||||||
|
|
||||||
/* Holds information about regions of the cmdline that should be
|
/* Holds information about regions of the cmdline that should be
|
||||||
|
@ -202,20 +222,8 @@ typedef struct Process_ {
|
||||||
/* Number of major faults the process has made which have required loading a memory page from disk */
|
/* Number of major faults the process has made which have required loading a memory page from disk */
|
||||||
unsigned long int majflt;
|
unsigned long int majflt;
|
||||||
|
|
||||||
/*
|
/* Process state enum field (platform dependent) */
|
||||||
* Process state (platform dependent):
|
ProcessState state;
|
||||||
* D - Waiting
|
|
||||||
* I - Idle
|
|
||||||
* L - Acquiring lock
|
|
||||||
* R - Running
|
|
||||||
* S - Sleeping
|
|
||||||
* T - Stopped (on a signal)
|
|
||||||
* X - Dead
|
|
||||||
* Z - Zombie
|
|
||||||
* t - Tracing stop
|
|
||||||
* ? - Unknown
|
|
||||||
*/
|
|
||||||
char state;
|
|
||||||
|
|
||||||
/* Whether the process was updated during the current scan */
|
/* Whether the process was updated during the current scan */
|
||||||
bool updated;
|
bool updated;
|
||||||
|
|
|
@ -331,7 +331,7 @@ void DarwinProcess_setFromKInfoProc(Process* proc, const struct kinfo_proc* ps,
|
||||||
proc->nice = ep->p_nice;
|
proc->nice = ep->p_nice;
|
||||||
proc->priority = ep->p_priority;
|
proc->priority = ep->p_priority;
|
||||||
|
|
||||||
proc->state = (ep->p_stat == SZOMB) ? 'Z' : '?';
|
proc->state = (ep->p_stat == SZOMB) ? ZOMBIE : UNKNOWN;
|
||||||
|
|
||||||
/* Make sure the updated flag is set */
|
/* Make sure the updated flag is set */
|
||||||
proc->updated = true;
|
proc->updated = true;
|
||||||
|
@ -386,7 +386,7 @@ void DarwinProcess_scanThreads(DarwinProcess* dp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proc->state == 'Z') {
|
if (proc->state == ZOMBIE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,15 +430,15 @@ void DarwinProcess_scanThreads(DarwinProcess* dp) {
|
||||||
vm_deallocate(mach_task_self(), (vm_address_t) thread_list, sizeof(thread_port_array_t) * thread_count);
|
vm_deallocate(mach_task_self(), (vm_address_t) thread_list, sizeof(thread_port_array_t) * thread_count);
|
||||||
mach_port_deallocate(mach_task_self(), port);
|
mach_port_deallocate(mach_task_self(), port);
|
||||||
|
|
||||||
char state = '?';
|
/* Taken from: https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/osfmk/mach/thread_info.h#L129 */
|
||||||
switch (run_state) {
|
switch (run_state) {
|
||||||
case TH_STATE_RUNNING: state = 'R'; break;
|
case TH_STATE_RUNNING: proc->state = RUNNING; break;
|
||||||
case TH_STATE_STOPPED: state = 'S'; break;
|
case TH_STATE_STOPPED: proc->state = STOPPED; break;
|
||||||
case TH_STATE_WAITING: state = 'W'; break;
|
case TH_STATE_WAITING: proc->state = WAITING; break;
|
||||||
case TH_STATE_UNINTERRUPTIBLE: state = 'U'; break;
|
case TH_STATE_UNINTERRUPTIBLE: proc->state = UNINTERRUPTIBLE_WAIT; break;
|
||||||
case TH_STATE_HALTED: state = 'H'; break;
|
case TH_STATE_HALTED: proc->state = BLOCKED; break;
|
||||||
|
default: proc->state = UNKNOWN;
|
||||||
}
|
}
|
||||||
proc->state = state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -542,60 +542,61 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// would be nice if we could store multiple states in proc->state (as enum) and have writeField render them
|
// would be nice if we could store multiple states in proc->state (as enum) and have writeField render them
|
||||||
|
/* Taken from: https://github.com/DragonFlyBSD/DragonFlyBSD/blob/c163a4d7ee9c6857ee4e04a3a2cbb50c3de29da1/sys/sys/proc_common.h */
|
||||||
switch (kproc->kp_stat) {
|
switch (kproc->kp_stat) {
|
||||||
case SIDL: proc->state = 'I'; isIdleProcess = true; break;
|
case SIDL: proc->state = IDLE; isIdleProcess = true; break;
|
||||||
case SACTIVE:
|
case SACTIVE:
|
||||||
switch (kproc->kp_lwp.kl_stat) {
|
switch (kproc->kp_lwp.kl_stat) {
|
||||||
case LSSLEEP:
|
case LSSLEEP:
|
||||||
if (kproc->kp_lwp.kl_flags & LWP_SINTR) // interruptible wait short/long
|
if (kproc->kp_lwp.kl_flags & LWP_SINTR) // interruptible wait short/long
|
||||||
if (kproc->kp_lwp.kl_slptime >= MAXSLP) {
|
if (kproc->kp_lwp.kl_slptime >= MAXSLP) {
|
||||||
proc->state = 'I';
|
proc->state = IDLE;
|
||||||
isIdleProcess = true;
|
isIdleProcess = true;
|
||||||
} else {
|
} else {
|
||||||
proc->state = 'S';
|
proc->state = SLEEPING;
|
||||||
}
|
}
|
||||||
else if (kproc->kp_lwp.kl_tdflags & TDF_SINTR) // interruptible lwkt wait
|
else if (kproc->kp_lwp.kl_tdflags & TDF_SINTR) // interruptible lwkt wait
|
||||||
proc->state = 'S';
|
proc->state = SLEEPING;
|
||||||
else if (kproc->kp_paddr) // uninterruptible wait
|
else if (kproc->kp_paddr) // uninterruptible wait
|
||||||
proc->state = 'D';
|
proc->state = UNINTERRUPTIBLE_WAIT;
|
||||||
else // uninterruptible lwkt wait
|
else // uninterruptible lwkt wait
|
||||||
proc->state = 'B';
|
proc->state = UNINTERRUPTIBLE_WAIT;
|
||||||
break;
|
break;
|
||||||
case LSRUN:
|
case LSRUN:
|
||||||
if (kproc->kp_lwp.kl_stat == LSRUN) {
|
if (kproc->kp_lwp.kl_stat == LSRUN) {
|
||||||
if (!(kproc->kp_lwp.kl_tdflags & (TDF_RUNNING | TDF_RUNQ)))
|
if (!(kproc->kp_lwp.kl_tdflags & (TDF_RUNNING | TDF_RUNQ)))
|
||||||
proc->state = 'Q';
|
proc->state = QUEUED;
|
||||||
else
|
else
|
||||||
proc->state = 'R';
|
proc->state = RUNNING;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LSSTOP:
|
case LSSTOP:
|
||||||
proc->state = 'T';
|
proc->state = STOPPED;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
proc->state = 'A';
|
proc->state = PAGING;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SSTOP: proc->state = 'T'; break;
|
case SSTOP: proc->state = STOPPED; break;
|
||||||
case SZOMB: proc->state = 'Z'; break;
|
case SZOMB: proc->state = ZOMBIE; break;
|
||||||
case SCORE: proc->state = 'C'; break;
|
case SCORE: proc->state = BLOCKED; break;
|
||||||
default: proc->state = '?';
|
default: proc->state = UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kproc->kp_flags & P_SWAPPEDOUT)
|
if (kproc->kp_flags & P_SWAPPEDOUT)
|
||||||
proc->state = 'W';
|
proc->state = SLEEPING;
|
||||||
if (kproc->kp_flags & P_TRACED)
|
if (kproc->kp_flags & P_TRACED)
|
||||||
proc->state = 'T';
|
proc->state = TRACED;
|
||||||
if (kproc->kp_flags & P_JAILED)
|
if (kproc->kp_flags & P_JAILED)
|
||||||
proc->state = 'J';
|
proc->state = TRACED;
|
||||||
|
|
||||||
if (Process_isKernelThread(proc))
|
if (Process_isKernelThread(proc))
|
||||||
super->kernelThreads++;
|
super->kernelThreads++;
|
||||||
|
|
||||||
super->totalTasks++;
|
super->totalTasks++;
|
||||||
|
|
||||||
if (proc->state == 'R')
|
if (proc->state == RUNNING)
|
||||||
super->runningTasks++;
|
super->runningTasks++;
|
||||||
|
|
||||||
proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) || (hideUserlandThreads && Process_isUserlandThread(proc)));
|
proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) || (hideUserlandThreads && Process_isUserlandThread(proc)));
|
||||||
|
|
|
@ -578,15 +578,16 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
|
||||||
proc->nice = PRIO_MAX + 1 + kproc->ki_pri.pri_level - PRI_MIN_IDLE;
|
proc->nice = PRIO_MAX + 1 + kproc->ki_pri.pri_level - PRI_MIN_IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Taken from: https://github.com/freebsd/freebsd-src/blob/1ad2d87778970582854082bcedd2df0394fd4933/sys/sys/proc.h#L851 */
|
||||||
switch (kproc->ki_stat) {
|
switch (kproc->ki_stat) {
|
||||||
case SIDL: proc->state = 'I'; break;
|
case SIDL: proc->state = IDLE; break;
|
||||||
case SRUN: proc->state = 'R'; break;
|
case SRUN: proc->state = RUNNING; break;
|
||||||
case SSLEEP: proc->state = 'S'; break;
|
case SSLEEP: proc->state = SLEEPING; break;
|
||||||
case SSTOP: proc->state = 'T'; break;
|
case SSTOP: proc->state = STOPPED; break;
|
||||||
case SZOMB: proc->state = 'Z'; break;
|
case SZOMB: proc->state = ZOMBIE; break;
|
||||||
case SWAIT: proc->state = 'D'; break;
|
case SWAIT: proc->state = WAITING; break;
|
||||||
case SLOCK: proc->state = 'L'; break;
|
case SLOCK: proc->state = BLOCKED; break;
|
||||||
default: proc->state = '?';
|
default: proc->state = UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Process_isKernelThread(proc))
|
if (Process_isKernelThread(proc))
|
||||||
|
@ -595,7 +596,7 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
|
||||||
proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) || (hideUserlandThreads && Process_isUserlandThread(proc)));
|
proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) || (hideUserlandThreads && Process_isUserlandThread(proc)));
|
||||||
|
|
||||||
super->totalTasks++;
|
super->totalTasks++;
|
||||||
if (proc->state == 'R')
|
if (proc->state == RUNNING)
|
||||||
super->runningTasks++;
|
super->runningTasks++;
|
||||||
proc->updated = true;
|
proc->updated = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -310,6 +310,22 @@ static inline unsigned long long LinuxProcessList_adjustTime(unsigned long long
|
||||||
return t * 100 / jiffy;
|
return t * 100 / jiffy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Taken from: https://github.com/torvalds/linux/blob/64570fbc14f8d7cb3fe3995f20e26bc25ce4b2cc/fs/proc/array.c#L120 */
|
||||||
|
static inline ProcessState LinuxProcessList_getProcessState(char state) {
|
||||||
|
switch (state) {
|
||||||
|
case 'S': return SLEEPING;
|
||||||
|
case 'X': return DEFUNCT;
|
||||||
|
case 'Z': return ZOMBIE;
|
||||||
|
case 't': return TRACED;
|
||||||
|
case 'T': return STOPPED;
|
||||||
|
case 'D': return UNINTERRUPTIBLE_WAIT;
|
||||||
|
case 'R': return RUNNING;
|
||||||
|
case 'P': return BLOCKED;
|
||||||
|
case 'I': return IDLE;
|
||||||
|
default: return UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool LinuxProcessList_readStatFile(Process* process, openat_arg_t procFd, char* command, size_t commLen) {
|
static bool LinuxProcessList_readStatFile(Process* process, openat_arg_t procFd, char* command, size_t commLen) {
|
||||||
LinuxProcess* lp = (LinuxProcess*) process;
|
LinuxProcess* lp = (LinuxProcess*) process;
|
||||||
|
|
||||||
|
@ -335,7 +351,7 @@ static bool LinuxProcessList_readStatFile(Process* process, openat_arg_t procFd,
|
||||||
location = end + 2;
|
location = end + 2;
|
||||||
|
|
||||||
/* (3) state - %c */
|
/* (3) state - %c */
|
||||||
process->state = location[0];
|
process->state = LinuxProcessList_getProcessState(location[0]);
|
||||||
location += 2;
|
location += 2;
|
||||||
|
|
||||||
/* (4) ppid - %d */
|
/* (4) ppid - %d */
|
||||||
|
@ -1098,7 +1114,7 @@ static bool LinuxProcessList_readCmdlineFile(Process* process, openat_arg_t proc
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (amtRead == 0) {
|
if (amtRead == 0) {
|
||||||
if (process->state != 'Z') {
|
if (process->state != ZOMBIE) {
|
||||||
process->isKernelThread = true;
|
process->isKernelThread = true;
|
||||||
}
|
}
|
||||||
Process_updateCmdline(process, NULL, 0, 0);
|
Process_updateCmdline(process, NULL, 0, 0);
|
||||||
|
@ -1511,7 +1527,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
|
||||||
|
|
||||||
ProcessList_add(pl, proc);
|
ProcessList_add(pl, proc);
|
||||||
} else {
|
} else {
|
||||||
if (settings->updateProcessNames && proc->state != 'Z') {
|
if (settings->updateProcessNames && proc->state != ZOMBIE) {
|
||||||
if (! LinuxProcessList_readCmdlineFile(proc, procFd)) {
|
if (! LinuxProcessList_readCmdlineFile(proc, procFd)) {
|
||||||
goto errorReadingProcess;
|
goto errorReadingProcess;
|
||||||
}
|
}
|
||||||
|
@ -1549,7 +1565,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!proc->cmdline && statCommand[0] &&
|
if (!proc->cmdline && statCommand[0] &&
|
||||||
(proc->state == 'Z' || Process_isKernelThread(proc) || settings->showThreadNames)) {
|
(proc->state == ZOMBIE || Process_isKernelThread(proc) || settings->showThreadNames)) {
|
||||||
Process_updateCmdline(proc, statCommand, 0, strlen(statCommand));
|
Process_updateCmdline(proc, statCommand, 0, strlen(statCommand));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -331,31 +331,33 @@ static void NetBSDProcessList_scanProcs(NetBSDProcessList* this) {
|
||||||
int nlwps = 0;
|
int nlwps = 0;
|
||||||
const struct kinfo_lwp* klwps = kvm_getlwps(this->kd, kproc->p_pid, kproc->p_paddr, sizeof(struct kinfo_lwp), &nlwps);
|
const struct kinfo_lwp* klwps = kvm_getlwps(this->kd, kproc->p_pid, kproc->p_paddr, sizeof(struct kinfo_lwp), &nlwps);
|
||||||
|
|
||||||
|
/* TODO: According to the link below, SDYING should be a regarded state */
|
||||||
|
/* Taken from: https://ftp.netbsd.org/pub/NetBSD/NetBSD-current/src/sys/sys/proc.h */
|
||||||
switch (kproc->p_realstat) {
|
switch (kproc->p_realstat) {
|
||||||
case SIDL: proc->state = 'I'; break;
|
case SIDL: proc->state = IDLE; break;
|
||||||
case SACTIVE:
|
case SACTIVE:
|
||||||
// We only consider the first LWP with a one of the below states.
|
// We only consider the first LWP with a one of the below states.
|
||||||
for (int j = 0; j < nlwps; j++) {
|
for (int j = 0; j < nlwps; j++) {
|
||||||
if (klwps) {
|
if (klwps) {
|
||||||
switch (klwps[j].l_stat) {
|
switch (klwps[j].l_stat) {
|
||||||
case LSONPROC: proc->state = 'P'; break;
|
case LSONPROC: proc->state = RUNNING; break;
|
||||||
case LSRUN: proc->state = 'R'; break;
|
case LSRUN: proc->state = RUNNABLE; break;
|
||||||
case LSSLEEP: proc->state = 'S'; break;
|
case LSSLEEP: proc->state = SLEEPING; break;
|
||||||
case LSSTOP: proc->state = 'T'; break;
|
case LSSTOP: proc->state = STOPPED; break;
|
||||||
default: proc->state = '?';
|
default: proc->state = UNKNOWN;
|
||||||
}
|
}
|
||||||
if (proc->state != '?')
|
if (proc->state != UNKNOWN)
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
proc->state = '?';
|
proc->state = UNKNOWN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SSTOP: proc->state = 'T'; break;
|
case SSTOP: proc->state = STOPPED; break;
|
||||||
case SZOMB: proc->state = 'Z'; break;
|
case SZOMB: proc->state = ZOMBIE; break;
|
||||||
case SDEAD: proc->state = 'D'; break;
|
case SDEAD: proc->state = DEFUNCT; break;
|
||||||
default: proc->state = '?';
|
default: proc->state = UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Process_isKernelThread(proc)) {
|
if (Process_isKernelThread(proc)) {
|
||||||
|
@ -365,8 +367,7 @@ static void NetBSDProcessList_scanProcs(NetBSDProcessList* this) {
|
||||||
}
|
}
|
||||||
|
|
||||||
this->super.totalTasks++;
|
this->super.totalTasks++;
|
||||||
// SRUN ('R') means runnable, not running
|
if (proc->state == RUNNING) {
|
||||||
if (proc->state == 'P') {
|
|
||||||
this->super.runningTasks++;
|
this->super.runningTasks++;
|
||||||
}
|
}
|
||||||
proc->updated = true;
|
proc->updated = true;
|
||||||
|
|
|
@ -345,15 +345,16 @@ static void OpenBSDProcessList_scanProcs(OpenBSDProcessList* this) {
|
||||||
proc->user = UsersTable_getRef(this->super.usersTable, proc->st_uid);
|
proc->user = UsersTable_getRef(this->super.usersTable, proc->st_uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Taken from: https://github.com/openbsd/src/blob/6a38af0976a6870911f4b2de19d8da28723a5778/sys/sys/proc.h#L420 */
|
||||||
switch (kproc->p_stat) {
|
switch (kproc->p_stat) {
|
||||||
case SIDL: proc->state = 'I'; break;
|
case SIDL: proc->state = IDLE; break;
|
||||||
case SRUN: proc->state = 'P'; break;
|
case SRUN: proc->state = RUNNABLE; break;
|
||||||
case SSLEEP: proc->state = 'S'; break;
|
case SSLEEP: proc->state = SLEEPING; break;
|
||||||
case SSTOP: proc->state = 'T'; break;
|
case SSTOP: proc->state = STOPPED; break;
|
||||||
case SZOMB: proc->state = 'Z'; break;
|
case SZOMB: proc->state = ZOMBIE; break;
|
||||||
case SDEAD: proc->state = 'D'; break;
|
case SDEAD: proc->state = DEFUNCT; break;
|
||||||
case SONPROC: proc->state = 'R'; break;
|
case SONPROC: proc->state = RUNNING; break;
|
||||||
default: proc->state = '?';
|
default: proc->state = UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Process_isKernelThread(proc)) {
|
if (Process_isKernelThread(proc)) {
|
||||||
|
@ -363,7 +364,7 @@ static void OpenBSDProcessList_scanProcs(OpenBSDProcessList* this) {
|
||||||
}
|
}
|
||||||
|
|
||||||
this->super.totalTasks++;
|
this->super.totalTasks++;
|
||||||
if (proc->state == 'R') {
|
if (proc->state == RUNNING) {
|
||||||
this->super.runningTasks++;
|
this->super.runningTasks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,10 +142,27 @@ static inline char Metric_instance_char(int metric, int pid, int offset, char fa
|
||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline PCPProcessList_getProcessState(char state) {
|
||||||
|
switch (state) {
|
||||||
|
case '?': return UNKNOWN;
|
||||||
|
case 'R': return RUNNING;
|
||||||
|
case 'W': return WAITING;
|
||||||
|
case 'D': return UNINTERRUPTIBLE_WAIT;
|
||||||
|
case 'P': return PAGING;
|
||||||
|
case 'T': return STOPPED;
|
||||||
|
case 't': return TRACED;
|
||||||
|
case 'Z': return ZOMBIE;
|
||||||
|
case 'X': return DEFUNCT;
|
||||||
|
case 'I': return IDLE;
|
||||||
|
case 'S': return SLEEPING;
|
||||||
|
default: return UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void PCPProcessList_updateID(Process* process, int pid, int offset) {
|
static void PCPProcessList_updateID(Process* process, int pid, int offset) {
|
||||||
process->tgid = Metric_instance_u32(PCP_PROC_TGID, pid, offset, 1);
|
process->tgid = Metric_instance_u32(PCP_PROC_TGID, pid, offset, 1);
|
||||||
process->ppid = Metric_instance_u32(PCP_PROC_PPID, pid, offset, 1);
|
process->ppid = Metric_instance_u32(PCP_PROC_PPID, pid, offset, 1);
|
||||||
process->state = Metric_instance_char(PCP_PROC_STATE, pid, offset, '?');
|
process->state = PCPProcessList_getProcessState(Metric_instance_char(PCP_PROC_STATE, pid, offset, '?'));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PCPProcessList_updateInfo(Process* process, int pid, int offset, char* command, size_t commLen) {
|
static void PCPProcessList_updateInfo(Process* process, int pid, int offset, char* command, size_t commLen) {
|
||||||
|
@ -283,7 +300,7 @@ static void PCPProcessList_updateUsername(Process* process, int pid, int offset,
|
||||||
static void PCPProcessList_updateCmdline(Process* process, int pid, int offset, const char* comm) {
|
static void PCPProcessList_updateCmdline(Process* process, int pid, int offset, const char* comm) {
|
||||||
pmAtomValue value;
|
pmAtomValue value;
|
||||||
if (!PCPMetric_instance(PCP_PROC_PSARGS, pid, offset, &value, PM_TYPE_STRING)) {
|
if (!PCPMetric_instance(PCP_PROC_PSARGS, pid, offset, &value, PM_TYPE_STRING)) {
|
||||||
if (process->state != 'Z')
|
if (process->state != ZOMBIE)
|
||||||
process->isKernelThread = true;
|
process->isKernelThread = true;
|
||||||
Process_updateCmdline(process, NULL, 0, 0);
|
Process_updateCmdline(process, NULL, 0, 0);
|
||||||
return;
|
return;
|
||||||
|
@ -351,7 +368,7 @@ static bool PCPProcessList_updateProcesses(PCPProcessList* this, double period,
|
||||||
if (preExisting && hideKernelThreads && Process_isKernelThread(proc)) {
|
if (preExisting && hideKernelThreads && Process_isKernelThread(proc)) {
|
||||||
proc->updated = true;
|
proc->updated = true;
|
||||||
proc->show = false;
|
proc->show = false;
|
||||||
if (proc->state == 'R')
|
if (proc->state == RUNNING)
|
||||||
pl->runningTasks++;
|
pl->runningTasks++;
|
||||||
pl->kernelThreads++;
|
pl->kernelThreads++;
|
||||||
pl->totalTasks++;
|
pl->totalTasks++;
|
||||||
|
@ -360,7 +377,7 @@ static bool PCPProcessList_updateProcesses(PCPProcessList* this, double period,
|
||||||
if (preExisting && hideUserlandThreads && Process_isUserlandThread(proc)) {
|
if (preExisting && hideUserlandThreads && Process_isUserlandThread(proc)) {
|
||||||
proc->updated = true;
|
proc->updated = true;
|
||||||
proc->show = false;
|
proc->show = false;
|
||||||
if (proc->state == 'R')
|
if (proc->state == RUNNING)
|
||||||
pl->runningTasks++;
|
pl->runningTasks++;
|
||||||
pl->userlandThreads++;
|
pl->userlandThreads++;
|
||||||
pl->totalTasks++;
|
pl->totalTasks++;
|
||||||
|
@ -398,7 +415,7 @@ static bool PCPProcessList_updateProcesses(PCPProcessList* this, double period,
|
||||||
PCPProcessList_updateCmdline(proc, pid, offset, command);
|
PCPProcessList_updateCmdline(proc, pid, offset, command);
|
||||||
Process_fillStarttimeBuffer(proc);
|
Process_fillStarttimeBuffer(proc);
|
||||||
ProcessList_add(pl, proc);
|
ProcessList_add(pl, proc);
|
||||||
} else if (settings->updateProcessNames && proc->state != 'Z') {
|
} else if (settings->updateProcessNames && proc->state != ZOMBIE) {
|
||||||
PCPProcessList_updateCmdline(proc, pid, offset, command);
|
PCPProcessList_updateCmdline(proc, pid, offset, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,7 +437,7 @@ static bool PCPProcessList_updateProcesses(PCPProcessList* this, double period,
|
||||||
if (settings->flags & PROCESS_FLAG_LINUX_AUTOGROUP)
|
if (settings->flags & PROCESS_FLAG_LINUX_AUTOGROUP)
|
||||||
PCPProcessList_readAutogroup(pp, pid, offset);
|
PCPProcessList_readAutogroup(pp, pid, offset);
|
||||||
|
|
||||||
if (proc->state == 'Z' && !proc->cmdline && command[0]) {
|
if (proc->state == ZOMBIE && !proc->cmdline && command[0]) {
|
||||||
Process_updateCmdline(proc, command, 0, strlen(command));
|
Process_updateCmdline(proc, command, 0, strlen(command));
|
||||||
} else if (Process_isThread(proc)) {
|
} else if (Process_isThread(proc)) {
|
||||||
if ((settings->showThreadNames || Process_isKernelThread(proc)) && command[0]) {
|
if ((settings->showThreadNames || Process_isKernelThread(proc)) && command[0]) {
|
||||||
|
@ -439,7 +456,7 @@ static bool PCPProcessList_updateProcesses(PCPProcessList* this, double period,
|
||||||
(hideUserlandThreads && Process_isUserlandThread(proc)));
|
(hideUserlandThreads && Process_isUserlandThread(proc)));
|
||||||
|
|
||||||
pl->totalTasks++;
|
pl->totalTasks++;
|
||||||
if (proc->state == 'R')
|
if (proc->state == RUNNING)
|
||||||
pl->runningTasks++;
|
pl->runningTasks++;
|
||||||
proc->updated = true;
|
proc->updated = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -363,6 +363,19 @@ static void SolarisProcessList_updateCwd(pid_t pid, Process* proc) {
|
||||||
free_and_xStrdup(&proc->procCwd, target);
|
free_and_xStrdup(&proc->procCwd, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Taken from: https://docs.oracle.com/cd/E19253-01/817-6223/6mlkidlom/index.html#tbl-sched-state */
|
||||||
|
static inline ProcessState SolarisProcessList_getProcessState(char state) {
|
||||||
|
switch (state) {
|
||||||
|
case 'S': return SLEEPING;
|
||||||
|
case 'R': return RUNNABLE;
|
||||||
|
case 'O': return RUNNING;
|
||||||
|
case 'Z': return ZOMBIE;
|
||||||
|
case 'T': return STOPPED;
|
||||||
|
case 'I': return IDLE;
|
||||||
|
default: return UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* NOTE: the following is a callback function of type proc_walk_f
|
/* NOTE: the following is a callback function of type proc_walk_f
|
||||||
* and MUST conform to the appropriate definition in order
|
* and MUST conform to the appropriate definition in order
|
||||||
* to work. See libproc(3LIB) on a Solaris or Illumos
|
* to work. See libproc(3LIB) on a Solaris or Illumos
|
||||||
|
@ -402,7 +415,7 @@ static int SolarisProcessList_walkproc(psinfo_t* _psinfo, lwpsinfo_t* _lwpsinfo,
|
||||||
proc->priority = _lwpsinfo->pr_pri;
|
proc->priority = _lwpsinfo->pr_pri;
|
||||||
proc->nice = _lwpsinfo->pr_nice - NZERO;
|
proc->nice = _lwpsinfo->pr_nice - NZERO;
|
||||||
proc->processor = _lwpsinfo->pr_onpro;
|
proc->processor = _lwpsinfo->pr_onpro;
|
||||||
proc->state = _lwpsinfo->pr_sname;
|
proc->state = SolarisProcessList_getProcessState(_lwpsinfo->pr_sname);
|
||||||
// NOTE: This 'percentage' is a 16-bit BINARY FRACTIONS where 1.0 = 0x8000
|
// NOTE: This 'percentage' is a 16-bit BINARY FRACTIONS where 1.0 = 0x8000
|
||||||
// Source: https://docs.oracle.com/cd/E19253-01/816-5174/proc-4/index.html
|
// Source: https://docs.oracle.com/cd/E19253-01/816-5174/proc-4/index.html
|
||||||
// (accessed on 18 November 2017)
|
// (accessed on 18 November 2017)
|
||||||
|
@ -462,11 +475,11 @@ static int SolarisProcessList_walkproc(psinfo_t* _psinfo, lwpsinfo_t* _lwpsinfo,
|
||||||
if (proc->isKernelThread && !pl->settings->hideKernelThreads) {
|
if (proc->isKernelThread && !pl->settings->hideKernelThreads) {
|
||||||
pl->kernelThreads += proc->nlwp;
|
pl->kernelThreads += proc->nlwp;
|
||||||
pl->totalTasks += proc->nlwp + 1;
|
pl->totalTasks += proc->nlwp + 1;
|
||||||
if (proc->state == 'O') {
|
if (proc->state == RUNNING) {
|
||||||
pl->runningTasks++;
|
pl->runningTasks++;
|
||||||
}
|
}
|
||||||
} else if (!proc->isKernelThread) {
|
} else if (!proc->isKernelThread) {
|
||||||
if (proc->state == 'O') {
|
if (proc->state == RUNNING) {
|
||||||
pl->runningTasks++;
|
pl->runningTasks++;
|
||||||
}
|
}
|
||||||
if (pl->settings->hideUserlandThreads) {
|
if (pl->settings->hideUserlandThreads) {
|
||||||
|
|
|
@ -57,7 +57,7 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
|
||||||
|
|
||||||
proc->updated = true;
|
proc->updated = true;
|
||||||
|
|
||||||
proc->state = 'R';
|
proc->state = RUNNING;
|
||||||
proc->isKernelThread = false;
|
proc->isKernelThread = false;
|
||||||
proc->isUserlandThread = false;
|
proc->isUserlandThread = false;
|
||||||
proc->show = true; /* Reflected in proc->settings-> "hideXXX" really */
|
proc->show = true; /* Reflected in proc->settings-> "hideXXX" really */
|
||||||
|
|
Loading…
Reference in New Issue