mirror of https://github.com/xzeldon/htop.git
Major advances in FreeBSD port.
This commit is contained in:
parent
9ff5d2b243
commit
272e2d9b34
27
Process.c
27
Process.c
|
@ -6,8 +6,8 @@ in the source distribution for its full text.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Process.h"
|
#include "Process.h"
|
||||||
|
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
|
||||||
#include "CRT.h"
|
#include "CRT.h"
|
||||||
#include "String.h"
|
#include "String.h"
|
||||||
#include "RichString.h"
|
#include "RichString.h"
|
||||||
|
@ -55,6 +55,7 @@ typedef enum ProcessFields {
|
||||||
PRIORITY = 18,
|
PRIORITY = 18,
|
||||||
NICE = 19,
|
NICE = 19,
|
||||||
STARTTIME = 21,
|
STARTTIME = 21,
|
||||||
|
PROCESSOR = 38,
|
||||||
M_SIZE = 39,
|
M_SIZE = 39,
|
||||||
M_RESIDENT = 40,
|
M_RESIDENT = 40,
|
||||||
ST_UID = 46,
|
ST_UID = 46,
|
||||||
|
@ -91,6 +92,7 @@ typedef struct Process_ {
|
||||||
int tpgid;
|
int tpgid;
|
||||||
uid_t st_uid;
|
uid_t st_uid;
|
||||||
unsigned long int flags;
|
unsigned long int flags;
|
||||||
|
int processor;
|
||||||
|
|
||||||
float percent_cpu;
|
float percent_cpu;
|
||||||
float percent_mem;
|
float percent_mem;
|
||||||
|
@ -147,6 +149,8 @@ extern ProcessFieldData Process_fields[];
|
||||||
extern char* Process_pidFormat;
|
extern char* Process_pidFormat;
|
||||||
extern char* Process_tpgidFormat;
|
extern char* Process_tpgidFormat;
|
||||||
|
|
||||||
|
typedef Process*(*Process_new_fn)(struct Settings_*);
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
static int Process_getuid = -1;
|
static int Process_getuid = -1;
|
||||||
|
@ -234,19 +238,13 @@ void Process_colorNumber(RichString* str, unsigned long long number, bool colori
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static double jiffy = 0.0;
|
void Process_printTime(RichString* str, unsigned long long totalHundredths) {
|
||||||
|
unsigned long long totalSeconds = totalHundredths / 100;
|
||||||
|
|
||||||
void Process_printTime(RichString* str, unsigned long long t) {
|
unsigned long long hours = totalSeconds / 3600;
|
||||||
if(jiffy == 0.0) jiffy = sysconf(_SC_CLK_TCK);
|
int minutes = (totalSeconds / 60) % 60;
|
||||||
double jiffytime = 1.0 / jiffy;
|
int seconds = totalSeconds % 60;
|
||||||
|
int hundredths = totalHundredths - (totalSeconds * 100);
|
||||||
double realTime = t * jiffytime;
|
|
||||||
unsigned long long iRealTime = (unsigned long long) realTime;
|
|
||||||
|
|
||||||
unsigned long long hours = iRealTime / 3600;
|
|
||||||
int minutes = (iRealTime / 60) % 60;
|
|
||||||
int seconds = iRealTime % 60;
|
|
||||||
int hundredths = (realTime - iRealTime) * 100;
|
|
||||||
char buffer[11];
|
char buffer[11];
|
||||||
if (hours >= 100) {
|
if (hours >= 100) {
|
||||||
snprintf(buffer, 10, "%7lluh ", hours);
|
snprintf(buffer, 10, "%7lluh ", hours);
|
||||||
|
@ -389,6 +387,7 @@ void Process_writeDefaultField(Process* this, RichString* str, ProcessField fiel
|
||||||
snprintf(buffer, n, "%3ld ", this->priority);
|
snprintf(buffer, n, "%3ld ", this->priority);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PROCESSOR: snprintf(buffer, n, "%3d ", Settings_cpuId(this->settings, this->processor)); break;
|
||||||
case SESSION: snprintf(buffer, n, Process_pidFormat, this->session); break;
|
case SESSION: snprintf(buffer, n, Process_pidFormat, this->session); break;
|
||||||
case STARTTIME: snprintf(buffer, n, "%s", this->starttime_show); break;
|
case STARTTIME: snprintf(buffer, n, "%s", this->starttime_show); break;
|
||||||
case STATE: {
|
case STATE: {
|
||||||
|
@ -527,6 +526,8 @@ long Process_defaultCompare(const void* v1, const void* v2) {
|
||||||
return (p1->ppid - p2->ppid);
|
return (p1->ppid - p2->ppid);
|
||||||
case PRIORITY:
|
case PRIORITY:
|
||||||
return (p1->priority - p2->priority);
|
return (p1->priority - p2->priority);
|
||||||
|
case PROCESSOR:
|
||||||
|
return (p1->processor - p2->processor);
|
||||||
case SESSION:
|
case SESSION:
|
||||||
return (p1->session - p2->session);
|
return (p1->session - p2->session);
|
||||||
case STARTTIME: {
|
case STARTTIME: {
|
||||||
|
|
|
@ -36,6 +36,7 @@ typedef enum ProcessFields {
|
||||||
PRIORITY = 18,
|
PRIORITY = 18,
|
||||||
NICE = 19,
|
NICE = 19,
|
||||||
STARTTIME = 21,
|
STARTTIME = 21,
|
||||||
|
PROCESSOR = 38,
|
||||||
M_SIZE = 39,
|
M_SIZE = 39,
|
||||||
M_RESIDENT = 40,
|
M_RESIDENT = 40,
|
||||||
ST_UID = 46,
|
ST_UID = 46,
|
||||||
|
@ -72,6 +73,7 @@ typedef struct Process_ {
|
||||||
int tpgid;
|
int tpgid;
|
||||||
uid_t st_uid;
|
uid_t st_uid;
|
||||||
unsigned long int flags;
|
unsigned long int flags;
|
||||||
|
int processor;
|
||||||
|
|
||||||
float percent_cpu;
|
float percent_cpu;
|
||||||
float percent_mem;
|
float percent_mem;
|
||||||
|
@ -128,6 +130,8 @@ extern ProcessFieldData Process_fields[];
|
||||||
extern char* Process_pidFormat;
|
extern char* Process_pidFormat;
|
||||||
extern char* Process_tpgidFormat;
|
extern char* Process_tpgidFormat;
|
||||||
|
|
||||||
|
typedef Process*(*Process_new_fn)(struct Settings_*);
|
||||||
|
|
||||||
|
|
||||||
#define ONE_K 1024L
|
#define ONE_K 1024L
|
||||||
#define ONE_M (ONE_K * ONE_K)
|
#define ONE_M (ONE_K * ONE_K)
|
||||||
|
@ -141,7 +145,7 @@ void Process_humanNumber(RichString* str, unsigned long number, bool coloring);
|
||||||
|
|
||||||
void Process_colorNumber(RichString* str, unsigned long long number, bool coloring);
|
void Process_colorNumber(RichString* str, unsigned long long number, bool coloring);
|
||||||
|
|
||||||
void Process_printTime(RichString* str, unsigned long long t);
|
void Process_printTime(RichString* str, unsigned long long totalHundredths);
|
||||||
|
|
||||||
void Process_outputRate(RichString* str, char* buffer, int n, double rate, int coloring);
|
void Process_outputRate(RichString* str, char* buffer, int n, double rate, int coloring);
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,11 @@ typedef struct ProcessList_ {
|
||||||
bool topologyOk;
|
bool topologyOk;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int totalTasks;
|
||||||
|
int runningTasks;
|
||||||
|
int userlandThreads;
|
||||||
|
int kernelThreads;
|
||||||
|
|
||||||
unsigned long long int totalMem;
|
unsigned long long int totalMem;
|
||||||
unsigned long long int usedMem;
|
unsigned long long int usedMem;
|
||||||
unsigned long long int freeMem;
|
unsigned long long int freeMem;
|
||||||
|
@ -65,7 +70,7 @@ typedef struct ProcessList_ {
|
||||||
|
|
||||||
ProcessList* ProcessList_new(UsersTable* ut, Hashtable* pidWhiteList, uid_t userId);
|
ProcessList* ProcessList_new(UsersTable* ut, Hashtable* pidWhiteList, uid_t userId);
|
||||||
void ProcessList_delete(ProcessList* pl);
|
void ProcessList_delete(ProcessList* pl);
|
||||||
void ProcessList_scan(ProcessList* pl);
|
void ProcessList_goThroughEntries(ProcessList* pl);
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
@ -282,3 +287,40 @@ void ProcessList_rebuildPanel(ProcessList* this) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Process* ProcessList_getProcess(ProcessList* this, pid_t pid, bool* preExisting, Process_new_fn constructor) {
|
||||||
|
Process* proc = (Process*) Hashtable_get(this->processTable, pid);
|
||||||
|
*preExisting = proc;
|
||||||
|
if (proc) {
|
||||||
|
assert(Vector_indexOf(this->processes, proc, Process_pidCompare) != -1);
|
||||||
|
assert(proc->pid == pid);
|
||||||
|
} else {
|
||||||
|
proc = constructor(this->settings);
|
||||||
|
assert(proc->comm == NULL);
|
||||||
|
proc->pid = pid;
|
||||||
|
}
|
||||||
|
return proc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessList_scan(ProcessList* this) {
|
||||||
|
|
||||||
|
// mark all process as "dirty"
|
||||||
|
for (int i = 0; i < Vector_size(this->processes); i++) {
|
||||||
|
Process* p = (Process*) Vector_get(this->processes, i);
|
||||||
|
p->updated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->totalTasks = 0;
|
||||||
|
this->userlandThreads = 0;
|
||||||
|
this->kernelThreads = 0;
|
||||||
|
this->runningTasks = 0;
|
||||||
|
|
||||||
|
ProcessList_goThroughEntries(this);
|
||||||
|
|
||||||
|
for (int i = Vector_size(this->processes) - 1; i >= 0; i--) {
|
||||||
|
Process* p = (Process*) Vector_get(this->processes, i);
|
||||||
|
if (p->updated == false)
|
||||||
|
ProcessList_remove(this, p);
|
||||||
|
else
|
||||||
|
p->updated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -43,6 +43,11 @@ typedef struct ProcessList_ {
|
||||||
bool topologyOk;
|
bool topologyOk;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int totalTasks;
|
||||||
|
int runningTasks;
|
||||||
|
int userlandThreads;
|
||||||
|
int kernelThreads;
|
||||||
|
|
||||||
unsigned long long int totalMem;
|
unsigned long long int totalMem;
|
||||||
unsigned long long int usedMem;
|
unsigned long long int usedMem;
|
||||||
unsigned long long int freeMem;
|
unsigned long long int freeMem;
|
||||||
|
@ -59,7 +64,7 @@ typedef struct ProcessList_ {
|
||||||
|
|
||||||
ProcessList* ProcessList_new(UsersTable* ut, Hashtable* pidWhiteList, uid_t userId);
|
ProcessList* ProcessList_new(UsersTable* ut, Hashtable* pidWhiteList, uid_t userId);
|
||||||
void ProcessList_delete(ProcessList* pl);
|
void ProcessList_delete(ProcessList* pl);
|
||||||
void ProcessList_scan(ProcessList* pl);
|
void ProcessList_goThroughEntries(ProcessList* pl);
|
||||||
|
|
||||||
|
|
||||||
ProcessList* ProcessList_init(ProcessList* this, UsersTable* usersTable, Hashtable* pidWhiteList, uid_t userId);
|
ProcessList* ProcessList_init(ProcessList* this, UsersTable* usersTable, Hashtable* pidWhiteList, uid_t userId);
|
||||||
|
@ -86,5 +91,8 @@ void ProcessList_expandTree(ProcessList* this);
|
||||||
|
|
||||||
void ProcessList_rebuildPanel(ProcessList* this);
|
void ProcessList_rebuildPanel(ProcessList* this);
|
||||||
|
|
||||||
|
Process* ProcessList_getProcess(ProcessList* this, pid_t pid, bool* preExisting, Process_new_fn constructor);
|
||||||
|
|
||||||
|
void ProcessList_scan(ProcessList* this);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,7 +19,14 @@ int TasksMeter_attributes[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void TasksMeter_setValues(Meter* this, char* buffer, int len) {
|
static void TasksMeter_setValues(Meter* this, char* buffer, int len) {
|
||||||
Platform_setTasksValues(this);
|
ProcessList* pl = this->pl;
|
||||||
|
this->values[0] = pl->kernelThreads;
|
||||||
|
this->values[1] = pl->userlandThreads;
|
||||||
|
this->values[2] = pl->totalTasks - pl->kernelThreads - pl->userlandThreads;
|
||||||
|
this->values[3] = pl->runningTasks;
|
||||||
|
if (pl->totalTasks > this->total) {
|
||||||
|
this->total = pl->totalTasks;
|
||||||
|
}
|
||||||
if (this->pl->settings->hideKernelThreads) {
|
if (this->pl->settings->hideKernelThreads) {
|
||||||
this->values[0] = 0;
|
this->values[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,14 @@ typedef struct FreeBSDProcess_ {
|
||||||
Process super;
|
Process super;
|
||||||
} FreeBSDProcess;
|
} FreeBSDProcess;
|
||||||
|
|
||||||
|
#ifndef Process_isKernelThread
|
||||||
|
#define Process_isKernelThread(_process) (_process->pgrp == 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef Process_isUserlandThread
|
||||||
|
#define Process_isUserlandThread(_process) (_process->pid != _process->tgid)
|
||||||
|
#endif
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
ProcessFieldData Process_fields[] = {
|
ProcessFieldData Process_fields[] = {
|
||||||
|
@ -44,6 +52,7 @@ ProcessFieldData Process_fields[] = {
|
||||||
[NICE] = { .name = "NICE", .title = " NI ", .description = "Nice value (the higher the value, the more it lets other processes take priority)", .flags = 0, },
|
[NICE] = { .name = "NICE", .title = " NI ", .description = "Nice value (the higher the value, the more it lets other processes take priority)", .flags = 0, },
|
||||||
[STARTTIME] = { .name = "STARTTIME", .title = "START ", .description = "Time the process was started", .flags = 0, },
|
[STARTTIME] = { .name = "STARTTIME", .title = "START ", .description = "Time the process was started", .flags = 0, },
|
||||||
|
|
||||||
|
[PROCESSOR] = { .name = "PROCESSOR", .title = "CPU ", .description = "Id of the CPU the process last executed on", .flags = 0, },
|
||||||
[M_SIZE] = { .name = "M_SIZE", .title = " VIRT ", .description = "Total program size in virtual memory", .flags = 0, },
|
[M_SIZE] = { .name = "M_SIZE", .title = " VIRT ", .description = "Total program size in virtual memory", .flags = 0, },
|
||||||
[M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, },
|
[M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, },
|
||||||
[ST_UID] = { .name = "ST_UID", .title = " UID ", .description = "User ID of the process owner", .flags = 0, },
|
[ST_UID] = { .name = "ST_UID", .title = " UID ", .description = "User ID of the process owner", .flags = 0, },
|
||||||
|
@ -128,7 +137,5 @@ long Process_compare(const void* v1, const void* v2) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Process_isThread(Process* this) {
|
bool Process_isThread(Process* this) {
|
||||||
(void) this;
|
return (Process_isKernelThread(this));
|
||||||
// TODO
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,14 @@ typedef struct FreeBSDProcess_ {
|
||||||
Process super;
|
Process super;
|
||||||
} FreeBSDProcess;
|
} FreeBSDProcess;
|
||||||
|
|
||||||
|
#ifndef Process_isKernelThread
|
||||||
|
#define Process_isKernelThread(_process) (_process->pgrp == 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef Process_isUserlandThread
|
||||||
|
#define Process_isUserlandThread(_process) (_process->pid != _process->tgid)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
extern ProcessFieldData Process_fields[];
|
extern ProcessFieldData Process_fields[];
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,15 @@ in the source distribution for its full text.
|
||||||
|
|
||||||
#include "ProcessList.h"
|
#include "ProcessList.h"
|
||||||
#include "FreeBSDProcessList.h"
|
#include "FreeBSDProcessList.h"
|
||||||
|
#include "FreeBSDProcess.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/user.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
/*{
|
/*{
|
||||||
|
|
||||||
|
@ -103,10 +106,101 @@ static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) {
|
||||||
pl->buffersMem = 0; // not exposed to userspace
|
pl->buffersMem = 0; // not exposed to userspace
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessList_scan(ProcessList* this) {
|
char* FreeBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, int* basenameEnd) {
|
||||||
(void) this;
|
char** argv = kvm_getargv(kd, kproc, 0);
|
||||||
|
if (!argv) {
|
||||||
|
return strdup(kproc->ki_comm);
|
||||||
|
}
|
||||||
|
int len = 0;
|
||||||
|
for (int i = 0; argv[i]; i++) {
|
||||||
|
len += strlen(argv[i]) + 1;
|
||||||
|
}
|
||||||
|
char* comm = malloc(len * sizeof(char));
|
||||||
|
char* at = comm;
|
||||||
|
*basenameEnd = 0;
|
||||||
|
for (int i = 0; argv[i]; i++) {
|
||||||
|
at = stpcpy(at, argv[i]);
|
||||||
|
if (!*basenameEnd) {
|
||||||
|
*basenameEnd = at - comm;
|
||||||
|
}
|
||||||
|
*at = ' ';
|
||||||
|
at++;
|
||||||
|
}
|
||||||
|
at--;
|
||||||
|
*at = '\0';
|
||||||
|
return comm;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessList_goThroughEntries(ProcessList* this) {
|
||||||
|
FreeBSDProcessList* fpl = (FreeBSDProcessList*) this;
|
||||||
|
Settings* settings = this->settings;
|
||||||
|
bool hideKernelThreads = settings->hideKernelThreads;
|
||||||
|
bool hideUserlandThreads = settings->hideUserlandThreads;
|
||||||
|
|
||||||
FreeBSDProcessList_scanMemoryInfo(this);
|
FreeBSDProcessList_scanMemoryInfo(this);
|
||||||
|
|
||||||
// stub!
|
int count = 0;
|
||||||
|
struct kinfo_proc* kprocs = kvm_getprocs(fpl->kd, KERN_PROC_ALL, 0, &count);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
struct kinfo_proc* kproc = &kprocs[i];
|
||||||
|
|
||||||
|
bool preExisting = false;
|
||||||
|
Process* proc = ProcessList_getProcess(this, kproc->ki_pid, &preExisting, (Process_new_fn) FreeBSDProcess_new);
|
||||||
|
FreeBSDProcess* fp = (FreeBSDProcess*) proc;
|
||||||
|
|
||||||
|
proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) || (hideUserlandThreads && Process_isUserlandThread(proc)));
|
||||||
|
|
||||||
|
if (!preExisting) {
|
||||||
|
proc->ppid = kproc->ki_ppid;
|
||||||
|
proc->tpgid = kproc->ki_tpgid;
|
||||||
|
proc->tgid = kproc->ki_pid;
|
||||||
|
proc->session = kproc->ki_sid;
|
||||||
|
proc->tty_nr = kproc->ki_tdev;
|
||||||
|
proc->pgrp = kproc->ki_pgid;
|
||||||
|
proc->st_uid = kproc->ki_uid;
|
||||||
|
proc->starttime_ctime = kproc->ki_start.tv_sec;
|
||||||
|
proc->user = UsersTable_getRef(this->usersTable, proc->st_uid);
|
||||||
|
ProcessList_add((ProcessList*)this, proc);
|
||||||
|
proc->comm = FreeBSDProcessList_readProcessName(fpl->kd, kproc, &proc->basenameOffset);
|
||||||
|
} else {
|
||||||
|
if (settings->updateProcessNames) {
|
||||||
|
free(proc->comm);
|
||||||
|
proc->comm = FreeBSDProcessList_readProcessName(fpl->kd, kproc, &proc->basenameOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proc->m_size = kproc->ki_size / pageSizeKb / 1000;
|
||||||
|
proc->m_resident = kproc->ki_rssize; // * pageSizeKb;
|
||||||
|
proc->nlwp = kproc->ki_numthreads;
|
||||||
|
proc->time = (kproc->ki_runtime + 5000) / 10000;
|
||||||
|
proc->priority = kproc->ki_pri.pri_level - PZERO;
|
||||||
|
if (kproc->ki_pri.pri_class == PRI_TIMESHARE) {
|
||||||
|
proc->nice = kproc->ki_nice - NZERO;
|
||||||
|
} else if (PRI_IS_REALTIME(kproc->ki_pri.pri_class)) {
|
||||||
|
proc->nice = PRIO_MIN - 1 - (PRI_MAX_REALTIME - kproc->ki_pri.pri_level);
|
||||||
|
} else {
|
||||||
|
proc->nice = PRIO_MAX + 1 + kproc->ki_pri.pri_level - PRI_MIN_IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (kproc->ki_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;
|
||||||
|
case SWAIT: proc->state = 'D'; break;
|
||||||
|
case SLOCK: proc->state = 'L'; break;
|
||||||
|
default: proc->state = '?';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Process_isKernelThread(proc)) {
|
||||||
|
this->kernelThreads++;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->totalTasks++;
|
||||||
|
if (proc->state == 'R')
|
||||||
|
this->runningTasks++;
|
||||||
|
proc->updated = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui
|
||||||
|
|
||||||
void ProcessList_delete(ProcessList* this);
|
void ProcessList_delete(ProcessList* this);
|
||||||
|
|
||||||
void ProcessList_scan(ProcessList* this);
|
char* FreeBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, int* basenameEnd);
|
||||||
|
|
||||||
|
void ProcessList_goThroughEntries(ProcessList* this);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -51,7 +51,6 @@ typedef enum LinuxProcessFields {
|
||||||
STIME = 15,
|
STIME = 15,
|
||||||
CUTIME = 16,
|
CUTIME = 16,
|
||||||
CSTIME = 17,
|
CSTIME = 17,
|
||||||
PROCESSOR = 38,
|
|
||||||
M_SHARE = 41,
|
M_SHARE = 41,
|
||||||
M_TRS = 42,
|
M_TRS = 42,
|
||||||
M_DRS = 43,
|
M_DRS = 43,
|
||||||
|
@ -97,7 +96,6 @@ typedef struct LinuxProcess_ {
|
||||||
unsigned long long int stime;
|
unsigned long long int stime;
|
||||||
unsigned long long int cutime;
|
unsigned long long int cutime;
|
||||||
unsigned long long int cstime;
|
unsigned long long int cstime;
|
||||||
int processor;
|
|
||||||
long m_share;
|
long m_share;
|
||||||
long m_trs;
|
long m_trs;
|
||||||
long m_drs;
|
long m_drs;
|
||||||
|
@ -309,7 +307,6 @@ void Process_writeField(Process* this, RichString* str, ProcessField field) {
|
||||||
switch ((int)field) {
|
switch ((int)field) {
|
||||||
case CMINFLT: Process_colorNumber(str, lp->cminflt, coloring); return;
|
case CMINFLT: Process_colorNumber(str, lp->cminflt, coloring); return;
|
||||||
case CMAJFLT: Process_colorNumber(str, lp->cmajflt, coloring); return;
|
case CMAJFLT: Process_colorNumber(str, lp->cmajflt, coloring); return;
|
||||||
case PROCESSOR: snprintf(buffer, n, "%3d ", Settings_cpuId(this->settings, lp->processor)); break;
|
|
||||||
case M_DRS: Process_humanNumber(str, lp->m_drs * PAGE_SIZE_KB, coloring); return;
|
case M_DRS: Process_humanNumber(str, lp->m_drs * PAGE_SIZE_KB, coloring); return;
|
||||||
case M_DT: Process_humanNumber(str, lp->m_dt * PAGE_SIZE_KB, coloring); return;
|
case M_DT: Process_humanNumber(str, lp->m_dt * PAGE_SIZE_KB, coloring); return;
|
||||||
case M_LRS: Process_humanNumber(str, lp->m_lrs * PAGE_SIZE_KB, coloring); return;
|
case M_LRS: Process_humanNumber(str, lp->m_lrs * PAGE_SIZE_KB, coloring); return;
|
||||||
|
@ -381,8 +378,6 @@ long Process_compare(const void* v1, const void* v2) {
|
||||||
}
|
}
|
||||||
long long diff;
|
long long diff;
|
||||||
switch ((int)settings->sortKey) {
|
switch ((int)settings->sortKey) {
|
||||||
case PROCESSOR:
|
|
||||||
return (p1->processor - p2->processor);
|
|
||||||
case M_DRS:
|
case M_DRS:
|
||||||
return (p2->m_drs - p1->m_drs);
|
return (p2->m_drs - p1->m_drs);
|
||||||
case M_DT:
|
case M_DT:
|
||||||
|
|
|
@ -62,11 +62,6 @@ typedef struct CPUData_ {
|
||||||
typedef struct LinuxProcessList_ {
|
typedef struct LinuxProcessList_ {
|
||||||
ProcessList super;
|
ProcessList super;
|
||||||
|
|
||||||
int totalTasks;
|
|
||||||
int userlandThreads;
|
|
||||||
int kernelThreads;
|
|
||||||
int runningTasks;
|
|
||||||
|
|
||||||
CPUData* cpus;
|
CPUData* cpus;
|
||||||
|
|
||||||
} LinuxProcessList;
|
} LinuxProcessList;
|
||||||
|
@ -141,6 +136,14 @@ static ssize_t xread(int fd, void *buf, size_t count) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double jiffy = 0.0;
|
||||||
|
|
||||||
|
static inline unsigned long long LinuxProcess_adjustTime(unsigned long long t) {
|
||||||
|
if(jiffy == 0.0) jiffy = sysconf(_SC_CLK_TCK);
|
||||||
|
double jiffytime = 1.0 / jiffy;
|
||||||
|
return (unsigned long long) t * jiffytime * 100;
|
||||||
|
}
|
||||||
|
|
||||||
static bool LinuxProcessList_readStatFile(Process *process, const char* dirname, const char* name, char* command) {
|
static bool LinuxProcessList_readStatFile(Process *process, const char* dirname, const char* name, char* command) {
|
||||||
LinuxProcess* lp = (LinuxProcess*) process;
|
LinuxProcess* lp = (LinuxProcess*) process;
|
||||||
char filename[MAX_NAME+1];
|
char filename[MAX_NAME+1];
|
||||||
|
@ -191,13 +194,13 @@ static bool LinuxProcessList_readStatFile(Process *process, const char* dirname,
|
||||||
location += 1;
|
location += 1;
|
||||||
lp->cmajflt = strtoull(location, &location, 10);
|
lp->cmajflt = strtoull(location, &location, 10);
|
||||||
location += 1;
|
location += 1;
|
||||||
lp->utime = strtoull(location, &location, 10);
|
lp->utime = LinuxProcess_adjustTime(strtoull(location, &location, 10));
|
||||||
location += 1;
|
location += 1;
|
||||||
lp->stime = strtoull(location, &location, 10);
|
lp->stime = LinuxProcess_adjustTime(strtoull(location, &location, 10));
|
||||||
location += 1;
|
location += 1;
|
||||||
lp->cutime = strtoull(location, &location, 10);
|
lp->cutime = LinuxProcess_adjustTime(strtoull(location, &location, 10));
|
||||||
location += 1;
|
location += 1;
|
||||||
lp->cstime = strtoull(location, &location, 10);
|
lp->cstime = LinuxProcess_adjustTime(strtoull(location, &location, 10));
|
||||||
location += 1;
|
location += 1;
|
||||||
process->priority = strtol(location, &location, 10);
|
process->priority = strtol(location, &location, 10);
|
||||||
location += 1;
|
location += 1;
|
||||||
|
@ -474,11 +477,11 @@ static bool LinuxProcessList_readCmdlineFile(Process* process, const char* dirna
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool LinuxProcessList_processEntries(LinuxProcessList* this, const char* dirname, Process* parent, double period, struct timeval tv) {
|
static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, const char* dirname, Process* parent, double period, struct timeval tv) {
|
||||||
ProcessList* pl = (ProcessList*) this;
|
ProcessList* pl = (ProcessList*) this;
|
||||||
DIR* dir;
|
DIR* dir;
|
||||||
struct dirent* entry;
|
struct dirent* entry;
|
||||||
Settings* settings = this->super.settings;
|
Settings* settings = pl->settings;
|
||||||
|
|
||||||
time_t curTime = tv.tv_sec;
|
time_t curTime = tv.tv_sec;
|
||||||
#ifdef HAVE_TASKSTATS
|
#ifdef HAVE_TASKSTATS
|
||||||
|
@ -487,7 +490,7 @@ static bool LinuxProcessList_processEntries(LinuxProcessList* this, const char*
|
||||||
|
|
||||||
dir = opendir(dirname);
|
dir = opendir(dirname);
|
||||||
if (!dir) return false;
|
if (!dir) return false;
|
||||||
int cpus = this->super.cpuCount;
|
int cpus = pl->cpuCount;
|
||||||
bool hideKernelThreads = settings->hideKernelThreads;
|
bool hideKernelThreads = settings->hideKernelThreads;
|
||||||
bool hideUserlandThreads = settings->hideUserlandThreads;
|
bool hideUserlandThreads = settings->hideUserlandThreads;
|
||||||
while ((entry = readdir(dir)) != NULL) {
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
@ -513,25 +516,15 @@ static bool LinuxProcessList_processEntries(LinuxProcessList* this, const char*
|
||||||
if (pid <= 0)
|
if (pid <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Process* proc = NULL;
|
bool preExisting = false;
|
||||||
Process* existingProc = (Process*) Hashtable_get(this->super.processTable, pid);
|
Process* proc = ProcessList_getProcess(pl, pid, &preExisting, (Process_new_fn) LinuxProcess_new);
|
||||||
|
|
||||||
if (existingProc) {
|
|
||||||
assert(Vector_indexOf(this->processes, existingProc, Process_pidCompare) != -1);
|
|
||||||
proc = existingProc;
|
|
||||||
assert(proc->pid == pid);
|
|
||||||
} else {
|
|
||||||
proc = (Process*) LinuxProcess_new(settings);
|
|
||||||
assert(proc->comm == NULL);
|
|
||||||
proc->pid = pid;
|
|
||||||
proc->tgid = parent ? parent->pid : pid;
|
proc->tgid = parent ? parent->pid : pid;
|
||||||
}
|
|
||||||
|
|
||||||
LinuxProcess* lp = (LinuxProcess*) proc;
|
LinuxProcess* lp = (LinuxProcess*) proc;
|
||||||
|
|
||||||
char subdirname[MAX_NAME+1];
|
char subdirname[MAX_NAME+1];
|
||||||
snprintf(subdirname, MAX_NAME, "%s/%s/task", dirname, name);
|
snprintf(subdirname, MAX_NAME, "%s/%s/task", dirname, name);
|
||||||
LinuxProcessList_processEntries(this, subdirname, proc, period, tv);
|
LinuxProcessList_recurseProcTree(this, subdirname, proc, period, tv);
|
||||||
|
|
||||||
#ifdef HAVE_TASKSTATS
|
#ifdef HAVE_TASKSTATS
|
||||||
if (settings->flags & PROCESS_FLAG_IO)
|
if (settings->flags & PROCESS_FLAG_IO)
|
||||||
|
@ -554,12 +547,12 @@ static bool LinuxProcessList_processEntries(LinuxProcessList* this, const char*
|
||||||
if (isnan(proc->percent_cpu)) proc->percent_cpu = 0.0;
|
if (isnan(proc->percent_cpu)) proc->percent_cpu = 0.0;
|
||||||
proc->percent_mem = (proc->m_resident * PAGE_SIZE_KB) / (double)(pl->totalMem) * 100.0;
|
proc->percent_mem = (proc->m_resident * PAGE_SIZE_KB) / (double)(pl->totalMem) * 100.0;
|
||||||
|
|
||||||
if(!existingProc) {
|
if(!preExisting) {
|
||||||
|
|
||||||
if (! LinuxProcessList_statProcessDir(proc, dirname, name, curTime))
|
if (! LinuxProcessList_statProcessDir(proc, dirname, name, curTime))
|
||||||
goto errorReadingProcess;
|
goto errorReadingProcess;
|
||||||
|
|
||||||
proc->user = UsersTable_getRef(this->super.usersTable, proc->st_uid);
|
proc->user = UsersTable_getRef(pl->usersTable, proc->st_uid);
|
||||||
|
|
||||||
#ifdef HAVE_OPENVZ
|
#ifdef HAVE_OPENVZ
|
||||||
LinuxProcessList_readOpenVZData(this, lp, dirname, name);
|
LinuxProcessList_readOpenVZData(this, lp, dirname, name);
|
||||||
|
@ -573,7 +566,7 @@ static bool LinuxProcessList_processEntries(LinuxProcessList* this, const char*
|
||||||
if (! LinuxProcessList_readCmdlineFile(proc, dirname, name))
|
if (! LinuxProcessList_readCmdlineFile(proc, dirname, name))
|
||||||
goto errorReadingProcess;
|
goto errorReadingProcess;
|
||||||
|
|
||||||
ProcessList_add((ProcessList*)this, proc);
|
ProcessList_add(pl, proc);
|
||||||
} else {
|
} else {
|
||||||
if (settings->updateProcessNames) {
|
if (settings->updateProcessNames) {
|
||||||
if (! LinuxProcessList_readCmdlineFile(proc, dirname, name))
|
if (! LinuxProcessList_readCmdlineFile(proc, dirname, name))
|
||||||
|
@ -614,22 +607,17 @@ static bool LinuxProcessList_processEntries(LinuxProcessList* this, const char*
|
||||||
if (proc->state == 'R')
|
if (proc->state == 'R')
|
||||||
this->runningTasks++;
|
this->runningTasks++;
|
||||||
proc->updated = true;
|
proc->updated = true;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Exception handler.
|
// Exception handler.
|
||||||
errorReadingProcess: {
|
errorReadingProcess: {
|
||||||
if (proc->comm) {
|
if (preExisting) {
|
||||||
free(proc->comm);
|
ProcessList_remove((pl, proc);
|
||||||
proc->basenameOffset = -1;
|
} else {
|
||||||
proc->comm = NULL;
|
|
||||||
}
|
|
||||||
if (existingProc)
|
|
||||||
ProcessList_remove((ProcessList*)this, proc);
|
|
||||||
else
|
|
||||||
Process_delete((Object*)proc);
|
Process_delete((Object*)proc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -752,35 +740,13 @@ static inline double LinuxProcessList_scanCPUTime(LinuxProcessList* this) {
|
||||||
return period;
|
return period;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessList_scan(ProcessList* super) {
|
void ProcessList_goThroughEntries(ProcessList* super) {
|
||||||
LinuxProcessList* this = (LinuxProcessList*) super;
|
LinuxProcessList* this = (LinuxProcessList*) super;
|
||||||
|
|
||||||
LinuxProcessList_scanMemoryInfo(super);
|
LinuxProcessList_scanMemoryInfo(super);
|
||||||
|
|
||||||
double period = LinuxProcessList_scanCPUTime(this);
|
double period = LinuxProcessList_scanCPUTime(this);
|
||||||
|
|
||||||
// mark all process as "dirty"
|
|
||||||
for (int i = 0; i < Vector_size(super->processes); i++) {
|
|
||||||
Process* p = (Process*) Vector_get(super->processes, i);
|
|
||||||
p->updated = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->totalTasks = 0;
|
|
||||||
this->userlandThreads = 0;
|
|
||||||
this->kernelThreads = 0;
|
|
||||||
this->runningTasks = 0;
|
|
||||||
|
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
LinuxProcessList_processEntries(this, PROCDIR, NULL, period, tv);
|
LinuxProcessList_recurseProcTree(this, PROCDIR, NULL, period, tv);
|
||||||
|
|
||||||
for (int i = Vector_size(this->super.processes) - 1; i >= 0; i--) {
|
|
||||||
Process* p = (Process*) Vector_get(this->super.processes, i);
|
|
||||||
if (p->updated == false)
|
|
||||||
ProcessList_remove(super, p);
|
|
||||||
else
|
|
||||||
p->updated = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -165,13 +165,3 @@ void Platform_setSwapValues(Meter* this) {
|
||||||
this->total = pl->totalSwap;
|
this->total = pl->totalSwap;
|
||||||
this->values[0] = pl->usedSwap;
|
this->values[0] = pl->usedSwap;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Platform_setTasksValues(Meter* this) {
|
|
||||||
LinuxProcessList* pl = (LinuxProcessList*) this->pl;
|
|
||||||
this->values[0] = pl->kernelThreads;
|
|
||||||
this->values[1] = pl->userlandThreads;
|
|
||||||
this->values[2] = pl->totalTasks - pl->kernelThreads - pl->userlandThreads;
|
|
||||||
this->values[3] = pl->runningTasks;
|
|
||||||
if (pl->totalTasks > this->total)
|
|
||||||
this->total = pl->totalTasks;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue