From ff9409b1737627857eb47f64f536a3f66b6a09a4 Mon Sep 17 00:00:00 2001 From: Daniel Lange Date: Mon, 11 Apr 2016 13:01:07 +0200 Subject: Imported Upstream version 2.0.0 --- openbsd/Battery.c | 16 +++ openbsd/Battery.h | 16 +++ openbsd/OpenBSDCRT.c | 22 ++++ openbsd/OpenBSDCRT.h | 16 +++ openbsd/OpenBSDProcess.c | 234 +++++++++++++++++++++++++++++++++ openbsd/OpenBSDProcess.h | 48 +++++++ openbsd/OpenBSDProcessList.c | 266 +++++++++++++++++++++++++++++++++++++ openbsd/OpenBSDProcessList.h | 48 +++++++ openbsd/Platform.c | 302 +++++++++++++++++++++++++++++++++++++++++++ openbsd/Platform.h | 73 +++++++++++ 10 files changed, 1041 insertions(+) create mode 100644 openbsd/Battery.c create mode 100644 openbsd/Battery.h create mode 100644 openbsd/OpenBSDCRT.c create mode 100644 openbsd/OpenBSDCRT.h create mode 100644 openbsd/OpenBSDProcess.c create mode 100644 openbsd/OpenBSDProcess.h create mode 100644 openbsd/OpenBSDProcessList.c create mode 100644 openbsd/OpenBSDProcessList.h create mode 100644 openbsd/Platform.c create mode 100644 openbsd/Platform.h (limited to 'openbsd') diff --git a/openbsd/Battery.c b/openbsd/Battery.c new file mode 100644 index 0000000..f9d0969 --- /dev/null +++ b/openbsd/Battery.c @@ -0,0 +1,16 @@ +/* +htop - openbsd/Battery.c +(C) 2015 Hisham H. Muhammad +(C) 2015 Michael McConville +Released under the GNU GPL, see the COPYING file +in the source distribution for its full text. +*/ + +#include "BatteryMeter.h" + +void Battery_getData(double* level, ACPresence* isOnAC) { + // TODO + *level = -1; + *isOnAC = AC_ERROR; +} + diff --git a/openbsd/Battery.h b/openbsd/Battery.h new file mode 100644 index 0000000..b1a4982 --- /dev/null +++ b/openbsd/Battery.h @@ -0,0 +1,16 @@ +/* Do not edit this file. It was automatically generated. */ + +#ifndef HEADER_Battery +#define HEADER_Battery +/* +htop - openbsd/Battery.h +(C) 2015 Hisham H. Muhammad +(C) 2015 Michael McConville +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/openbsd/OpenBSDCRT.c b/openbsd/OpenBSDCRT.c new file mode 100644 index 0000000..c5dcec4 --- /dev/null +++ b/openbsd/OpenBSDCRT.c @@ -0,0 +1,22 @@ +/* +htop - UnsupportedCRT.c +(C) 2014 Hisham H. Muhammad +(C) 2015 Michael McConville +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/openbsd/OpenBSDCRT.h b/openbsd/OpenBSDCRT.h new file mode 100644 index 0000000..c48309a --- /dev/null +++ b/openbsd/OpenBSDCRT.h @@ -0,0 +1,16 @@ +/* Do not edit this file. It was automatically generated. */ + +#ifndef HEADER_OpenBSDCRT +#define HEADER_OpenBSDCRT +/* +htop - UnsupportedCRT.h +(C) 2014 Hisham H. Muhammad +(C) 2015 Michael McConville +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/openbsd/OpenBSDProcess.c b/openbsd/OpenBSDProcess.c new file mode 100644 index 0000000..71c84e8 --- /dev/null +++ b/openbsd/OpenBSDProcess.c @@ -0,0 +1,234 @@ +/* +htop - OpenBSDProcess.c +(C) 2015 Hisham H. Muhammad +(C) 2015 Michael McConville +Released under the GNU GPL, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Process.h" +#include "ProcessList.h" +#include "OpenBSDProcess.h" +#include "Platform.h" +#include "CRT.h" + +#include +#include +#include + +/*{ + +typedef enum OpenBSDProcessFields { + // Add platform-specific fields here, with ids >= 100 + LAST_PROCESSFIELD = 100, +} OpenBSDProcessField; + +typedef struct OpenBSDProcess_ { + Process super; +} OpenBSDProcess; + +#ifndef Process_isKernelThread +#define Process_isKernelThread(_process) (_process->pgrp == 0) +#endif + +#ifndef Process_isUserlandThread +#define Process_isUserlandThread(_process) (_process->pid != _process->tgid) +#endif + +}*/ + +ProcessClass OpenBSDProcess_class = { + .super = { + .extends = Class(Process), + .display = Process_display, + .delete = Process_delete, + .compare = OpenBSDProcess_compare + }, + .writeField = (Process_WriteField) OpenBSDProcess_writeField, +}; + +ProcessFieldData Process_fields[] = { + [0] = { + .name = "", + .title = NULL, + .description = NULL, + .flags = 0, }, + [PID] = { + .name = "PID", + .title = " PID ", + .description = "Process/thread ID", + .flags = 0, }, + [COMM] = { + .name = "Command", + .title = "Command ", + .description = "Command line", + .flags = 0, }, + [STATE] = { + .name = "STATE", + .title = "S ", + .description = "Process state (S sleeping, R running, D disk, Z zombie, T traced, W paging)", + .flags = 0, }, + [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 = " SESN ", + .description = "Process's session ID", + .flags = 0, }, + [TTY_NR] = { + .name = "TTY_NR", + .title = " TTY ", + .description = "Controlling terminal", + .flags = 0, }, + [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, }, + [PRIORITY] = { + .name = "PRIORITY", + .title = "PRI ", + .description = "Kernel's internal priority for the process", + .flags = 0, }, + [NICE] = { + .name = "NICE", + .title = " NI ", + .description = "Nice value (the higher the value, the more it lets other processes take priority)", + .flags = 0, }, + [STARTTIME] = { + .name = "STARTTIME", + .title = "START ", + .description = "Time the process was started", + .flags = 0, }, + [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_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_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, }, + [NLWP] = { + .name = "NLWP", + .title = "NLWP ", + .description = "Number of threads in the process", + .flags = 0, }, + [TGID] = { + .name = "TGID", + .title = " TGID ", + .description = "Thread group ID (i.e. process ID)", + .flags = 0, }, + [LAST_PROCESSFIELD] = { + .name = "*** report bug! ***", + .title = NULL, + .description = NULL, + .flags = 0, }, +}; + +ProcessPidColumn Process_pidColumns[] = { + { .id = PID, .label = "PID" }, + { .id = PPID, .label = "PPID" }, + { .id = TPGID, .label = "TPGID" }, + { .id = TGID, .label = "TGID" }, + { .id = PGRP, .label = "PGRP" }, + { .id = SESSION, .label = "SESN" }, + { .id = 0, .label = NULL }, +}; + +OpenBSDProcess* OpenBSDProcess_new(Settings* settings) { + OpenBSDProcess* this = xCalloc(sizeof(OpenBSDProcess), 1); + Object_setClass(this, Class(OpenBSDProcess)); + Process_init(&this->super, settings); + return this; +} + +void Process_delete(Object* cast) { + OpenBSDProcess* this = (OpenBSDProcess*) cast; + Process_done((Process*)cast); + free(this); +} + +void OpenBSDProcess_writeField(Process* this, RichString* str, ProcessField field) { + //OpenBSDProcess* fp = (OpenBSDProcess*) this; + char buffer[256]; buffer[255] = '\0'; + int attr = CRT_colors[DEFAULT_COLOR]; + //int n = sizeof(buffer) - 1; + switch (field) { + // add OpenBSD-specific fields here + default: + Process_writeField(this, str, field); + return; + } + RichString_append(str, attr, buffer); +} + +long OpenBSDProcess_compare(const void* v1, const void* v2) { + OpenBSDProcess *p1, *p2; + Settings *settings = ((Process*)v1)->settings; + if (settings->direction == 1) { + p1 = (OpenBSDProcess*)v1; + p2 = (OpenBSDProcess*)v2; + } else { + p2 = (OpenBSDProcess*)v1; + p1 = (OpenBSDProcess*)v2; + } + switch (settings->sortKey) { + // add OpenBSD-specific fields here + default: + return Process_compare(v1, v2); + } +} + +bool Process_isThread(Process* this) { + return (Process_isKernelThread(this)); +} diff --git a/openbsd/OpenBSDProcess.h b/openbsd/OpenBSDProcess.h new file mode 100644 index 0000000..ba55e5e --- /dev/null +++ b/openbsd/OpenBSDProcess.h @@ -0,0 +1,48 @@ +/* Do not edit this file. It was automatically generated. */ + +#ifndef HEADER_OpenBSDProcess +#define HEADER_OpenBSDProcess +/* +htop - OpenBSDProcess.h +(C) 2015 Hisham H. Muhammad +(C) 2015 Michael McConville +Released under the GNU GPL, see the COPYING file +in the source distribution for its full text. +*/ + + +typedef enum OpenBSDProcessFields { + // Add platform-specific fields here, with ids >= 100 + LAST_PROCESSFIELD = 100, +} OpenBSDProcessField; + +typedef struct OpenBSDProcess_ { + Process super; +} OpenBSDProcess; + +#ifndef Process_isKernelThread +#define Process_isKernelThread(_process) (_process->pgrp == 0) +#endif + +#ifndef Process_isUserlandThread +#define Process_isUserlandThread(_process) (_process->pid != _process->tgid) +#endif + + +extern ProcessClass OpenBSDProcess_class; + +extern ProcessFieldData Process_fields[]; + +extern ProcessPidColumn Process_pidColumns[]; + +OpenBSDProcess* OpenBSDProcess_new(Settings* settings); + +void Process_delete(Object* cast); + +void OpenBSDProcess_writeField(Process* this, RichString* str, ProcessField field); + +long OpenBSDProcess_compare(const void* v1, const void* v2); + +bool Process_isThread(Process* this); + +#endif diff --git a/openbsd/OpenBSDProcessList.c b/openbsd/OpenBSDProcessList.c new file mode 100644 index 0000000..97e40cb --- /dev/null +++ b/openbsd/OpenBSDProcessList.c @@ -0,0 +1,266 @@ +/* +htop - OpenBSDProcessList.c +(C) 2014 Hisham H. Muhammad +(C) 2015 Michael McConville +Released under the GNU GPL, see the COPYING file +in the source distribution for its full text. +*/ + +#include "ProcessList.h" +#include "OpenBSDProcessList.h" +#include "OpenBSDProcess.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*{ + +#include + +typedef struct CPUData_ { + unsigned long long int totalTime; + unsigned long long int totalPeriod; +} CPUData; + +typedef struct OpenBSDProcessList_ { + ProcessList super; + kvm_t* kd; + + CPUData* cpus; + +} OpenBSDProcessList; + +}*/ + +#ifndef CLAMP +#define CLAMP(x,low,high) (((x)>(high))?(high):(((x)<(low))?(low):(x))) +#endif + +static int pageSizeKb; +static long fscale; + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, uid_t userId) { + int mib[] = { CTL_HW, HW_NCPU }; + int fmib[] = { CTL_KERN, KERN_FSCALE }; + int i, e; + OpenBSDProcessList* opl = xCalloc(1, sizeof(OpenBSDProcessList)); + ProcessList* pl = (ProcessList*) opl; + size_t size = sizeof(pl->cpuCount); + + ProcessList_init(pl, Class(OpenBSDProcess), usersTable, pidWhiteList, userId); + e = sysctl(mib, 2, &pl->cpuCount, &size, NULL, 0); + if (e == -1 || pl->cpuCount < 1) { + pl->cpuCount = 1; + } + opl->cpus = xRealloc(opl->cpus, pl->cpuCount * sizeof(CPUData)); + + size = sizeof(fscale); + if (sysctl(fmib, 2, &fscale, &size, NULL, 0) < 0) + err(1, "fscale sysctl call failed"); + + for (i = 0; i < pl->cpuCount; i++) { + opl->cpus[i].totalTime = 1; + opl->cpus[i].totalPeriod = 1; + } + + pageSizeKb = PAGE_SIZE_KB; + + // XXX: last arg should eventually be an errbuf + opl->kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL); + assert(opl->kd); + + return pl; +} + +void ProcessList_delete(ProcessList* this) { + const OpenBSDProcessList* opl = (OpenBSDProcessList*) this; + if (opl->kd) kvm_close(opl->kd); + + free(opl->cpus); + + ProcessList_done(this); + free(this); +} + +static inline void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) { + static int uvmexp_mib[] = {CTL_VM, VM_UVMEXP}; + struct uvmexp uvmexp; + size_t size = sizeof(uvmexp); + + if (sysctl(uvmexp_mib, 2, &uvmexp, &size, NULL, 0) < 0) { + err(1, "uvmexp sysctl call failed"); + } + + //kb_pagesize = uvmexp.pagesize / 1024; + pl->usedMem = uvmexp.active * pageSizeKb; + pl->totalMem = uvmexp.npages * pageSizeKb; + + /* + const OpenBSDProcessList* opl = (OpenBSDProcessList*) pl; + + size_t len = sizeof(pl->totalMem); + sysctl(MIB_hw_physmem, 2, &(pl->totalMem), &len, NULL, 0); + pl->totalMem /= 1024; + sysctl(MIB_vm_stats_vm_v_wire_count, 4, &(pl->usedMem), &len, NULL, 0); + pl->usedMem *= pageSizeKb; + pl->freeMem = pl->totalMem - pl->usedMem; + sysctl(MIB_vm_stats_vm_v_cache_count, 4, &(pl->cachedMem), &len, NULL, 0); + pl->cachedMem *= pageSizeKb; + + struct kvm_swap swap[16]; + int nswap = kvm_getswapinfo(opl->kd, swap, sizeof(swap)/sizeof(swap[0]), 0); + pl->totalSwap = 0; + pl->usedSwap = 0; + for (int i = 0; i < nswap; i++) { + pl->totalSwap += swap[i].ksw_total; + pl->usedSwap += swap[i].ksw_used; + } + pl->totalSwap *= pageSizeKb; + pl->usedSwap *= pageSizeKb; + + pl->sharedMem = 0; // currently unused + pl->buffersMem = 0; // not exposed to userspace + */ +} + +char *OpenBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, int* basenameEnd) { + char *s, *buf, **arg; + size_t cpsz, len = 0, n; + int i; + + /* + * We attempt to fall back to just the command name (argv[0]) if we + * fail to construct the full command at any point. + */ + arg = kvm_getargv(kd, kproc, 500); + if (arg == NULL) { + if ((s = xStrdup(kproc->p_comm)) == NULL) { + err(1, NULL); + } + return s; + } + for (i = 0; arg[i] != NULL; i++) { + len += strlen(arg[i]) + 1; + } + if ((buf = s = xMalloc(len)) == NULL) { + if ((s = xStrdup(kproc->p_comm)) == NULL) { + err(1, NULL); + } + return s; + } + for (i = 0; arg[i] != NULL; i++) { + n = strlcpy(buf, arg[i], (s + len) - buf); + buf += n; + if (i == 0) { + *basenameEnd = n; + } + *buf = ' '; + buf++; + } + *(buf - 1) = '\0'; + return s; +} + +/* + * Taken from OpenBSD's ps(1). + */ +double getpcpu(const struct kinfo_proc *kp) { + if (fscale == 0) + return (0.0); + +#define fxtofl(fixpt) ((double)(fixpt) / fscale) + + return (100.0 * fxtofl(kp->p_pctcpu)); +} + +void ProcessList_goThroughEntries(ProcessList* this) { + OpenBSDProcessList* opl = (OpenBSDProcessList*) this; + Settings* settings = this->settings; + bool hideKernelThreads = settings->hideKernelThreads; + bool hideUserlandThreads = settings->hideUserlandThreads; + struct kinfo_proc* kproc; + bool preExisting; + Process* proc; + OpenBSDProcess* fp; + int count = 0; + int i; + + OpenBSDProcessList_scanMemoryInfo(this); + + // use KERN_PROC_KTHREAD to also include kernel threads + struct kinfo_proc* kprocs = kvm_getprocs(opl->kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &count); + //struct kinfo_proc* kprocs = getprocs(KERN_PROC_ALL, 0, &count); + + for (i = 0; i < count; i++) { + kproc = &kprocs[i]; + + preExisting = false; + proc = ProcessList_getProcess(this, kproc->p_pid, &preExisting, (Process_New) OpenBSDProcess_new); + fp = (OpenBSDProcess*) proc; + + proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) + || (hideUserlandThreads && Process_isUserlandThread(proc))); + + if (!preExisting) { + proc->ppid = kproc->p_ppid; + proc->tpgid = kproc->p_tpgid; + proc->tgid = kproc->p_pid; + proc->session = kproc->p_sid; + proc->tty_nr = kproc->p_tdev; + proc->pgrp = kproc->p__pgid; + proc->st_uid = kproc->p_uid; + proc->starttime_ctime = kproc->p_ustart_sec; + proc->user = UsersTable_getRef(this->usersTable, proc->st_uid); + ProcessList_add((ProcessList*)this, proc); + proc->comm = OpenBSDProcessList_readProcessName(opl->kd, kproc, &proc->basenameOffset); + } else { + if (settings->updateProcessNames) { + free(proc->comm); + proc->comm = OpenBSDProcessList_readProcessName(opl->kd, kproc, &proc->basenameOffset); + } + } + + proc->m_size = kproc->p_vm_dsize; + proc->m_resident = kproc->p_vm_rssize; + proc->percent_mem = (proc->m_resident * PAGE_SIZE_KB) / (double)(this->totalMem) * 100.0; + proc->percent_cpu = CLAMP(getpcpu(kproc), 0.0, this->cpuCount*100.0); + //proc->nlwp = kproc->p_numthreads; + //proc->time = kproc->p_rtime_sec + ((kproc->p_rtime_usec + 500000) / 10); + proc->nice = kproc->p_nice - 20; + proc->time = kproc->p_rtime_sec + ((kproc->p_rtime_usec + 500000) / 1000000); + proc->time *= 100; + proc->priority = kproc->p_priority - PZERO; + + switch (kproc->p_stat) { + case SIDL: proc->state = 'I'; break; + case SRUN: proc->state = 'R'; break; + case SSLEEP: proc->state = 'S'; break; + case SSTOP: proc->state = 'T'; break; + case SZOMB: proc->state = 'Z'; break; + case SDEAD: proc->state = 'D'; break; + case SONPROC: proc->state = 'P'; break; + default: proc->state = '?'; + } + + if (Process_isKernelThread(proc)) { + this->kernelThreads++; + } + + this->totalTasks++; + // SRUN ('R') means runnable, not running + if (proc->state == 'P') { + this->runningTasks++; + } + proc->updated = true; + } +} diff --git a/openbsd/OpenBSDProcessList.h b/openbsd/OpenBSDProcessList.h new file mode 100644 index 0000000..192fb34 --- /dev/null +++ b/openbsd/OpenBSDProcessList.h @@ -0,0 +1,48 @@ +/* Do not edit this file. It was automatically generated. */ + +#ifndef HEADER_OpenBSDProcessList +#define HEADER_OpenBSDProcessList +/* +htop - OpenBSDProcessList.h +(C) 2014 Hisham H. Muhammad +(C) 2015 Michael McConville +Released under the GNU GPL, see the COPYING file +in the source distribution for its full text. +*/ + + +#include + +typedef struct CPUData_ { + unsigned long long int totalTime; + unsigned long long int totalPeriod; +} CPUData; + +typedef struct OpenBSDProcessList_ { + ProcessList super; + kvm_t* kd; + + CPUData* cpus; + +} OpenBSDProcessList; + + +#ifndef CLAMP +#define CLAMP(x,low,high) (((x)>(high))?(high):(((x)<(low))?(low):(x))) +#endif + + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, uid_t userId); + +void ProcessList_delete(ProcessList* this); + +char *OpenBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, int* basenameEnd); + +/* + * Taken from OpenBSD's ps(1). + */ +double getpcpu(const struct kinfo_proc *kp); + +void ProcessList_goThroughEntries(ProcessList* this); + +#endif diff --git a/openbsd/Platform.c b/openbsd/Platform.c new file mode 100644 index 0000000..251a713 --- /dev/null +++ b/openbsd/Platform.c @@ -0,0 +1,302 @@ +/* +htop - openbsd/Platform.c +(C) 2014 Hisham H. Muhammad +(C) 2015 Michael McConville +Released under the GNU GPL, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Platform.h" +#include "Meter.h" +#include "CPUMeter.h" +#include "MemoryMeter.h" +#include "SwapMeter.h" +#include "TasksMeter.h" +#include "LoadAverageMeter.h" +#include "UptimeMeter.h" +#include "ClockMeter.h" +#include "HostnameMeter.h" +#include "SignalsPanel.h" +#include "OpenBSDProcess.h" +#include "OpenBSDProcessList.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*{ +#include "Action.h" +#include "BatteryMeter.h" +#include "SignalsPanel.h" + +extern ProcessFieldData Process_fields[]; + +}*/ + +#define MAXCPU 256 +// XXX: probably should be a struct member +static int64_t old_v[MAXCPU][5]; + +/* + * Copyright (c) 1984, 1989, William LeFebvre, Rice University + * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University + * + * Taken directly from OpenBSD's top(1). + * + * percentages(cnt, out, new, old, diffs) - calculate percentage change + * between array "old" and "new", putting the percentages in "out". + * "cnt" is size of each array and "diffs" is used for scratch space. + * The array "old" is updated on each call. + * The routine assumes modulo arithmetic. This function is especially + * useful on BSD machines for calculating cpu state percentages. + */ +static int percentages(int cnt, int64_t *out, int64_t *new, int64_t *old, int64_t *diffs) { + int64_t change, total_change, *dp, half_total; + int i; + + /* initialization */ + total_change = 0; + dp = diffs; + + /* calculate changes for each state and the overall change */ + for (i = 0; i < cnt; i++) { + if ((change = *new - *old) < 0) { + /* this only happens when the counter wraps */ + change = INT64_MAX - *old + *new; + } + total_change += (*dp++ = change); + *old++ = *new++; + } + + /* avoid divide by zero potential */ + if (total_change == 0) + total_change = 1; + + /* calculate percentages based on overall change, rounding up */ + half_total = total_change / 2l; + for (i = 0; i < cnt; i++) + *out++ = ((*diffs++ * 1000 + half_total) / total_change); + + /* return the total in case the caller wants to use it */ + return (total_change); +} + +ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_SIZE, M_RESIDENT, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; + +int Platform_numberOfFields = LAST_PROCESSFIELD; + +/* + * See /usr/include/sys/signal.h + */ +SignalItem Platform_signals[] = { + { .name = " 0 Cancel", .number = 0 }, + { .name = " 1 SIGHUP", .number = 1 }, + { .name = " 2 SIGINT", .number = 2 }, + { .name = " 3 SIGQUIT", .number = 3 }, + { .name = " 4 SIGILL", .number = 4 }, + { .name = " 5 SIGTRAP", .number = 5 }, + { .name = " 6 SIGABRT", .number = 6 }, + { .name = " 6 SIGIOT", .number = 6 }, + { .name = " 7 SIGEMT", .number = 7 }, + { .name = " 8 SIGFPE", .number = 8 }, + { .name = " 9 SIGKILL", .number = 9 }, + { .name = "10 SIGBUS", .number = 10 }, + { .name = "11 SIGSEGV", .number = 11 }, + { .name = "12 SIGSYS", .number = 12 }, + { .name = "13 SIGPIPE", .number = 13 }, + { .name = "14 SIGALRM", .number = 14 }, + { .name = "15 SIGTERM", .number = 15 }, + { .name = "16 SIGURG", .number = 16 }, + { .name = "17 SIGSTOP", .number = 17 }, + { .name = "18 SIGTSTP", .number = 18 }, + { .name = "19 SIGCONT", .number = 19 }, + { .name = "20 SIGCHLD", .number = 20 }, + { .name = "21 SIGTTIN", .number = 21 }, + { .name = "22 SIGTTOU", .number = 22 }, + { .name = "23 SIGIO", .number = 23 }, + { .name = "24 SIGXCPU", .number = 24 }, + { .name = "25 SIGXFSZ", .number = 25 }, + { .name = "26 SIGVTALRM", .number = 26 }, + { .name = "27 SIGPROF", .number = 27 }, + { .name = "28 SIGWINCH", .number = 28 }, + { .name = "29 SIGINFO", .number = 29 }, + { .name = "30 SIGUSR1", .number = 30 }, + { .name = "31 SIGUSR2", .number = 31 }, + { .name = "32 SIGTHR", .number = 32 }, +}; + +unsigned int Platform_numberOfSignals = sizeof(Platform_signals)/sizeof(SignalItem); + +void Platform_setBindings(Htop_Action* keys) { + (void) keys; +} + +MeterClass* Platform_meterTypes[] = { + &CPUMeter_class, + &ClockMeter_class, + &LoadAverageMeter_class, + &LoadMeter_class, + &MemoryMeter_class, + &SwapMeter_class, + &TasksMeter_class, + &UptimeMeter_class, + &BatteryMeter_class, + &HostnameMeter_class, + &AllCPUsMeter_class, + &AllCPUs2Meter_class, + &LeftCPUsMeter_class, + &RightCPUsMeter_class, + &LeftCPUs2Meter_class, + &RightCPUs2Meter_class, + &BlankMeter_class, + NULL +}; + +// preserved from FreeBSD port +int Platform_getUptime() { + struct timeval bootTime, currTime; + int mib[2] = { CTL_KERN, KERN_BOOTTIME }; + size_t size = sizeof(bootTime); + + int err = sysctl(mib, 2, &bootTime, &size, NULL, 0); + if (err) { + return -1; + } + gettimeofday(&currTime, NULL); + + return (int) difftime(currTime.tv_sec, bootTime.tv_sec); +} + +void Platform_getLoadAverage(double* one, double* five, double* fifteen) { + struct loadavg loadAverage; + int mib[2] = { CTL_VM, VM_LOADAVG }; + size_t size = sizeof(loadAverage); + + int err = sysctl(mib, 2, &loadAverage, &size, NULL, 0); + if (err) { + *one = 0; + *five = 0; + *fifteen = 0; + return; + } + *one = (double) loadAverage.ldavg[0] / loadAverage.fscale; + *five = (double) loadAverage.ldavg[1] / loadAverage.fscale; + *fifteen = (double) loadAverage.ldavg[2] / loadAverage.fscale; +} + +int Platform_getMaxPid() { + // this is hard-coded in sys/sys/proc.h - no sysctl exists + return 32766; +} + +double Platform_setCPUValues(Meter* this, int cpu) { + int i; + double perc; + + OpenBSDProcessList* pl = (OpenBSDProcessList*) this->pl; + CPUData* cpuData = &(pl->cpus[cpu]); + int64_t new_v[CPUSTATES], diff_v[CPUSTATES], scratch_v[CPUSTATES]; + double *v = this->values; + size_t size = sizeof(double) * CPUSTATES; + int mib[] = { CTL_KERN, KERN_CPTIME2, cpu-1 }; + if (sysctl(mib, 3, new_v, &size, NULL, 0) == -1) { + return 0.; + } + + // XXX: why? + cpuData->totalPeriod = 1; + + percentages(CPUSTATES, diff_v, new_v, + (int64_t *)old_v[cpu-1], scratch_v); + + for (i = 0; i < CPUSTATES; i++) { + old_v[cpu-1][i] = new_v[i]; + v[i] = diff_v[i] / 10.; + } + + Meter_setItems(this, 4); + + perc = v[0] + v[1] + v[2] + v[3]; + + if (perc <= 100. && perc >= 0.) { + return perc; + } else { + return 0.; + } +} + +void Platform_setMemoryValues(Meter* this) { + ProcessList* pl = (ProcessList*) this->pl; + long int usedMem = pl->usedMem; + long int buffersMem = pl->buffersMem; + long int cachedMem = pl->cachedMem; + usedMem -= buffersMem + cachedMem; + this->total = pl->totalMem; + this->values[0] = usedMem; + this->values[1] = buffersMem; + this->values[2] = cachedMem; +} + +/* + * Copyright (c) 1994 Thorsten Lockert + * All rights reserved. + * + * Taken almost directly from OpenBSD's top(1) + */ +void Platform_setSwapValues(Meter* this) { + ProcessList* pl = (ProcessList*) this->pl; + struct swapent *swdev; + unsigned long long int total, used; + int nswap, rnswap, i; + nswap = swapctl(SWAP_NSWAP, 0, 0); + if (nswap == 0) { + return; + } + + swdev = xCalloc(nswap, sizeof(*swdev)); + if (swdev == NULL) { + return; + } + + rnswap = swapctl(SWAP_STATS, swdev, nswap); + if (rnswap == -1) { + free(swdev); + return; + } + + // if rnswap != nswap, then what? + + /* Total things up */ + total = used = 0; + for (i = 0; i < nswap; i++) { + if (swdev[i].se_flags & SWF_ENABLE) { + used += (swdev[i].se_inuse / (1024 / DEV_BSIZE)); + total += (swdev[i].se_nblks / (1024 / DEV_BSIZE)); + } + } + + this->total = pl->totalSwap = total; + this->values[0] = pl->usedSwap = used; + + free(swdev); +} + +void Platform_setTasksValues(Meter* this) { + // TODO +} + +char* Platform_getProcessEnv(pid_t pid) { + // TODO + return NULL; +} diff --git a/openbsd/Platform.h b/openbsd/Platform.h new file mode 100644 index 0000000..6665093 --- /dev/null +++ b/openbsd/Platform.h @@ -0,0 +1,73 @@ +/* Do not edit this file. It was automatically generated. */ + +#ifndef HEADER_Platform +#define HEADER_Platform +/* +htop - openbsd/Platform.h +(C) 2014 Hisham H. Muhammad +(C) 2015 Michael McConville +Released under the GNU GPL, see the COPYING file +in the source distribution for its full text. +*/ + +#include "Action.h" +#include "BatteryMeter.h" +#include "SignalsPanel.h" + +extern ProcessFieldData Process_fields[]; + + +#define MAXCPU 256 +// XXX: probably should be a struct member +/* + * Copyright (c) 1984, 1989, William LeFebvre, Rice University + * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University + * + * Taken directly from OpenBSD's top(1). + * + * percentages(cnt, out, new, old, diffs) - calculate percentage change + * between array "old" and "new", putting the percentages in "out". + * "cnt" is size of each array and "diffs" is used for scratch space. + * The array "old" is updated on each call. + * The routine assumes modulo arithmetic. This function is especially + * useful on BSD machines for calculating cpu state percentages. + */ +extern ProcessField Platform_defaultFields[]; + +extern int Platform_numberOfFields; + +/* + * See /usr/include/sys/signal.h + */ +extern SignalItem Platform_signals[]; + +extern unsigned int Platform_numberOfSignals; + +void Platform_setBindings(Htop_Action* keys); + +extern MeterClass* Platform_meterTypes[]; + +// preserved from FreeBSD port +int Platform_getUptime(); + +void Platform_getLoadAverage(double* one, double* five, double* fifteen); + +int Platform_getMaxPid(); + +double Platform_setCPUValues(Meter* this, int cpu); + +void Platform_setMemoryValues(Meter* this); + +/* + * Copyright (c) 1994 Thorsten Lockert + * All rights reserved. + * + * Taken almost directly from OpenBSD's top(1) + */ +void Platform_setSwapValues(Meter* this); + +void Platform_setTasksValues(Meter* this); + +char* Platform_getProcessEnv(pid_t pid); + +#endif -- cgit v1.2.3