From 65357c8c46154de4e4eca14075bfe5523bb5fc14 Mon Sep 17 00:00:00 2001 From: Daniel Lange Date: Mon, 7 Dec 2020 10:26:01 +0100 Subject: New upstream version 3.0.3 --- freebsd/FreeBSDProcessList.c | 312 +++++++++++++++++++++++++++---------------- 1 file changed, 199 insertions(+), 113 deletions(-) (limited to 'freebsd/FreeBSDProcessList.c') 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 -#include -#include -#include -#include +#include +#include #include -#include #include +#include #include -#include +#include +#include +#include +#include // needs to be included before for MAXPATHLEN +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; } } -- cgit v1.2.3