aboutsummaryrefslogtreecommitdiffstats
path: root/freebsd/FreeBSDProcessList.c
diff options
context:
space:
mode:
authorDaniel Lange <DLange@git.local>2020-12-07 10:26:01 +0100
committerDaniel Lange <DLange@git.local>2020-12-07 10:26:01 +0100
commit65357c8c46154de4e4eca14075bfe5523bb5fc14 (patch)
tree8f430ee5a0d5de377c4e7c94e47842a27c70d7e8 /freebsd/FreeBSDProcessList.c
parentf80394a20254938142011855f2954b3f63fe5909 (diff)
downloaddebian_htop-65357c8c46154de4e4eca14075bfe5523bb5fc14.tar.gz
debian_htop-65357c8c46154de4e4eca14075bfe5523bb5fc14.tar.bz2
debian_htop-65357c8c46154de4e4eca14075bfe5523bb5fc14.zip
New upstream version 3.0.3upstream/3.0.3
Diffstat (limited to 'freebsd/FreeBSDProcessList.c')
-rw-r--r--freebsd/FreeBSDProcessList.c312
1 files changed, 199 insertions, 113 deletions
diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c
index 6318d42..9aaab5d 100644
--- a/freebsd/FreeBSDProcessList.c
+++ b/freebsd/FreeBSDProcessList.c
@@ -1,26 +1,44 @@
/*
htop - FreeBSDProcessList.c
(C) 2014 Hisham H. Muhammad
-Released under the GNU GPL, see the COPYING file
+Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
-#include "ProcessList.h"
#include "FreeBSDProcessList.h"
-#include "FreeBSDProcess.h"
-#include "zfs/ZfsArcStats.h"
-#include "zfs/openzfs_sysctl.h"
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
-#include <sys/user.h>
+#include <assert.h>
+#include <dirent.h>
#include <err.h>
-#include <fcntl.h>
#include <limits.h>
+#include <stdlib.h>
#include <string.h>
-#include <time.h>
+#include <sys/_iovec.h>
+#include <sys/dirent.h>
+#include <sys/errno.h>
+#include <sys/param.h> // needs to be included before <sys/jail.h> for MAXPATHLEN
+#include <sys/jail.h>
+#include <sys/priority.h>
+#include <sys/proc.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/user.h>
+
+#include "CRT.h"
+#include "Compat.h"
+#include "FreeBSDProcess.h"
+#include "Macros.h"
+#include "Object.h"
+#include "Process.h"
+#include "ProcessList.h"
+#include "Settings.h"
+#include "XUtils.h"
+#include "zfs/ZfsArcStats.h"
+#include "zfs/openzfs_sysctl.h"
+
char jail_errmsg[JAIL_ERRMSGLEN];
@@ -55,8 +73,8 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui
len = sizeof(pageSize);
if (sysctlbyname("vm.stats.vm.v_page_size", &pageSize, &len, NULL, 0) == -1) {
- pageSize = PAGE_SIZE;
- pageSizeKb = PAGE_SIZE_KB;
+ pageSize = CRT_pageSize;
+ pageSizeKb = CRT_pageSize;
} else {
pageSizeKb = pageSize / ONE_K;
}
@@ -88,7 +106,9 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui
if (smp) {
int err = sysctlbyname("kern.smp.cpus", &cpus, &len, NULL, 0);
- if (err) cpus = 1;
+ if (err) {
+ cpus = 1;
+ }
} else {
cpus = 1;
}
@@ -114,10 +134,10 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui
pl->cpuCount = MAXIMUM(cpus, 1);
if (cpus == 1 ) {
- fpl->cpus = xRealloc(fpl->cpus, sizeof(CPUData));
+ fpl->cpus = xRealloc(fpl->cpus, sizeof(CPUData));
} else {
- // on smp we need CPUs + 1 to store averages too (as kernel kindly provides that as well)
- fpl->cpus = xRealloc(fpl->cpus, (pl->cpuCount + 1) * sizeof(CPUData));
+ // on smp we need CPUs + 1 to store averages too (as kernel kindly provides that as well)
+ fpl->cpus = xRealloc(fpl->cpus, (pl->cpuCount + 1) * sizeof(CPUData));
}
@@ -132,12 +152,19 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui
errx(1, "kvm_open: %s", errbuf);
}
+ fpl->ttys = Hashtable_new(20, true);
+
return pl;
}
void ProcessList_delete(ProcessList* this) {
const FreeBSDProcessList* fpl = (FreeBSDProcessList*) this;
- if (fpl->kd) kvm_close(fpl->kd);
+
+ Hashtable_delete(fpl->ttys);
+
+ if (fpl->kd) {
+ kvm_close(fpl->kd);
+ }
free(fpl->cp_time_o);
free(fpl->cp_time_n);
@@ -160,8 +187,8 @@ static inline void FreeBSDProcessList_scanCPUTime(ProcessList* pl) {
size_t sizeof_cp_time_array;
- unsigned long *cp_time_n; // old clicks state
- unsigned long *cp_time_o; // current clicks state
+ unsigned long* cp_time_n; // old clicks state
+ unsigned long* cp_time_o; // current clicks state
unsigned long cp_time_d[CPUSTATES];
double cp_time_p[CPUSTATES];
@@ -172,12 +199,12 @@ static inline void FreeBSDProcessList_scanCPUTime(ProcessList* pl) {
// get rest of CPUs
if (cpus > 1) {
- // on smp systems FreeBSD kernel concats all CPU states into one long array in
- // kern.cp_times sysctl OID
- // we store averages in fpl->cpus[0], and actual cores after that
- maxcpu = cpus + 1;
- sizeof_cp_time_array = cpus * sizeof(unsigned long) * CPUSTATES;
- sysctl(MIB_kern_cp_times, 2, fpl->cp_times_n, &sizeof_cp_time_array, NULL, 0);
+ // on smp systems FreeBSD kernel concats all CPU states into one long array in
+ // kern.cp_times sysctl OID
+ // we store averages in fpl->cpus[0], and actual cores after that
+ maxcpu = cpus + 1;
+ sizeof_cp_time_array = cpus * sizeof(unsigned long) * CPUSTATES;
+ sysctl(MIB_kern_cp_times, 2, fpl->cp_times_n, &sizeof_cp_time_array, NULL, 0);
}
for (int i = 0; i < maxcpu; i++) {
@@ -187,14 +214,14 @@ static inline void FreeBSDProcessList_scanCPUTime(ProcessList* pl) {
cp_time_o = fpl->cp_time_o;
} else {
if (i == 0 ) {
- // average
- cp_time_n = fpl->cp_time_n;
- cp_time_o = fpl->cp_time_o;
+ // average
+ cp_time_n = fpl->cp_time_n;
+ cp_time_o = fpl->cp_time_o;
} else {
- // specific smp cores
- cp_times_offset = i - 1;
- cp_time_n = fpl->cp_times_n + (cp_times_offset * CPUSTATES);
- cp_time_o = fpl->cp_times_o + (cp_times_offset * CPUSTATES);
+ // specific smp cores
+ cp_times_offset = i - 1;
+ cp_time_n = fpl->cp_times_n + (cp_times_offset * CPUSTATES);
+ cp_time_o = fpl->cp_times_o + (cp_times_offset * CPUSTATES);
}
}
@@ -203,19 +230,21 @@ static inline void FreeBSDProcessList_scanCPUTime(ProcessList* pl) {
unsigned long long total_n = 0;
unsigned long long total_d = 0;
for (int s = 0; s < CPUSTATES; s++) {
- cp_time_d[s] = cp_time_n[s] - cp_time_o[s];
- total_o += cp_time_o[s];
- total_n += cp_time_n[s];
+ cp_time_d[s] = cp_time_n[s] - cp_time_o[s];
+ total_o += cp_time_o[s];
+ total_n += cp_time_n[s];
}
// totals
total_d = total_n - total_o;
- if (total_d < 1 ) total_d = 1;
+ if (total_d < 1 ) {
+ total_d = 1;
+ }
// save current state as old and calc percentages
for (int s = 0; s < CPUSTATES; ++s) {
- cp_time_o[s] = cp_time_n[s];
- cp_time_p[s] = ((double)cp_time_d[s]) / ((double)total_d) * 100;
+ cp_time_o[s] = cp_time_n[s];
+ cp_time_p[s] = ((double)cp_time_d[s]) / ((double)total_d) * 100;
}
CPUData* cpuData = &(fpl->cpus[i]);
@@ -247,7 +276,6 @@ static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) {
u_long totalMem;
u_int memActive, memWire, cachedMem;
long buffersMem;
- uint64_t memZfsArc;
size_t len;
//disabled for now, as it is always smaller than phycal amount of memory...
@@ -286,14 +314,8 @@ static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) {
pl->usedMem = fpl->memActive + fpl->memWire;
- //currently unused, same as with arc, custom meter perhaps
- //sysctl(MIB_vm_stats_vm_v_inactive_count, 4, &(fpl->memInactive), &len, NULL, 0);
- //sysctl(MIB_vm_stats_vm_v_free_count, 4, &(fpl->memFree), &len, NULL, 0);
- //pl->freeMem = fpl->memInactive + fpl->memFree;
- //pl->freeMem *= pageSizeKb;
-
struct kvm_swap swap[16];
- int nswap = kvm_getswapinfo(fpl->kd, swap, sizeof(swap)/sizeof(swap[0]), 0);
+ int nswap = kvm_getswapinfo(fpl->kd, swap, ARRAYSIZE(swap), 0);
pl->totalSwap = 0;
pl->usedSwap = 0;
for (int i = 0; i < nswap; i++) {
@@ -302,11 +324,73 @@ static inline void FreeBSDProcessList_scanMemoryInfo(ProcessList* pl) {
}
pl->totalSwap *= pageSizeKb;
pl->usedSwap *= pageSizeKb;
+}
+
+static void FreeBSDProcessList_scanTTYs(ProcessList* pl) {
+ FreeBSDProcessList* fpl = (FreeBSDProcessList*) pl;
+
+ // scan /dev/tty*
+ {
+ DIR* dirPtr = opendir("/dev");
+ if (!dirPtr)
+ return;
- pl->sharedMem = 0; // currently unused
+ int dirFd = dirfd(dirPtr);
+ if (dirFd < 0)
+ goto err1;
+
+ const struct dirent* entry;
+ while ((entry = readdir(dirPtr))) {
+ if (!String_startsWith(entry->d_name, "tty"))
+ continue;
+
+ struct stat info;
+ if (Compat_fstatat(dirFd, "/dev", entry->d_name, &info, 0) < 0)
+ continue;
+
+ if (!S_ISCHR(info.st_mode))
+ continue;
+
+ if (!Hashtable_get(fpl->ttys, info.st_rdev))
+ Hashtable_put(fpl->ttys, info.st_rdev, xStrdup(entry->d_name));
+ }
+
+err1:
+ closedir(dirPtr);
+ }
+
+ // scan /dev/pts/*
+ {
+ DIR* dirPtr = opendir("/dev/pts");
+ if (!dirPtr)
+ return;
+
+ int dirFd = dirfd(dirPtr);
+ if (dirFd < 0)
+ goto err2;
+
+ const struct dirent* entry;
+ while ((entry = readdir(dirPtr))) {
+ struct stat info;
+ if (Compat_fstatat(dirFd, "/dev/pts", entry->d_name, &info, 0) < 0)
+ continue;
+
+ if (!S_ISCHR(info.st_mode))
+ continue;
+
+ if (!Hashtable_get(fpl->ttys, info.st_rdev)) {
+ char* path;
+ xAsprintf(&path, "pts/%s", entry->d_name);
+ Hashtable_put(fpl->ttys, info.st_rdev, path);
+ }
+ }
+
+err2:
+ closedir(dirPtr);
+ }
}
-char* FreeBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, int* basenameEnd) {
+static char* FreeBSDProcessList_readProcessName(kvm_t* kd, const struct kinfo_proc* kproc, int* basenameEnd) {
char** argv = kvm_getargv(kd, kproc, 0);
if (!argv) {
return xStrdup(kproc->ki_comm);
@@ -331,109 +415,109 @@ char* FreeBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, in
return comm;
}
-char* FreeBSDProcessList_readJailName(struct kinfo_proc* kproc) {
- int jid;
- struct iovec jiov[6];
- char* jname;
+static char* FreeBSDProcessList_readJailName(const struct kinfo_proc* kproc) {
+ char* jname = NULL;
char jnamebuf[MAXHOSTNAMELEN];
- if (kproc->ki_jid != 0 ){
+ if (kproc->ki_jid != 0 ) {
+ struct iovec jiov[6];
+
memset(jnamebuf, 0, sizeof(jnamebuf));
- *(const void **)&jiov[0].iov_base = "jid";
+IGNORE_WCASTQUAL_BEGIN
+ *(const void**)&jiov[0].iov_base = "jid";
jiov[0].iov_len = sizeof("jid");
- jiov[1].iov_base = &kproc->ki_jid;
+ jiov[1].iov_base = (void*) &kproc->ki_jid;
jiov[1].iov_len = sizeof(kproc->ki_jid);
- *(const void **)&jiov[2].iov_base = "name";
+ *(const void**)&jiov[2].iov_base = "name";
jiov[2].iov_len = sizeof("name");
jiov[3].iov_base = jnamebuf;
jiov[3].iov_len = sizeof(jnamebuf);
- *(const void **)&jiov[4].iov_base = "errmsg";
+ *(const void**)&jiov[4].iov_base = "errmsg";
jiov[4].iov_len = sizeof("errmsg");
jiov[5].iov_base = jail_errmsg;
jiov[5].iov_len = JAIL_ERRMSGLEN;
+IGNORE_WCASTQUAL_END
jail_errmsg[0] = 0;
- jid = jail_get(jiov, 6, 0);
+
+ int jid = jail_get(jiov, 6, 0);
if (jid < 0) {
- if (!jail_errmsg[0])
+ if (!jail_errmsg[0]) {
xSnprintf(jail_errmsg, JAIL_ERRMSGLEN, "jail_get: %s", strerror(errno));
- return NULL;
+ }
} else if (jid == kproc->ki_jid) {
jname = xStrdup(jnamebuf);
- if (jname == NULL)
- strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
- return jname;
- } else {
- return NULL;
}
} else {
- jnamebuf[0]='-';
- jnamebuf[1]='\0';
- jname = xStrdup(jnamebuf);
+ jname = xStrdup("-");
}
+
return jname;
}
-void ProcessList_goThroughEntries(ProcessList* this) {
- FreeBSDProcessList* fpl = (FreeBSDProcessList*) this;
- Settings* settings = this->settings;
+void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
+ FreeBSDProcessList* fpl = (FreeBSDProcessList*) super;
+ const Settings* settings = super->settings;
bool hideKernelThreads = settings->hideKernelThreads;
bool hideUserlandThreads = settings->hideUserlandThreads;
openzfs_sysctl_updateArcStats(&fpl->zfs);
- FreeBSDProcessList_scanMemoryInfo(this);
- FreeBSDProcessList_scanCPUTime(this);
+ FreeBSDProcessList_scanMemoryInfo(super);
+ FreeBSDProcessList_scanCPUTime(super);
+
+ // in pause mode only gather global data for meters (CPU/memory/...)
+ if (pauseProcessUpdate) {
+ return;
+ }
+
+ if (settings->flags & PROCESS_FLAG_FREEBSD_TTY) {
+ FreeBSDProcessList_scanTTYs(super);
+ }
- int cpus = this->cpuCount;
int count = 0;
struct kinfo_proc* kprocs = kvm_getprocs(fpl->kd, KERN_PROC_PROC, 0, &count);
- struct timeval tv;
- gettimeofday(&tv, NULL);
-
for (int i = 0; i < count; i++) {
struct kinfo_proc* kproc = &kprocs[i];
bool preExisting = false;
- bool isIdleProcess = false;
- struct tm date;
- Process* proc = ProcessList_getProcess(this, kproc->ki_pid, &preExisting, (Process_New) FreeBSDProcess_new);
+ // TODO: bool isIdleProcess = false;
+ Process* proc = ProcessList_getProcess(super, kproc->ki_pid, &preExisting, FreeBSDProcess_new);
FreeBSDProcess* fp = (FreeBSDProcess*) proc;
- proc->show = ! ((hideKernelThreads && Process_isKernelThread(fp)) || (hideUserlandThreads && Process_isUserlandThread(proc)));
+ proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) || (hideUserlandThreads && Process_isUserlandThread(proc)));
if (!preExisting) {
fp->jid = kproc->ki_jid;
proc->pid = kproc->ki_pid;
- if ( ! ((kproc->ki_pid == 0) || (kproc->ki_pid == 1) ) && kproc->ki_flag & P_SYSTEM)
- fp->kernel = 1;
- else
- fp->kernel = 0;
+ if ( ! ((kproc->ki_pid == 0) || (kproc->ki_pid == 1) ) && kproc->ki_flag & P_SYSTEM) {
+ fp->kernel = 1;
+ } else {
+ fp->kernel = 0;
+ }
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);
+ Process_fillStarttimeBuffer(proc);
+ proc->user = UsersTable_getRef(super->usersTable, proc->st_uid);
+ ProcessList_add(super, proc);
proc->comm = FreeBSDProcessList_readProcessName(fpl->kd, kproc, &proc->basenameOffset);
fp->jname = FreeBSDProcessList_readJailName(kproc);
} else {
- if(fp->jid != kproc->ki_jid) {
+ if (fp->jid != kproc->ki_jid) {
// process can enter jail anytime
fp->jid = kproc->ki_jid;
free(fp->jname);
fp->jname = FreeBSDProcessList_readJailName(kproc);
}
- if (proc->ppid != kproc->ki_ppid) {
- // if there are reapers in the system, process can get reparented anytime
- proc->ppid = kproc->ki_ppid;
- }
- if(proc->st_uid != kproc->ki_uid) {
+ // if there are reapers in the system, process can get reparented anytime
+ proc->ppid = kproc->ki_ppid;
+ if (proc->st_uid != kproc->ki_uid) {
// some processes change users (eg. to lower privs)
proc->st_uid = kproc->ki_uid;
- proc->user = UsersTable_getRef(this->usersTable, proc->st_uid);
+ proc->user = UsersTable_getRef(super->usersTable, proc->st_uid);
}
if (settings->updateProcessNames) {
free(proc->comm);
@@ -442,21 +526,23 @@ void ProcessList_goThroughEntries(ProcessList* this) {
}
// from FreeBSD source /src/usr.bin/top/machine.c
- proc->m_size = kproc->ki_size / 1024 / pageSizeKb;
+ proc->m_virt = kproc->ki_size / pageSize;
proc->m_resident = kproc->ki_rssize;
- proc->percent_mem = (proc->m_resident * PAGE_SIZE_KB) / (double)(this->totalMem) * 100.0;
proc->nlwp = kproc->ki_numthreads;
proc->time = (kproc->ki_runtime + 5000) / 10000;
proc->percent_cpu = 100.0 * ((double)kproc->ki_pctcpu / (double)kernelFScale);
- proc->percent_mem = 100.0 * (proc->m_resident * PAGE_SIZE_KB) / (double)(this->totalMem);
-
- if (proc->percent_cpu > 0.1) {
- // system idle process should own all CPU time left regardless of CPU count
- if ( strcmp("idle", kproc->ki_comm) == 0 ) {
- isIdleProcess = true;
- }
- }
+ proc->percent_mem = 100.0 * (proc->m_resident * pageSizeKb) / (double)(super->totalMem);
+
+ /*
+ * TODO
+ * if (proc->percent_cpu > 0.1) {
+ * // system idle process should own all CPU time left regardless of CPU count
+ * if ( strcmp("idle", kproc->ki_comm) == 0 ) {
+ * isIdleProcess = true;
+ * }
+ * }
+ */
proc->priority = kproc->ki_pri.pri_level - PZERO;
@@ -481,16 +567,16 @@ void ProcessList_goThroughEntries(ProcessList* this) {
default: proc->state = '?';
}
- if (Process_isKernelThread(fp)) {
- this->kernelThreads++;
+ if (settings->flags & PROCESS_FLAG_FREEBSD_TTY) {
+ fp->ttyPath = (kproc->ki_tdev == NODEV) ? nodevStr : Hashtable_get(fpl->ttys, kproc->ki_tdev);
}
- (void) localtime_r((time_t*) &proc->starttime_ctime, &date);
- strftime(proc->starttime_show, 7, ((proc->starttime_ctime > tv.tv_sec - 86400) ? "%R " : "%b%d "), &date);
+ if (Process_isKernelThread(proc))
+ super->kernelThreads++;
- this->totalTasks++;
+ super->totalTasks++;
if (proc->state == 'R')
- this->runningTasks++;
+ super->runningTasks++;
proc->updated = true;
}
}

© 2014-2024 Faster IT GmbH | imprint | privacy policy