summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Action.c11
-rw-r--r--Affinity.c19
-rw-r--r--Affinity.h9
-rw-r--r--CRT.c8
-rw-r--r--CRT.h2
-rw-r--r--InfoScreen.c1
-rw-r--r--Makefile.am2
-rw-r--r--MetersPanel.c5
-rw-r--r--Panel.c2
-rw-r--r--Process.c5
-rw-r--r--ProcessList.c10
-rw-r--r--ProcessList.h4
-rw-r--r--ScreenManager.c28
-rwxr-xr-xautogen.sh14
-rw-r--r--configure.ac12
-rw-r--r--darwin/DarwinProcess.c146
-rw-r--r--darwin/DarwinProcess.h9
-rw-r--r--darwin/DarwinProcessList.c4
-rw-r--r--freebsd/FreeBSDProcess.c4
-rw-r--r--freebsd/FreeBSDProcessList.c25
-rw-r--r--freebsd/FreeBSDProcessList.h1
-rw-r--r--freebsd/Platform.c11
-rw-r--r--htop.c196
-rw-r--r--linux/LinuxProcess.c16
-rw-r--r--linux/LinuxProcessList.c53
-rw-r--r--openbsd/OpenBSDProcessList.c104
-rw-r--r--openbsd/OpenBSDProcessList.h14
-rwxr-xr-xtest_spec.lua146
-rw-r--r--unsupported/Platform.c44
-rw-r--r--unsupported/Platform.h12
30 files changed, 393 insertions, 524 deletions
diff --git a/Action.c b/Action.c
index 4ef06f48..3fc22177 100644
--- a/Action.c
+++ b/Action.c
@@ -271,7 +271,7 @@ static Htop_Reaction actionQuit() {
static Htop_Reaction actionSetAffinity(State* st) {
if (st->pl->cpuCount == 1)
return HTOP_OK;
-#if (HAVE_LIBHWLOC || HAVE_NATIVE_AFFINITY)
+#if (HAVE_LIBHWLOC || HAVE_LINUX_AFFINITY)
Panel* panel = st->panel;
Process* p = (Process*) Panel_getSelected(panel);
@@ -387,6 +387,7 @@ static struct { const char* key; const char* info; } helpLeft[] = {
{ .key = " F3 /: ", .info = "incremental name search" },
{ .key = " F4 \\: ",.info = "incremental name filtering" },
{ .key = " F5 t: ", .info = "tree view" },
+ { .key = " p: ", .info = "toggle program path" },
{ .key = " u: ", .info = "show processes of a single user" },
{ .key = " H: ", .info = "hide/show user process threads" },
{ .key = " K: ", .info = "hide/show kernel threads" },
@@ -405,11 +406,11 @@ static struct { const char* key; const char* info; } helpRight[] = {
{ .key = " F9 k: ", .info = "kill process/tagged processes" },
{ .key = " F7 ]: ", .info = "higher priority (root only)" },
{ .key = " F8 [: ", .info = "lower priority (+ nice)" },
-#if (HAVE_LIBHWLOC || HAVE_NATIVE_AFFINITY)
+#if (HAVE_LIBHWLOC || HAVE_LINUX_AFFINITY)
{ .key = " a: ", .info = "set CPU affinity" },
#endif
{ .key = " e: ", .info = "show process environment" },
- { .key = " i: ", .info = "set IO prority" },
+ { .key = " i: ", .info = "set IO priority" },
{ .key = " l: ", .info = "list open files with lsof" },
{ .key = " s: ", .info = "trace syscalls with strace" },
{ .key = " ", .info = "" },
@@ -479,8 +480,8 @@ static Htop_Reaction actionHelp(State* st) {
for (int i = 0; helpLeft[i].key; i++) { mvaddstr(9+i, 0, helpLeft[i].key); }
for (int i = 0; helpRight[i].key; i++) { mvaddstr(9+i, 40, helpRight[i].key); }
attrset(CRT_colors[PROCESS_THREAD]);
- mvaddstr(15, 32, "threads");
- mvaddstr(16, 26, "threads");
+ mvaddstr(16, 32, "threads");
+ mvaddstr(17, 26, "threads");
attrset(CRT_colors[DEFAULT_COLOR]);
attrset(CRT_colors[HELP_BOLD]);
diff --git a/Affinity.c b/Affinity.c
index 471e1028..c928fec1 100644
--- a/Affinity.c
+++ b/Affinity.c
@@ -10,8 +10,13 @@ in the source distribution for its full text.
#include <stdlib.h>
#ifdef HAVE_LIBHWLOC
-#include <hwloc/linux.h>
-#elif HAVE_NATIVE_AFFINITY
+#include <hwloc.h>
+#if __linux__
+#define HTOP_HWLOC_CPUBIND_FLAG HWLOC_CPUBIND_THREAD
+#else
+#define HTOP_HWLOC_CPUBIND_FLAG HWLOC_CPUBIND_PROCESS
+#endif
+#elif HAVE_LINUX_AFFINITY
#include <sched.h>
#endif
@@ -55,7 +60,7 @@ void Affinity_add(Affinity* this, int id) {
Affinity* Affinity_get(Process* proc, ProcessList* pl) {
hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
- bool ok = (hwloc_linux_get_tid_cpubind(pl->topology, proc->pid, cpuset) == 0);
+ bool ok = (hwloc_get_proc_cpubind(pl->topology, proc->pid, cpuset, HTOP_HWLOC_CPUBIND_FLAG) == 0);
Affinity* affinity = NULL;
if (ok) {
affinity = Affinity_new(pl);
@@ -76,15 +81,15 @@ Affinity* Affinity_get(Process* proc, ProcessList* pl) {
bool Affinity_set(Process* proc, Affinity* this) {
hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
- for (int i = 0; i < affinity->used; i++) {
- hwloc_bitmap_set(cpuset, affinity->cpus[i]);
+ for (int i = 0; i < this->used; i++) {
+ hwloc_bitmap_set(cpuset, this->cpus[i]);
}
- bool ok = (hwloc_linux_set_tid_cpubind(this->pl->topology, proc->pid, cpuset) == 0);
+ bool ok = (hwloc_set_proc_cpubind(this->pl->topology, proc->pid, cpuset, HTOP_HWLOC_CPUBIND_FLAG) == 0);
hwloc_bitmap_free(cpuset);
return ok;
}
-#elif HAVE_NATIVE_AFFINITY
+#elif HAVE_LINUX_AFFINITY
Affinity* Affinity_get(Process* proc, ProcessList* pl) {
cpu_set_t cpuset;
diff --git a/Affinity.h b/Affinity.h
index 8f8dde9c..fd2c599e 100644
--- a/Affinity.h
+++ b/Affinity.h
@@ -10,7 +10,12 @@ in the source distribution for its full text.
*/
#ifdef HAVE_LIBHWLOC
-#elif HAVE_NATIVE_AFFINITY
+#if __linux__
+#define HTOP_HWLOC_CPUBIND_FLAG HWLOC_CPUBIND_THREAD
+#else
+#define HTOP_HWLOC_CPUBIND_FLAG HWLOC_CPUBIND_PROCESS
+#endif
+#elif HAVE_LINUX_AFFINITY
#endif
#include "Process.h"
@@ -36,7 +41,7 @@ Affinity* Affinity_get(Process* proc, ProcessList* pl);
bool Affinity_set(Process* proc, Affinity* this);
-#elif HAVE_NATIVE_AFFINITY
+#elif HAVE_LINUX_AFFINITY
Affinity* Affinity_get(Process* proc, ProcessList* pl);
diff --git a/CRT.c b/CRT.c
index 2ab20c2d..673e9512 100644
--- a/CRT.c
+++ b/CRT.c
@@ -125,6 +125,8 @@ void CRT_fatalError(const char* note) __attribute__ ((noreturn));
void CRT_handleSIGSEGV(int sgn);
+#define KEY_ALT(x) KEY_F(60) + (x - 'A')
+
}*/
const char *CRT_treeStrAscii[TREE_STR_COUNT] = {
@@ -587,6 +589,11 @@ void CRT_init(int delay, int colorScheme) {
define_key("\033[13~", KEY_F(3));
define_key("\033[14~", KEY_F(4));
define_key("\033[17;2~", KEY_F(18));
+ char sequence[3] = "\033a";
+ for (char c = 'a'; c <= 'z'; c++) {
+ sequence[1] = c;
+ define_key(sequence, KEY_ALT('A' + (c - 'a')));
+ }
}
#ifndef DEBUG
signal(11, CRT_handleSIGSEGV);
@@ -618,6 +625,7 @@ void CRT_init(int delay, int colorScheme) {
#else
mousemask(BUTTON1_RELEASED, NULL);
#endif
+
}
void CRT_done() {
diff --git a/CRT.h b/CRT.h
index 5aac2171..ba10699e 100644
--- a/CRT.h
+++ b/CRT.h
@@ -115,6 +115,8 @@ void CRT_fatalError(const char* note) __attribute__ ((noreturn));
void CRT_handleSIGSEGV(int sgn);
+#define KEY_ALT(x) KEY_F(60) + (x - 'A')
+
extern const char *CRT_treeStrAscii[TREE_STR_COUNT];
diff --git a/InfoScreen.c b/InfoScreen.c
index 7ce9ca6a..a6dd55ad 100644
--- a/InfoScreen.c
+++ b/InfoScreen.c
@@ -116,6 +116,7 @@ void InfoScreen_run(InfoScreen* this) {
if (this->inc->active)
move(LINES-1, CRT_cursorX);
+ ESCDELAY = 25;
int ch = getch();
if (ch == ERR) {
diff --git a/Makefile.am b/Makefile.am
index 8b316270..19c9eb47 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -95,7 +95,7 @@ debug:
$(MAKE) all CFLAGS="" AM_CPPFLAGS="-ggdb -DDEBUG"
coverage:
- $(MAKE) all CFLAGS="" AM_CPPFLAGS="-fprofile-arcs -ftest-coverage -DDEBUG" AM_LDFLAGS="-lgcov"
+ $(MAKE) all CFLAGS="" AM_CPPFLAGS="-fprofile-arcs -ftest-coverage -DDEBUG" LDFLAGS="-lgcov"
.c.h:
@srcdir@/scripts/MakeHeader.py $<
diff --git a/MetersPanel.c b/MetersPanel.c
index bdbe83ee..302b6d1a 100644
--- a/MetersPanel.c
+++ b/MetersPanel.c
@@ -50,7 +50,10 @@ static void MetersPanel_delete(Object* object) {
void MetersPanel_setMoving(MetersPanel* this, bool moving) {
Panel* super = (Panel*) this;
this->moving = moving;
- ((ListItem*)Panel_getSelected(super))->moving = moving;
+ ListItem* selected = (ListItem*)Panel_getSelected(super);
+ if (selected) {
+ selected->moving = moving;
+ }
if (!moving) {
Panel_setSelectionColor(super, CRT_colors[PANEL_SELECTION_FOCUS]);
Panel_setDefaultBar(super);
diff --git a/Panel.c b/Panel.c
index dd94ceae..1c45714f 100644
--- a/Panel.c
+++ b/Panel.c
@@ -441,7 +441,7 @@ bool Panel_onKey(Panel* this, int key) {
}
// ensure selection within bounds
- if (this->selected < 0) {
+ if (this->selected < 0 || size == 0) {
this->selected = 0;
this->needsRedraw = true;
} else if (this->selected >= size) {
diff --git a/Process.c b/Process.c
index 07ecba15..dddd7fcd 100644
--- a/Process.c
+++ b/Process.c
@@ -335,7 +335,10 @@ void Process_outputRate(RichString* str, char* buffer, int n, double rate, int c
largeNumberColor = CRT_colors[PROCESS];
processMegabytesColor = CRT_colors[PROCESS];
}
- if (rate < ONE_K) {
+ if (rate == -1) {
+ int len = snprintf(buffer, n, " no perm ");
+ RichString_appendn(str, CRT_colors[PROCESS_SHADOW], buffer, len);
+ } else if (rate < ONE_K) {
int len = snprintf(buffer, n, "%7.2f B/s ", rate);
RichString_appendn(str, processColor, buffer, len);
} else if (rate < ONE_K * ONE_K) {
diff --git a/ProcessList.c b/ProcessList.c
index 5f5151f6..a49b4f12 100644
--- a/ProcessList.c
+++ b/ProcessList.c
@@ -22,6 +22,10 @@ in the source distribution for its full text.
#include "Process.h"
#include "Settings.h"
+#ifdef HAVE_LIBHWLOC
+#include <hwloc.h>
+#endif
+
#ifndef MAX_NAME
#define MAX_NAME 128
#endif
@@ -104,6 +108,11 @@ ProcessList* ProcessList_init(ProcessList* this, ObjectClass* klass, UsersTable*
}
void ProcessList_done(ProcessList* this) {
+#ifdef HAVE_LIBHWLOC
+ if (this->topologyOk) {
+ hwloc_topology_destroy(this->topology);
+ }
+#endif
Hashtable_delete(this->processTable);
Vector_delete(this->processes);
Vector_delete(this->processes2);
@@ -307,6 +316,7 @@ void ProcessList_scan(ProcessList* this) {
for (int i = 0; i < Vector_size(this->processes); i++) {
Process* p = (Process*) Vector_get(this->processes, i);
p->updated = false;
+ p->show = true;
}
this->totalTasks = 0;
diff --git a/ProcessList.h b/ProcessList.h
index f96481ea..572d4843 100644
--- a/ProcessList.h
+++ b/ProcessList.h
@@ -16,6 +16,10 @@ in the source distribution for its full text.
#include "Process.h"
#include "Settings.h"
+#ifdef HAVE_LIBHWLOC
+#include <hwloc.h>
+#endif
+
#ifndef MAX_NAME
#define MAX_NAME 128
#endif
diff --git a/ScreenManager.c b/ScreenManager.c
index a33d3420..db3fdee4 100644
--- a/ScreenManager.c
+++ b/ScreenManager.c
@@ -189,6 +189,7 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
}
int prevCh = ch;
+ ESCDELAY = 25;
ch = getch();
HandlerResult result = IGNORED;
@@ -244,28 +245,11 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
redraw = false;
continue;
}
- else if (ch == 27) {
- int ch2 = getch();
- if (ch2 != ERR) {
- switch(ch2)
- {
- case 'h':
- ch = KEY_LEFT;
- break;
- case 'j':
- ch = KEY_DOWN;
- break;
- case 'k':
- ch = KEY_UP;
- break;
- case 'l':
- ch = KEY_RIGHT;
- break;
- default:
- ungetch(ch2);
- break;
- }
- }
+ switch (ch) {
+ case KEY_ALT('H'): ch = KEY_LEFT; break;
+ case KEY_ALT('J'): ch = KEY_DOWN; break;
+ case KEY_ALT('K'): ch = KEY_UP; break;
+ case KEY_ALT('L'): ch = KEY_RIGHT; break;
}
redraw = true;
if (Panel_eventHandlerFn(panelFocus)) {
diff --git a/autogen.sh b/autogen.sh
index a3b71cce..c07e0854 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,15 +1,3 @@
#!/bin/sh
-
-glibtoolize=$(which glibtoolize 2> /dev/null)
-if [ ${#glibtoolize} -gt 0 ]
-then libtoolize=glibtoolize
-else libtoolize=libtoolize
-fi
-
mkdir -p m4
-aclocal -I m4
-autoconf
-autoheader
-$libtoolize --copy --force
-automake --add-missing --copy
-
+autoreconf --install --force
diff --git a/configure.ac b/configure.ac
index 3bd58bce..6073175f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -211,8 +211,8 @@ 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_ARG_ENABLE(linux_affinity, [AC_HELP_STRING([--enable-linux-affinity], [enable Linux sched_setaffinity and sched_getaffinity for affinity support, disables hwloc])], ,enable_linux_affinity="yes")
+if test "x$enable_linux_affinity" = xyes -a "x$cross_compiling" = xno; then
AC_MSG_CHECKING([for usable sched_setaffinity])
AC_RUN_IFELSE([
AC_LANG_PROGRAM([[
@@ -225,17 +225,17 @@ if test "x$enable_native_affinity" = xyes -a "x$cross_compiling" = xno; then
if (errno == ENOSYS) return 1;
]])],
[AC_MSG_RESULT([yes])],
- [enable_native_affinity=no
+ [enable_linux_affinity=no
AC_MSG_RESULT([no])])
fi
-if test "x$enable_native_affinity" = xyes; then
- AC_DEFINE(HAVE_NATIVE_AFFINITY, 1, [Define if native sched_setaffinity and sched_getaffinity are to be used.])
+if test "x$enable_linux_affinity" = xyes; then
+ AC_DEFINE(HAVE_LINUX_AFFINITY, 1, [Define if Linux sched_setaffinity and sched_getaffinity are to be used.])
fi
AC_ARG_ENABLE(hwloc, [AC_HELP_STRING([--enable-hwloc], [enable hwloc support for CPU affinity])],, enable_hwloc="no")
if test "x$enable_hwloc" = xyes
then
- AC_CHECK_LIB([hwloc], [hwloc_linux_get_tid_cpubind], [], [missing_libraries="$missing_libraries libhwloc"])
+ AC_CHECK_LIB([hwloc], [hwloc_get_proc_cpubind], [], [missing_libraries="$missing_libraries libhwloc"])
AC_CHECK_HEADERS([hwloc.h],[:], [missing_headers="$missing_headers $ac_header"])
fi
diff --git a/darwin/DarwinProcess.c b/darwin/DarwinProcess.c
index 9c460469..2bc67448 100644
--- a/darwin/DarwinProcess.c
+++ b/darwin/DarwinProcess.c
@@ -13,6 +13,8 @@ in the source distribution for its full text.
#include <string.h>
#include <stdio.h>
+#include <mach/mach.h>
+
/*{
#include "Settings.h"
#include "DarwinProcessList.h"
@@ -69,7 +71,7 @@ void DarwinProcess_setStartTime(Process *proc, struct extern_proc *ep, time_t no
strftime(proc->starttime_show, 7, ((proc->starttime_ctime > now - 86400) ? "%R " : "%b%d "), &date);
}
-char *DarwinProcess_getCmdLine(struct kinfo_proc* k, int show_args ) {
+char *DarwinProcess_getCmdLine(struct kinfo_proc* k, int* basenameOffset) {
/* This function is from the old Mac version of htop. Originally from ps? */
int mib[3], argmax, nargs, c = 0;
size_t size;
@@ -167,13 +169,7 @@ char *DarwinProcess_getCmdLine(struct kinfo_proc* k, int show_args ) {
/* Save where the argv[0] string starts. */
sp = cp;
- /*
- * Iterate through the '\0'-terminated strings and convert '\0' to ' '
- * until a string is found that has a '=' character in it (or there are
- * no more strings in procargs). There is no way to deterministically
- * know where the command arguments end and the environment strings
- * start, which is why the '=' character is searched for as a heuristic.
- */
+ *basenameOffset = 0;
for ( np = NULL; c < nargs && cp < &procargs[size]; cp++ ) {
if ( *cp == '\0' ) {
c++;
@@ -183,49 +179,11 @@ char *DarwinProcess_getCmdLine(struct kinfo_proc* k, int show_args ) {
}
/* Note location of current '\0'. */
np = cp;
-
- if ( !show_args ) {
- /*
- * Don't convert '\0' characters to ' '.
- * However, we needed to know that the
- * command name was terminated, which we
- * now know.
- */
- break;
+ if (*basenameOffset == 0) {
+ *basenameOffset = cp - sp;
}
}
- }
-#if 0
- /*
- * If eflg is non-zero, continue converting '\0' characters to ' '
- * characters until no more strings that look like environment settings
- * follow.
- */
- if ( ( eflg != 0 )
- && ( ( getuid( ) == 0 )
- || ( k->kp_eproc.e_pcred.p_ruid == getuid( ) ) ) ) {
- for ( ; cp < &procargs[size]; cp++ ) {
- if ( *cp == '\0' ) {
- if ( np != NULL ) {
- if ( &np[1] == cp ) {
- /*
- * Two '\0' characters in a row.
- * This should normally only
- * happen after all the strings
- * have been seen, but in any
- * case, stop parsing.
- */
- break;
- }
- /* Convert previous '\0'. */
- *np = ' ';
- }
- /* Note location of current '\0'. */
- np = cp;
- }
- }
}
-#endif
/*
* sp points to the beginning of the arguments/environment string, and
@@ -235,6 +193,9 @@ char *DarwinProcess_getCmdLine(struct kinfo_proc* k, int show_args ) {
/* Empty or unterminated string. */
goto ERROR_B;
}
+ if (*basenameOffset == 0) {
+ *basenameOffset = np - sp;
+ }
/* Make a copy of the string. */
retval = xStrdup(sp);
@@ -248,7 +209,8 @@ ERROR_B:
free( procargs );
ERROR_A:
retval = xStrdup(k->kp_proc.p_comm);
-
+ *basenameOffset = strlen(retval);
+
return retval;
}
@@ -275,35 +237,22 @@ void DarwinProcess_setFromKInfoProc(Process *proc, struct kinfo_proc *ps, time_t
proc->ppid = ps->kp_eproc.e_ppid;
proc->pgrp = ps->kp_eproc.e_pgid;
proc->session = 0; /* TODO Get the session id */
- proc->tgid = ps->kp_eproc.e_tpgid;
+ proc->tpgid = ps->kp_eproc.e_tpgid;
+ proc->tgid = proc->pid;
proc->st_uid = ps->kp_eproc.e_ucred.cr_uid;
/* e_tdev = (major << 24) | (minor & 0xffffff) */
/* e_tdev == -1 for "no device" */
proc->tty_nr = ps->kp_eproc.e_tdev & 0xff; /* TODO tty_nr is unsigned */
DarwinProcess_setStartTime(proc, ep, now);
-
- /* The command is from the old Mac htop */
- char *slash;
-
- proc->comm = DarwinProcess_getCmdLine(ps, false);
- slash = strrchr(proc->comm, '/');
- proc->basenameOffset = (NULL != slash) ? (slash - proc->comm) : 0;
+ proc->comm = DarwinProcess_getCmdLine(ps, &(proc->basenameOffset));
}
/* Mutable information */
proc->nice = ep->p_nice;
proc->priority = ep->p_priority;
- /* Set the state */
- switch(ep->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;
- default: proc->state = '?'; break;
- }
+ proc->state = (ep->p_stat == SZOMB) ? 'Z' : '?';
/* Make sure the updated flag is set */
proc->updated = true;
@@ -327,8 +276,8 @@ void DarwinProcess_setFromLibprocPidinfo(DarwinProcess *proc, DarwinProcessList
proc->super.time = (pti.pti_total_system + pti.pti_total_user) / 10000000;
proc->super.nlwp = pti.pti_threadnum;
- proc->super.m_size = pti.pti_virtual_size / 1024;
- proc->super.m_resident = pti.pti_resident_size / 1024;
+ proc->super.m_size = pti.pti_virtual_size / 1024 / PAGE_SIZE_KB;
+ proc->super.m_resident = pti.pti_resident_size / 1024 / PAGE_SIZE_KB;
proc->super.majflt = pti.pti_faults;
proc->super.percent_mem = (double)pti.pti_resident_size * 100.0
/ (double)dpl->host_info.max_mem;
@@ -342,3 +291,64 @@ void DarwinProcess_setFromLibprocPidinfo(DarwinProcess *proc, DarwinProcessList
dpl->super.runningTasks += pti.pti_numrunning;
}
}
+
+/*
+ * Scan threads for process state information.
+ * Based on: http://stackoverflow.com/questions/6788274/ios-mac-cpu-usage-for-thread
+ * and https://github.com/max-horvath/htop-osx/blob/e86692e869e30b0bc7264b3675d2a4014866ef46/ProcessList.c
+ */
+void DarwinProcess_scanThreads(DarwinProcess *dp) {
+ Process* proc = (Process*) dp;
+ kern_return_t ret;
+
+ if (proc->state == 'Z') {
+ return;
+ }
+
+ task_t port;
+ ret = task_for_pid(mach_task_self(), proc->pid, &port);
+ if (ret != KERN_SUCCESS) {
+ return;
+ }
+
+ task_info_data_t tinfo;
+ mach_msg_type_number_t task_info_count = TASK_INFO_MAX;
+ ret = task_info(port, TASK_BASIC_INFO, (task_info_t) tinfo, &task_info_count);
+ if (ret != KERN_SUCCESS) {
+ return;
+ }
+
+ thread_array_t thread_list;
+ mach_msg_type_number_t thread_count;
+ ret = task_threads(port, &thread_list, &thread_count);
+ if (ret != KERN_SUCCESS) {
+ mach_port_deallocate(mach_task_self(), port);
+ return;
+ }
+
+ integer_t run_state = 999;
+ for (unsigned int i = 0; i < thread_count; i++) {
+ thread_info_data_t thinfo;
+ mach_msg_type_number_t thread_info_count = THREAD_BASIC_INFO_COUNT;
+ ret = thread_info(thread_list[i], THREAD_BASIC_INFO, (thread_info_t)thinfo, &thread_info_count);
+ if (ret == KERN_SUCCESS) {
+ thread_basic_info_t basic_info_th = (thread_basic_info_t) thinfo;
+ if (basic_info_th->run_state < run_state) {
+ run_state = basic_info_th->run_state;
+ }
+ mach_port_deallocate(mach_task_self(), thread_list[i]);
+ }
+ }
+ vm_deallocate(mach_task_self(), (vm_address_t) thread_list, sizeof(thread_port_array_t) * thread_count);
+ mach_port_deallocate(mach_task_self(), port);
+
+ char state = '?';
+ switch (run_state) {
+ case TH_STATE_RUNNING: state = 'R'; break;
+ case TH_STATE_STOPPED: state = 'S'; break;
+ case TH_STATE_WAITING: state = 'W'; break;
+ case TH_STATE_UNINTERRUPTIBLE: state = 'U'; break;
+ case TH_STATE_HALTED: state = 'H'; break;
+ }
+ proc->state = state;
+}
diff --git a/darwin/DarwinProcess.h b/darwin/DarwinProcess.h
index c479acfd..df1a79ff 100644
--- a/darwin/DarwinProcess.h
+++ b/darwin/DarwinProcess.h
@@ -32,10 +32,17 @@ bool Process_isThread(Process* this);
void DarwinProcess_setStartTime(Process *proc, struct extern_proc *ep, time_t now);
-char *DarwinProcess_getCmdLine(struct kinfo_proc* k, int show_args );
+char *DarwinProcess_getCmdLine(struct kinfo_proc* k, int* basenameOffset);
void DarwinProcess_setFromKInfoProc(Process *proc, struct kinfo_proc *ps, time_t now, bool exists);
void DarwinProcess_setFromLibprocPidinfo(DarwinProcess *proc, DarwinProcessList *dpl);
+/*
+ * Scan threads for process state information.
+ * Based on: http://stackoverflow.com/questions/6788274/ios-mac-cpu-usage-for-thread
+ * and https://github.com/max-horvath/htop-osx/blob/e86692e869e30b0bc7264b3675d2a4014866ef46/ProcessList.c
+ */
+void DarwinProcess_scanThreads(DarwinProcess *dp);
+
#endif
diff --git a/darwin/DarwinProcessList.c b/darwin/DarwinProcessList.c
index 7ea89d9f..7492f822 100644
--- a/darwin/DarwinProcessList.c
+++ b/darwin/DarwinProcessList.c
@@ -168,8 +168,10 @@ void ProcessList_goThroughEntries(ProcessList* super) {
for(size_t i = 0; i < count; ++i) {
proc = (DarwinProcess *)ProcessList_getProcess(super, ps[i].kp_proc.p_pid, &preExisting, (Process_New)DarwinProcess_new);
- DarwinProcess_setFromKInfoProc(&proc->super, ps + i, tv.tv_sec, preExisting);
+ DarwinProcess_setFromKInfoProc(&proc->super, &ps[i], tv.tv_sec, preExisting);
DarwinProcess_setFromLibprocPidinfo(proc, dpl);
+
+ DarwinProcess_scanThreads(proc);
super->totalTasks += 1;
diff --git a/freebsd/FreeBSDProcess.c b/freebsd/FreeBSDProcess.c
index 70cfb954..b0d2c37c 100644
--- a/freebsd/FreeBSDProcess.c
+++ b/freebsd/FreeBSDProcess.c
@@ -115,7 +115,7 @@ void FreeBSDProcess_writeField(Process* this, RichString* str, ProcessField fiel
char buffer[256]; buffer[255] = '\0';
int attr = CRT_colors[DEFAULT_COLOR];
int n = sizeof(buffer) - 1;
- switch (field) {
+ switch ((int) field) {
// add FreeBSD-specific fields here
case JID: snprintf(buffer, n, Process_pidFormat, fp->jid); break;
case JAIL:{
@@ -143,7 +143,7 @@ long FreeBSDProcess_compare(const void* v1, const void* v2) {
p2 = (FreeBSDProcess*)v1;
p1 = (FreeBSDProcess*)v2;
}
- switch (settings->sortKey) {
+ switch ((int) settings->sortKey) {
// add FreeBSD-specific fields here
case JID:
return (p1->jid - p2->jid);
diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c
index b9359e54..241bee23 100644
--- a/freebsd/FreeBSDProcessList.c
+++ b/freebsd/FreeBSDProcessList.c
@@ -14,7 +14,9 @@ in the source distribution for its full text.
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/user.h>
+#include <err.h>
#include <fcntl.h>
+#include <limits.h>
#include <string.h>
/*{
@@ -84,14 +86,13 @@ static int MIB_kern_cp_time[2];
static int MIB_kern_cp_times[2];
static int kernelFScale;
-
ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, uid_t userId) {
+ size_t len;
+ char errbuf[_POSIX2_LINE_MAX];
FreeBSDProcessList* fpl = xCalloc(1, sizeof(FreeBSDProcessList));
ProcessList* pl = (ProcessList*) fpl;
ProcessList_init(pl, Class(FreeBSDProcess), usersTable, pidWhiteList, userId);
- size_t len;
-
// physical memory in system: hw.physmem
// physical page size: hw.pagesize
// usable pagesize : vm.stats.vm.v_page_size
@@ -178,8 +179,10 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui
kernelFScale = 2048;
}
- fpl->kd = kvm_open(NULL, "/dev/null", NULL, 0, NULL);
- assert(fpl->kd);
+ fpl->kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, errbuf);
+ if (fpl->kd == NULL) {
+ errx(1, "kvm_open: %s", errbuf);
+ }
return pl;
}
@@ -212,9 +215,6 @@ static inline void FreeBSDProcessList_scanCPUTime(ProcessList* pl) {
unsigned long *cp_time_n; // old clicks state
unsigned long *cp_time_o; // current clicks state
- unsigned long long total_o = 0;
- unsigned long long total_n = 0;
- unsigned long long total_d = 0;
unsigned long cp_time_d[CPUSTATES];
double cp_time_p[CPUSTATES];
@@ -251,6 +251,9 @@ static inline void FreeBSDProcessList_scanCPUTime(ProcessList* pl) {
}
// diff old vs new
+ unsigned long long total_o = 0;
+ unsigned long long total_n = 0;
+ unsigned long long total_d = 0;
for (int s = 0; s < CPUSTATES; s++) {
cp_time_d[s] = cp_time_n[s] - cp_time_o[s];
total_o += cp_time_o[s];
@@ -479,17 +482,17 @@ void ProcessList_goThroughEntries(ProcessList* this) {
// from FreeBSD source /src/usr.bin/top/machine.c
proc->m_size = kproc->ki_size / 1024 / pageSizeKb;
proc->m_resident = kproc->ki_rssize;
+ proc->percent_mem = (proc->m_resident * PAGE_SIZE_KB) / (double)(this->totalMem) * 100.0;
proc->nlwp = kproc->ki_numthreads;
proc->time = (kproc->ki_runtime + 5000) / 10000;
proc->percent_cpu = 100.0 * ((double)kproc->ki_pctcpu / (double)kernelFScale);
+ proc->percent_mem = 100.0 * (proc->m_resident * PAGE_SIZE_KB) / (double)(this->totalMem);
+
if (proc->percent_cpu > 0.1) {
// system idle process should own all CPU time left regardless of CPU count
if ( strcmp("idle", kproc->ki_comm) == 0 ) {
isIdleProcess = true;
- } else {
- if (cpus > 1)
- proc->percent_cpu = proc->percent_cpu / (double) cpus;
}
}
if (isIdleProcess == false && proc->percent_cpu >= 99.8) {
diff --git a/free