mirror of https://github.com/xzeldon/htop.git
(Very) initial working OpenBSD port
This commit is contained in:
parent
445222e48c
commit
a9a5a539cf
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
13
htop.c
13
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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 <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
/*{
|
||||
|
||||
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));
|
||||
}
|
|
@ -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
|
|
@ -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 <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/user.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
/*{
|
||||
|
||||
#include <kvm.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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 <kvm.h>
|
||||
|
||||
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
|
|
@ -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 <sys/sched.h>
|
||||
#include <uvm/uvmexp.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/swap.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <time.h>
|
||||
|
||||
/*{
|
||||
#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 <tholo@sigmasoft.com>
|
||||
* 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
|
||||
}
|
|
@ -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 <tholo@sigmasoft.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Taken almost directly from OpenBSD's top(1)
|
||||
*/
|
||||
void Platform_setSwapValues(Meter* this);
|
||||
|
||||
void Platform_setTasksValues(Meter* this);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue