From 445222e48c380bbb5d209a82f9614187bc751b41 Mon Sep 17 00:00:00 2001 From: Michael McConville Date: Wed, 16 Sep 2015 23:42:36 -0400 Subject: [PATCH 1/6] Clean up some needless malloc casts, convert some mallocs to callocs, and fix some style --- FunctionBar.c | 4 ++-- Hashtable.c | 4 ++-- OpenFilesScreen.c | 2 +- StringUtils.c | 6 +++--- TraceScreen.c | 2 +- Vector.c | 2 +- darwin/DarwinProcessList.c | 26 +++++++++----------------- freebsd/FreeBSDProcessList.c | 2 +- 8 files changed, 20 insertions(+), 28 deletions(-) diff --git a/FunctionBar.c b/FunctionBar.c index 55e1f9a2..ab44839a 100644 --- a/FunctionBar.c +++ b/FunctionBar.c @@ -52,8 +52,8 @@ FunctionBar* FunctionBar_new(const char** functions, const char** keys, int* eve } if (keys && events) { this->staticData = false; - this->keys = malloc(sizeof(char*) * 15); - this->events = malloc(sizeof(int) * 15); + this->keys = calloc(15, sizeof(char*)); + this->events = calloc(15, sizeof(int)); int i = 0; while (i < 15 && functions[i]) { this->keys[i] = strdup(keys[i]); diff --git a/Hashtable.c b/Hashtable.c index 0f61519e..9cb2f932 100644 --- a/Hashtable.c +++ b/Hashtable.c @@ -63,7 +63,7 @@ int Hashtable_count(Hashtable* this) { static HashtableItem* HashtableItem_new(unsigned int key, void* value) { HashtableItem* this; - this = (HashtableItem*) malloc(sizeof(HashtableItem)); + this = malloc(sizeof(HashtableItem)); this->key = key; this->value = value; this->next = NULL; @@ -73,7 +73,7 @@ static HashtableItem* HashtableItem_new(unsigned int key, void* value) { Hashtable* Hashtable_new(int size, bool owner) { Hashtable* this; - this = (Hashtable*) malloc(sizeof(Hashtable)); + this = malloc(sizeof(Hashtable)); this->items = 0; this->size = size; this->buckets = (HashtableItem**) calloc(size, sizeof(HashtableItem*)); diff --git a/OpenFilesScreen.c b/OpenFilesScreen.c index 86eb3f8e..2a5e20af 100644 --- a/OpenFilesScreen.c +++ b/OpenFilesScreen.c @@ -58,7 +58,7 @@ static const char* OpenFilesScreenKeys[] = {"F3", "F4", "F5", "Esc"}; static int OpenFilesScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(5), 27}; OpenFilesScreen* OpenFilesScreen_new(Process* process) { - OpenFilesScreen* this = (OpenFilesScreen*) malloc(sizeof(OpenFilesScreen)); + OpenFilesScreen* this = malloc(sizeof(OpenFilesScreen)); this->process = process; FunctionBar* bar = FunctionBar_new(OpenFilesScreenFunctions, OpenFilesScreenKeys, OpenFilesScreenEvents); this->display = Panel_new(0, 1, COLS, LINES-3, false, Class(ListItem), bar); diff --git a/StringUtils.c b/StringUtils.c index 834b4311..54a61584 100644 --- a/StringUtils.c +++ b/StringUtils.c @@ -55,13 +55,13 @@ inline int String_eq(const char* s1, const char* s2) { char** String_split(const char* s, char sep, int* n) { *n = 0; const int rate = 10; - char** out = (char**) malloc(sizeof(char*) * rate); + char** out = calloc(rate, sizeof(char**)); int ctr = 0; int blocks = rate; char* where; while ((where = strchr(s, sep)) != NULL) { int size = where - s; - char* token = (char*) malloc(size + 1); + char* token = malloc(size + 1); strncpy(token, s, size); token[size] = '\0'; out[ctr] = token; @@ -80,7 +80,7 @@ char** String_split(const char* s, char sep, int* n) { } if (s[0] != '\0') { int size = strlen(s); - char* token = (char*) malloc(size + 1); + char* token = malloc(size + 1); strncpy(token, s, size + 1); out[ctr] = token; ctr++; diff --git a/TraceScreen.c b/TraceScreen.c index 48107438..ecd0c0ab 100644 --- a/TraceScreen.c +++ b/TraceScreen.c @@ -44,7 +44,7 @@ static const char* TraceScreenKeys[] = {"F3", "F4", "F8", "F9", "Esc"}; static int TraceScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(8), KEY_F(9), 27}; TraceScreen* TraceScreen_new(Process* process) { - TraceScreen* this = (TraceScreen*) malloc(sizeof(TraceScreen)); + TraceScreen* this = malloc(sizeof(TraceScreen)); this->process = process; FunctionBar* fuBar = FunctionBar_new(TraceScreenFunctions, TraceScreenKeys, TraceScreenEvents); this->display = Panel_new(0, 1, COLS, LINES-2, false, Class(ListItem), fuBar); diff --git a/Vector.c b/Vector.c index c1e2768a..8200564c 100644 --- a/Vector.c +++ b/Vector.c @@ -37,7 +37,7 @@ Vector* Vector_new(ObjectClass* type, bool owner, int size) { if (size == DEFAULT_SIZE) size = 10; - this = (Vector*) malloc(sizeof(Vector)); + this = malloc(sizeof(Vector)); this->growthRate = size; this->array = (Object**) calloc(size, sizeof(Object*)); this->arraySize = size; diff --git a/darwin/DarwinProcessList.c b/darwin/DarwinProcessList.c index 5d125891..9dbe4c89 100644 --- a/darwin/DarwinProcessList.c +++ b/darwin/DarwinProcessList.c @@ -73,10 +73,8 @@ unsigned ProcessList_allocateCPULoadInfo(processor_cpu_load_info_t *p) { void ProcessList_getVMStats(vm_statistics64_t p) { mach_msg_type_number_t info_size = HOST_VM_INFO64_COUNT; - if(0 != host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info_t)p, &info_size)) { - fprintf(stderr, "Unable to retrieve VM statistics\n"); - exit(9); - } + if (host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info_t)p, &info_size) != 0) + err(9, "Unable to retrieve VM statistics\n"); } struct kinfo_proc *ProcessList_getKInfoProcs(size_t *count) { @@ -88,21 +86,15 @@ struct kinfo_proc *ProcessList_getKInfoProcs(size_t *count) { * process entry or two. */ *count = 0; - if(0 > sysctl(mib, 4, NULL, count, NULL, 0)) { - fprintf(stderr, "Unable to get size of kproc_infos"); - exit(5); - } + if (sysctl(mib, 4, NULL, count, NULL, 0) < 0) + err(5, "Unable to get size of kproc_infos"); - processes = (struct kinfo_proc *)malloc(*count); - if(NULL == processes) { - fprintf(stderr, "Out of memory for kproc_infos\n"); - exit(6); - } + processes = malloc(*count); + if (processes == NULL) + err(6, "Out of memory for kproc_infos"); - if(0 > sysctl(mib, 4, processes, count, NULL, 0)) { - fprintf(stderr, "Unable to get kinfo_procs\n"); - exit(7); - } + if (sysctl(mib, 4, processes, count, NULL, 0) < 0) + err(7, "Unable to get kinfo_procs"); *count = *count / sizeof(struct kinfo_proc); diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index cc51a7cd..4abe7b8c 100644 --- a/freebsd/FreeBSDProcessList.c +++ b/freebsd/FreeBSDProcessList.c @@ -115,7 +115,7 @@ char* FreeBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, in for (int i = 0; argv[i]; i++) { len += strlen(argv[i]) + 1; } - char* comm = malloc(len * sizeof(char)); + char* comm = malloc(len); char* at = comm; *basenameEnd = 0; for (int i = 0; argv[i]; i++) { From a9a5a539cf59cb81d2a3da610b0d1ff56c1247cc Mon Sep 17 00:00:00 2001 From: Michael McConville Date: Fri, 18 Sep 2015 00:46:48 -0400 Subject: [PATCH 2/6] (Very) initial working OpenBSD port --- Makefile.am | 8 ++ StringUtils.c | 2 +- configure.ac | 8 ++ htop.c | 13 +- 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 | 249 ++++++++++++++++++++++++++++++++++ openbsd/OpenBSDProcessList.h | 44 ++++++ openbsd/Platform.c | 254 +++++++++++++++++++++++++++++++++++ openbsd/Platform.h | 63 +++++++++ 14 files changed, 984 insertions(+), 9 deletions(-) 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 diff --git a/Makefile.am b/Makefile.am index 8fa38197..b54b9a91 100644 --- a/Makefile.am +++ b/Makefile.am @@ -51,6 +51,14 @@ myhtopplatheaders = freebsd/Platform.h freebsd/FreeBSDProcessList.h \ freebsd/FreeBSDProcess.h freebsd/FreeBSDCRT.h freebsd/Battery.h endif +if HTOP_OPENBSD +myhtopplatsources = openbsd/Platform.c openbsd/OpenBSDProcessList.c \ +openbsd/OpenBSDProcess.c openbsd/OpenBSDCRT.c openbsd/Battery.c + +myhtopplatheaders = openbsd/Platform.h openbsd/OpenBSDProcessList.h \ +openbsd/OpenBSDProcess.h openbsd/OpenBSDCRT.h openbsd/Battery.h +endif + if HTOP_DARWIN htop_LDFLAGS += -framework IOKit -framework CoreFoundation myhtopplatsources = darwin/Platform.c darwin/DarwinProcess.c \ diff --git a/StringUtils.c b/StringUtils.c index 54a61584..ec123e9f 100644 --- a/StringUtils.c +++ b/StringUtils.c @@ -55,7 +55,7 @@ inline int String_eq(const char* s1, const char* s2) { char** String_split(const char* s, char sep, int* n) { *n = 0; const int rate = 10; - char** out = calloc(rate, sizeof(char**)); + char** out = calloc(rate, sizeof(char*)); int ctr = 0; int blocks = rate; char* where; diff --git a/configure.ac b/configure.ac index 13b09a6b..f865cbf2 100644 --- a/configure.ac +++ b/configure.ac @@ -33,6 +33,9 @@ case "$target" in *freebsd*) my_htop_platform=freebsd ;; +*openbsd*) + my_htop_platform=openbsd + ;; *darwin*) my_htop_platform=darwin ;; @@ -168,6 +171,10 @@ if test "$my_htop_platform" = "freebsd"; then AC_CHECK_LIB([kvm], [kvm_open], [], [missing_libraries="$missing_libraries libkvm"]) fi +if test "$my_htop_platform" = "openbsd"; then + AC_CHECK_LIB([kvm], [kvm_open], [], [missing_libraries="$missing_libraries libkvm"]) +fi + AC_ARG_ENABLE(native_affinity, [AC_HELP_STRING([--enable-native-affinity], [enable native sched_setaffinity and sched_getaffinity for affinity support, disables hwloc])], ,enable_native_affinity="yes") if test "x$enable_native_affinity" = xyes -a "x$cross_compiling" = xno; then AC_MSG_CHECKING([for usable sched_setaffinity]) @@ -211,6 +218,7 @@ AC_DEFINE_UNQUOTED(COPYRIGHT, "(C) 2004-$year Hisham Muhammad", [Copyright messa # ---------------------------------------------------------------------- AM_CONDITIONAL([HTOP_LINUX], [test "$my_htop_platform" = linux]) AM_CONDITIONAL([HTOP_FREEBSD], [test "$my_htop_platform" = freebsd]) +AM_CONDITIONAL([HTOP_OPENBSD], [test "$my_htop_platform" = openbsd]) AM_CONDITIONAL([HTOP_DARWIN], [test "$my_htop_platform" = darwin]) AM_CONDITIONAL([HTOP_UNSUPPORTED], [test "$my_htop_platform" = unsupported]) AC_SUBST(my_htop_platform) diff --git a/htop.c b/htop.c index a031cde3..32c0c510 100644 --- a/htop.c +++ b/htop.c @@ -108,24 +108,21 @@ static CommandLineSettings parseArguments(int argc, char** argv) { } flags.sortKey = ColumnsPanel_fieldNameToIndex(optarg); if (flags.sortKey == -1) { - fprintf(stderr, "Error: invalid column \"%s\".\n", optarg); - exit(1); - } + errx(1, stderr, "Error: invalid column \"%s\".\n", optarg); + } break; case 'd': if (sscanf(optarg, "%16d", &(flags.delay)) == 1) { if (flags.delay < 1) flags.delay = 1; if (flags.delay > 100) flags.delay = 100; } else { - fprintf(stderr, "Error: invalid delay value \"%s\".\n", optarg); - exit(1); + errx(1, stderr, "Error: invalid delay value \"%s\".\n", optarg); } break; case 'u': if (!Action_setUserOnly(optarg, &(flags.userId))) { - fprintf(stderr, "Error: invalid user \"%s\".\n", optarg); - exit(1); - } + errx(1, stderr, "Error: invalid user \"%s\".\n", optarg); + } break; case 'C': flags.useColors = false; diff --git a/openbsd/Battery.c b/openbsd/Battery.c new file mode 100644 index 00000000..f9d0969a --- /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 00000000..b1a4982e --- /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 00000000..552ca30d --- /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 mantainer!\n\n"); + abort(); +} + diff --git a/openbsd/OpenBSDCRT.h b/openbsd/OpenBSDCRT.h new file mode 100644 index 00000000..3af9787d --- /dev/null +++ b/openbsd/OpenBSDCRT.h @@ -0,0 +1,16 @@ +/* Do not edit this file. It was automatically generated. */ + +#ifndef HEADER_UnsupportedCRT +#define HEADER_UnsupportedCRT +/* +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 00000000..f9c90842 --- /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 = calloc(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 00000000..ba55e5ea --- /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 00000000..b4e3013c --- /dev/null +++ b/openbsd/OpenBSDProcessList.c @@ -0,0 +1,249 @@ +/* +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; + +}*/ + +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; + OpenBSDProcessList* fpl = calloc(1, sizeof(OpenBSDProcessList)); + ProcessList* pl = (ProcessList*) fpl; + size_t size = sizeof(pl->cpuCount); + + ProcessList_init(pl, Class(OpenBSDProcess), usersTable, pidWhiteList, userId); + pl->cpuCount = 1; // default to 1 on sysctl() error + (void)sysctl(mib, 2, &pl->cpuCount, &size, NULL, 0); + fpl->cpus = realloc(fpl->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++) { + fpl->cpus[i].totalTime = 1; + fpl->cpus[i].totalPeriod = 1; + } + + pageSizeKb = PAGE_SIZE_KB; + + // XXX: last arg should eventually be an errbuf + fpl->kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL); + assert(fpl->kd); + + return pl; +} + +void ProcessList_delete(ProcessList* this) { + const OpenBSDProcessList* fpl = (OpenBSDProcessList*) this; + if (fpl->kd) kvm_close(fpl->kd); + + 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* fpl = (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(fpl->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 *str, *buf, **argv; + size_t cpsz; + size_t len = 500; + + argv = kvm_getargv(kd, kproc, 500); + + if (argv == NULL) + err(1, "kvm call failed"); + + str = buf = malloc(len+1); + if (str == NULL) + err(1, "out of memory"); + + while (*argv != NULL) { + cpsz = MIN(len, strlen(*argv)); + strncpy(buf, *argv, cpsz); + buf += cpsz; + len -= cpsz; + argv++; + if (len > 0) { + *buf = ' '; + buf++; + len--; + } + } + + *buf = '\0'; + return str; +} + +/* + * 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* fpl = (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(fpl->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(fpl->kd, kproc, &proc->basenameOffset); + } else { + if (settings->updateProcessNames) { + free(proc->comm); + proc->comm = OpenBSDProcessList_readProcessName(fpl->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 = MAX(MIN(getpcpu(kproc), this->cpuCount*100.0), 0.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++; + if (proc->state == 'R') + this->runningTasks++; + proc->updated = true; + } +} diff --git a/openbsd/OpenBSDProcessList.h b/openbsd/OpenBSDProcessList.h new file mode 100644 index 00000000..567dd25e --- /dev/null +++ b/openbsd/OpenBSDProcessList.h @@ -0,0 +1,44 @@ +/* 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; + + + +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 00000000..675a5191 --- /dev/null +++ b/openbsd/Platform.c @@ -0,0 +1,254 @@ +/* +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 "OpenBSDProcess.h" +#include "OpenBSDProcessList.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*{ +#include "Action.h" +#include "BatteryMeter.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; + +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) { + puts("err!"); + //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 12.34; + } +} + +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 = calloc(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 +} diff --git a/openbsd/Platform.h b/openbsd/Platform.h new file mode 100644 index 00000000..f44fea2d --- /dev/null +++ b/openbsd/Platform.h @@ -0,0 +1,63 @@ +/* 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" + +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; + +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); + +#endif From e2bbd5cfa45e02c00ba932e2cd519382b203157a Mon Sep 17 00:00:00 2001 From: Michael McConville Date: Sat, 19 Sep 2015 12:08:34 -0400 Subject: [PATCH 3/6] Change some tabs to three spaces --- openbsd/OpenBSDProcess.c | 200 +++++++++++++++++------------------ openbsd/OpenBSDProcessList.c | 61 +++++------ openbsd/Platform.c | 158 +++++++++++++-------------- 3 files changed, 210 insertions(+), 209 deletions(-) diff --git a/openbsd/OpenBSDProcess.c b/openbsd/OpenBSDProcess.c index f9c90842..65caf72b 100644 --- a/openbsd/OpenBSDProcess.c +++ b/openbsd/OpenBSDProcess.c @@ -49,130 +49,130 @@ ProcessClass OpenBSDProcess_class = { ProcessFieldData Process_fields[] = { [0] = { - .name = "", - .title = NULL, - .description = NULL, - .flags = 0, }, + .name = "", + .title = NULL, + .description = NULL, + .flags = 0, }, [PID] = { - .name = "PID", - .title = " PID ", - .description = "Process/thread ID", - .flags = 0, }, + .name = "PID", + .title = " PID ", + .description = "Process/thread ID", + .flags = 0, }, [COMM] = { - .name = "Command", - .title = "Command ", - .description = "Command line", - .flags = 0, }, + .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, }, + .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, }, + .name = "PPID", + .title = " PPID ", + .description = "Parent process ID", + .flags = 0, }, [PGRP] = { - .name = "PGRP", - .title = " PGRP ", - .description = "Process group ID", - .flags = 0, }, + .name = "PGRP", + .title = " PGRP ", + .description = "Process group ID", + .flags = 0, }, [SESSION] = { - .name = "SESSION", - .title = " SESN ", - .description = "Process's session ID", - .flags = 0, }, + .name = "SESSION", + .title = " SESN ", + .description = "Process's session ID", + .flags = 0, }, [TTY_NR] = { - .name = "TTY_NR", - .title = " TTY ", - .description = "Controlling terminal", - .flags = 0, }, + .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, }, + .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, }, + .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, }, + .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, }, + .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, }, + .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, }, + .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, }, + .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, }, + .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, }, + .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, }, + .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, }, + .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, }, + .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, }, + .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, }, + .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, }, + .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, }, + .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, }, + .name = "*** report bug! ***", + .title = NULL, + .description = NULL, + .flags = 0, }, }; ProcessPidColumn Process_pidColumns[] = { diff --git a/openbsd/OpenBSDProcessList.c b/openbsd/OpenBSDProcessList.c index b4e3013c..c51a4f20 100644 --- a/openbsd/OpenBSDProcessList.c +++ b/openbsd/OpenBSDProcessList.c @@ -60,7 +60,7 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui size = sizeof(fscale); if (sysctl(fmib, 2, &fscale, &size, NULL, 0) < 0) - err(1, "fscale sysctl call failed"); + err(1, "fscale sysctl call failed"); for (i = 0; i < pl->cpuCount; i++) { fpl->cpus[i].totalTime = 1; @@ -90,14 +90,14 @@ static inline void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) { size_t size = sizeof(uvmexp); if (sysctl(uvmexp_mib, 2, &uvmexp, &size, NULL, 0) < 0) { - err(1, "uvmexp sysctl call failed"); + err(1, "uvmexp sysctl call failed"); } //kb_pagesize = uvmexp.pagesize / 1024; pl->usedMem = uvmexp.active * pageSizeKb; pl->totalMem = uvmexp.npages * pageSizeKb; - /* + /* const OpenBSDProcessList* fpl = (OpenBSDProcessList*) pl; size_t len = sizeof(pl->totalMem); @@ -142,14 +142,14 @@ char *OpenBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, in while (*argv != NULL) { cpsz = MIN(len, strlen(*argv)); strncpy(buf, *argv, cpsz); - buf += cpsz; - len -= cpsz; - argv++; - if (len > 0) { - *buf = ' '; - buf++; - len--; - } + buf += cpsz; + len -= cpsz; + argv++; + if (len > 0) { + *buf = ' '; + buf++; + len--; + } } *buf = '\0'; @@ -160,12 +160,12 @@ char *OpenBSDProcessList_readProcessName(kvm_t* kd, struct kinfo_proc* kproc, in * Taken from OpenBSD's ps(1). */ double getpcpu(const struct kinfo_proc *kp) { - if (fscale == 0) - return (0.0); + if (fscale == 0) + return (0.0); -#define fxtofl(fixpt) ((double)(fixpt) / fscale) +#define fxtofl(fixpt) ((double)(fixpt) / fscale) - return (100.0 * fxtofl(kp->p_pctcpu)); + return (100.0 * fxtofl(kp->p_pctcpu)); } void ProcessList_goThroughEntries(ProcessList* this) { @@ -194,7 +194,7 @@ void ProcessList_goThroughEntries(ProcessList* this) { fp = (OpenBSDProcess*) proc; proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) - || (hideUserlandThreads && Process_isUserlandThread(proc))); + || (hideUserlandThreads && Process_isUserlandThread(proc))); if (!preExisting) { proc->ppid = kproc->p_ppid; @@ -217,24 +217,24 @@ void ProcessList_goThroughEntries(ProcessList* this) { 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 = MAX(MIN(getpcpu(kproc), this->cpuCount*100.0), 0.0); + proc->percent_mem = (proc->m_resident * PAGE_SIZE_KB) / (double)(this->totalMem) * 100.0; + proc->percent_cpu = MAX(MIN(getpcpu(kproc), this->cpuCount*100.0), 0.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->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 = '?'; + 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)) { @@ -242,8 +242,9 @@ void ProcessList_goThroughEntries(ProcessList* this) { } this->totalTasks++; - if (proc->state == 'R') + if (proc->state == 'R') { this->runningTasks++; + } proc->updated = true; } } diff --git a/openbsd/Platform.c b/openbsd/Platform.c index 675a5191..1b02450a 100644 --- a/openbsd/Platform.c +++ b/openbsd/Platform.c @@ -60,34 +60,34 @@ static int64_t old_v[MAXCPU][5]; * 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; + int64_t change, total_change, *dp, half_total; + int i; - /* initialization */ - total_change = 0; - dp = diffs; + /* 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++; - } + /* 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; + /* 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); + /* 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); + /* 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 }; @@ -157,40 +157,40 @@ int Platform_getMaxPid() { } double Platform_setCPUValues(Meter* this, int cpu) { - int i; - double perc; + 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) { - puts("err!"); - //return 0.; - } + 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) { + puts("err!"); + //return 0.; + } - // XXX: why? - cpuData->totalPeriod = 1; + // XXX: why? + cpuData->totalPeriod = 1; - percentages(CPUSTATES, diff_v, new_v, - (int64_t *)old_v[cpu-1], scratch_v); + 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.; - } + for (i = 0; i < CPUSTATES; i++) { + old_v[cpu-1][i] = new_v[i]; + v[i] = diff_v[i] / 10.; + } - Meter_setItems(this, 4); + Meter_setItems(this, 4); - perc = v[0] + v[1] + v[2] + v[3]; + perc = v[0] + v[1] + v[2] + v[3]; - if (perc <= 100. && perc >= 0.) { - return perc; - } else { - return 12.34; - } + if (perc <= 100. && perc >= 0.) { + return perc; + } else { + return 12.34; + } } void Platform_setMemoryValues(Meter* this) { @@ -212,41 +212,41 @@ void Platform_setMemoryValues(Meter* this) { * 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; - } + 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 = calloc(nswap, sizeof(*swdev)); - if (swdev == NULL) { - return; - } + swdev = calloc(nswap, sizeof(*swdev)); + if (swdev == NULL) { + return; + } - rnswap = swapctl(SWAP_STATS, swdev, nswap); - if (rnswap == -1) { - free(swdev); - return; - } + rnswap = swapctl(SWAP_STATS, swdev, nswap); + if (rnswap == -1) { + free(swdev); + return; + } - // if rnswap != nswap, then what? + // 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)); - } - } + /* 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; + this->total = pl->totalSwap = total; + this->values[0] = pl->usedSwap = used; - free(swdev); + free(swdev); } void Platform_setTasksValues(Meter* this) { From 571cbc0aa1138891f2233db681531d132b31b88f Mon Sep 17 00:00:00 2001 From: Michael McConville Date: Sat, 19 Sep 2015 12:15:26 -0400 Subject: [PATCH 4/6] Change more fprintf(stderr, ...); exit(...); to err[x](...). Tweak a few existing ones and fix some style. --- darwin/DarwinProcessList.c | 11 ++++------- htop.c | 7 +++---- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/darwin/DarwinProcessList.c b/darwin/DarwinProcessList.c index 9dbe4c89..2260f833 100644 --- a/darwin/DarwinProcessList.c +++ b/darwin/DarwinProcessList.c @@ -41,16 +41,14 @@ void ProcessList_getHostInfo(host_basic_info_data_t *p) { mach_msg_type_number_t info_size = HOST_BASIC_INFO_COUNT; if(0 != host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)p, &info_size)) { - fprintf(stderr, "Unable to retrieve host info\n"); - exit(2); + err(2, "Unable to retrieve host info\n"); } } void ProcessList_freeCPULoadInfo(processor_cpu_load_info_t *p) { if(NULL != p && NULL != *p) { if(0 != munmap(*p, vm_page_size)) { - fprintf(stderr, "Unable to free old CPU load information\n"); - exit(8); + err(8, "Unable to free old CPU load information\n"); } } @@ -63,8 +61,7 @@ unsigned ProcessList_allocateCPULoadInfo(processor_cpu_load_info_t *p) { // TODO Improving the accuracy of the load counts woule help a lot. if(0 != host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &cpu_count, (processor_info_array_t *)p, &info_size)) { - fprintf(stderr, "Unable to retrieve CPU info\n"); - exit(4); + err(4, "Unable to retrieve CPU info\n"); } return cpu_count; @@ -91,7 +88,7 @@ struct kinfo_proc *ProcessList_getKInfoProcs(size_t *count) { processes = malloc(*count); if (processes == NULL) - err(6, "Out of memory for kproc_infos"); + errx(6, "Out of memory for kproc_infos"); if (sysctl(mib, 4, processes, count, NULL, 0) < 0) err(7, "Unable to get kinfo_procs"); diff --git a/htop.c b/htop.c index 32c0c510..538d1094 100644 --- a/htop.c +++ b/htop.c @@ -132,11 +132,11 @@ static CommandLineSettings parseArguments(int argc, char** argv) { char* saveptr; char* pid = strtok_r(argCopy, ",", &saveptr); - if( !flags.pidWhiteList ) { + if(!flags.pidWhiteList) { flags.pidWhiteList = Hashtable_new(8, false); } - while( pid ) { + while(pid) { unsigned int num_pid = atoi(pid); Hashtable_put(flags.pidWhiteList, num_pid, (void *) 1); pid = strtok_r(NULL, ",", &saveptr); @@ -176,8 +176,7 @@ int main(int argc, char** argv) { #ifdef HAVE_PROC if (access(PROCDIR, R_OK) != 0) { - fprintf(stderr, "Error: could not read procfs (compiled to look in %s).\n", PROCDIR); - exit(1); + errx(1, "Error: could not read procfs (compiled to look in %s).\n", PROCDIR); } #endif From ad1a0ad08d4b91852a465a0913618044c7a79873 Mon Sep 17 00:00:00 2001 From: Michael McConville Date: Sat, 19 Sep 2015 12:21:22 -0400 Subject: [PATCH 5/6] Replace some remaining tabs --- CRT.c | 4 ++-- ListItem.c | 4 ++-- htop.c | 4 ++-- openbsd/OpenBSDProcessList.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CRT.c b/CRT.c index 8e3311ed..48182200 100644 --- a/CRT.c +++ b/CRT.c @@ -609,9 +609,9 @@ void CRT_init(int delay, int colorScheme) { CRT_treeStr = #ifdef HAVE_LIBNCURSESW - CRT_utf8 ? CRT_treeStrUtf8 : + CRT_utf8 ? CRT_treeStrUtf8 : #endif - CRT_treeStrAscii; + CRT_treeStrAscii; #if NCURSES_MOUSE_VERSION > 1 mousemask(BUTTON1_RELEASED | BUTTON4_PRESSED | BUTTON5_PRESSED, NULL); diff --git a/ListItem.c b/ListItem.c index 07788e73..a675327d 100644 --- a/ListItem.c +++ b/ListItem.c @@ -44,9 +44,9 @@ static void ListItem_display(Object* cast, RichString* out) { if (this->moving) { RichString_write(out, CRT_colors[DEFAULT_COLOR], #ifdef HAVE_LIBNCURSESW - CRT_utf8 ? "↕ " : + CRT_utf8 ? "↕ " : #endif - "+ "); + "+ "); } else { RichString_prune(out); } diff --git a/htop.c b/htop.c index 538d1094..a5e75660 100644 --- a/htop.c +++ b/htop.c @@ -109,7 +109,7 @@ static CommandLineSettings parseArguments(int argc, char** argv) { flags.sortKey = ColumnsPanel_fieldNameToIndex(optarg); if (flags.sortKey == -1) { errx(1, stderr, "Error: invalid column \"%s\".\n", optarg); - } + } break; case 'd': if (sscanf(optarg, "%16d", &(flags.delay)) == 1) { @@ -122,7 +122,7 @@ static CommandLineSettings parseArguments(int argc, char** argv) { case 'u': if (!Action_setUserOnly(optarg, &(flags.userId))) { errx(1, stderr, "Error: invalid user \"%s\".\n", optarg); - } + } break; case 'C': flags.useColors = false; diff --git a/openbsd/OpenBSDProcessList.c b/openbsd/OpenBSDProcessList.c index c51a4f20..e003bde0 100644 --- a/openbsd/OpenBSDProcessList.c +++ b/openbsd/OpenBSDProcessList.c @@ -244,7 +244,7 @@ void ProcessList_goThroughEntries(ProcessList* this) { this->totalTasks++; if (proc->state == 'R') { this->runningTasks++; - } + } proc->updated = true; } } From 6a21d2f3a6d1f4735e5a2a2145eb78309f4d9073 Mon Sep 17 00:00:00 2001 From: Michael McConville Date: Sat, 19 Sep 2015 12:45:22 -0400 Subject: [PATCH 6/6] Fix enumeratoin of on-CPU processes in OpenBSD --- openbsd/OpenBSDProcessList.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openbsd/OpenBSDProcessList.c b/openbsd/OpenBSDProcessList.c index e003bde0..10ba2d62 100644 --- a/openbsd/OpenBSDProcessList.c +++ b/openbsd/OpenBSDProcessList.c @@ -242,7 +242,8 @@ void ProcessList_goThroughEntries(ProcessList* this) { } this->totalTasks++; - if (proc->state == 'R') { + // SRUN ('R') means runnable, not running + if (proc->state == 'P') { this->runningTasks++; } proc->updated = true;