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/Battery.c | 25 ---- freebsd/Battery.h | 12 -- freebsd/FreeBSDCRT.c | 20 --- freebsd/FreeBSDCRT.h | 12 -- freebsd/FreeBSDProcess.c | 93 +++++++------ freebsd/FreeBSDProcess.h | 32 +++-- freebsd/FreeBSDProcessList.c | 312 +++++++++++++++++++++++++++---------------- freebsd/FreeBSDProcessList.h | 32 ++--- freebsd/Platform.c | 244 +++++++++++++++++++++++++++------ freebsd/Platform.h | 37 ++++- 10 files changed, 524 insertions(+), 295 deletions(-) delete mode 100644 freebsd/Battery.c delete mode 100644 freebsd/Battery.h delete mode 100644 freebsd/FreeBSDCRT.c delete mode 100644 freebsd/FreeBSDCRT.h (limited to 'freebsd') diff --git a/freebsd/Battery.c b/freebsd/Battery.c deleted file mode 100644 index b8c5e31..0000000 --- a/freebsd/Battery.c +++ /dev/null @@ -1,25 +0,0 @@ -/* -htop - freebsd/Battery.c -(C) 2015 Hisham H. Muhammad -Released under the GNU GPL, see the COPYING file -in the source distribution for its full text. -*/ - -#include "BatteryMeter.h" -#include - -void Battery_getData(double* level, ACPresence* isOnAC) { - int life; - size_t life_len = sizeof(life); - if (sysctlbyname("hw.acpi.battery.life", &life, &life_len, NULL, 0) == -1) - *level = -1; - else - *level = life; - - int acline; - size_t acline_len = sizeof(acline); - if (sysctlbyname("hw.acpi.acline", &acline, &acline_len, NULL, 0) == -1) - *isOnAC = AC_ERROR; - else - *isOnAC = acline == 0 ? AC_ABSENT : AC_PRESENT; -} diff --git a/freebsd/Battery.h b/freebsd/Battery.h deleted file mode 100644 index 6987d78..0000000 --- a/freebsd/Battery.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef HEADER_Battery -#define HEADER_Battery -/* -htop - freebsd/Battery.h -(C) 2015 Hisham H. Muhammad -Released under the GNU GPL, see the COPYING file -in the source distribution for its full text. -*/ - -void Battery_getData(double* level, ACPresence* isOnAC); - -#endif diff --git a/freebsd/FreeBSDCRT.c b/freebsd/FreeBSDCRT.c deleted file mode 100644 index 49cc5d0..0000000 --- a/freebsd/FreeBSDCRT.c +++ /dev/null @@ -1,20 +0,0 @@ -/* -htop - UnsupportedCRT.c -(C) 2014 Hisham H. Muhammad -Released under the GNU GPL, see the COPYING file -in the source distribution for its full text. -*/ - -#include "config.h" -#include "CRT.h" -#include -#include - -void CRT_handleSIGSEGV(int sgn) { - (void) sgn; - CRT_done(); - fprintf(stderr, "\n\nhtop " VERSION " aborting.\n"); - fprintf(stderr, "\nUnfortunately, you seem to be using an unsupported platform!"); - fprintf(stderr, "\nPlease contact your platform package maintainer!\n\n"); - abort(); -} diff --git a/freebsd/FreeBSDCRT.h b/freebsd/FreeBSDCRT.h deleted file mode 100644 index eb88fcc..0000000 --- a/freebsd/FreeBSDCRT.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef HEADER_FreeBSDCRT -#define HEADER_FreeBSDCRT -/* -htop - UnsupportedCRT.h -(C) 2014 Hisham H. Muhammad -Released under the GNU GPL, see the COPYING file -in the source distribution for its full text. -*/ - -void CRT_handleSIGSEGV(int sgn); - -#endif diff --git a/freebsd/FreeBSDProcess.c b/freebsd/FreeBSDProcess.c index 33dc751..d6d67b7 100644 --- a/freebsd/FreeBSDProcess.c +++ b/freebsd/FreeBSDProcess.c @@ -1,31 +1,22 @@ /* htop - FreeBSDProcess.c (C) 2015 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 "Process.h" -#include "ProcessList.h" #include "FreeBSDProcess.h" -#include "Platform.h" -#include "CRT.h" #include -#include -#include -#include +#include "CRT.h" +#include "Macros.h" +#include "Process.h" +#include "RichString.h" +#include "XUtils.h" -ProcessClass FreeBSDProcess_class = { - .super = { - .extends = Class(Process), - .display = Process_display, - .delete = Process_delete, - .compare = FreeBSDProcess_compare - }, - .writeField = (Process_WriteField) FreeBSDProcess_writeField, -}; + +const char* const nodevStr = "nodev"; ProcessFieldData Process_fields[] = { [0] = { .name = "", .title = NULL, .description = NULL, .flags = 0, }, @@ -35,7 +26,7 @@ ProcessFieldData Process_fields[] = { [PPID] = { .name = "PPID", .title = " PPID ", .description = "Parent process ID", .flags = 0, }, [PGRP] = { .name = "PGRP", .title = " PGRP ", .description = "Process group ID", .flags = 0, }, [SESSION] = { .name = "SESSION", .title = " SID ", .description = "Process's session ID", .flags = 0, }, - [TTY_NR] = { .name = "TTY_NR", .title = " TTY ", .description = "Controlling terminal", .flags = 0, }, + [TTY_NR] = { .name = "TTY_NR", .title = " TTY ", .description = "Controlling terminal", .flags = PROCESS_FLAG_FREEBSD_TTY, }, [TPGID] = { .name = "TPGID", .title = " TPGID ", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, }, [MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, }, [MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, }, @@ -44,10 +35,11 @@ ProcessFieldData Process_fields[] = { [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_VIRT] = { .name = "M_VIRT", .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, }, [ST_UID] = { .name = "ST_UID", .title = " UID ", .description = "User ID of the process owner", .flags = 0, }, [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = "CPU% ", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, }, + [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, }, [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, }, [USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, }, [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, }, @@ -69,11 +61,11 @@ ProcessPidColumn Process_pidColumns[] = { { .id = 0, .label = NULL }, }; -FreeBSDProcess* FreeBSDProcess_new(Settings* settings) { +Process* FreeBSDProcess_new(const Settings* settings) { FreeBSDProcess* this = xCalloc(1, sizeof(FreeBSDProcess)); Object_setClass(this, Class(FreeBSDProcess)); Process_init(&this->super, settings); - return this; + return &this->super; } void Process_delete(Object* cast) { @@ -83,15 +75,15 @@ void Process_delete(Object* cast) { free(this); } -void FreeBSDProcess_writeField(Process* this, RichString* str, ProcessField field) { - FreeBSDProcess* fp = (FreeBSDProcess*) this; +static void FreeBSDProcess_writeField(const Process* this, RichString* str, ProcessField field) { + const FreeBSDProcess* fp = (const FreeBSDProcess*) this; char buffer[256]; buffer[255] = '\0'; int attr = CRT_colors[DEFAULT_COLOR]; int n = sizeof(buffer) - 1; switch ((int) field) { // add FreeBSD-specific fields here case JID: xSnprintf(buffer, n, Process_pidFormat, fp->jid); break; - case JAIL:{ + case JAIL: { xSnprintf(buffer, n, "%-11s ", fp->jname); if (buffer[11] != '\0') { buffer[11] = ' '; @@ -99,6 +91,16 @@ void FreeBSDProcess_writeField(Process* this, RichString* str, ProcessField fiel } break; } + case TTY_NR: + if (fp->ttyPath) { + if (fp->ttyPath == nodevStr) + attr = CRT_colors[PROCESS_SHADOW]; + xSnprintf(buffer, n, "%-8s", fp->ttyPath); + } else { + attr = CRT_colors[PROCESS_SHADOW]; + xSnprintf(buffer, n, "? "); + } + break; default: Process_writeField(this, str, field); return; @@ -106,32 +108,47 @@ void FreeBSDProcess_writeField(Process* this, RichString* str, ProcessField fiel RichString_append(str, attr, buffer); } -long FreeBSDProcess_compare(const void* v1, const void* v2) { - FreeBSDProcess *p1, *p2; - Settings *settings = ((Process*)v1)->settings; +static long FreeBSDProcess_compare(const void* v1, const void* v2) { + const FreeBSDProcess *p1, *p2; + const Settings *settings = ((const Process*)v1)->settings; + if (settings->direction == 1) { - p1 = (FreeBSDProcess*)v1; - p2 = (FreeBSDProcess*)v2; + p1 = (const FreeBSDProcess*)v1; + p2 = (const FreeBSDProcess*)v2; } else { - p2 = (FreeBSDProcess*)v1; - p1 = (FreeBSDProcess*)v2; + p2 = (const FreeBSDProcess*)v1; + p1 = (const FreeBSDProcess*)v2; } + switch ((int) settings->sortKey) { // add FreeBSD-specific fields here case JID: - return (p1->jid - p2->jid); + return SPACESHIP_NUMBER(p1->jid, p2->jid); case JAIL: - return strcmp(p1->jname ? p1->jname : "", p2->jname ? p2->jname : ""); + return SPACESHIP_NULLSTR(p1->jname, p2->jname); + case TTY_NR: + return SPACESHIP_NULLSTR(p1->ttyPath, p2->ttyPath); default: return Process_compare(v1, v2); } } -bool Process_isThread(Process* this) { - FreeBSDProcess* fp = (FreeBSDProcess*) this; +bool Process_isThread(const Process* this) { + const FreeBSDProcess* fp = (const FreeBSDProcess*) this; - if (fp->kernel == 1 ) + if (fp->kernel == 1 ) { return 1; - else - return (Process_isUserlandThread(this)); + } else { + return Process_isUserlandThread(this); + } } + +const ProcessClass FreeBSDProcess_class = { + .super = { + .extends = Class(Process), + .display = Process_display, + .delete = Process_delete, + .compare = FreeBSDProcess_compare + }, + .writeField = FreeBSDProcess_writeField, +}; diff --git a/freebsd/FreeBSDProcess.h b/freebsd/FreeBSDProcess.h index 897c532..8911976 100644 --- a/freebsd/FreeBSDProcess.h +++ b/freebsd/FreeBSDProcess.h @@ -3,10 +3,21 @@ /* htop - FreeBSDProcess.h (C) 2015 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 + +#include "Object.h" +#include "Process.h" +#include "Settings.h" + + +#define PROCESS_FLAG_FREEBSD_TTY 0x0100 + +extern const char* const nodevStr; + typedef enum FreeBSDProcessFields_ { // Add platform-specific fields here, with ids >= 100 JID = 100, @@ -19,26 +30,27 @@ typedef struct FreeBSDProcess_ { int kernel; int jid; char* jname; + const char* ttyPath; } FreeBSDProcess; -#define Process_isKernelThread(_process) (_process->kernel == 1) +static inline bool Process_isKernelThread(const Process* this) { + return ((const FreeBSDProcess*)this)->kernel == 1; +} -#define Process_isUserlandThread(_process) (_process->pid != _process->tgid) +static inline bool Process_isUserlandThread(const Process* this) { + return this->pid != this->tgid; +} -extern ProcessClass FreeBSDProcess_class; +extern const ProcessClass FreeBSDProcess_class; extern ProcessFieldData Process_fields[]; extern ProcessPidColumn Process_pidColumns[]; -FreeBSDProcess* FreeBSDProcess_new(Settings* settings); +Process* FreeBSDProcess_new(const Settings* settings); void Process_delete(Object* cast); -void FreeBSDProcess_writeField(Process* this, RichString* str, ProcessField field); - -long FreeBSDProcess_compare(const void* v1, const void* v2); - -bool Process_isThread(Process* this); +bool Process_isThread(const Process* this); #endif 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; } } diff --git a/freebsd/FreeBSDProcessList.h b/freebsd/FreeBSDProcessList.h index 281bf3e..f18275d 100644 --- a/freebsd/FreeBSDProcessList.h +++ b/freebsd/FreeBSDProcessList.h @@ -3,19 +3,21 @@ /* htop - FreeBSDProcessList.h (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 +#include +#include + +#include "Hashtable.h" +#include "ProcessList.h" +#include "UsersTable.h" #include "zfs/ZfsArcStats.h" -#include -#include -#include -#include -#include -#define JAIL_ERRMSGLEN 1024 +#define JAIL_ERRMSGLEN 1024 extern char jail_errmsg[JAIL_ERRMSGLEN]; typedef struct CPUData_ { @@ -40,11 +42,13 @@ typedef struct FreeBSDProcessList_ { CPUData* cpus; - unsigned long *cp_time_o; - unsigned long *cp_time_n; + Hashtable* ttys; - unsigned long *cp_times_o; - unsigned long *cp_times_n; + unsigned long* cp_time_o; + unsigned long* cp_time_n; + + unsigned long* cp_times_o; + unsigned long* cp_times_n; } FreeBSDProcessList; @@ -52,10 +56,6 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui void ProcessList_delete(ProcessList* this); -char* FreeBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, int* basenameEnd); - -char* FreeBSDProcessList_readJailName(struct kinfo_proc* kproc); - -void ProcessList_goThroughEntries(ProcessList* this); +void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate); #endif diff --git a/freebsd/Platform.c b/freebsd/Platform.c index c51b37c..bc77cf4 100644 --- a/freebsd/Platform.c +++ b/freebsd/Platform.c @@ -1,35 +1,53 @@ /* htop - freebsd/Platform.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 "Platform.h" -#include "Meter.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "CPUMeter.h" +#include "ClockMeter.h" +#include "DateMeter.h" +#include "DateTimeMeter.h" +#include "DiskIOMeter.h" +#include "FreeBSDProcess.h" +#include "FreeBSDProcessList.h" +#include "HostnameMeter.h" +#include "LoadAverageMeter.h" +#include "Macros.h" #include "MemoryMeter.h" +#include "Meter.h" +#include "NetworkIOMeter.h" +#include "ProcessList.h" +#include "Settings.h" #include "SwapMeter.h" #include "TasksMeter.h" -#include "LoadAverageMeter.h" #include "UptimeMeter.h" -#include "ClockMeter.h" -#include "HostnameMeter.h" +#include "XUtils.h" #include "zfs/ZfsArcMeter.h" #include "zfs/ZfsCompressedArcMeter.h" -#include "FreeBSDProcess.h" -#include "FreeBSDProcessList.h" - -#include -#include -#include -#include -#include -#include -#include -ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_SIZE, M_RESIDENT, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; +ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_VIRT, M_RESIDENT, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; int Platform_numberOfFields = LAST_PROCESSFIELD; @@ -70,15 +88,13 @@ const SignalItem Platform_signals[] = { { .name = "33 SIGLIBRT", .number = 33 }, }; -const unsigned int Platform_numberOfSignals = sizeof(Platform_signals)/sizeof(SignalItem); - -void Platform_setBindings(Htop_Action* keys) { - (void) keys; -} +const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals); -MeterClass* Platform_meterTypes[] = { +const MeterClass* const Platform_meterTypes[] = { &CPUMeter_class, &ClockMeter_class, + &DateMeter_class, + &DateTimeMeter_class, &LoadAverageMeter_class, &LoadMeter_class, &MemoryMeter_class, @@ -89,16 +105,37 @@ MeterClass* Platform_meterTypes[] = { &HostnameMeter_class, &AllCPUsMeter_class, &AllCPUs2Meter_class, + &AllCPUs4Meter_class, + &AllCPUs8Meter_class, &LeftCPUsMeter_class, &RightCPUsMeter_class, &LeftCPUs2Meter_class, &RightCPUs2Meter_class, + &LeftCPUs4Meter_class, + &RightCPUs4Meter_class, + &LeftCPUs8Meter_class, + &RightCPUs8Meter_class, &BlankMeter_class, &ZfsArcMeter_class, &ZfsCompressedArcMeter_class, + &DiskIOMeter_class, + &NetworkIOMeter_class, NULL }; +void Platform_init(void) { + /* no platform-specific setup needed */ +} + +void Platform_done(void) { + /* no platform-specific cleanup needed */ +} + +void Platform_setBindings(Htop_Action* keys) { + /* no platform-specific key bindings */ + (void) keys; +} + int Platform_getUptime() { struct timeval bootTime, currTime; int mib[2] = { CTL_KERN, KERN_BOOTTIME }; @@ -141,15 +178,15 @@ int Platform_getMaxPid() { } double Platform_setCPUValues(Meter* this, int cpu) { - FreeBSDProcessList* fpl = (FreeBSDProcessList*) this->pl; + const FreeBSDProcessList* fpl = (const FreeBSDProcessList*) this->pl; int cpus = this->pl->cpuCount; - CPUData* cpuData; + const CPUData* cpuData; if (cpus == 1) { - // single CPU box has everything in fpl->cpus[0] - cpuData = &(fpl->cpus[0]); + // single CPU box has everything in fpl->cpus[0] + cpuData = &(fpl->cpus[0]); } else { - cpuData = &(fpl->cpus[cpu]); + cpuData = &(fpl->cpus[cpu]); } double percent; @@ -160,25 +197,25 @@ double Platform_setCPUValues(Meter* this, int cpu) { if (this->pl->settings->detailedCPUTime) { v[CPU_METER_KERNEL] = cpuData->systemPercent; v[CPU_METER_IRQ] = cpuData->irqPercent; - Meter_setItems(this, 4); - percent = v[0]+v[1]+v[2]+v[3]; + this->curItems = 4; + percent = v[0] + v[1] + v[2] + v[3]; } else { v[2] = cpuData->systemAllPercent; - Meter_setItems(this, 3); - percent = v[0]+v[1]+v[2]; + this->curItems = 3; + percent = v[0] + v[1] + v[2]; } percent = CLAMP(percent, 0.0, 100.0); - if (isnan(percent)) percent = 0.0; - v[CPU_METER_FREQUENCY] = -1; + v[CPU_METER_FREQUENCY] = NAN; + v[CPU_METER_TEMPERATURE] = NAN; return percent; } void Platform_setMemoryValues(Meter* this) { // TODO - ProcessList* pl = (ProcessList*) this->pl; + const ProcessList* pl = this->pl; this->total = pl->totalMem; this->values[0] = pl->usedMem; @@ -187,28 +224,151 @@ void Platform_setMemoryValues(Meter* this) { } void Platform_setSwapValues(Meter* this) { - ProcessList* pl = (ProcessList*) this->pl; + const ProcessList* pl = this->pl; this->total = pl->totalSwap; this->values[0] = pl->usedSwap; } void Platform_setZfsArcValues(Meter* this) { - FreeBSDProcessList* fpl = (FreeBSDProcessList*) this->pl; + const FreeBSDProcessList* fpl = (const FreeBSDProcessList*) this->pl; ZfsArcMeter_readStats(this, &(fpl->zfs)); } void Platform_setZfsCompressedArcValues(Meter* this) { - FreeBSDProcessList* fpl = (FreeBSDProcessList*) this->pl; + const FreeBSDProcessList* fpl = (const FreeBSDProcessList*) this->pl; ZfsCompressedArcMeter_readStats(this, &(fpl->zfs)); } -void Platform_setTasksValues(Meter* this) { - // TODO +char* Platform_getProcessEnv(pid_t pid) { + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ENV, pid }; + + size_t capacity = ARG_MAX; + char* env = xMalloc(capacity); + + int err = sysctl(mib, 4, env, &capacity, NULL, 0); + if (err || capacity == 0) { + free(env); + return NULL; + } + + if (env[capacity - 1] || env[capacity - 2]) { + env = xRealloc(env, capacity + 2); + env[capacity] = 0; + env[capacity + 1] = 0; + } + + return env; } -char* Platform_getProcessEnv(pid_t pid) { - // TODO - return NULL; +char* Platform_getInodeFilename(pid_t pid, ino_t inode) { + (void)pid; + (void)inode; + return NULL; +} + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) { + (void)pid; + return NULL; +} + +bool Platform_getDiskIO(DiskIOData* data) { + + if (devstat_checkversion(NULL) < 0) + return false; + + struct devinfo info = { 0 }; + struct statinfo current = { .dinfo = &info }; + + // get number of devices + if (devstat_getdevs(NULL, ¤t) < 0) + return false; + + int count = current.dinfo->numdevs; + + unsigned long int bytesReadSum = 0, bytesWriteSum = 0, timeSpendSum = 0; + + // get data + for (int i = 0; i < count; i++) { + uint64_t bytes_read, bytes_write; + long double busy_time; + + devstat_compute_statistics(¤t.dinfo->devices[i], + NULL, + 1.0, + DSM_TOTAL_BYTES_READ, &bytes_read, + DSM_TOTAL_BYTES_WRITE, &bytes_write, + DSM_TOTAL_BUSY_TIME, &busy_time, + DSM_NONE); + + bytesReadSum += bytes_read; + bytesWriteSum += bytes_write; + timeSpendSum += 1000 * busy_time; + } + + data->totalBytesRead = bytesReadSum; + data->totalBytesWritten = bytesWriteSum; + data->totalMsTimeSpend = timeSpendSum; + return true; +} + +bool Platform_getNetworkIO(unsigned long int* bytesReceived, + unsigned long int* packetsReceived, + unsigned long int* bytesTransmitted, + unsigned long int* packetsTransmitted) { + int r; + + // get number of interfaces + int count; + size_t countLen = sizeof(count); + const int countMib[] = { CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_SYSTEM, IFMIB_IFCOUNT }; + + r = sysctl(countMib, ARRAYSIZE(countMib), &count, &countLen, NULL, 0); + if (r < 0) + return false; + + + unsigned long int bytesReceivedSum = 0, packetsReceivedSum = 0, bytesTransmittedSum = 0, packetsTransmittedSum = 0; + + for (int i = 1; i <= count; i++) { + struct ifmibdata ifmd; + size_t ifmdLen = sizeof(ifmd); + + const int dataMib[] = { CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_IFDATA, i, IFDATA_GENERAL }; + + r = sysctl(dataMib, ARRAYSIZE(dataMib), &ifmd, &ifmdLen, NULL, 0); + if (r < 0) + continue; + + if (ifmd.ifmd_flags & IFF_LOOPBACK) + continue; + + bytesReceivedSum += ifmd.ifmd_data.ifi_ibytes; + packetsReceivedSum += ifmd.ifmd_data.ifi_ipackets; + bytesTransmittedSum += ifmd.ifmd_data.ifi_obytes; + packetsTransmittedSum += ifmd.ifmd_data.ifi_opackets; + } + + *bytesReceived = bytesReceivedSum; + *packetsReceived = packetsReceivedSum; + *bytesTransmitted = bytesTransmittedSum; + *packetsTransmitted = packetsTransmittedSum; + return true; +} + +void Platform_getBattery(double* percent, ACPresence* isOnAC) { + int life; + size_t life_len = sizeof(life); + if (sysctlbyname("hw.acpi.battery.life", &life, &life_len, NULL, 0) == -1) + *percent = NAN; + else + *percent = life; + + int acline; + size_t acline_len = sizeof(acline); + if (sysctlbyname("hw.acpi.acline", &acline, &acline_len, NULL, 0) == -1) + *isOnAC = AC_ERROR; + else + *isOnAC = acline == 0 ? AC_ABSENT : AC_PRESENT; } diff --git a/freebsd/Platform.h b/freebsd/Platform.h index 1a18055..5b3b019 100644 --- a/freebsd/Platform.h +++ b/freebsd/Platform.h @@ -3,14 +3,22 @@ /* htop - freebsd/Platform.h (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 +#include + #include "Action.h" #include "BatteryMeter.h" +#include "DiskIOMeter.h" +#include "Meter.h" +#include "Process.h" +#include "ProcessLocksScreen.h" #include "SignalsPanel.h" + extern ProcessFieldData Process_fields[]; extern ProcessField Platform_defaultFields[]; @@ -21,15 +29,19 @@ extern const SignalItem Platform_signals[]; extern const unsigned int Platform_numberOfSignals; -void Platform_setBindings(Htop_Action* keys); +extern const MeterClass* const Platform_meterTypes[]; -extern MeterClass* Platform_meterTypes[]; +void Platform_init(void); + +void Platform_done(void); + +void Platform_setBindings(Htop_Action* keys); -int Platform_getUptime(); +int Platform_getUptime(void); void Platform_getLoadAverage(double* one, double* five, double* fifteen); -int Platform_getMaxPid(); +int Platform_getMaxPid(void); double Platform_setCPUValues(Meter* this, int cpu); @@ -41,8 +53,19 @@ void Platform_setZfsArcValues(Meter* this); void Platform_setZfsCompressedArcValues(Meter* this); -void Platform_setTasksValues(Meter* this); - char* Platform_getProcessEnv(pid_t pid); +char* Platform_getInodeFilename(pid_t pid, ino_t inode); + +FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid); + +bool Platform_getDiskIO(DiskIOData* data); + +bool Platform_getNetworkIO(unsigned long int* bytesReceived, + unsigned long int* packetsReceived, + unsigned long int* bytesTransmitted, + unsigned long int* packetsTransmitted); + +void Platform_getBattery(double* percent, ACPresence* isOnAC); + #endif -- cgit v1.2.3