2015-09-18 04:46:48 +00:00
|
|
|
|
/*
|
|
|
|
|
htop - OpenBSDProcessList.c
|
|
|
|
|
(C) 2014 Hisham H. Muhammad
|
|
|
|
|
(C) 2015 Michael McConville
|
2020-10-05 07:51:32 +00:00
|
|
|
|
Released under the GNU GPLv2, see the COPYING file
|
2015-09-18 04:46:48 +00:00
|
|
|
|
in the source distribution for its full text.
|
|
|
|
|
*/
|
|
|
|
|
|
2021-04-29 18:13:36 +00:00
|
|
|
|
#include "openbsd/OpenBSDProcessList.h"
|
2015-09-18 04:46:48 +00:00
|
|
|
|
|
2020-12-05 21:57:07 +00:00
|
|
|
|
#include <kvm.h>
|
|
|
|
|
#include <limits.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <unistd.h>
|
2016-02-12 00:28:22 +00:00
|
|
|
|
#include <sys/mount.h>
|
2015-09-18 04:46:48 +00:00
|
|
|
|
#include <sys/param.h>
|
|
|
|
|
#include <sys/proc.h>
|
2018-12-16 08:25:54 +00:00
|
|
|
|
#include <sys/sched.h>
|
2020-12-05 21:57:07 +00:00
|
|
|
|
#include <sys/swap.h>
|
2015-09-18 04:46:48 +00:00
|
|
|
|
#include <sys/sysctl.h>
|
2016-02-12 00:28:22 +00:00
|
|
|
|
#include <sys/types.h>
|
2020-12-05 21:57:07 +00:00
|
|
|
|
#include <uvm/uvmexp.h>
|
|
|
|
|
|
|
|
|
|
#include "CRT.h"
|
|
|
|
|
#include "Macros.h"
|
|
|
|
|
#include "Object.h"
|
|
|
|
|
#include "Process.h"
|
|
|
|
|
#include "ProcessList.h"
|
|
|
|
|
#include "Settings.h"
|
|
|
|
|
#include "XUtils.h"
|
2021-04-29 18:13:36 +00:00
|
|
|
|
#include "openbsd/OpenBSDProcess.h"
|
2020-12-05 21:57:07 +00:00
|
|
|
|
|
2015-09-18 04:46:48 +00:00
|
|
|
|
|
|
|
|
|
static long fscale;
|
2020-12-10 00:57:48 +00:00
|
|
|
|
static int pageSize;
|
|
|
|
|
static int pageSizeKB;
|
2015-09-18 04:46:48 +00:00
|
|
|
|
|
2021-06-13 12:24:51 +00:00
|
|
|
|
static void OpenBSDProcessList_updateCPUcount(ProcessList* super) {
|
|
|
|
|
OpenBSDProcessList* opl = (OpenBSDProcessList*) super;
|
2021-03-27 13:26:26 +00:00
|
|
|
|
const int nmib[] = { CTL_HW, HW_NCPU };
|
|
|
|
|
const int mib[] = { CTL_HW, HW_NCPUONLINE };
|
2020-12-05 21:57:07 +00:00
|
|
|
|
int r;
|
2021-06-13 12:24:51 +00:00
|
|
|
|
unsigned int value;
|
2016-03-06 04:23:29 +00:00
|
|
|
|
size_t size;
|
2021-06-13 12:24:51 +00:00
|
|
|
|
bool change = false;
|
2016-03-06 04:23:29 +00:00
|
|
|
|
|
2021-06-13 12:24:51 +00:00
|
|
|
|
size = sizeof(value);
|
|
|
|
|
r = sysctl(mib, 2, &value, &size, NULL, 0);
|
|
|
|
|
if (r < 0 || value < 1) {
|
|
|
|
|
value = 1;
|
|
|
|
|
}
|
2016-03-06 04:23:29 +00:00
|
|
|
|
|
2021-06-13 12:24:51 +00:00
|
|
|
|
if (value != super->activeCPUs) {
|
|
|
|
|
super->activeCPUs = value;
|
|
|
|
|
change = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size = sizeof(value);
|
|
|
|
|
r = sysctl(nmib, 2, &value, &size, NULL, 0);
|
|
|
|
|
if (r < 0 || value < 1) {
|
|
|
|
|
value = super->activeCPUs;
|
|
|
|
|
}
|
2021-06-12 16:17:28 +00:00
|
|
|
|
|
2021-06-13 12:24:51 +00:00
|
|
|
|
if (value != super->existingCPUs) {
|
|
|
|
|
opl->cpuData = xReallocArray(opl->cpuData, value + 1, sizeof(CPUData));
|
|
|
|
|
super->existingCPUs = value;
|
|
|
|
|
change = true;
|
2016-01-03 21:56:33 +00:00
|
|
|
|
}
|
2015-09-18 04:46:48 +00:00
|
|
|
|
|
2021-06-13 12:24:51 +00:00
|
|
|
|
if (change) {
|
|
|
|
|
CPUData* dAvg = &opl->cpuData[0];
|
|
|
|
|
memset(dAvg, '\0', sizeof(CPUData));
|
|
|
|
|
dAvg->totalTime = 1;
|
|
|
|
|
dAvg->totalPeriod = 1;
|
|
|
|
|
dAvg->online = true;
|
|
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < super->existingCPUs; i++) {
|
|
|
|
|
CPUData* d = &opl->cpuData[i + 1];
|
|
|
|
|
memset(d, '\0', sizeof(CPUData));
|
|
|
|
|
d->totalTime = 1;
|
|
|
|
|
d->totalPeriod = 1;
|
|
|
|
|
|
|
|
|
|
const int ncmib[] = { CTL_KERN, KERN_CPUSTATS, i };
|
|
|
|
|
struct cpustats cpu_stats;
|
|
|
|
|
|
|
|
|
|
size = sizeof(cpu_stats);
|
|
|
|
|
if (sysctl(ncmib, 3, &cpu_stats, &size, NULL, 0) < 0) {
|
|
|
|
|
CRT_fatalError("ncmib sysctl call failed");
|
|
|
|
|
}
|
|
|
|
|
d->online = (cpu_stats.cs_flags & CPUSTATS_ONLINE);
|
|
|
|
|
}
|
2021-03-27 13:26:26 +00:00
|
|
|
|
}
|
2021-06-13 12:24:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
PCP: support for 'dynamic columns' added at runtime
Implements support for arbitrary Performance Co-Pilot
metrics with per-process instance domains to form new
htop columns. The column-to-metric mappings are setup
using configuration files which will be documented via
man pages as part of a follow-up commit.
We provide an initial set of column configurations so
as to provide new capabilities to pcp-htop: including
configs for containers, open fd counts, scheduler run
queue time, tcp/udp bytes/calls sent/recv, delay acct,
virtual machine guests, detailed virtual memory, swap.
Note there is a change to the configuration file path
resolution algorithm introduced for 'dynamic meters'.
First, look in any custom PCP_HTOP_DIR location. Then
iterate, in priority order, users home directory, then
local sysadmins files in /etc/pcp/htop, then readonly
configuration files below /usr/share/pcp/htop. This
final location becomes the preferred place for our own
shipped meter and column files.
The Settings file (htoprc) writing code is updated to
not using the numeric identifier for dynamic columns.
The same strategy used for dynamic meters is used here
where we write Dynamic(name) so the name can be setup
once more at start. Regular (static) columns writing
to htoprc - i.e. numerically indexed - is unchanged.
2021-07-11 01:11:29 +00:00
|
|
|
|
ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* dynamicColumns, Hashtable* pidMatchList, uid_t userId) {
|
2021-06-13 12:24:51 +00:00
|
|
|
|
const int fmib[] = { CTL_KERN, KERN_FSCALE };
|
|
|
|
|
size_t size;
|
|
|
|
|
char errbuf[_POSIX2_LINE_MAX];
|
|
|
|
|
|
|
|
|
|
OpenBSDProcessList* opl = xCalloc(1, sizeof(OpenBSDProcessList));
|
|
|
|
|
ProcessList* pl = (ProcessList*) opl;
|
PCP: support for 'dynamic columns' added at runtime
Implements support for arbitrary Performance Co-Pilot
metrics with per-process instance domains to form new
htop columns. The column-to-metric mappings are setup
using configuration files which will be documented via
man pages as part of a follow-up commit.
We provide an initial set of column configurations so
as to provide new capabilities to pcp-htop: including
configs for containers, open fd counts, scheduler run
queue time, tcp/udp bytes/calls sent/recv, delay acct,
virtual machine guests, detailed virtual memory, swap.
Note there is a change to the configuration file path
resolution algorithm introduced for 'dynamic meters'.
First, look in any custom PCP_HTOP_DIR location. Then
iterate, in priority order, users home directory, then
local sysadmins files in /etc/pcp/htop, then readonly
configuration files below /usr/share/pcp/htop. This
final location becomes the preferred place for our own
shipped meter and column files.
The Settings file (htoprc) writing code is updated to
not using the numeric identifier for dynamic columns.
The same strategy used for dynamic meters is used here
where we write Dynamic(name) so the name can be setup
once more at start. Regular (static) columns writing
to htoprc - i.e. numerically indexed - is unchanged.
2021-07-11 01:11:29 +00:00
|
|
|
|
ProcessList_init(pl, Class(OpenBSDProcess), usersTable, dynamicMeters, dynamicColumns, pidMatchList, userId);
|
2021-06-13 12:24:51 +00:00
|
|
|
|
|
|
|
|
|
OpenBSDProcessList_updateCPUcount(pl);
|
2021-03-27 13:26:26 +00:00
|
|
|
|
|
2015-09-18 04:46:48 +00:00
|
|
|
|
size = sizeof(fscale);
|
2016-03-06 04:23:29 +00:00
|
|
|
|
if (sysctl(fmib, 2, &fscale, &size, NULL, 0) < 0) {
|
2021-01-07 15:08:43 +00:00
|
|
|
|
CRT_fatalError("fscale sysctl call failed");
|
2016-03-06 04:23:29 +00:00
|
|
|
|
}
|
2015-09-18 04:46:48 +00:00
|
|
|
|
|
2020-12-10 00:57:48 +00:00
|
|
|
|
if ((pageSize = sysconf(_SC_PAGESIZE)) == -1)
|
2021-01-07 15:08:43 +00:00
|
|
|
|
CRT_fatalError("pagesize sysconf call failed");
|
2020-12-10 00:57:48 +00:00
|
|
|
|
pageSizeKB = pageSize / ONE_K;
|
|
|
|
|
|
2016-03-06 04:23:29 +00:00
|
|
|
|
opl->kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
|
|
|
|
|
if (opl->kd == NULL) {
|
2021-01-07 15:08:43 +00:00
|
|
|
|
CRT_fatalError("kvm_openfiles() failed");
|
2016-03-06 04:23:29 +00:00
|
|
|
|
}
|
2015-09-18 04:46:48 +00:00
|
|
|
|
|
2021-03-19 16:34:12 +00:00
|
|
|
|
opl->cpuSpeed = -1;
|
|
|
|
|
|
2015-09-18 04:46:48 +00:00
|
|
|
|
return pl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ProcessList_delete(ProcessList* this) {
|
2020-12-05 21:57:07 +00:00
|
|
|
|
OpenBSDProcessList* opl = (OpenBSDProcessList*) this;
|
2016-03-06 04:23:29 +00:00
|
|
|
|
|
|
|
|
|
if (opl->kd) {
|
|
|
|
|
kvm_close(opl->kd);
|
|
|
|
|
}
|
2015-10-13 15:05:52 +00:00
|
|
|
|
|
2021-06-13 12:24:51 +00:00
|
|
|
|
free(opl->cpuData);
|
2016-01-03 21:56:33 +00:00
|
|
|
|
|
2015-09-18 04:46:48 +00:00
|
|
|
|
ProcessList_done(this);
|
|
|
|
|
free(this);
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-05 21:57:07 +00:00
|
|
|
|
static void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) {
|
|
|
|
|
const int uvmexp_mib[] = { CTL_VM, VM_UVMEXP };
|
2015-09-18 04:46:48 +00:00
|
|
|
|
struct uvmexp uvmexp;
|
2016-02-12 00:28:22 +00:00
|
|
|
|
size_t size_uvmexp = sizeof(uvmexp);
|
2015-09-18 04:46:48 +00:00
|
|
|
|
|
2016-02-12 00:28:22 +00:00
|
|
|
|
if (sysctl(uvmexp_mib, 2, &uvmexp, &size_uvmexp, NULL, 0) < 0) {
|
2021-01-07 15:08:43 +00:00
|
|
|
|
CRT_fatalError("uvmexp sysctl call failed");
|
2015-09-18 04:46:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-12-10 00:57:48 +00:00
|
|
|
|
pl->totalMem = uvmexp.npages * pageSizeKB;
|
|
|
|
|
pl->usedMem = (uvmexp.npages - uvmexp.free - uvmexp.paging) * pageSizeKB;
|
2015-09-18 04:46:48 +00:00
|
|
|
|
|
2016-02-12 00:28:22 +00:00
|
|
|
|
// Taken from OpenBSD systat/iostat.c, top/machine.c and uvm_sysctl(9)
|
2020-12-05 21:57:07 +00:00
|
|
|
|
const int bcache_mib[] = { CTL_VFS, VFS_GENERIC, VFS_BCACHESTAT };
|
2016-02-12 00:28:22 +00:00
|
|
|
|
struct bcachestats bcstats;
|
|
|
|
|
size_t size_bcstats = sizeof(bcstats);
|
|
|
|
|
|
|
|
|
|
if (sysctl(bcache_mib, 3, &bcstats, &size_bcstats, NULL, 0) < 0) {
|
2021-01-07 15:08:43 +00:00
|
|
|
|
CRT_fatalError("cannot get vfs.bcachestat");
|
2016-02-12 00:28:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-12-10 00:57:48 +00:00
|
|
|
|
pl->cachedMem = bcstats.numbufpages * pageSizeKB;
|
2016-02-12 00:28:22 +00:00
|
|
|
|
|
2015-09-19 16:08:34 +00:00
|
|
|
|
/*
|
2020-12-05 21:57:07 +00:00
|
|
|
|
* Copyright (c) 1994 Thorsten Lockert <tholo@sigmasoft.com>
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* Taken almost directly from OpenBSD's top(1)
|
|
|
|
|
*
|
|
|
|
|
* Originally released under a BSD-3 license
|
|
|
|
|
* Modified through htop developers applying GPL-2
|
|
|
|
|
*/
|
|
|
|
|
int nswap = swapctl(SWAP_NSWAP, 0, 0);
|
|
|
|
|
if (nswap > 0) {
|
|
|
|
|
struct swapent swdev[nswap];
|
|
|
|
|
int rnswap = swapctl(SWAP_STATS, swdev, nswap);
|
|
|
|
|
|
|
|
|
|
/* Total things up */
|
|
|
|
|
unsigned long long int total = 0, used = 0;
|
|
|
|
|
for (int i = 0; i < rnswap; i++) {
|
|
|
|
|
if (swdev[i].se_flags & SWF_ENABLE) {
|
|
|
|
|
used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
|
|
|
|
|
total += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-10-13 15:05:52 +00:00
|
|
|
|
|
2020-12-05 21:57:07 +00:00
|
|
|
|
pl->totalSwap = total;
|
|
|
|
|
pl->usedSwap = used;
|
|
|
|
|
} else {
|
|
|
|
|
pl->totalSwap = pl->usedSwap = 0;
|
|
|
|
|
}
|
2015-09-18 04:46:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-05-25 17:08:14 +00:00
|
|
|
|
static void OpenBSDProcessList_updateCwd(const struct kinfo_proc* kproc, Process* proc) {
|
2021-06-13 11:57:18 +00:00
|
|
|
|
const int mib[] = { CTL_KERN, KERN_PROC_CWD, kproc->p_pid };
|
2021-05-25 17:08:14 +00:00
|
|
|
|
char buffer[2048];
|
|
|
|
|
size_t size = sizeof(buffer);
|
|
|
|
|
if (sysctl(mib, 3, buffer, &size, NULL, 0) != 0) {
|
|
|
|
|
free(proc->procCwd);
|
|
|
|
|
proc->procCwd = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Kernel threads return an empty buffer */
|
|
|
|
|
if (buffer[0] == '\0') {
|
|
|
|
|
free(proc->procCwd);
|
|
|
|
|
proc->procCwd = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free_and_xStrdup(&proc->procCwd, buffer);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-18 21:00:30 +00:00
|
|
|
|
static void OpenBSDProcessList_updateProcessName(kvm_t* kd, const struct kinfo_proc* kproc, Process* proc) {
|
|
|
|
|
Process_updateComm(proc, kproc->p_comm);
|
|
|
|
|
|
2016-01-03 03:05:20 +00:00
|
|
|
|
/*
|
2016-03-06 04:23:29 +00:00
|
|
|
|
* Like OpenBSD's top(1), we try to fall back to the command name
|
|
|
|
|
* (argv[0]) if we fail to construct the full command.
|
2016-01-03 03:05:20 +00:00
|
|
|
|
*/
|
2020-12-05 21:57:07 +00:00
|
|
|
|
char** arg = kvm_getargv(kd, kproc, 500);
|
2016-03-06 04:38:12 +00:00
|
|
|
|
if (arg == NULL || *arg == NULL) {
|
2021-05-18 21:00:30 +00:00
|
|
|
|
Process_updateCmdline(proc, kproc->p_comm, 0, strlen(kproc->p_comm));
|
|
|
|
|
return;
|
2016-01-02 16:57:53 +00:00
|
|
|
|
}
|
2020-12-05 21:57:07 +00:00
|
|
|
|
|
|
|
|
|
size_t len = 0;
|
|
|
|
|
for (int i = 0; arg[i] != NULL; i++) {
|
2016-03-06 04:23:29 +00:00
|
|
|
|
len += strlen(arg[i]) + 1; /* room for arg and trailing space or NUL */
|
2016-01-02 16:57:53 +00:00
|
|
|
|
}
|
2020-12-05 21:57:07 +00:00
|
|
|
|
|
2016-03-06 04:23:29 +00:00
|
|
|
|
/* don't use xMalloc here - we want to handle huge argv's gracefully */
|
2020-12-05 21:57:07 +00:00
|
|
|
|
char* s;
|
2016-03-06 04:38:12 +00:00
|
|
|
|
if ((s = malloc(len)) == NULL) {
|
2021-05-18 21:00:30 +00:00
|
|
|
|
Process_updateCmdline(proc, kproc->p_comm, 0, strlen(kproc->p_comm));
|
|
|
|
|
return;
|
2016-01-03 03:05:20 +00:00
|
|
|
|
}
|
2016-03-06 04:38:12 +00:00
|
|
|
|
|
|
|
|
|
*s = '\0';
|
|
|
|
|
|
2021-05-18 21:00:30 +00:00
|
|
|
|
int start = 0;
|
|
|
|
|
int end = 0;
|
2020-12-05 21:57:07 +00:00
|
|
|
|
for (int i = 0; arg[i] != NULL; i++) {
|
2020-11-21 23:59:00 +00:00
|
|
|
|
size_t n = strlcat(s, arg[i], len);
|
2016-01-02 16:57:53 +00:00
|
|
|
|
if (i == 0) {
|
2021-05-18 21:00:30 +00:00
|
|
|
|
end = MINIMUM(n, len - 1);
|
|
|
|
|
/* check if cmdline ended earlier, e.g 'kdeinit5: Running...' */
|
|
|
|
|
for (int j = end; j > 0; j--) {
|
2021-07-14 17:18:27 +00:00
|
|
|
|
if (arg[0][j] == ' ' && arg[0][j - 1] != '\\') {
|
|
|
|
|
end = (arg[0][j - 1] == ':') ? (j - 1) : j;
|
2021-05-18 21:00:30 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-01-02 16:57:53 +00:00
|
|
|
|
}
|
2016-03-06 04:38:12 +00:00
|
|
|
|
/* the trailing space should get truncated anyway */
|
2016-03-06 04:23:29 +00:00
|
|
|
|
strlcat(s, " ", len);
|
2016-01-02 16:57:53 +00:00
|
|
|
|
}
|
2016-03-06 04:38:12 +00:00
|
|
|
|
|
2021-05-18 21:00:30 +00:00
|
|
|
|
Process_updateCmdline(proc, s, start, end);
|
2015-09-18 04:46:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Taken from OpenBSD's ps(1).
|
|
|
|
|
*/
|
2020-10-31 22:28:02 +00:00
|
|
|
|
static double getpcpu(const struct kinfo_proc* kp) {
|
2015-09-19 16:08:34 +00:00
|
|
|
|
if (fscale == 0)
|
2020-10-31 22:28:02 +00:00
|
|
|
|
return 0.0;
|
2015-09-18 04:46:48 +00:00
|
|
|
|
|
2020-12-05 21:57:07 +00:00
|
|
|
|
return 100.0 * (double)kp->p_pctcpu / fscale;
|
2015-09-18 04:46:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-12-05 21:57:07 +00:00
|
|
|
|
static void OpenBSDProcessList_scanProcs(OpenBSDProcessList* this) {
|
2020-10-21 19:26:09 +00:00
|
|
|
|
const Settings* settings = this->super.settings;
|
2021-03-19 16:34:12 +00:00
|
|
|
|
const bool hideKernelThreads = settings->hideKernelThreads;
|
|
|
|
|
const bool hideUserlandThreads = settings->hideUserlandThreads;
|
2015-09-18 04:46:48 +00:00
|
|
|
|
int count = 0;
|
2015-10-13 15:05:52 +00:00
|
|
|
|
|
2021-03-19 16:34:12 +00:00
|
|
|
|
const struct kinfo_proc* kprocs = kvm_getprocs(this->kd, KERN_PROC_KTHREAD | KERN_PROC_SHOW_THREADS, 0, sizeof(struct kinfo_proc), &count);
|
2015-10-13 15:05:52 +00:00
|
|
|
|
|
2020-11-21 23:59:00 +00:00
|
|
|
|
for (int i = 0; i < count; i++) {
|
2020-12-05 21:57:07 +00:00
|
|
|
|
const struct kinfo_proc* kproc = &kprocs[i];
|
2015-10-13 15:05:52 +00:00
|
|
|
|
|
2021-03-19 16:34:12 +00:00
|
|
|
|
/* Ignore main threads */
|
|
|
|
|
if (kproc->p_tid != -1) {
|
|
|
|
|
Process* containingProcess = ProcessList_findProcess(&this->super, kproc->p_pid);
|
|
|
|
|
if (containingProcess) {
|
|
|
|
|
if (((OpenBSDProcess*)containingProcess)->addr == kproc->p_addr)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
containingProcess->nlwp++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-21 23:59:00 +00:00
|
|
|
|
bool preExisting = false;
|
2021-03-19 16:34:12 +00:00
|
|
|
|
Process* proc = ProcessList_getProcess(&this->super, (kproc->p_tid == -1) ? kproc->p_pid : kproc->p_tid, &preExisting, OpenBSDProcess_new);
|
|
|
|
|
OpenBSDProcess* fp = (OpenBSDProcess*) proc;
|
2015-09-18 04:46:48 +00:00
|
|
|
|
|
|
|
|
|
if (!preExisting) {
|
|
|
|
|
proc->ppid = kproc->p_ppid;
|
|
|
|
|
proc->tpgid = kproc->p_tpgid;
|
|
|
|
|
proc->tgid = kproc->p_pid;
|
|
|
|
|
proc->session = kproc->p_sid;
|
|
|
|
|
proc->pgrp = kproc->p__pgid;
|
2021-04-10 12:08:26 +00:00
|
|
|
|
proc->isKernelThread = proc->pgrp == 0;
|
|
|
|
|
proc->isUserlandThread = kproc->p_tid != -1;
|
2015-09-18 04:46:48 +00:00
|
|
|
|
proc->starttime_ctime = kproc->p_ustart_sec;
|
2020-10-13 12:26:40 +00:00
|
|
|
|
Process_fillStarttimeBuffer(proc);
|
2018-12-16 08:25:54 +00:00
|
|
|
|
ProcessList_add(&this->super, proc);
|
2021-04-18 16:10:04 +00:00
|
|
|
|
|
2021-05-18 21:00:30 +00:00
|
|
|
|
OpenBSDProcessList_updateProcessName(this->kd, kproc, proc);
|
2021-03-21 18:40:56 +00:00
|
|
|
|
|
2021-05-25 17:08:14 +00:00
|
|
|
|
if (settings->flags & PROCESS_FLAG_CWD) {
|
|
|
|
|
OpenBSDProcessList_updateCwd(kproc, proc);
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-21 18:40:56 +00:00
|
|
|
|
proc->tty_nr = kproc->p_tdev;
|
|
|
|
|
const char* name = ((dev_t)kproc->p_tdev != NODEV) ? devname(kproc->p_tdev, S_IFCHR) : NULL;
|
|
|
|
|
if (!name || String_eq(name, "??")) {
|
|
|
|
|
free(proc->tty_name);
|
|
|
|
|
proc->tty_name = NULL;
|
|
|
|
|
} else {
|
|
|
|
|
free_and_xStrdup(&proc->tty_name, name);
|
|
|
|
|
}
|
2015-09-18 04:46:48 +00:00
|
|
|
|
} else {
|
|
|
|
|
if (settings->updateProcessNames) {
|
2021-05-18 21:00:30 +00:00
|
|
|
|
OpenBSDProcessList_updateProcessName(this->kd, kproc, proc);
|
2015-09-18 04:46:48 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-19 16:34:12 +00:00
|
|
|
|
fp->addr = kproc->p_addr;
|
2020-12-10 00:57:48 +00:00
|
|
|
|
proc->m_virt = kproc->p_vm_dsize * pageSizeKB;
|
|
|
|
|
proc->m_resident = kproc->p_vm_rssize * pageSizeKB;
|
2021-03-19 16:34:12 +00:00
|
|
|
|
proc->percent_mem = proc->m_resident / (float)this->super.totalMem * 100.0F;
|
2021-06-12 16:17:28 +00:00
|
|
|
|
proc->percent_cpu = CLAMP(getpcpu(kproc), 0.0F, this->super.activeCPUs * 100.0F);
|
2015-09-19 16:08:34 +00:00
|
|
|
|
proc->nice = kproc->p_nice - 20;
|
2020-12-05 21:57:07 +00:00
|
|
|
|
proc->time = 100 * (kproc->p_rtime_sec + ((kproc->p_rtime_usec + 500000) / 1000000));
|
2015-09-18 04:46:48 +00:00
|
|
|
|
proc->priority = kproc->p_priority - PZERO;
|
2021-03-19 16:34:12 +00:00
|
|
|
|
proc->processor = kproc->p_cpuid;
|
|
|
|
|
proc->minflt = kproc->p_uru_minflt;
|
|
|
|
|
proc->majflt = kproc->p_uru_majflt;
|
|
|
|
|
proc->nlwp = 1;
|
2015-09-18 04:46:48 +00:00
|
|
|
|
|
2021-06-18 18:42:25 +00:00
|
|
|
|
if (proc->st_uid != kproc->p_uid) {
|
|
|
|
|
proc->st_uid = kproc->p_uid;
|
|
|
|
|
proc->user = UsersTable_getRef(this->super.usersTable, proc->st_uid);
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-18 04:46:48 +00:00
|
|
|
|
switch (kproc->p_stat) {
|
2015-09-19 16:08:34 +00:00
|
|
|
|
case SIDL: proc->state = 'I'; break;
|
2021-03-19 16:34:12 +00:00
|
|
|
|
case SRUN: proc->state = 'P'; break;
|
2015-09-19 16:08:34 +00:00
|
|
|
|
case SSLEEP: proc->state = 'S'; break;
|
|
|
|
|
case SSTOP: proc->state = 'T'; break;
|
|
|
|
|
case SZOMB: proc->state = 'Z'; break;
|
|
|
|
|
case SDEAD: proc->state = 'D'; break;
|
2021-03-19 16:34:12 +00:00
|
|
|
|
case SONPROC: proc->state = 'R'; break;
|
2015-09-19 16:08:34 +00:00
|
|
|
|
default: proc->state = '?';
|
2015-09-18 04:46:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Process_isKernelThread(proc)) {
|
2018-12-16 08:25:54 +00:00
|
|
|
|
this->super.kernelThreads++;
|
2021-03-19 16:34:12 +00:00
|
|
|
|
} else if (Process_isUserlandThread(proc)) {
|
|
|
|
|
this->super.userlandThreads++;
|
2015-09-18 04:46:48 +00:00
|
|
|
|
}
|
2015-10-13 15:05:52 +00:00
|
|
|
|
|
2018-12-16 08:25:54 +00:00
|
|
|
|
this->super.totalTasks++;
|
2021-03-19 16:34:12 +00:00
|
|
|
|
if (proc->state == 'R') {
|
2018-12-16 08:25:54 +00:00
|
|
|
|
this->super.runningTasks++;
|
2015-09-19 16:21:22 +00:00
|
|
|
|
}
|
2021-06-13 12:24:51 +00:00
|
|
|
|
|
|
|
|
|
proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) || (hideUserlandThreads && Process_isUserlandThread(proc)));
|
2015-09-18 04:46:48 +00:00
|
|
|
|
proc->updated = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-12-16 08:25:54 +00:00
|
|
|
|
|
2021-06-13 12:24:51 +00:00
|
|
|
|
static void getKernelCPUTimes(unsigned int cpuId, u_int64_t* times) {
|
2020-12-05 21:57:07 +00:00
|
|
|
|
const int mib[] = { CTL_KERN, KERN_CPTIME2, cpuId };
|
|
|
|
|
size_t length = sizeof(*times) * CPUSTATES;
|
|
|
|
|
if (sysctl(mib, 3, times, &length, NULL, 0) == -1 || length != sizeof(*times) * CPUSTATES) {
|
2018-12-16 08:25:54 +00:00
|
|
|
|
CRT_fatalError("sysctl kern.cp_time2 failed");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void kernelCPUTimesToHtop(const u_int64_t* times, CPUData* cpu) {
|
|
|
|
|
unsigned long long totalTime = 0;
|
|
|
|
|
for (int i = 0; i < CPUSTATES; i++) {
|
|
|
|
|
totalTime += times[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned long long sysAllTime = times[CP_INTR] + times[CP_SYS];
|
|
|
|
|
|
|
|
|
|
// XXX Not sure if CP_SPIN should be added to sysAllTime.
|
|
|
|
|
// See https://github.com/openbsd/src/commit/531d8034253fb82282f0f353c086e9ad827e031c
|
|
|
|
|
#ifdef CP_SPIN
|
|
|
|
|
sysAllTime += times[CP_SPIN];
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
cpu->totalPeriod = saturatingSub(totalTime, cpu->totalTime);
|
|
|
|
|
cpu->userPeriod = saturatingSub(times[CP_USER], cpu->userTime);
|
|
|
|
|
cpu->nicePeriod = saturatingSub(times[CP_NICE], cpu->niceTime);
|
|
|
|
|
cpu->sysPeriod = saturatingSub(times[CP_SYS], cpu->sysTime);
|
|
|
|
|
cpu->sysAllPeriod = saturatingSub(sysAllTime, cpu->sysAllTime);
|
|
|
|
|
#ifdef CP_SPIN
|
|
|
|
|
cpu->spinPeriod = saturatingSub(times[CP_SPIN], cpu->spinTime);
|
|
|
|
|
#endif
|
|
|
|
|
cpu->intrPeriod = saturatingSub(times[CP_INTR], cpu->intrTime);
|
|
|
|
|
cpu->idlePeriod = saturatingSub(times[CP_IDLE], cpu->idleTime);
|
|
|
|
|
|
|
|
|
|
cpu->totalTime = totalTime;
|
|
|
|
|
cpu->userTime = times[CP_USER];
|
|
|
|
|
cpu->niceTime = times[CP_NICE];
|
|
|
|
|
cpu->sysTime = times[CP_SYS];
|
|
|
|
|
cpu->sysAllTime = sysAllTime;
|
|
|
|
|
#ifdef CP_SPIN
|
|
|
|
|
cpu->spinTime = times[CP_SPIN];
|
|
|
|
|
#endif
|
|
|
|
|
cpu->intrTime = times[CP_INTR];
|
|
|
|
|
cpu->idleTime = times[CP_IDLE];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void OpenBSDProcessList_scanCPUTime(OpenBSDProcessList* this) {
|
|
|
|
|
u_int64_t kernelTimes[CPUSTATES] = {0};
|
|
|
|
|
u_int64_t avg[CPUSTATES] = {0};
|
|
|
|
|
|
2021-06-13 12:24:51 +00:00
|
|
|
|
for (unsigned int i = 0; i < this->super.existingCPUs; i++) {
|
|
|
|
|
CPUData* cpu = &this->cpuData[i + 1];
|
|
|
|
|
|
|
|
|
|
if (!cpu->online) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getKernelCPUTimes(i, kernelTimes);
|
2018-12-16 08:25:54 +00:00
|
|
|
|
kernelCPUTimesToHtop(kernelTimes, cpu);
|
|
|
|
|
|
|
|
|
|
avg[CP_USER] += cpu->userTime;
|
|
|
|
|
avg[CP_NICE] += cpu->niceTime;
|
|
|
|
|
avg[CP_SYS] += cpu->sysTime;
|
|
|
|
|
#ifdef CP_SPIN
|
|
|
|
|
avg[CP_SPIN] += cpu->spinTime;
|
|
|
|
|
#endif
|
|
|
|
|
avg[CP_INTR] += cpu->intrTime;
|
|
|
|
|
avg[CP_IDLE] += cpu->idleTime;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < CPUSTATES; i++) {
|
2021-06-12 16:17:28 +00:00
|
|
|
|
avg[i] /= this->super.activeCPUs;
|
2018-12-16 08:25:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-13 12:24:51 +00:00
|
|
|
|
kernelCPUTimesToHtop(avg, &this->cpuData[0]);
|
2021-03-19 16:34:12 +00:00
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const int mib[] = { CTL_HW, HW_CPUSPEED };
|
|
|
|
|
int cpuSpeed;
|
|
|
|
|
size_t size = sizeof(cpuSpeed);
|
|
|
|
|
if (sysctl(mib, 2, &cpuSpeed, &size, NULL, 0) == -1) {
|
|
|
|
|
this->cpuSpeed = -1;
|
|
|
|
|
} else {
|
|
|
|
|
this->cpuSpeed = cpuSpeed;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-12-16 08:25:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-10-27 20:26:28 +00:00
|
|
|
|
void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
|
|
|
|
|
OpenBSDProcessList* opl = (OpenBSDProcessList*) super;
|
2018-12-16 08:25:54 +00:00
|
|
|
|
|
2021-06-13 12:24:51 +00:00
|
|
|
|
OpenBSDProcessList_updateCPUcount(super);
|
2020-10-27 20:26:28 +00:00
|
|
|
|
OpenBSDProcessList_scanMemoryInfo(super);
|
2018-12-16 08:25:54 +00:00
|
|
|
|
OpenBSDProcessList_scanCPUTime(opl);
|
2020-10-13 14:03:37 +00:00
|
|
|
|
|
|
|
|
|
// in pause mode only gather global data for meters (CPU/memory/...)
|
2020-11-01 00:09:51 +00:00
|
|
|
|
if (pauseProcessUpdate) {
|
2020-10-13 14:03:37 +00:00
|
|
|
|
return;
|
2020-11-01 00:09:51 +00:00
|
|
|
|
}
|
2020-10-13 14:03:37 +00:00
|
|
|
|
|
|
|
|
|
OpenBSDProcessList_scanProcs(opl);
|
2018-12-16 08:25:54 +00:00
|
|
|
|
}
|
2021-06-12 20:04:37 +00:00
|
|
|
|
|
|
|
|
|
bool ProcessList_isCPUonline(const ProcessList* super, unsigned int id) {
|
|
|
|
|
assert(id < super->existingCPUs);
|
|
|
|
|
|
|
|
|
|
const OpenBSDProcessList* opl = (const OpenBSDProcessList*) super;
|
2021-06-13 12:24:51 +00:00
|
|
|
|
return opl->cpuData[id + 1].online;
|
2021-06-12 20:04:37 +00:00
|
|
|
|
}
|