mirror of
https://github.com/xzeldon/htop.git
synced 2025-07-15 13:34:35 +03:00
Compare commits
59 Commits
Author | SHA1 | Date | |
---|---|---|---|
691b7dd5af | |||
ad0f9c58bf | |||
a8d0f2a7fe | |||
e6596cbd69 | |||
40c9f89971 | |||
09ad8067f4 | |||
bda3ee2b81 | |||
bdb015ffa3 | |||
80a515abcc | |||
5000cefc13 | |||
bf7d98e7ac | |||
c096712b8d | |||
be82448bd5 | |||
68c00b9cdb | |||
3c8d586a1c | |||
3869c43393 | |||
fcca4c2f2d | |||
dd88510dcd | |||
43ffdb0eda | |||
bf395e10c5 | |||
8f259bc5e1 | |||
38e6136b82 | |||
589b0733d9 | |||
c9b58c7fbe | |||
ca06e68037 | |||
a516e0852e | |||
3f805cf347 | |||
556d7c03e8 | |||
0925c54caa | |||
d0f5b61aa5 | |||
284f8c5e0b | |||
11b65a2861 | |||
b85b718e69 | |||
7891cdc552 | |||
b9fdf1c2a1 | |||
2844429f15 | |||
3834f2a68f | |||
343c2e58be | |||
fd2c4f5ddd | |||
7f95ed8528 | |||
9579d9b7aa | |||
0580dbb202 | |||
c0c2bb98a2 | |||
9b30870eec | |||
25c945e2ef | |||
f94934472f | |||
becd33795c | |||
74f99e3693 | |||
e1f4645bd1 | |||
0afd0fe572 | |||
ff336b652c | |||
58a59c11f4 | |||
3f806368e0 | |||
4855d92469 | |||
b81bb9038c | |||
1f2f567ca1 | |||
393330239e | |||
d2c34259b4 | |||
858ad8029d |
@ -9,7 +9,8 @@ os:
|
|||||||
|
|
||||||
script:
|
script:
|
||||||
- ./autogen.sh
|
- ./autogen.sh
|
||||||
# clang might warn about C11 generic selections in isnan()
|
- ./configure --enable-werror
|
||||||
- CFLAGS=-Wno-c11-extensions ./configure --enable-werror
|
|
||||||
- make -k
|
- make -k
|
||||||
- CFLAGS=-Wno-c11-extensions make distcheck DISTCHECK_CONFIGURE_FLAGS=--enable-werror
|
- make distcheck DISTCHECK_CONFIGURE_FLAGS=--enable-werror
|
||||||
|
- sudo make install
|
||||||
|
- make installcheck
|
||||||
|
@ -63,9 +63,9 @@ Affinity* Affinity_get(const Process* proc, ProcessList* pl) {
|
|||||||
Affinity_add(affinity, i);
|
Affinity_add(affinity, i);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unsigned int id;
|
int id;
|
||||||
hwloc_bitmap_foreach_begin(id, cpuset);
|
hwloc_bitmap_foreach_begin(id, cpuset)
|
||||||
Affinity_add(affinity, id);
|
Affinity_add(affinity, (unsigned)id);
|
||||||
hwloc_bitmap_foreach_end();
|
hwloc_bitmap_foreach_end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,9 +425,9 @@ Affinity* AffinityPanel_getAffinity(Panel* super, ProcessList* pl) {
|
|||||||
Affinity* affinity = Affinity_new(pl);
|
Affinity* affinity = Affinity_new(pl);
|
||||||
|
|
||||||
#ifdef HAVE_LIBHWLOC
|
#ifdef HAVE_LIBHWLOC
|
||||||
unsigned int i;
|
int i;
|
||||||
hwloc_bitmap_foreach_begin(i, this->workCpuset)
|
hwloc_bitmap_foreach_begin(i, this->workCpuset)
|
||||||
Affinity_add(affinity, i);
|
Affinity_add(affinity, (unsigned)i);
|
||||||
hwloc_bitmap_foreach_end();
|
hwloc_bitmap_foreach_end();
|
||||||
#else
|
#else
|
||||||
for (int i = 0; i < Vector_size(this->cpuids); i++) {
|
for (int i = 0; i < Vector_size(this->cpuids); i++) {
|
||||||
|
15
CPUMeter.c
15
CPUMeter.c
@ -52,9 +52,9 @@ static void CPUMeter_init(Meter* this) {
|
|||||||
// Custom uiName runtime logic to include the param (processor)
|
// Custom uiName runtime logic to include the param (processor)
|
||||||
static void CPUMeter_getUiName(const Meter* this, char* buffer, size_t length) {
|
static void CPUMeter_getUiName(const Meter* this, char* buffer, size_t length) {
|
||||||
if (this->param > 0)
|
if (this->param > 0)
|
||||||
xSnprintf(buffer, sizeof(length), "%s %u", Meter_uiName(this), this->param);
|
xSnprintf(buffer, length, "%s %u", Meter_uiName(this), this->param);
|
||||||
else
|
else
|
||||||
xSnprintf(buffer, sizeof(length), "%s", Meter_uiName(this));
|
xSnprintf(buffer, length, "%s", Meter_uiName(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CPUMeter_updateValues(Meter* this) {
|
static void CPUMeter_updateValues(Meter* this) {
|
||||||
@ -381,6 +381,7 @@ const MeterClass AllCPUs2Meter_class = {
|
|||||||
},
|
},
|
||||||
.updateValues = AllCPUsMeter_updateValues,
|
.updateValues = AllCPUsMeter_updateValues,
|
||||||
.defaultMode = CUSTOM_METERMODE,
|
.defaultMode = CUSTOM_METERMODE,
|
||||||
|
.isMultiColumn = true,
|
||||||
.total = 100.0,
|
.total = 100.0,
|
||||||
.attributes = CPUMeter_attributes,
|
.attributes = CPUMeter_attributes,
|
||||||
.name = "AllCPUs2",
|
.name = "AllCPUs2",
|
||||||
@ -401,6 +402,7 @@ const MeterClass LeftCPUsMeter_class = {
|
|||||||
},
|
},
|
||||||
.updateValues = AllCPUsMeter_updateValues,
|
.updateValues = AllCPUsMeter_updateValues,
|
||||||
.defaultMode = CUSTOM_METERMODE,
|
.defaultMode = CUSTOM_METERMODE,
|
||||||
|
.isMultiColumn = true,
|
||||||
.total = 100.0,
|
.total = 100.0,
|
||||||
.attributes = CPUMeter_attributes,
|
.attributes = CPUMeter_attributes,
|
||||||
.name = "LeftCPUs",
|
.name = "LeftCPUs",
|
||||||
@ -421,6 +423,7 @@ const MeterClass RightCPUsMeter_class = {
|
|||||||
},
|
},
|
||||||
.updateValues = AllCPUsMeter_updateValues,
|
.updateValues = AllCPUsMeter_updateValues,
|
||||||
.defaultMode = CUSTOM_METERMODE,
|
.defaultMode = CUSTOM_METERMODE,
|
||||||
|
.isMultiColumn = true,
|
||||||
.total = 100.0,
|
.total = 100.0,
|
||||||
.attributes = CPUMeter_attributes,
|
.attributes = CPUMeter_attributes,
|
||||||
.name = "RightCPUs",
|
.name = "RightCPUs",
|
||||||
@ -441,6 +444,7 @@ const MeterClass LeftCPUs2Meter_class = {
|
|||||||
},
|
},
|
||||||
.updateValues = AllCPUsMeter_updateValues,
|
.updateValues = AllCPUsMeter_updateValues,
|
||||||
.defaultMode = CUSTOM_METERMODE,
|
.defaultMode = CUSTOM_METERMODE,
|
||||||
|
.isMultiColumn = true,
|
||||||
.total = 100.0,
|
.total = 100.0,
|
||||||
.attributes = CPUMeter_attributes,
|
.attributes = CPUMeter_attributes,
|
||||||
.name = "LeftCPUs2",
|
.name = "LeftCPUs2",
|
||||||
@ -461,6 +465,7 @@ const MeterClass RightCPUs2Meter_class = {
|
|||||||
},
|
},
|
||||||
.updateValues = AllCPUsMeter_updateValues,
|
.updateValues = AllCPUsMeter_updateValues,
|
||||||
.defaultMode = CUSTOM_METERMODE,
|
.defaultMode = CUSTOM_METERMODE,
|
||||||
|
.isMultiColumn = true,
|
||||||
.total = 100.0,
|
.total = 100.0,
|
||||||
.attributes = CPUMeter_attributes,
|
.attributes = CPUMeter_attributes,
|
||||||
.name = "RightCPUs2",
|
.name = "RightCPUs2",
|
||||||
@ -481,6 +486,7 @@ const MeterClass AllCPUs4Meter_class = {
|
|||||||
},
|
},
|
||||||
.updateValues = AllCPUsMeter_updateValues,
|
.updateValues = AllCPUsMeter_updateValues,
|
||||||
.defaultMode = CUSTOM_METERMODE,
|
.defaultMode = CUSTOM_METERMODE,
|
||||||
|
.isMultiColumn = true,
|
||||||
.total = 100.0,
|
.total = 100.0,
|
||||||
.attributes = CPUMeter_attributes,
|
.attributes = CPUMeter_attributes,
|
||||||
.name = "AllCPUs4",
|
.name = "AllCPUs4",
|
||||||
@ -501,6 +507,7 @@ const MeterClass LeftCPUs4Meter_class = {
|
|||||||
},
|
},
|
||||||
.updateValues = AllCPUsMeter_updateValues,
|
.updateValues = AllCPUsMeter_updateValues,
|
||||||
.defaultMode = CUSTOM_METERMODE,
|
.defaultMode = CUSTOM_METERMODE,
|
||||||
|
.isMultiColumn = true,
|
||||||
.total = 100.0,
|
.total = 100.0,
|
||||||
.attributes = CPUMeter_attributes,
|
.attributes = CPUMeter_attributes,
|
||||||
.name = "LeftCPUs4",
|
.name = "LeftCPUs4",
|
||||||
@ -521,6 +528,7 @@ const MeterClass RightCPUs4Meter_class = {
|
|||||||
},
|
},
|
||||||
.updateValues = AllCPUsMeter_updateValues,
|
.updateValues = AllCPUsMeter_updateValues,
|
||||||
.defaultMode = CUSTOM_METERMODE,
|
.defaultMode = CUSTOM_METERMODE,
|
||||||
|
.isMultiColumn = true,
|
||||||
.total = 100.0,
|
.total = 100.0,
|
||||||
.attributes = CPUMeter_attributes,
|
.attributes = CPUMeter_attributes,
|
||||||
.name = "RightCPUs4",
|
.name = "RightCPUs4",
|
||||||
@ -541,6 +549,7 @@ const MeterClass AllCPUs8Meter_class = {
|
|||||||
},
|
},
|
||||||
.updateValues = AllCPUsMeter_updateValues,
|
.updateValues = AllCPUsMeter_updateValues,
|
||||||
.defaultMode = CUSTOM_METERMODE,
|
.defaultMode = CUSTOM_METERMODE,
|
||||||
|
.isMultiColumn = true,
|
||||||
.total = 100.0,
|
.total = 100.0,
|
||||||
.attributes = CPUMeter_attributes,
|
.attributes = CPUMeter_attributes,
|
||||||
.name = "AllCPUs8",
|
.name = "AllCPUs8",
|
||||||
@ -561,6 +570,7 @@ const MeterClass LeftCPUs8Meter_class = {
|
|||||||
},
|
},
|
||||||
.updateValues = AllCPUsMeter_updateValues,
|
.updateValues = AllCPUsMeter_updateValues,
|
||||||
.defaultMode = CUSTOM_METERMODE,
|
.defaultMode = CUSTOM_METERMODE,
|
||||||
|
.isMultiColumn = true,
|
||||||
.total = 100.0,
|
.total = 100.0,
|
||||||
.attributes = CPUMeter_attributes,
|
.attributes = CPUMeter_attributes,
|
||||||
.name = "LeftCPUs8",
|
.name = "LeftCPUs8",
|
||||||
@ -581,6 +591,7 @@ const MeterClass RightCPUs8Meter_class = {
|
|||||||
},
|
},
|
||||||
.updateValues = AllCPUsMeter_updateValues,
|
.updateValues = AllCPUsMeter_updateValues,
|
||||||
.defaultMode = CUSTOM_METERMODE,
|
.defaultMode = CUSTOM_METERMODE,
|
||||||
|
.isMultiColumn = true,
|
||||||
.total = 100.0,
|
.total = 100.0,
|
||||||
.attributes = CPUMeter_attributes,
|
.attributes = CPUMeter_attributes,
|
||||||
.name = "RightCPUs8",
|
.name = "RightCPUs8",
|
||||||
|
22
CRT.c
22
CRT.c
@ -138,7 +138,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||||||
[PROCESS_GIGABYTES] = ColorPair(Green, Black),
|
[PROCESS_GIGABYTES] = ColorPair(Green, Black),
|
||||||
[PROCESS_BASENAME] = A_BOLD | ColorPair(Cyan, Black),
|
[PROCESS_BASENAME] = A_BOLD | ColorPair(Cyan, Black),
|
||||||
[PROCESS_TREE] = ColorPair(Cyan, Black),
|
[PROCESS_TREE] = ColorPair(Cyan, Black),
|
||||||
[PROCESS_R_STATE] = ColorPair(Green, Black),
|
[PROCESS_RUN_STATE] = ColorPair(Green, Black),
|
||||||
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black),
|
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black),
|
||||||
[PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black),
|
[PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black),
|
||||||
[PROCESS_LOW_PRIORITY] = ColorPair(Green, Black),
|
[PROCESS_LOW_PRIORITY] = ColorPair(Green, Black),
|
||||||
@ -240,7 +240,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||||||
[PROCESS_GIGABYTES] = A_BOLD,
|
[PROCESS_GIGABYTES] = A_BOLD,
|
||||||
[PROCESS_BASENAME] = A_BOLD,
|
[PROCESS_BASENAME] = A_BOLD,
|
||||||
[PROCESS_TREE] = A_BOLD,
|
[PROCESS_TREE] = A_BOLD,
|
||||||
[PROCESS_R_STATE] = A_BOLD,
|
[PROCESS_RUN_STATE] = A_BOLD,
|
||||||
[PROCESS_D_STATE] = A_BOLD,
|
[PROCESS_D_STATE] = A_BOLD,
|
||||||
[PROCESS_HIGH_PRIORITY] = A_BOLD,
|
[PROCESS_HIGH_PRIORITY] = A_BOLD,
|
||||||
[PROCESS_LOW_PRIORITY] = A_DIM,
|
[PROCESS_LOW_PRIORITY] = A_DIM,
|
||||||
@ -342,7 +342,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||||||
[PROCESS_GIGABYTES] = ColorPair(Green, White),
|
[PROCESS_GIGABYTES] = ColorPair(Green, White),
|
||||||
[PROCESS_BASENAME] = ColorPair(Blue, White),
|
[PROCESS_BASENAME] = ColorPair(Blue, White),
|
||||||
[PROCESS_TREE] = ColorPair(Green, White),
|
[PROCESS_TREE] = ColorPair(Green, White),
|
||||||
[PROCESS_R_STATE] = ColorPair(Green, White),
|
[PROCESS_RUN_STATE] = ColorPair(Green, White),
|
||||||
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red, White),
|
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red, White),
|
||||||
[PROCESS_HIGH_PRIORITY] = ColorPair(Red, White),
|
[PROCESS_HIGH_PRIORITY] = ColorPair(Red, White),
|
||||||
[PROCESS_LOW_PRIORITY] = ColorPair(Green, White),
|
[PROCESS_LOW_PRIORITY] = ColorPair(Green, White),
|
||||||
@ -444,7 +444,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||||||
[PROCESS_GIGABYTES] = ColorPair(Green, Black),
|
[PROCESS_GIGABYTES] = ColorPair(Green, Black),
|
||||||
[PROCESS_BASENAME] = ColorPair(Green, Black),
|
[PROCESS_BASENAME] = ColorPair(Green, Black),
|
||||||
[PROCESS_TREE] = ColorPair(Blue, Black),
|
[PROCESS_TREE] = ColorPair(Blue, Black),
|
||||||
[PROCESS_R_STATE] = ColorPair(Green, Black),
|
[PROCESS_RUN_STATE] = ColorPair(Green, Black),
|
||||||
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black),
|
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black),
|
||||||
[PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black),
|
[PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black),
|
||||||
[PROCESS_LOW_PRIORITY] = ColorPair(Green, Black),
|
[PROCESS_LOW_PRIORITY] = ColorPair(Green, Black),
|
||||||
@ -546,7 +546,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||||||
[PROCESS_GIGABYTES] = ColorPair(Green, Blue),
|
[PROCESS_GIGABYTES] = ColorPair(Green, Blue),
|
||||||
[PROCESS_BASENAME] = A_BOLD | ColorPair(Cyan, Blue),
|
[PROCESS_BASENAME] = A_BOLD | ColorPair(Cyan, Blue),
|
||||||
[PROCESS_TREE] = ColorPair(Cyan, Blue),
|
[PROCESS_TREE] = ColorPair(Cyan, Blue),
|
||||||
[PROCESS_R_STATE] = ColorPair(Green, Blue),
|
[PROCESS_RUN_STATE] = ColorPair(Green, Blue),
|
||||||
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Blue),
|
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Blue),
|
||||||
[PROCESS_HIGH_PRIORITY] = ColorPair(Red, Blue),
|
[PROCESS_HIGH_PRIORITY] = ColorPair(Red, Blue),
|
||||||
[PROCESS_LOW_PRIORITY] = ColorPair(Green, Blue),
|
[PROCESS_LOW_PRIORITY] = ColorPair(Green, Blue),
|
||||||
@ -652,7 +652,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
|||||||
[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue, Black),
|
[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue, Black),
|
||||||
[PROCESS_COMM] = ColorPair(Magenta, Black),
|
[PROCESS_COMM] = ColorPair(Magenta, Black),
|
||||||
[PROCESS_THREAD_COMM] = ColorPair(Yellow, Black),
|
[PROCESS_THREAD_COMM] = ColorPair(Yellow, Black),
|
||||||
[PROCESS_R_STATE] = ColorPair(Green, Black),
|
[PROCESS_RUN_STATE] = ColorPair(Green, Black),
|
||||||
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black),
|
[PROCESS_D_STATE] = A_BOLD | ColorPair(Red, Black),
|
||||||
[PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black),
|
[PROCESS_HIGH_PRIORITY] = ColorPair(Red, Black),
|
||||||
[PROCESS_LOW_PRIORITY] = ColorPair(Green, Black),
|
[PROCESS_LOW_PRIORITY] = ColorPair(Green, Black),
|
||||||
@ -772,6 +772,8 @@ static void dumpStderr(void) {
|
|||||||
|
|
||||||
fsync(STDERR_FILENO);
|
fsync(STDERR_FILENO);
|
||||||
dup2(stderrRedirectBackupFd, STDERR_FILENO);
|
dup2(stderrRedirectBackupFd, STDERR_FILENO);
|
||||||
|
close(stderrRedirectBackupFd);
|
||||||
|
stderrRedirectBackupFd = -1;
|
||||||
lseek(stderrRedirectNewFd, 0, SEEK_SET);
|
lseek(stderrRedirectNewFd, 0, SEEK_SET);
|
||||||
|
|
||||||
bool header = false;
|
bool header = false;
|
||||||
@ -886,6 +888,10 @@ void CRT_init(const Settings* settings, bool allowUnicode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (termType && (String_startsWith(termType, "xterm") || String_eq(termType, "vt220"))) {
|
if (termType && (String_startsWith(termType, "xterm") || String_eq(termType, "vt220"))) {
|
||||||
|
#ifdef HTOP_NETBSD
|
||||||
|
#define define_key(s_, k_) define_key((char*)s_, k_)
|
||||||
|
IGNORE_WCASTQUAL_BEGIN
|
||||||
|
#endif
|
||||||
define_key("\033[H", KEY_HOME);
|
define_key("\033[H", KEY_HOME);
|
||||||
define_key("\033[F", KEY_END);
|
define_key("\033[F", KEY_END);
|
||||||
define_key("\033[7~", KEY_HOME);
|
define_key("\033[7~", KEY_HOME);
|
||||||
@ -906,6 +912,10 @@ void CRT_init(const Settings* settings, bool allowUnicode) {
|
|||||||
sequence[1] = c;
|
sequence[1] = c;
|
||||||
define_key(sequence, KEY_ALT('A' + (c - 'a')));
|
define_key(sequence, KEY_ALT('A' + (c - 'a')));
|
||||||
}
|
}
|
||||||
|
#ifdef HTOP_NETBSD
|
||||||
|
IGNORE_WCASTQUAL_END
|
||||||
|
#undef define_key
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
CRT_installSignalHandlers();
|
CRT_installSignalHandlers();
|
||||||
|
2
CRT.h
2
CRT.h
@ -74,7 +74,7 @@ typedef enum ColorElements_ {
|
|||||||
PROCESS_MEGABYTES,
|
PROCESS_MEGABYTES,
|
||||||
PROCESS_GIGABYTES,
|
PROCESS_GIGABYTES,
|
||||||
PROCESS_TREE,
|
PROCESS_TREE,
|
||||||
PROCESS_R_STATE,
|
PROCESS_RUN_STATE,
|
||||||
PROCESS_D_STATE,
|
PROCESS_D_STATE,
|
||||||
PROCESS_BASENAME,
|
PROCESS_BASENAME,
|
||||||
PROCESS_HIGH_PRIORITY,
|
PROCESS_HIGH_PRIORITY,
|
||||||
|
@ -40,7 +40,7 @@ static void CategoriesPanel_delete(Object* object) {
|
|||||||
|
|
||||||
static void CategoriesPanel_makeMetersPage(CategoriesPanel* this) {
|
static void CategoriesPanel_makeMetersPage(CategoriesPanel* this) {
|
||||||
size_t columns = HeaderLayout_getColumns(this->scr->header->headerLayout);
|
size_t columns = HeaderLayout_getColumns(this->scr->header->headerLayout);
|
||||||
MetersPanel** meterPanels = xMallocArray(columns, sizeof(MetersPanel));
|
MetersPanel** meterPanels = xMallocArray(columns, sizeof(MetersPanel*));
|
||||||
|
|
||||||
for (size_t i = 0; i < columns; i++) {
|
for (size_t i = 0; i < columns; i++) {
|
||||||
char titleBuffer[32];
|
char titleBuffer[32];
|
||||||
|
18
ChangeLog
18
ChangeLog
@ -1,6 +1,5 @@
|
|||||||
What's new in version 3.1.0
|
What's new in version 3.1.0
|
||||||
|
|
||||||
|
|
||||||
* Updated COPYING file to remove the PLPA exemption (appendix 2)
|
* Updated COPYING file to remove the PLPA exemption (appendix 2)
|
||||||
With this change the license is now GPLv2 without any additional wording.
|
With this change the license is now GPLv2 without any additional wording.
|
||||||
* Improved default sort ordering
|
* Improved default sort ordering
|
||||||
@ -26,10 +25,11 @@ What's new in version 3.1.0
|
|||||||
Moving this column to be handled as a platform-independently available
|
Moving this column to be handled as a platform-independently available
|
||||||
information simplifies the markup of the command line.
|
information simplifies the markup of the command line.
|
||||||
* Introduce configuration file versioning and config_reader_min_version
|
* Introduce configuration file versioning and config_reader_min_version
|
||||||
Starting with this version the configuration file contains an version
|
Starting with this version the configuration file contains a version
|
||||||
identifying the minimum version of the configuration parser needed to
|
identifying the minimum version of the configuration parser needed to
|
||||||
fully understand the configuration file format.
|
fully understand the configuration file format.
|
||||||
Old configuration file formats are automatically upgraded on startup.
|
Old configuration file formats are automatically upgraded when
|
||||||
|
saving the config file (htoprc).
|
||||||
* Make the configuration parser friendlier to users (thanks to Bart Bakker)
|
* Make the configuration parser friendlier to users (thanks to Bart Bakker)
|
||||||
With this change only settings that cannot be parsed properly are
|
With this change only settings that cannot be parsed properly are
|
||||||
reset to their defaults.
|
reset to their defaults.
|
||||||
@ -48,12 +48,12 @@ What's new in version 3.1.0
|
|||||||
* Option and key ("*") to collapse / expand all branches under PID 1
|
* Option and key ("*") to collapse / expand all branches under PID 1
|
||||||
(and PID 2 if kernel threads are shown) (thanks to Krishna Chaitanya)
|
(and PID 2 if kernel threads are shown) (thanks to Krishna Chaitanya)
|
||||||
* Keep following a process when inverting the sort order, displaying
|
* Keep following a process when inverting the sort order, displaying
|
||||||
the help screen or hiding/unhiding userland threads
|
the help screen or hiding/unhiding userland threads.
|
||||||
If a thread is currently selected the selection is updated to point
|
If a thread is currently selected the selection is updated to point
|
||||||
to the thread's parent process. (thanks to Gonzalo, et.al.)
|
to the thread's parent process. (thanks to Gonzalo, et.al.)
|
||||||
* Reorder process scanning to be performed before updating the display
|
* Reorder process scanning to be performed before updating the display
|
||||||
of the meters in the header
|
of the meters in the header
|
||||||
* Always check the user for a process for any changes
|
* Always check the user for a process for any changes.
|
||||||
This affects multiple platforms that previously didn't correctly handle
|
This affects multiple platforms that previously didn't correctly handle
|
||||||
the user field for a process to change at runtime (e.g. due to seteuid
|
the user field for a process to change at runtime (e.g. due to seteuid
|
||||||
or similar syscalls).
|
or similar syscalls).
|
||||||
@ -105,14 +105,14 @@ What's new in version 3.1.0
|
|||||||
* Correctly color the ZFS ARC ratio (thanks to Ross Williams)
|
* Correctly color the ZFS ARC ratio (thanks to Ross Williams)
|
||||||
* Bugfixes related to CPU time display/calculations for darwin on M1 systems
|
* Bugfixes related to CPU time display/calculations for darwin on M1 systems
|
||||||
(thanks to Alexander Momchilov)
|
(thanks to Alexander Momchilov)
|
||||||
* Harmonize the handling of multiple batteries across different platforms
|
* Harmonize the handling of multiple batteries across different platforms.
|
||||||
The system is now considered to run on AC if at least one power supply
|
The system is now considered to run on AC if at least one power supply
|
||||||
marked as AC is found in the system.
|
marked as AC is found in the system.
|
||||||
Battery capacity is summed up over all batteries found.
|
Battery capacity is summed up over all batteries found.
|
||||||
This also changes the old behavior that batteries reported by the
|
This also changes the old behavior that batteries reported by the
|
||||||
system after the first AC adapter where sometimes ignored.
|
system after the first AC adapter where sometimes ignored.
|
||||||
* Correctly handle multiple batteries on Darwin
|
* Correctly handle multiple batteries on Darwin.
|
||||||
Resolves a possible memory leak on systems with multiple batteries
|
Resolves a possible memory leak on systems with multiple batteries.
|
||||||
* Handle Linux Shmem being part of Cached in the MemoryMeter
|
* Handle Linux Shmem being part of Cached in the MemoryMeter
|
||||||
* Add SwapCached to the Linux swap meter (thanks to David Zarzycki)
|
* Add SwapCached to the Linux swap meter (thanks to David Zarzycki)
|
||||||
* Convert process time to days if applicable (thanks to David Zarzycki)
|
* Convert process time to days if applicable (thanks to David Zarzycki)
|
||||||
@ -138,7 +138,7 @@ What's new in version 3.1.0
|
|||||||
* Add command line option to drop Linux capabilities
|
* Add command line option to drop Linux capabilities
|
||||||
* Support scheduler affinity on platforms beyond Linux
|
* Support scheduler affinity on platforms beyond Linux
|
||||||
* Report on any failure to write the configuration file
|
* Report on any failure to write the configuration file
|
||||||
* Cache stderr to be able to print assert messages
|
* Cache stderr to be able to print assert messages.
|
||||||
These messages are shown in case htop terminates unexpectedly.
|
These messages are shown in case htop terminates unexpectedly.
|
||||||
* Print current settings on crash
|
* Print current settings on crash
|
||||||
* Reset signal handlers on program exit
|
* Reset signal handlers on program exit
|
||||||
|
@ -118,12 +118,6 @@ const PanelClass ColumnsPanel_class = {
|
|||||||
.eventHandler = ColumnsPanel_eventHandler
|
.eventHandler = ColumnsPanel_eventHandler
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
Panel* super;
|
|
||||||
unsigned int id;
|
|
||||||
unsigned int offset;
|
|
||||||
} DynamicIterator;
|
|
||||||
|
|
||||||
static void ColumnsPanel_add(Panel* super, unsigned int key, Hashtable* columns) {
|
static void ColumnsPanel_add(Panel* super, unsigned int key, Hashtable* columns) {
|
||||||
const char* name;
|
const char* name;
|
||||||
if (key < LAST_PROCESSFIELD) {
|
if (key < LAST_PROCESSFIELD) {
|
||||||
|
@ -393,10 +393,8 @@ int CommandLine_run(const char* name, int argc, char** argv) {
|
|||||||
|
|
||||||
/* Delete these last, since they can get accessed in the crash handler */
|
/* Delete these last, since they can get accessed in the crash handler */
|
||||||
Settings_delete(settings);
|
Settings_delete(settings);
|
||||||
if (dc)
|
DynamicColumns_delete(dc);
|
||||||
Hashtable_delete(dc);
|
DynamicMeters_delete(dm);
|
||||||
if (dm)
|
|
||||||
Hashtable_delete(dm);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,13 @@ Hashtable* DynamicColumns_new(void) {
|
|||||||
return Platform_dynamicColumns();
|
return Platform_dynamicColumns();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DynamicColumns_delete(Hashtable* dynamics) {
|
||||||
|
if (dynamics) {
|
||||||
|
Platform_dynamicColumnsDone(dynamics);
|
||||||
|
Hashtable_delete(dynamics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const char* DynamicColumn_init(unsigned int key) {
|
const char* DynamicColumn_init(unsigned int key) {
|
||||||
return Platform_dynamicColumnInit(key);
|
return Platform_dynamicColumnInit(key);
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,8 @@ typedef struct DynamicColumn_ {
|
|||||||
|
|
||||||
Hashtable* DynamicColumns_new(void);
|
Hashtable* DynamicColumns_new(void);
|
||||||
|
|
||||||
|
void DynamicColumns_delete(Hashtable* dynamics);
|
||||||
|
|
||||||
const char* DynamicColumn_init(unsigned int key);
|
const char* DynamicColumn_init(unsigned int key);
|
||||||
|
|
||||||
const DynamicColumn* DynamicColumn_lookup(Hashtable* dynamics, unsigned int key);
|
const DynamicColumn* DynamicColumn_lookup(Hashtable* dynamics, unsigned int key);
|
||||||
|
@ -38,6 +38,13 @@ Hashtable* DynamicMeters_new(void) {
|
|||||||
return Platform_dynamicMeters();
|
return Platform_dynamicMeters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DynamicMeters_delete(Hashtable* dynamics) {
|
||||||
|
if (dynamics) {
|
||||||
|
Platform_dynamicMetersDone(dynamics);
|
||||||
|
Hashtable_delete(dynamics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int key;
|
unsigned int key;
|
||||||
const char* name;
|
const char* name;
|
||||||
|
@ -17,6 +17,8 @@ typedef struct DynamicMeter_ {
|
|||||||
|
|
||||||
Hashtable* DynamicMeters_new(void);
|
Hashtable* DynamicMeters_new(void);
|
||||||
|
|
||||||
|
void DynamicMeters_delete(Hashtable* dynamics);
|
||||||
|
|
||||||
const char* DynamicMeter_lookup(Hashtable* dynamics, unsigned int key);
|
const char* DynamicMeter_lookup(Hashtable* dynamics, unsigned int key);
|
||||||
|
|
||||||
bool DynamicMeter_search(Hashtable* dynamics, const char* name, unsigned int* key);
|
bool DynamicMeter_search(Hashtable* dynamics, const char* name, unsigned int* key);
|
||||||
|
20
Header.c
20
Header.c
@ -86,8 +86,9 @@ static void Header_addMeterByName(Header* this, const char* name, MeterModeId mo
|
|||||||
if (paren) {
|
if (paren) {
|
||||||
int ok = sscanf(paren, "(%10u)", ¶m); // CPUMeter
|
int ok = sscanf(paren, "(%10u)", ¶m); // CPUMeter
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
char* end, dynamic[32] = {0};
|
char dynamic[32] = {0};
|
||||||
if (sscanf(paren, "(%30s)", dynamic)) { // DynamicMeter
|
if (sscanf(paren, "(%30s)", dynamic)) { // DynamicMeter
|
||||||
|
char* end;
|
||||||
if ((end = strrchr(dynamic, ')')) == NULL)
|
if ((end = strrchr(dynamic, ')')) == NULL)
|
||||||
return; // htoprc parse failure
|
return; // htoprc parse failure
|
||||||
*end = '\0';
|
*end = '\0';
|
||||||
@ -195,25 +196,28 @@ void Header_draw(const Header* this) {
|
|||||||
}
|
}
|
||||||
const int width = COLS - pad;
|
const int width = COLS - pad;
|
||||||
int x = pad;
|
int x = pad;
|
||||||
float roundingLoss = 0.0f;
|
float roundingLoss = 0.0F;
|
||||||
|
|
||||||
Header_forEachColumn(this, col) {
|
Header_forEachColumn(this, col) {
|
||||||
Vector* meters = this->columns[col];
|
Vector* meters = this->columns[col];
|
||||||
float colWidth = (float)width * HeaderLayout_layouts[this->headerLayout].widths[col] / 100.0f;
|
float colWidth = (float)width * HeaderLayout_layouts[this->headerLayout].widths[col] / 100.0F;
|
||||||
|
|
||||||
roundingLoss += colWidth - floorf(colWidth);
|
roundingLoss += colWidth - floorf(colWidth);
|
||||||
if (roundingLoss >= 1.0f) {
|
if (roundingLoss >= 1.0F) {
|
||||||
colWidth += 1.0f;
|
colWidth += 1.0F;
|
||||||
roundingLoss -= 1.0f;
|
roundingLoss -= 1.0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int y = (pad / 2), i = 0; i < Vector_size(meters); i++) {
|
for (int y = (pad / 2), i = 0; i < Vector_size(meters); i++) {
|
||||||
Meter* meter = (Meter*) Vector_get(meters, i);
|
Meter* meter = (Meter*) Vector_get(meters, i);
|
||||||
|
|
||||||
float actualWidth = colWidth;
|
float actualWidth = colWidth;
|
||||||
if (meter->mode == TEXT_METERMODE) {
|
|
||||||
|
/* Let meters in text mode expand to the right on empty neighbors;
|
||||||
|
except for multi column meters. */
|
||||||
|
if (meter->mode == TEXT_METERMODE && !Meter_isMultiColumn(meter)) {
|
||||||
for (int j = 1; j < meter->columnWidthCount; j++) {
|
for (int j = 1; j < meter->columnWidthCount; j++) {
|
||||||
actualWidth += (float)width * HeaderLayout_layouts[this->headerLayout].widths[col + j] / 100.0f;
|
actualWidth += (float)width * HeaderLayout_layouts[this->headerLayout].widths[col + j] / 100.0F;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
Header.h
2
Header.h
@ -23,7 +23,7 @@ typedef struct Header_ {
|
|||||||
int height;
|
int height;
|
||||||
} Header;
|
} Header;
|
||||||
|
|
||||||
#define Header_forEachColumn(this_, i_) for (size_t (i_)=0; (i_) < HeaderLayout_getColumns((this_)->headerLayout); ++(i_))
|
#define Header_forEachColumn(this_, i_) for (size_t (i_)=0, H_fEC_numColumns_ = HeaderLayout_getColumns((this_)->headerLayout); (i_) < H_fEC_numColumns_; ++(i_))
|
||||||
|
|
||||||
Header* Header_new(ProcessList* pl, Settings* settings, HeaderLayout hLayout);
|
Header* Header_new(ProcessList* pl, Settings* settings, HeaderLayout hLayout);
|
||||||
|
|
||||||
|
@ -82,6 +82,6 @@ HeaderOptionsPanel* HeaderOptionsPanel_new(Settings* settings, ScreenManager* sc
|
|||||||
for (int i = 0; i < LAST_HEADER_LAYOUT; i++) {
|
for (int i = 0; i < LAST_HEADER_LAYOUT; i++) {
|
||||||
Panel_add(super, (Object*) CheckItem_newByVal(HeaderLayout_layouts[i].description, false));
|
Panel_add(super, (Object*) CheckItem_newByVal(HeaderLayout_layouts[i].description, false));
|
||||||
}
|
}
|
||||||
CheckItem_set((CheckItem*)Panel_get(super, settings->hLayout), true);
|
CheckItem_set((CheckItem*)Panel_get(super, scr->header->headerLayout), true);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -61,8 +61,8 @@ static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
|
|||||||
if (ch == KEY_RESIZE)
|
if (ch == KEY_RESIZE)
|
||||||
return IGNORED;
|
return IGNORED;
|
||||||
|
|
||||||
/* reset on every normal key */
|
/* reset on every normal key, except mouse events while mouse support is disabled */
|
||||||
if (ch != ERR)
|
if (ch != ERR && (ch != KEY_MOUSE || this->state->settings->enableMouse))
|
||||||
this->state->hideProcessSelection = false;
|
this->state->hideProcessSelection = false;
|
||||||
|
|
||||||
if (EVENT_IS_HEADER_CLICK(ch)) {
|
if (EVENT_IS_HEADER_CLICK(ch)) {
|
||||||
|
@ -33,10 +33,14 @@ static void MemorySwapMeter_updateValues(Meter* this) {
|
|||||||
static void MemorySwapMeter_draw(Meter* this, int x, int y, int w) {
|
static void MemorySwapMeter_draw(Meter* this, int x, int y, int w) {
|
||||||
MemorySwapMeterData* data = this->meterData;
|
MemorySwapMeterData* data = this->meterData;
|
||||||
|
|
||||||
|
/* Use the same width for each sub meter to align with CPU meter */
|
||||||
|
const int colwidth = w / 2;
|
||||||
|
const int diff = w - colwidth * 2;
|
||||||
|
|
||||||
assert(data->memoryMeter->draw);
|
assert(data->memoryMeter->draw);
|
||||||
data->memoryMeter->draw(data->memoryMeter, x, y, w / 2);
|
data->memoryMeter->draw(data->memoryMeter, x, y, colwidth);
|
||||||
assert(data->swapMeter->draw);
|
assert(data->swapMeter->draw);
|
||||||
data->swapMeter->draw(data->swapMeter, x + w / 2, y, w - w / 2);
|
data->swapMeter->draw(data->swapMeter, x + colwidth + diff, y, colwidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MemorySwapMeter_init(Meter* this) {
|
static void MemorySwapMeter_init(Meter* this) {
|
||||||
@ -91,6 +95,7 @@ const MeterClass MemorySwapMeter_class = {
|
|||||||
},
|
},
|
||||||
.updateValues = MemorySwapMeter_updateValues,
|
.updateValues = MemorySwapMeter_updateValues,
|
||||||
.defaultMode = CUSTOM_METERMODE,
|
.defaultMode = CUSTOM_METERMODE,
|
||||||
|
.isMultiColumn = true,
|
||||||
.name = "MemorySwap",
|
.name = "MemorySwap",
|
||||||
.uiName = "Memory & Swap",
|
.uiName = "Memory & Swap",
|
||||||
.description = "Combined memory and swap usage",
|
.description = "Combined memory and swap usage",
|
||||||
|
2
Meter.h
2
Meter.h
@ -73,6 +73,7 @@ typedef struct MeterClass_ {
|
|||||||
const char* const caption; /* prefix in the actual header */
|
const char* const caption; /* prefix in the actual header */
|
||||||
const char* const description; /* optional meter description in header setup menu */
|
const char* const description; /* optional meter description in header setup menu */
|
||||||
const uint8_t maxItems;
|
const uint8_t maxItems;
|
||||||
|
const bool isMultiColumn; /* whether the meter draws multiple sub-columns (defaults to false) */
|
||||||
} MeterClass;
|
} MeterClass;
|
||||||
|
|
||||||
#define As_Meter(this_) ((const MeterClass*)((this_)->super.klass))
|
#define As_Meter(this_) ((const MeterClass*)((this_)->super.klass))
|
||||||
@ -92,6 +93,7 @@ typedef struct MeterClass_ {
|
|||||||
#define Meter_attributes(this_) As_Meter(this_)->attributes
|
#define Meter_attributes(this_) As_Meter(this_)->attributes
|
||||||
#define Meter_name(this_) As_Meter(this_)->name
|
#define Meter_name(this_) As_Meter(this_)->name
|
||||||
#define Meter_uiName(this_) As_Meter(this_)->uiName
|
#define Meter_uiName(this_) As_Meter(this_)->uiName
|
||||||
|
#define Meter_isMultiColumn(this_) As_Meter(this_)->isMultiColumn
|
||||||
|
|
||||||
typedef struct GraphData_ {
|
typedef struct GraphData_ {
|
||||||
struct timeval time;
|
struct timeval time;
|
||||||
|
55
Process.c
55
Process.c
@ -707,6 +707,26 @@ void Process_printLeftAlignedField(RichString* str, int attr, const char* conten
|
|||||||
RichString_appendChr(str, attr, ' ', width + 1 - columns);
|
RichString_appendChr(str, attr, ' ', width + 1 - columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Process_printPercentage(float val, char* buffer, int n, int* attr) {
|
||||||
|
if (val >= 0) {
|
||||||
|
if (val < 99.9F) {
|
||||||
|
if (val < 0.05F) {
|
||||||
|
*attr = CRT_colors[PROCESS_SHADOW];
|
||||||
|
}
|
||||||
|
xSnprintf(buffer, n, "%4.1f ", val);
|
||||||
|
} else if (val < 999) {
|
||||||
|
*attr = CRT_colors[PROCESS_MEGABYTES];
|
||||||
|
xSnprintf(buffer, n, "%3d. ", (int)val);
|
||||||
|
} else {
|
||||||
|
*attr = CRT_colors[PROCESS_MEGABYTES];
|
||||||
|
xSnprintf(buffer, n, "%4d ", (int)val);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*attr = CRT_colors[PROCESS_SHADOW];
|
||||||
|
xSnprintf(buffer, n, " N/A ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Process_writeField(const Process* this, RichString* str, ProcessField field) {
|
void Process_writeField(const Process* this, RichString* str, ProcessField field) {
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
size_t n = sizeof(buffer);
|
size_t n = sizeof(buffer);
|
||||||
@ -821,34 +841,13 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field
|
|||||||
|
|
||||||
xSnprintf(buffer, n, "%4ld ", this->nlwp);
|
xSnprintf(buffer, n, "%4ld ", this->nlwp);
|
||||||
break;
|
break;
|
||||||
case PERCENT_CPU:
|
case PERCENT_CPU: Process_printPercentage(this->percent_cpu, buffer, n, &attr); break;
|
||||||
case PERCENT_NORM_CPU: {
|
case PERCENT_NORM_CPU: {
|
||||||
float cpuPercentage = this->percent_cpu;
|
float cpuPercentage = this->percent_cpu / this->processList->activeCPUs;
|
||||||
if (field == PERCENT_NORM_CPU) {
|
Process_printPercentage(cpuPercentage, buffer, n, &attr);
|
||||||
cpuPercentage /= this->processList->activeCPUs;
|
|
||||||
}
|
|
||||||
if (cpuPercentage > 999.9F) {
|
|
||||||
xSnprintf(buffer, n, "%4u ", (unsigned int)cpuPercentage);
|
|
||||||
} else if (cpuPercentage > 99.9F) {
|
|
||||||
xSnprintf(buffer, n, "%3u. ", (unsigned int)cpuPercentage);
|
|
||||||
} else {
|
|
||||||
if (cpuPercentage < 0.05F)
|
|
||||||
attr = CRT_colors[PROCESS_SHADOW];
|
|
||||||
|
|
||||||
xSnprintf(buffer, n, "%4.1f ", cpuPercentage);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PERCENT_MEM:
|
case PERCENT_MEM: Process_printPercentage(this->percent_mem, buffer, n, &attr); break;
|
||||||
if (this->percent_mem > 99.9F) {
|
|
||||||
xSnprintf(buffer, n, "100. ");
|
|
||||||
} else {
|
|
||||||
if (this->percent_mem < 0.05F)
|
|
||||||
attr = CRT_colors[PROCESS_SHADOW];
|
|
||||||
|
|
||||||
xSnprintf(buffer, n, "%4.1f ", this->percent_mem);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PGRP: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->pgrp); break;
|
case PGRP: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->pgrp); break;
|
||||||
case PID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->pid); break;
|
case PID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->pid); break;
|
||||||
case PPID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->ppid); break;
|
case PPID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->ppid); break;
|
||||||
@ -864,8 +863,12 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field
|
|||||||
case STATE:
|
case STATE:
|
||||||
xSnprintf(buffer, n, "%c ", this->state);
|
xSnprintf(buffer, n, "%c ", this->state);
|
||||||
switch (this->state) {
|
switch (this->state) {
|
||||||
|
#ifdef HTOP_NETBSD
|
||||||
|
case 'P':
|
||||||
|
#else
|
||||||
case 'R':
|
case 'R':
|
||||||
attr = CRT_colors[PROCESS_R_STATE];
|
#endif
|
||||||
|
attr = CRT_colors[PROCESS_RUN_STATE];
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
attr = CRT_colors[PROCESS_D_STATE];
|
attr = CRT_colors[PROCESS_D_STATE];
|
||||||
|
@ -79,8 +79,6 @@ typedef struct ProcessMergedCommand_ {
|
|||||||
char* str; /* merged Command string */
|
char* str; /* merged Command string */
|
||||||
size_t highlightCount; /* how many portions of cmdline to highlight */
|
size_t highlightCount; /* how many portions of cmdline to highlight */
|
||||||
ProcessCmdlineHighlight highlights[8]; /* which portions of cmdline to highlight */
|
ProcessCmdlineHighlight highlights[8]; /* which portions of cmdline to highlight */
|
||||||
bool separateComm : 1; /* whether comm is a separate field */
|
|
||||||
bool unmatchedExe : 1; /* whether exe matched with cmdline */
|
|
||||||
bool cmdlineChanged : 1; /* whether cmdline changed */
|
bool cmdlineChanged : 1; /* whether cmdline changed */
|
||||||
bool exeChanged : 1; /* whether exe changed */
|
bool exeChanged : 1; /* whether exe changed */
|
||||||
bool commChanged : 1; /* whether comm changed */
|
bool commChanged : 1; /* whether comm changed */
|
||||||
@ -358,6 +356,8 @@ void Process_fillStarttimeBuffer(Process* this);
|
|||||||
|
|
||||||
void Process_printLeftAlignedField(RichString* str, int attr, const char* content, unsigned int width);
|
void Process_printLeftAlignedField(RichString* str, int attr, const char* content, unsigned int width);
|
||||||
|
|
||||||
|
void Process_printPercentage(float val, char* buffer, int n, int* attr);
|
||||||
|
|
||||||
void Process_display(const Object* cast, RichString* out);
|
void Process_display(const Object* cast, RichString* out);
|
||||||
|
|
||||||
void Process_done(Process* this);
|
void Process_done(Process* this);
|
||||||
|
100
README
100
README
@ -1,10 +1,12 @@
|
|||||||
# [](https://htop.dev)
|
# [](https://htop.dev)
|
||||||
|
|
||||||
[](https://github.com/htop-dev/htop/actions)
|
[](https://github.com/htop-dev/htop/actions)
|
||||||
[](https://scan.coverity.com/projects/21665)
|
[](https://scan.coverity.com/projects/21665)
|
||||||
[](https://groups.io/g/htop)
|
[](https://groups.io/g/htop)
|
||||||
[](https://web.libera.chat/#htop)
|
[](https://web.libera.chat/#htop)
|
||||||
[](https://github.com/htop-dev/htop/releases/latest)
|
[](https://github.com/htop-dev/htop/releases/latest)
|
||||||
|
[](https://repology.org/project/htop/versions)
|
||||||
|
[](COPYING?raw=true)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@ -13,23 +15,27 @@
|
|||||||
`htop` is a cross-platform interactive process viewer.
|
`htop` is a cross-platform interactive process viewer.
|
||||||
|
|
||||||
`htop` allows scrolling the list of processes vertically and horizontally to see their full command lines and related information like memory and CPU consumption.
|
`htop` allows scrolling the list of processes vertically and horizontally to see their full command lines and related information like memory and CPU consumption.
|
||||||
|
Also system wide information, like load average or swap usage, is shown.
|
||||||
|
|
||||||
The information displayed is configurable through a graphical setup and can be sorted and filtered interactively.
|
The information displayed is configurable through a graphical setup and can be sorted and filtered interactively.
|
||||||
|
|
||||||
Tasks related to processes (e.g. killing and renicing) can be done without entering their PIDs.
|
Tasks related to processes (e.g. killing and renicing) can be done without entering their PIDs.
|
||||||
|
|
||||||
Running `htop` requires `ncurses` libraries (typically named libncursesw*).
|
Running `htop` requires `ncurses` libraries, typically named libncurses(w).
|
||||||
|
|
||||||
For more information and details on how to contribute to `htop` visit [htop.dev](https://htop.dev).
|
`htop` is written in C.
|
||||||
|
|
||||||
|
For more information and details visit [htop.dev](https://htop.dev).
|
||||||
|
|
||||||
## Build instructions
|
## Build instructions
|
||||||
|
|
||||||
### Prerequisite
|
### Prerequisite
|
||||||
List of build-time dependencies:
|
List of build-time dependencies:
|
||||||
* `build-essential` standard GNU autotools-based
|
* standard GNU autotools-based C toolchain
|
||||||
* `autoconf`
|
- C99 compliant compiler
|
||||||
* `autotools`
|
- `autoconf`
|
||||||
* `ncurses`
|
- `autotools`
|
||||||
|
* `ncurses`
|
||||||
|
|
||||||
**Note about `ncurses`:**
|
**Note about `ncurses`:**
|
||||||
> htop requires ncurses 6.0. Be aware the appropriate package is sometimes still called libncurses5 (on Debian/Ubuntu). Also ncurses usually comes in two flavours:
|
> htop requires ncurses 6.0. Be aware the appropriate package is sometimes still called libncurses5 (on Debian/Ubuntu). Also ncurses usually comes in two flavours:
|
||||||
@ -42,27 +48,26 @@ List of additional build-time dependencies (based on feature flags):
|
|||||||
* `sensors`
|
* `sensors`
|
||||||
* `hwloc`
|
* `hwloc`
|
||||||
* `libcap`
|
* `libcap`
|
||||||
|
* `libnl-3`
|
||||||
|
|
||||||
Compiling `htop` requires the header files for `ncurses` . Install these and other required packages for C development from your package manager.
|
Install these and other required packages for C development from your package manager.
|
||||||
|
|
||||||
**Debian/Ubuntu**
|
**Debian/Ubuntu**
|
||||||
~~~ shell
|
~~~ shell
|
||||||
sudo apt install libncursesw5-dev autotools-dev autoconf
|
sudo apt install libncursesw5-dev autotools-dev autoconf build-essential
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
**Fedora/RHEL**
|
**Fedora/RHEL**
|
||||||
~~~ shell
|
~~~ shell
|
||||||
sudo dnf install ncurses-devel automake autoconf
|
sudo dnf install ncurses-devel automake autoconf gcc
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
### Compiling from source:
|
### Compile from source:
|
||||||
To compile from sources downloaded from the Git repository (`git clone` or downloads from [Github releases](https://github.com/htop-dev/htop/releases/)), then run:
|
To compile from source, download from the Git repository (`git clone` or downloads from [GitHub releases](https://github.com/htop-dev/htop/releases/)), then run:
|
||||||
~~~ shell
|
~~~ shell
|
||||||
./autogen.sh && ./configure && make
|
./autogen.sh && ./configure && make
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
By default `make install` will install into `/usr/local`, for changing the path use `./configure --prefix=/some/path`.
|
|
||||||
|
|
||||||
### Install
|
### Install
|
||||||
To install on the local system run `make install`. By default `make install` installs into `/usr/local`. To change this path use `./configure --prefix=/some/path`.
|
To install on the local system run `make install`. By default `make install` installs into `/usr/local`. To change this path use `./configure --prefix=/some/path`.
|
||||||
|
|
||||||
@ -74,52 +79,55 @@ To install on the local system run `make install`. By default `make install` ins
|
|||||||
|
|
||||||
* `--enable-unicode`:
|
* `--enable-unicode`:
|
||||||
enable Unicode support
|
enable Unicode support
|
||||||
dependency: *libncursesw*
|
- dependency: *libncursesw*
|
||||||
default: *yes*
|
- default: *yes*
|
||||||
* `--enable-pcp`:
|
|
||||||
enable Performance Co-Pilot support via a new pcp-htop utility
|
|
||||||
dependency: *libpcp*
|
|
||||||
default: *no*
|
|
||||||
* `--enable-affinity`:
|
* `--enable-affinity`:
|
||||||
enable `sched_setaffinity(2)` and `sched_getaffinity(2)` for affinity support; conflicts with hwloc
|
enable `sched_setaffinity(2)` and `sched_getaffinity(2)` for affinity support; conflicts with hwloc
|
||||||
default: *check*
|
- default: *check*
|
||||||
* `--enable-hwloc`:
|
* `--enable-hwloc`:
|
||||||
enable hwloc support for CPU affinity; disables affinity support
|
enable hwloc support for CPU affinity; disables affinity support
|
||||||
dependency: *libhwloc*
|
- dependency: *libhwloc*
|
||||||
default: *no*
|
- default: *no*
|
||||||
* `--enable-static`:
|
* `--enable-static`:
|
||||||
build a static htop binary; hwloc and delay accounting are not supported
|
build a static htop binary; hwloc and delay accounting are not supported
|
||||||
default: *no*
|
- default: *no*
|
||||||
* `--enable-debug`:
|
* `--enable-debug`:
|
||||||
Enable asserts and internal sanity checks; implies a performance penalty
|
Enable asserts and internal sanity checks; implies a performance penalty
|
||||||
default: *no*
|
- default: *no*
|
||||||
|
|
||||||
|
#### Performance Co-Pilot
|
||||||
|
|
||||||
|
* `--enable-pcp`:
|
||||||
|
enable Performance Co-Pilot support via a new pcp-htop utility
|
||||||
|
- dependency: *libpcp*
|
||||||
|
- default: *no*
|
||||||
|
|
||||||
#### Linux
|
#### Linux
|
||||||
|
|
||||||
* `--enable-sensors`:
|
* `--enable-sensors`:
|
||||||
enable libsensors(3) support for reading temperature data
|
enable libsensors(3) support for reading temperature data
|
||||||
dependencies: *libsensors-dev*(build-time), at runtime *libsensors* is loaded via `dlopen(3)` if available
|
- dependencies: *libsensors-dev*(build-time), at runtime *libsensors* is loaded via `dlopen(3)` if available
|
||||||
default: *check*
|
- default: *check*
|
||||||
* `--enable-capabilities`:
|
* `--enable-capabilities`:
|
||||||
enable Linux capabilities support
|
enable Linux capabilities support
|
||||||
dependency: *libcap*
|
- dependency: *libcap*
|
||||||
default: *check*
|
- default: *check*
|
||||||
* `--with-proc`:
|
* `--with-proc`:
|
||||||
location of a Linux-compatible proc filesystem
|
location of a Linux-compatible proc filesystem
|
||||||
default: */proc*
|
- default: */proc*
|
||||||
* `--enable-openvz`:
|
* `--enable-openvz`:
|
||||||
enable OpenVZ support
|
enable OpenVZ support
|
||||||
default: *no*
|
- default: *no*
|
||||||
* `--enable-vserver`:
|
* `--enable-vserver`:
|
||||||
enable VServer support
|
enable VServer support
|
||||||
default: *no*
|
- default: *no*
|
||||||
* `--enable-ancient-vserver`:
|
* `--enable-ancient-vserver`:
|
||||||
enable ancient VServer support (implies `--enable-vserver`)
|
enable ancient VServer support (implies `--enable-vserver`)
|
||||||
default: *no*
|
- default: *no*
|
||||||
* `--enable-delayacct`:
|
* `--enable-delayacct`:
|
||||||
enable Linux delay accounting support
|
enable Linux delay accounting support
|
||||||
dependencies: *pkg-config*(build-time), *libnl-3* and *libnl-genl-3*
|
- dependencies: *pkg-config*(build-time), *libnl-3* and *libnl-genl-3*
|
||||||
default: *check*
|
- default: *check*
|
||||||
|
|
||||||
|
|
||||||
## Runtime dependencies:
|
## Runtime dependencies:
|
||||||
@ -128,20 +136,22 @@ To install on the local system run `make install`. By default `make install` ins
|
|||||||
|
|
||||||
### Runtime optional dependencies:
|
### Runtime optional dependencies:
|
||||||
`htop` has a set of fixed optional dependencies, depending on build/configure option used:
|
`htop` has a set of fixed optional dependencies, depending on build/configure option used:
|
||||||
* `libdl`, if not building static and support for some of the optional libraries is enabled, is always required when support for to optionally load dependencies (i.e. `libsensors`, `systemd`) is present.
|
|
||||||
|
#### Linux
|
||||||
|
* `libdl`, if not building a static binary, is always required when support for to optionally dependencies (i.e. `libsensors`, `libsystemd`) is present.
|
||||||
* `libcap`, user-space interfaces to the POSIX 1003.1e, is always required when `--enable-capabilities` was used to configure `htop`.
|
* `libcap`, user-space interfaces to the POSIX 1003.1e, is always required when `--enable-capabilities` was used to configure `htop`.
|
||||||
* `libsensors`, readout of temperatures and CPU speeds, is optional even when `--enable-sensors` was used to configure `htop`.
|
* `libsensors`, readout of temperatures and CPU speeds, is optional even when `--enable-sensors` was used to configure `htop`.
|
||||||
* `systemd` is optional when `--enable-static` was not used to configure `htop` (Linux only). If building statically and `libsystemd` is not found by `configure` support for the SystemD meter is disabled entirely.
|
* `libsystemd` is optional when `--enable-static` was not used to configure `htop`. If building statically and `libsystemd` is not found by `configure`, support for the systemd meter is disabled entirely.
|
||||||
|
|
||||||
`htop` checks for the availability of the actual runtime lib as `htop` runs.
|
`htop` checks for the availability of the actual runtime lib as `htop` runs.
|
||||||
|
|
||||||
**BSD**
|
#### BSD
|
||||||
On most *BSD systems you also have `kvm` as a static requirement to read all the kernel information.
|
On most BSD systems `kvm` is a requirement to read kernel information.
|
||||||
|
|
||||||
More information on required and optional dependencies can be found in [configure.ac](configure.ac).
|
More information on required and optional dependencies can be found in [configure.ac](configure.ac).
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
See the manual page (`man htop`) or the on-line help ('F1' or 'h' inside `htop`) for a list of supported key commands.
|
See the manual page (`man htop`) or the help menu (**F1** or **h** inside `htop`) for a list of supported key commands.
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
@ -151,14 +161,14 @@ If you have trouble running `htop` please consult your Operating System / Linux
|
|||||||
|
|
||||||
We have a [development mailing list](https://htop.dev/mailinglist.html). Feel free to subscribe for release announcements or asking questions on the development of htop.
|
We have a [development mailing list](https://htop.dev/mailinglist.html). Feel free to subscribe for release announcements or asking questions on the development of htop.
|
||||||
|
|
||||||
You can also join our IRC channel #htop on Libera.Chat and talk to the developers there.
|
You can also join our IRC channel [#htop on Libera.Chat](https://web.libera.chat/#htop) and talk to the developers there.
|
||||||
|
|
||||||
If you have found an issue with the source of htop, please check whether this has already been reported in our [Github issue tracker](https://github.com/htop-dev/htop/issues).
|
If you have found an issue within the source of htop, please check whether this has already been reported in our [GitHub issue tracker](https://github.com/htop-dev/htop/issues).
|
||||||
If not, please file a new issue describing the problem you have found, the location in the source code you are referring to and a possible fix.
|
If not, please file a new issue describing the problem you have found, the potential location in the source code you are referring to and a possible fix if available.
|
||||||
|
|
||||||
## History
|
## History
|
||||||
|
|
||||||
`htop` was invented, developed and maintained by Hisham Muhammad from 2004 to 2019. His [legacy repository](https://github.com/hishamhm/htop/) has been archived to preserve the history.
|
`htop` was invented, developed and maintained by [Hisham Muhammad](https://hisham.hm/) from 2004 to 2019. His [legacy repository](https://github.com/hishamhm/htop/) has been archived to preserve the history.
|
||||||
|
|
||||||
In 2020 a [team](https://github.com/orgs/htop-dev/people) took over the development amicably and continues to maintain `htop` collaboratively.
|
In 2020 a [team](https://github.com/orgs/htop-dev/people) took over the development amicably and continues to maintain `htop` collaboratively.
|
||||||
|
|
||||||
|
16
Settings.c
16
Settings.c
@ -134,8 +134,9 @@ static void Settings_readFields(Settings* settings, const char* line) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dynamically-defined columns are always stored by-name.
|
// Dynamically-defined columns are always stored by-name.
|
||||||
char* end, dynamic[32] = {0};
|
char dynamic[32] = {0};
|
||||||
if (sscanf(ids[i], "Dynamic(%30s)", dynamic)) {
|
if (sscanf(ids[i], "Dynamic(%30s)", dynamic)) {
|
||||||
|
char* end;
|
||||||
if ((end = strrchr(dynamic, ')')) == NULL)
|
if ((end = strrchr(dynamic, ')')) == NULL)
|
||||||
continue;
|
continue;
|
||||||
*end = '\0';
|
*end = '\0';
|
||||||
@ -180,8 +181,10 @@ static bool Settings_read(Settings* this, const char* fileName, unsigned int ini
|
|||||||
this->config_version = atoi(option[1]);
|
this->config_version = atoi(option[1]);
|
||||||
if (this->config_version > CONFIG_READER_MIN_VERSION) {
|
if (this->config_version > CONFIG_READER_MIN_VERSION) {
|
||||||
// the version of the config file on disk is newer than what we can read
|
// the version of the config file on disk is newer than what we can read
|
||||||
fprintf(stderr, "WARNING: %s specifies configuration format version v%d, but this %s binary supports up to v%d.", fileName, this->config_version, PACKAGE, CONFIG_READER_MIN_VERSION);
|
fprintf(stderr, "WARNING: %s specifies configuration format version v%d, but this %s binary supports up to v%d\n.", fileName, this->config_version, PACKAGE, CONFIG_READER_MIN_VERSION);
|
||||||
fprintf(stderr, " The configuration version will be downgraded to v%d when %s exits.\n", CONFIG_READER_MIN_VERSION, PACKAGE);
|
fprintf(stderr, " The configuration version will be downgraded to v%d when %s exits.\n", CONFIG_READER_MIN_VERSION, PACKAGE);
|
||||||
|
String_freeArray(option);
|
||||||
|
fclose(fd);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (String_eq(option[0], "fields")) {
|
} else if (String_eq(option[0], "fields")) {
|
||||||
@ -355,9 +358,9 @@ int Settings_write(const Settings* this, bool onCrash) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define printSettingInteger(setting_, value_) \
|
#define printSettingInteger(setting_, value_) \
|
||||||
fprintf(fd, setting_ "=%d%c", (int) value_, separator);
|
fprintf(fd, setting_ "=%d%c", (int) (value_), separator)
|
||||||
#define printSettingString(setting_, value_) \
|
#define printSettingString(setting_, value_) \
|
||||||
fprintf(fd, setting_ "=%s%c", value_, separator);
|
fprintf(fd, setting_ "=%s%c", value_, separator)
|
||||||
|
|
||||||
if (!onCrash) {
|
if (!onCrash) {
|
||||||
fprintf(fd, "# Beware! This file is rewritten by htop when settings are changed in the interface.\n");
|
fprintf(fd, "# Beware! This file is rewritten by htop when settings are changed in the interface.\n");
|
||||||
@ -539,7 +542,10 @@ Settings* Settings_new(unsigned int initialCpuCount, Hashtable* dynamicColumns)
|
|||||||
}
|
}
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
this->changed = true;
|
this->changed = true;
|
||||||
Settings_read(this, SYSCONFDIR "/htoprc", initialCpuCount);
|
ok = Settings_read(this, SYSCONFDIR "/htoprc", initialCpuCount);
|
||||||
|
}
|
||||||
|
if (!ok) {
|
||||||
|
Settings_defaultMeters(this, initialCpuCount);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
16
XUtils.c
16
XUtils.c
@ -78,6 +78,22 @@ void* xReallocArray(void* ptr, size_t nmemb, size_t size) {
|
|||||||
return xRealloc(ptr, nmemb * size);
|
return xRealloc(ptr, nmemb * size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* xReallocArrayZero(void* ptr, size_t prevmemb, size_t newmemb, size_t size) {
|
||||||
|
assert((ptr == NULL) == (prevmemb == 0));
|
||||||
|
|
||||||
|
if (prevmemb == newmemb) {
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* ret = xReallocArray(ptr, newmemb, size);
|
||||||
|
|
||||||
|
if (newmemb > prevmemb) {
|
||||||
|
memset((unsigned char*)ret + prevmemb * size, '\0', (newmemb - prevmemb) * size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool String_contains_i(const char* s1, const char* s2) {
|
inline bool String_contains_i(const char* s1, const char* s2) {
|
||||||
return strcasestr(s1, s2) != NULL;
|
return strcasestr(s1, s2) != NULL;
|
||||||
}
|
}
|
||||||
|
2
XUtils.h
2
XUtils.h
@ -30,6 +30,8 @@ void* xRealloc(void* ptr, size_t size) ATTR_ALLOC_SIZE1(2);
|
|||||||
|
|
||||||
void* xReallocArray(void* ptr, size_t nmemb, size_t size) ATTR_ALLOC_SIZE2(2, 3);
|
void* xReallocArray(void* ptr, size_t nmemb, size_t size) ATTR_ALLOC_SIZE2(2, 3);
|
||||||
|
|
||||||
|
void* xReallocArrayZero(void* ptr, size_t prevmemb, size_t newmemb, size_t size) ATTR_ALLOC_SIZE2(3, 4);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* String_startsWith gives better performance if strlen(match) can be computed
|
* String_startsWith gives better performance if strlen(match) can be computed
|
||||||
* at compile time (e.g. when they are immutable string literals). :)
|
* at compile time (e.g. when they are immutable string literals). :)
|
||||||
|
13
configure.ac
13
configure.ac
@ -6,7 +6,7 @@
|
|||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
AC_PREREQ([2.69])
|
AC_PREREQ([2.69])
|
||||||
AC_INIT([htop], [3.1.0-dev], [htop@groups.io], [], [https://htop.dev/])
|
AC_INIT([htop], [3.1.0-rc2], [htop@groups.io], [], [https://htop.dev/])
|
||||||
|
|
||||||
AC_CONFIG_SRCDIR([htop.c])
|
AC_CONFIG_SRCDIR([htop.c])
|
||||||
AC_CONFIG_AUX_DIR([build-aux])
|
AC_CONFIG_AUX_DIR([build-aux])
|
||||||
@ -367,7 +367,7 @@ if test "$enable_static" = yes; then
|
|||||||
fi
|
fi
|
||||||
if test "$my_htop_platform" = "solaris"; then
|
if test "$my_htop_platform" = "solaris"; then
|
||||||
# On OmniOS /usr/include/sys/regset.h redefines ERR to 13 - \r, breaking the Enter key.
|
# On OmniOS /usr/include/sys/regset.h redefines ERR to 13 - \r, breaking the Enter key.
|
||||||
# Since ncruses macros use the ERR macro, we can not use another name.
|
# Since ncurses macros use the ERR macro, we can not use another name.
|
||||||
AC_DEFINE([ERR], [(-1)], [Predefine ncurses macro.])
|
AC_DEFINE([ERR], [(-1)], [Predefine ncurses macro.])
|
||||||
fi
|
fi
|
||||||
AC_CHECK_FUNCS( [set_escdelay] )
|
AC_CHECK_FUNCS( [set_escdelay] )
|
||||||
@ -472,7 +472,7 @@ AC_ARG_ENABLE([vserver],
|
|||||||
[],
|
[],
|
||||||
[enable_vserver=no])
|
[enable_vserver=no])
|
||||||
if test "x$enable_vserver" = xyes; then
|
if test "x$enable_vserver" = xyes; then
|
||||||
AC_DEFINE([HAVE_VSERVER], [1], [Define if VServer support enabled.])
|
AC_DEFINE([HAVE_VSERVER], [1], [Define if VServer support enabled.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
@ -482,8 +482,11 @@ AC_ARG_ENABLE([ancient_vserver],
|
|||||||
[],
|
[],
|
||||||
[enable_ancient_vserver=no])
|
[enable_ancient_vserver=no])
|
||||||
if test "x$enable_ancient_vserver" = xyes; then
|
if test "x$enable_ancient_vserver" = xyes; then
|
||||||
AC_DEFINE([HAVE_VSERVER], [1], [Define if VServer support enabled.])
|
if test "x$enable_vserver" != xyes; then
|
||||||
AC_DEFINE([HAVE_ANCIENT_VSERVER], [1], [Define if ancient vserver support enabled.])
|
enable_vserver=implied
|
||||||
|
fi
|
||||||
|
AC_DEFINE([HAVE_VSERVER], [1], [Define if VServer support enabled.])
|
||||||
|
AC_DEFINE([HAVE_ANCIENT_VSERVER], [1], [Define if ancient vserver support enabled.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ ERROR_A:
|
|||||||
Process_updateCmdline(proc, k->kp_proc.p_comm, 0, strlen(k->kp_proc.p_comm));
|
Process_updateCmdline(proc, k->kp_proc.p_comm, 0, strlen(k->kp_proc.p_comm));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts nanoseconds to hundreths of a second (centiseconds) as needed by the "time" field of the Process struct.
|
// Converts nanoseconds to hundredths of a second (centiseconds) as needed by the "time" field of the Process struct.
|
||||||
static long long int nanosecondsToCentiseconds(uint64_t nanoseconds) {
|
static long long int nanosecondsToCentiseconds(uint64_t nanoseconds) {
|
||||||
const uint64_t centiseconds_per_second = 100;
|
const uint64_t centiseconds_per_second = 100;
|
||||||
const uint64_t nanoseconds_per_second = 1e9;
|
const uint64_t nanoseconds_per_second = 1e9;
|
||||||
|
@ -432,7 +432,8 @@ void Platform_gettime_monotonic(uint64_t* msec) {
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
Generic_gettime_monotomic(msec);
|
Generic_gettime_monotonic(msec);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,8 @@ void Platform_gettime_monotonic(uint64_t* msec);
|
|||||||
|
|
||||||
static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
|
static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
|
||||||
|
|
||||||
|
static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
|
||||||
|
|
||||||
static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { }
|
static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { }
|
||||||
|
|
||||||
static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { }
|
static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { }
|
||||||
@ -107,6 +109,8 @@ static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter,
|
|||||||
|
|
||||||
static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
|
static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
|
||||||
|
|
||||||
|
static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
|
||||||
|
|
||||||
static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
|
static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
|
||||||
|
|
||||||
static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
|
static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
|
||||||
|
@ -92,6 +92,8 @@ static inline void Platform_gettime_monotonic(uint64_t* msec) {
|
|||||||
|
|
||||||
static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
|
static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
|
||||||
|
|
||||||
|
static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
|
||||||
|
|
||||||
static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { }
|
static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { }
|
||||||
|
|
||||||
static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { }
|
static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { }
|
||||||
@ -100,6 +102,8 @@ static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter,
|
|||||||
|
|
||||||
static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
|
static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
|
||||||
|
|
||||||
|
static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
|
||||||
|
|
||||||
static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
|
static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
|
||||||
|
|
||||||
static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
|
static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
|
||||||
|
@ -92,6 +92,8 @@ static inline void Platform_gettime_monotonic(uint64_t* msec) {
|
|||||||
|
|
||||||
static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
|
static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
|
||||||
|
|
||||||
|
static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
|
||||||
|
|
||||||
static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { }
|
static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { }
|
||||||
|
|
||||||
static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { }
|
static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { }
|
||||||
@ -102,6 +104,8 @@ static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
|
|||||||
|
|
||||||
static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
|
static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
|
||||||
|
|
||||||
|
static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
|
||||||
|
|
||||||
static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
|
static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -392,9 +392,6 @@ except the process's executable instructions).
|
|||||||
.B M_LRS (LIB)
|
.B M_LRS (LIB)
|
||||||
The library size of the process.
|
The library size of the process.
|
||||||
.TP
|
.TP
|
||||||
.B M_DT (DIRTY)
|
|
||||||
The size of the dirty pages of the process.
|
|
||||||
.TP
|
|
||||||
.B M_SWAP (SWAP)
|
.B M_SWAP (SWAP)
|
||||||
The size of the process's swapped pages.
|
The size of the process's swapped pages.
|
||||||
.TP
|
.TP
|
||||||
|
@ -30,8 +30,6 @@ typedef int IOPriority;
|
|||||||
|
|
||||||
#define IOPriority_tuple(class_, data_) (((class_) << IOPRIO_CLASS_SHIFT) | (data_))
|
#define IOPriority_tuple(class_, data_) (((class_) << IOPRIO_CLASS_SHIFT) | (data_))
|
||||||
|
|
||||||
#define IOPriority_error 0xffffffff
|
|
||||||
|
|
||||||
#define IOPriority_None IOPriority_tuple(IOPRIO_CLASS_NONE, 0)
|
#define IOPriority_None IOPriority_tuple(IOPRIO_CLASS_NONE, 0)
|
||||||
#define IOPriority_Idle IOPriority_tuple(IOPRIO_CLASS_IDLE, 7)
|
#define IOPriority_Idle IOPriority_tuple(IOPRIO_CLASS_IDLE, 7)
|
||||||
|
|
||||||
|
@ -56,7 +56,6 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
|
|||||||
[M_TRS] = { .name = "M_TRS", .title = " CODE ", .description = "Size of the text segment of the process", .flags = 0, .defaultSortDesc = true, },
|
[M_TRS] = { .name = "M_TRS", .title = " CODE ", .description = "Size of the text segment of the process", .flags = 0, .defaultSortDesc = true, },
|
||||||
[M_DRS] = { .name = "M_DRS", .title = " DATA ", .description = "Size of the data segment plus stack usage of the process", .flags = 0, .defaultSortDesc = true, },
|
[M_DRS] = { .name = "M_DRS", .title = " DATA ", .description = "Size of the data segment plus stack usage of the process", .flags = 0, .defaultSortDesc = true, },
|
||||||
[M_LRS] = { .name = "M_LRS", .title = " LIB ", .description = "The library size of the process (calculated from memory maps)", .flags = PROCESS_FLAG_LINUX_LRS_FIX, .defaultSortDesc = true, },
|
[M_LRS] = { .name = "M_LRS", .title = " LIB ", .description = "The library size of the process (calculated from memory maps)", .flags = PROCESS_FLAG_LINUX_LRS_FIX, .defaultSortDesc = true, },
|
||||||
[M_DT] = { .name = "M_DT", .title = " DIRTY ", .description = "Size of the dirty pages of the process (unused since Linux 2.6; always 0)", .flags = 0, .defaultSortDesc = true, },
|
|
||||||
[ST_UID] = { .name = "ST_UID", .title = " UID ", .description = "User ID of the process owner", .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, .defaultSortDesc = true, },
|
[PERCENT_CPU] = { .name = "PERCENT_CPU", .title = "CPU% ", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, },
|
||||||
[PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, },
|
[PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, },
|
||||||
@ -86,9 +85,9 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
|
|||||||
[OOM] = { .name = "OOM", .title = " OOM ", .description = "OOM (Out-of-Memory) killer score", .flags = PROCESS_FLAG_LINUX_OOM, .defaultSortDesc = true, },
|
[OOM] = { .name = "OOM", .title = " OOM ", .description = "OOM (Out-of-Memory) killer score", .flags = PROCESS_FLAG_LINUX_OOM, .defaultSortDesc = true, },
|
||||||
[IO_PRIORITY] = { .name = "IO_PRIORITY", .title = "IO ", .description = "I/O priority", .flags = PROCESS_FLAG_LINUX_IOPRIO, },
|
[IO_PRIORITY] = { .name = "IO_PRIORITY", .title = "IO ", .description = "I/O priority", .flags = PROCESS_FLAG_LINUX_IOPRIO, },
|
||||||
#ifdef HAVE_DELAYACCT
|
#ifdef HAVE_DELAYACCT
|
||||||
[PERCENT_CPU_DELAY] = { .name = "PERCENT_CPU_DELAY", .title = "CPUD% ", .description = "CPU delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, .defaultSortDesc = true, },
|
[PERCENT_CPU_DELAY] = { .name = "PERCENT_CPU_DELAY", .title = "CPUD%", .description = "CPU delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, .defaultSortDesc = true, },
|
||||||
[PERCENT_IO_DELAY] = { .name = "PERCENT_IO_DELAY", .title = "IOD% ", .description = "Block I/O delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, .defaultSortDesc = true, },
|
[PERCENT_IO_DELAY] = { .name = "PERCENT_IO_DELAY", .title = "IOD% ", .description = "Block I/O delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, .defaultSortDesc = true, },
|
||||||
[PERCENT_SWAP_DELAY] = { .name = "PERCENT_SWAP_DELAY", .title = "SWAPD% ", .description = "Swapin delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, .defaultSortDesc = true, },
|
[PERCENT_SWAP_DELAY] = { .name = "PERCENT_SWAP_DELAY", .title = "SWPD%", .description = "Swapin delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, .defaultSortDesc = true, },
|
||||||
#endif
|
#endif
|
||||||
[M_PSS] = { .name = "M_PSS", .title = " PSS ", .description = "proportional set size, same as M_RESIDENT but each page is divided by the number of processes sharing it", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, },
|
[M_PSS] = { .name = "M_PSS", .title = " PSS ", .description = "proportional set size, same as M_RESIDENT but each page is divided by the number of processes sharing it", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, },
|
||||||
[M_SWAP] = { .name = "M_SWAP", .title = " SWAP ", .description = "Size of the process's swapped pages", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, },
|
[M_SWAP] = { .name = "M_SWAP", .title = " SWAP ", .description = "Size of the process's swapped pages", .flags = PROCESS_FLAG_LINUX_SMAPS, .defaultSortDesc = true, },
|
||||||
@ -190,16 +189,6 @@ bool LinuxProcess_changeAutogroupPriorityBy(Process* this, Arg delta) {
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DELAYACCT
|
|
||||||
static void LinuxProcess_printDelay(float delay_percent, char* buffer, int n) {
|
|
||||||
if (isnan(delay_percent)) {
|
|
||||||
xSnprintf(buffer, n, " N/A ");
|
|
||||||
} else {
|
|
||||||
xSnprintf(buffer, n, "%4.1f ", delay_percent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void LinuxProcess_writeField(const Process* this, RichString* str, ProcessField field) {
|
static void LinuxProcess_writeField(const Process* this, RichString* str, ProcessField field) {
|
||||||
const LinuxProcess* lp = (const LinuxProcess*) this;
|
const LinuxProcess* lp = (const LinuxProcess*) this;
|
||||||
bool coloring = this->settings->highlightMegabytes;
|
bool coloring = this->settings->highlightMegabytes;
|
||||||
@ -210,7 +199,6 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces
|
|||||||
case CMINFLT: Process_printCount(str, lp->cminflt, coloring); return;
|
case CMINFLT: Process_printCount(str, lp->cminflt, coloring); return;
|
||||||
case CMAJFLT: Process_printCount(str, lp->cmajflt, coloring); return;
|
case CMAJFLT: Process_printCount(str, lp->cmajflt, coloring); return;
|
||||||
case M_DRS: Process_printBytes(str, lp->m_drs * pageSize, coloring); return;
|
case M_DRS: Process_printBytes(str, lp->m_drs * pageSize, coloring); return;
|
||||||
case M_DT: Process_printBytes(str, lp->m_dt * pageSize, coloring); return;
|
|
||||||
case M_LRS:
|
case M_LRS:
|
||||||
if (lp->m_lrs) {
|
if (lp->m_lrs) {
|
||||||
Process_printBytes(str, lp->m_lrs * pageSize, coloring);
|
Process_printBytes(str, lp->m_lrs * pageSize, coloring);
|
||||||
@ -279,9 +267,9 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_DELAYACCT
|
#ifdef HAVE_DELAYACCT
|
||||||
case PERCENT_CPU_DELAY: LinuxProcess_printDelay(lp->cpu_delay_percent, buffer, n); break;
|
case PERCENT_CPU_DELAY: Process_printPercentage(lp->cpu_delay_percent, buffer, n, &attr); break;
|
||||||
case PERCENT_IO_DELAY: LinuxProcess_printDelay(lp->blkio_delay_percent, buffer, n); break;
|
case PERCENT_IO_DELAY: Process_printPercentage(lp->blkio_delay_percent, buffer, n, &attr); break;
|
||||||
case PERCENT_SWAP_DELAY: LinuxProcess_printDelay(lp->swapin_delay_percent, buffer, n); break;
|
case PERCENT_SWAP_DELAY: Process_printPercentage(lp->swapin_delay_percent, buffer, n, &attr); break;
|
||||||
#endif
|
#endif
|
||||||
case CTXT:
|
case CTXT:
|
||||||
if (lp->ctxt_diff > 1000) {
|
if (lp->ctxt_diff > 1000) {
|
||||||
@ -330,8 +318,6 @@ static int LinuxProcess_compareByKey(const Process* v1, const Process* v2, Proce
|
|||||||
switch (key) {
|
switch (key) {
|
||||||
case M_DRS:
|
case M_DRS:
|
||||||
return SPACESHIP_NUMBER(p1->m_drs, p2->m_drs);
|
return SPACESHIP_NUMBER(p1->m_drs, p2->m_drs);
|
||||||
case M_DT:
|
|
||||||
return SPACESHIP_NUMBER(p1->m_dt, p2->m_dt);
|
|
||||||
case M_LRS:
|
case M_LRS:
|
||||||
return SPACESHIP_NUMBER(p1->m_lrs, p2->m_lrs);
|
return SPACESHIP_NUMBER(p1->m_lrs, p2->m_lrs);
|
||||||
case M_TRS:
|
case M_TRS:
|
||||||
|
@ -47,7 +47,6 @@ typedef struct LinuxProcess_ {
|
|||||||
long m_trs;
|
long m_trs;
|
||||||
long m_drs;
|
long m_drs;
|
||||||
long m_lrs;
|
long m_lrs;
|
||||||
long m_dt;
|
|
||||||
|
|
||||||
/* Data read (in bytes) */
|
/* Data read (in bytes) */
|
||||||
unsigned long long io_rchar;
|
unsigned long long io_rchar;
|
||||||
|
@ -167,11 +167,11 @@ static void LinuxProcessList_updateCPUcount(ProcessList* super) {
|
|||||||
|
|
||||||
DIR* dir = opendir("/sys/devices/system/cpu");
|
DIR* dir = opendir("/sys/devices/system/cpu");
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
super->activeCPUs = 1;
|
this->cpuData = xReallocArrayZero(this->cpuData, super->existingCPUs ? (super->existingCPUs + 1) : 0, 2, sizeof(CPUData));
|
||||||
super->existingCPUs = 1;
|
|
||||||
this->cpuData = xReallocArray(this->cpuData, 2, sizeof(CPUData));
|
|
||||||
this->cpuData[0].online = true; /* average is always "online" */
|
this->cpuData[0].online = true; /* average is always "online" */
|
||||||
this->cpuData[1].online = true;
|
this->cpuData[1].online = true;
|
||||||
|
super->activeCPUs = 1;
|
||||||
|
super->existingCPUs = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,10 +204,7 @@ static void LinuxProcessList_updateCPUcount(ProcessList* super) {
|
|||||||
/* readdir() iterates with no specific order */
|
/* readdir() iterates with no specific order */
|
||||||
unsigned int max = MAXIMUM(existing, id + 1);
|
unsigned int max = MAXIMUM(existing, id + 1);
|
||||||
if (max > currExisting) {
|
if (max > currExisting) {
|
||||||
this->cpuData = xReallocArray(this->cpuData, max + /* aggregate */ 1, sizeof(CPUData));
|
this->cpuData = xReallocArrayZero(this->cpuData, currExisting ? (currExisting + 1) : 0, max + /* aggregate */ 1, sizeof(CPUData));
|
||||||
for (unsigned int j = currExisting; j < max; j++) {
|
|
||||||
this->cpuData[j].online = false;
|
|
||||||
}
|
|
||||||
this->cpuData[0].online = true; /* average is always "online" */
|
this->cpuData[0].online = true; /* average is always "online" */
|
||||||
currExisting = max;
|
currExisting = max;
|
||||||
}
|
}
|
||||||
@ -678,7 +675,7 @@ static bool LinuxProcessList_readStatmFile(LinuxProcess* process, openat_arg_t p
|
|||||||
if (!statmfile)
|
if (!statmfile)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
long int dummy;
|
long int dummy, dummy2;
|
||||||
|
|
||||||
int r = fscanf(statmfile, "%ld %ld %ld %ld %ld %ld %ld",
|
int r = fscanf(statmfile, "%ld %ld %ld %ld %ld %ld %ld",
|
||||||
&process->super.m_virt,
|
&process->super.m_virt,
|
||||||
@ -687,7 +684,7 @@ static bool LinuxProcessList_readStatmFile(LinuxProcess* process, openat_arg_t p
|
|||||||
&process->m_trs,
|
&process->m_trs,
|
||||||
&dummy, /* unused since Linux 2.6; always 0 */
|
&dummy, /* unused since Linux 2.6; always 0 */
|
||||||
&process->m_drs,
|
&process->m_drs,
|
||||||
&process->m_dt);
|
&dummy2); /* unused since Linux 2.6; always 0 */
|
||||||
fclose(statmfile);
|
fclose(statmfile);
|
||||||
|
|
||||||
if (r == 7) {
|
if (r == 7) {
|
||||||
@ -1426,14 +1423,14 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
|
|||||||
{
|
{
|
||||||
bool prev = proc->usesDeletedLib;
|
bool prev = proc->usesDeletedLib;
|
||||||
|
|
||||||
if ((lp->m_lrs == 0 && (settings->flags & PROCESS_FLAG_LINUX_LRS_FIX)) ||
|
if ((settings->flags & PROCESS_FLAG_LINUX_LRS_FIX) ||
|
||||||
(settings->highlightDeletedExe && !proc->procExeDeleted && !proc->isKernelThread && !proc->isUserlandThread)) {
|
(settings->highlightDeletedExe && !proc->procExeDeleted && !proc->isKernelThread && !proc->isUserlandThread)) {
|
||||||
// Check if we really should recalculate the M_LRS value for this process
|
// Check if we really should recalculate the M_LRS value for this process
|
||||||
uint64_t passedTimeInMs = pl->realtimeMs - lp->last_mlrs_calctime;
|
uint64_t passedTimeInMs = pl->realtimeMs - lp->last_mlrs_calctime;
|
||||||
|
|
||||||
uint64_t recheck = ((uint64_t)rand()) % 2048;
|
uint64_t recheck = ((uint64_t)rand()) % 2048;
|
||||||
|
|
||||||
if (passedTimeInMs > 2000 || passedTimeInMs > recheck) {
|
if (passedTimeInMs > recheck) {
|
||||||
lp->last_mlrs_calctime = pl->realtimeMs;
|
lp->last_mlrs_calctime = pl->realtimeMs;
|
||||||
LinuxProcessList_readMaps(lp, procFd, settings->flags & PROCESS_FLAG_LINUX_LRS_FIX, settings->highlightDeletedExe);
|
LinuxProcessList_readMaps(lp, procFd, settings->flags & PROCESS_FLAG_LINUX_LRS_FIX, settings->highlightDeletedExe);
|
||||||
}
|
}
|
||||||
|
@ -543,6 +543,8 @@ bool Platform_getDiskIO(DiskIOData* data) {
|
|||||||
if (!fd)
|
if (!fd)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
char lastTopDisk[32] = { '\0' };
|
||||||
|
|
||||||
unsigned long long int read_sum = 0, write_sum = 0, timeSpend_sum = 0;
|
unsigned long long int read_sum = 0, write_sum = 0, timeSpend_sum = 0;
|
||||||
char lineBuffer[256];
|
char lineBuffer[256];
|
||||||
while (fgets(lineBuffer, sizeof(lineBuffer), fd)) {
|
while (fgets(lineBuffer, sizeof(lineBuffer), fd)) {
|
||||||
@ -556,22 +558,11 @@ bool Platform_getDiskIO(DiskIOData* data) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* only count root disks, e.g. do not count IO from sda and sda1 twice */
|
/* only count root disks, e.g. do not count IO from sda and sda1 twice */
|
||||||
if ((diskname[0] == 's' || diskname[0] == 'h')
|
if (lastTopDisk[0] && String_startsWith(diskname, lastTopDisk))
|
||||||
&& diskname[1] == 'd'
|
|
||||||
&& isalpha((unsigned char)diskname[2])
|
|
||||||
&& isdigit((unsigned char)diskname[3]))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* only count root disks, e.g. do not count IO from mmcblk0 and mmcblk0p1 twice */
|
/* This assumes disks are listed directly before any of their partitions */
|
||||||
if (diskname[0] == 'm'
|
String_safeStrncpy(lastTopDisk, diskname, sizeof(lastTopDisk));
|
||||||
&& diskname[1] == 'm'
|
|
||||||
&& diskname[2] == 'c'
|
|
||||||
&& diskname[3] == 'b'
|
|
||||||
&& diskname[4] == 'l'
|
|
||||||
&& diskname[5] == 'k'
|
|
||||||
&& isdigit((unsigned char)diskname[6])
|
|
||||||
&& diskname[7] == 'p')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
read_sum += read_tmp;
|
read_sum += read_tmp;
|
||||||
write_sum += write_tmp;
|
write_sum += write_tmp;
|
||||||
|
@ -112,6 +112,8 @@ static inline void Platform_gettime_monotonic(uint64_t* msec) {
|
|||||||
|
|
||||||
static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
|
static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
|
||||||
|
|
||||||
|
static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
|
||||||
|
|
||||||
static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { }
|
static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { }
|
||||||
|
|
||||||
static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { }
|
static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { }
|
||||||
@ -120,6 +122,8 @@ static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter,
|
|||||||
|
|
||||||
static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
|
static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
|
||||||
|
|
||||||
|
static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
|
||||||
|
|
||||||
static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
|
static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
|
||||||
|
|
||||||
static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
|
static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
|
||||||
|
@ -19,7 +19,6 @@ in the source distribution for its full text.
|
|||||||
M_TRS = 42, \
|
M_TRS = 42, \
|
||||||
M_DRS = 43, \
|
M_DRS = 43, \
|
||||||
M_LRS = 44, \
|
M_LRS = 44, \
|
||||||
M_DT = 45, \
|
|
||||||
CTID = 100, \
|
CTID = 100, \
|
||||||
VPID = 101, \
|
VPID = 101, \
|
||||||
VXID = 102, \
|
VXID = 102, \
|
||||||
|
@ -39,14 +39,17 @@ static long fscale;
|
|||||||
static int pageSize;
|
static int pageSize;
|
||||||
static int pageSizeKB;
|
static int pageSizeKB;
|
||||||
|
|
||||||
static char const *freqSysctls[] = {
|
static const struct {
|
||||||
"machdep.est.frequency.current",
|
const char* name;
|
||||||
"machdep.powernow.frequency.current",
|
long int scale;
|
||||||
"machdep.intrepid.frequency.current",
|
} freqSysctls[] = {
|
||||||
"machdep.loongson.frequency.current",
|
{ "machdep.est.frequency.current", 1 },
|
||||||
"machdep.cpu.frequency.current",
|
{ "machdep.powernow.frequency.current", 1 },
|
||||||
"machdep.frequency.current",
|
{ "machdep.intrepid.frequency.current", 1 },
|
||||||
NULL
|
{ "machdep.loongson.frequency.current", 1 },
|
||||||
|
{ "machdep.cpu.frequency.current", 1 },
|
||||||
|
{ "machdep.frequency.current", 1 },
|
||||||
|
{ "machdep.tsc_freq", 1000000 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static void NetBSDProcessList_updateCPUcount(ProcessList* super) {
|
static void NetBSDProcessList_updateCPUcount(ProcessList* super) {
|
||||||
@ -261,7 +264,6 @@ static void NetBSDProcessList_scanProcs(NetBSDProcessList* this) {
|
|||||||
bool hideKernelThreads = settings->hideKernelThreads;
|
bool hideKernelThreads = settings->hideKernelThreads;
|
||||||
bool hideUserlandThreads = settings->hideUserlandThreads;
|
bool hideUserlandThreads = settings->hideUserlandThreads;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int nlwps = 0;
|
|
||||||
|
|
||||||
const struct kinfo_proc2* kprocs = kvm_getproc2(this->kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &count);
|
const struct kinfo_proc2* kprocs = kvm_getproc2(this->kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &count);
|
||||||
|
|
||||||
@ -279,7 +281,6 @@ static void NetBSDProcessList_scanProcs(NetBSDProcessList* this) {
|
|||||||
proc->tpgid = kproc->p_tpgid;
|
proc->tpgid = kproc->p_tpgid;
|
||||||
proc->tgid = kproc->p_pid;
|
proc->tgid = kproc->p_pid;
|
||||||
proc->session = kproc->p_sid;
|
proc->session = kproc->p_sid;
|
||||||
proc->tty_nr = kproc->p_tdev;
|
|
||||||
proc->pgrp = kproc->p__pgid;
|
proc->pgrp = kproc->p__pgid;
|
||||||
proc->isKernelThread = !!(kproc->p_flag & P_SYSTEM);
|
proc->isKernelThread = !!(kproc->p_flag & P_SYSTEM);
|
||||||
proc->isUserlandThread = proc->pid != proc->tgid;
|
proc->isUserlandThread = proc->pid != proc->tgid;
|
||||||
@ -287,6 +288,15 @@ static void NetBSDProcessList_scanProcs(NetBSDProcessList* this) {
|
|||||||
Process_fillStarttimeBuffer(proc);
|
Process_fillStarttimeBuffer(proc);
|
||||||
ProcessList_add(&this->super, proc);
|
ProcessList_add(&this->super, proc);
|
||||||
|
|
||||||
|
proc->tty_nr = kproc->p_tdev;
|
||||||
|
const char* name = ((dev_t)kproc->p_tdev != KERN_PROC_TTY_NODEV) ? devname(kproc->p_tdev, S_IFCHR) : NULL;
|
||||||
|
if (!name) {
|
||||||
|
free(proc->tty_name);
|
||||||
|
proc->tty_name = NULL;
|
||||||
|
} else {
|
||||||
|
free_and_xStrdup(&proc->tty_name, name);
|
||||||
|
}
|
||||||
|
|
||||||
NetBSDProcessList_updateExe(kproc, proc);
|
NetBSDProcessList_updateExe(kproc, proc);
|
||||||
NetBSDProcessList_updateProcessName(this->kd, kproc, proc);
|
NetBSDProcessList_updateProcessName(this->kd, kproc, proc);
|
||||||
} else {
|
} else {
|
||||||
@ -312,8 +322,12 @@ static void NetBSDProcessList_scanProcs(NetBSDProcessList* this) {
|
|||||||
proc->nice = kproc->p_nice - 20;
|
proc->nice = kproc->p_nice - 20;
|
||||||
proc->time = 100 * (kproc->p_rtime_sec + ((kproc->p_rtime_usec + 500000) / 1000000));
|
proc->time = 100 * (kproc->p_rtime_sec + ((kproc->p_rtime_usec + 500000) / 1000000));
|
||||||
proc->priority = kproc->p_priority - PZERO;
|
proc->priority = kproc->p_priority - PZERO;
|
||||||
|
proc->processor = kproc->p_cpuid;
|
||||||
|
proc->minflt = kproc->p_uru_minflt;
|
||||||
|
proc->majflt = kproc->p_uru_majflt;
|
||||||
|
|
||||||
struct kinfo_lwp* klwps = kvm_getlwps(this->kd, kproc->p_pid, kproc->p_paddr, sizeof(struct kinfo_lwp), &nlwps);
|
int nlwps = 0;
|
||||||
|
const struct kinfo_lwp* klwps = kvm_getlwps(this->kd, kproc->p_pid, kproc->p_paddr, sizeof(struct kinfo_lwp), &nlwps);
|
||||||
|
|
||||||
switch (kproc->p_realstat) {
|
switch (kproc->p_realstat) {
|
||||||
case SIDL: proc->state = 'I'; break;
|
case SIDL: proc->state = 'I'; break;
|
||||||
@ -417,7 +431,7 @@ static void NetBSDProcessList_scanCPUFrequency(NetBSDProcessList* this) {
|
|||||||
unsigned int cpus = this->super.existingCPUs;
|
unsigned int cpus = this->super.existingCPUs;
|
||||||
bool match = false;
|
bool match = false;
|
||||||
char name[64];
|
char name[64];
|
||||||
int freq = 0;
|
long int freq = 0;
|
||||||
size_t freqSize;
|
size_t freqSize;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < cpus; i++) {
|
for (unsigned int i = 0; i < cpus; i++) {
|
||||||
@ -429,7 +443,7 @@ static void NetBSDProcessList_scanCPUFrequency(NetBSDProcessList* this) {
|
|||||||
xSnprintf(name, sizeof(name), "machdep.cpufreq.cpu%u.current", i);
|
xSnprintf(name, sizeof(name), "machdep.cpufreq.cpu%u.current", i);
|
||||||
freqSize = sizeof(freq);
|
freqSize = sizeof(freq);
|
||||||
if (sysctlbyname(name, &freq, &freqSize, NULL, 0) != -1) {
|
if (sysctlbyname(name, &freq, &freqSize, NULL, 0) != -1) {
|
||||||
this->cpuData[i + 1].frequency = freq;
|
this->cpuData[i + 1].frequency = freq; /* already in MHz */
|
||||||
match = true;
|
match = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -442,9 +456,10 @@ static void NetBSDProcessList_scanCPUFrequency(NetBSDProcessList* this) {
|
|||||||
* Iterate through legacy sysctl nodes for single-core frequency until
|
* Iterate through legacy sysctl nodes for single-core frequency until
|
||||||
* we find a match...
|
* we find a match...
|
||||||
*/
|
*/
|
||||||
for (const char** s = freqSysctls; *s != NULL; ++s) {
|
for (size_t i = 0; i < ARRAYSIZE(freqSysctls); i++) {
|
||||||
freqSize = sizeof(freq);
|
freqSize = sizeof(freq);
|
||||||
if (sysctlbyname(*s, &freq, &freqSize, NULL, 0) != -1) {
|
if (sysctlbyname(freqSysctls[i].name, &freq, &freqSize, NULL, 0) != -1) {
|
||||||
|
freq /= freqSysctls[i].scale; /* scale to MHz */
|
||||||
match = true;
|
match = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -260,14 +260,11 @@ double Platform_setCPUValues(Meter* this, int cpu) {
|
|||||||
|
|
||||||
void Platform_setMemoryValues(Meter* this) {
|
void Platform_setMemoryValues(Meter* this) {
|
||||||
const ProcessList* pl = this->pl;
|
const ProcessList* pl = this->pl;
|
||||||
long int usedMem = pl->usedMem;
|
|
||||||
long int buffersMem = pl->buffersMem;
|
|
||||||
long int cachedMem = pl->cachedMem;
|
|
||||||
this->total = pl->totalMem;
|
this->total = pl->totalMem;
|
||||||
this->values[0] = usedMem;
|
this->values[0] = pl->usedMem;
|
||||||
this->values[1] = buffersMem;
|
this->values[1] = pl->buffersMem;
|
||||||
// this->values[2] = "shared memory, like tmpfs and shm"
|
// this->values[2] = "shared memory, like tmpfs and shm"
|
||||||
this->values[3] = cachedMem;
|
this->values[3] = pl->cachedMem;
|
||||||
// this->values[4] = "available memory"
|
// this->values[4] = "available memory"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,19 +281,19 @@ char* Platform_getProcessEnv(pid_t pid) {
|
|||||||
char** ptr;
|
char** ptr;
|
||||||
int count;
|
int count;
|
||||||
kvm_t* kt;
|
kvm_t* kt;
|
||||||
struct kinfo_proc* kproc;
|
const struct kinfo_proc2* kproc;
|
||||||
size_t capacity = 4096, size = 0;
|
size_t capacity = 4096, size = 0;
|
||||||
|
|
||||||
if ((kt = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL) {
|
if ((kt = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((kproc = kvm_getprocs(kt, KERN_PROC_PID, pid, &count)) == NULL) {
|
if ((kproc = kvm_getproc2(kt, KERN_PROC_PID, pid, sizeof(struct kinfo_proc2), &count)) == NULL) {
|
||||||
(void) kvm_close(kt);
|
(void) kvm_close(kt);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ptr = kvm_getenvv(kt, kproc, 0)) == NULL) {
|
if ((ptr = kvm_getenvv2(kt, kproc, 0)) == NULL) {
|
||||||
(void) kvm_close(kt);
|
(void) kvm_close(kt);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -393,7 +390,7 @@ bool Platform_getNetworkIO(NetworkIOData* data) {
|
|||||||
if (getifaddrs(&ifaddrs) != 0)
|
if (getifaddrs(&ifaddrs) != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (struct ifaddrs* ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
|
for (const struct ifaddrs* ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
|
||||||
if (!ifa->ifa_addr)
|
if (!ifa->ifa_addr)
|
||||||
continue;
|
continue;
|
||||||
if (ifa->ifa_addr->sa_family != AF_LINK)
|
if (ifa->ifa_addr->sa_family != AF_LINK)
|
||||||
@ -401,7 +398,7 @@ bool Platform_getNetworkIO(NetworkIOData* data) {
|
|||||||
if (ifa->ifa_flags & IFF_LOOPBACK)
|
if (ifa->ifa_flags & IFF_LOOPBACK)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
struct if_data* ifd = (struct if_data *)ifa->ifa_data;
|
const struct if_data* ifd = (const struct if_data *)ifa->ifa_data;
|
||||||
|
|
||||||
data->bytesReceived += ifd->ifi_ibytes;
|
data->bytesReceived += ifd->ifi_ibytes;
|
||||||
data->packetsReceived += ifd->ifi_ipackets;
|
data->packetsReceived += ifd->ifi_ipackets;
|
||||||
|
@ -96,6 +96,8 @@ static inline void Platform_gettime_monotonic(uint64_t* msec) {
|
|||||||
|
|
||||||
static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
|
static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
|
||||||
|
|
||||||
|
static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
|
||||||
|
|
||||||
static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { }
|
static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { }
|
||||||
|
|
||||||
static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { }
|
static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { }
|
||||||
@ -104,6 +106,8 @@ static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter,
|
|||||||
|
|
||||||
static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
|
static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
|
||||||
|
|
||||||
|
static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
|
||||||
|
|
||||||
static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
|
static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
|
||||||
|
|
||||||
static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
|
static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
|
||||||
|
@ -90,6 +90,8 @@ static inline void Platform_gettime_monotonic(uint64_t* msec) {
|
|||||||
|
|
||||||
static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
|
static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
|
||||||
|
|
||||||
|
static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
|
||||||
|
|
||||||
static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { }
|
static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { }
|
||||||
|
|
||||||
static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { }
|
static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { }
|
||||||
@ -98,6 +100,8 @@ static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter,
|
|||||||
|
|
||||||
static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
|
static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
|
||||||
|
|
||||||
|
static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
|
||||||
|
|
||||||
static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
|
static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
|
||||||
|
|
||||||
static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
|
static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
|
||||||
|
@ -226,6 +226,18 @@ void PCPDynamicColumns_init(PCPDynamicColumns* columns) {
|
|||||||
free(path);
|
free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void PCPDynamicColumns_free(ATTR_UNUSED ht_key_t key, void* value, ATTR_UNUSED void* data) {
|
||||||
|
PCPDynamicColumn* column = (PCPDynamicColumn*) value;
|
||||||
|
free(column->metricName);
|
||||||
|
free(column->super.heading);
|
||||||
|
free(column->super.caption);
|
||||||
|
free(column->super.description);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PCPDynamicColumns_done(Hashtable* table) {
|
||||||
|
Hashtable_foreach(table, PCPDynamicColumns_free, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void PCPDynamicColumn_writeField(PCPDynamicColumn* this, const Process* proc, RichString* str) {
|
void PCPDynamicColumn_writeField(PCPDynamicColumn* this, const Process* proc, RichString* str) {
|
||||||
const PCPProcess* pp = (const PCPProcess*) proc;
|
const PCPProcess* pp = (const PCPProcess*) proc;
|
||||||
unsigned int type = PCPMetric_type(this->id);
|
unsigned int type = PCPMetric_type(this->id);
|
||||||
|
@ -26,6 +26,8 @@ typedef struct PCPDynamicColumns_ {
|
|||||||
|
|
||||||
void PCPDynamicColumns_init(PCPDynamicColumns* columns);
|
void PCPDynamicColumns_init(PCPDynamicColumns* columns);
|
||||||
|
|
||||||
|
void PCPDynamicColumns_done(Hashtable* table);
|
||||||
|
|
||||||
void PCPDynamicColumn_writeField(PCPDynamicColumn* this, const Process* proc, RichString* str);
|
void PCPDynamicColumn_writeField(PCPDynamicColumn* this, const Process* proc, RichString* str);
|
||||||
|
|
||||||
int PCPDynamicColumn_compareByKey(const PCPProcess* p1, const PCPProcess* p2, ProcessField key);
|
int PCPDynamicColumn_compareByKey(const PCPProcess* p1, const PCPProcess* p2, ProcessField key);
|
||||||
|
@ -283,6 +283,22 @@ void PCPDynamicMeters_init(PCPDynamicMeters* meters) {
|
|||||||
free(path);
|
free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void PCPDynamicMeter_free(ATTR_UNUSED ht_key_t key, void* value, ATTR_UNUSED void* data) {
|
||||||
|
PCPDynamicMeter* meter = (PCPDynamicMeter*) value;
|
||||||
|
for (size_t i = 0; i < meter->totalMetrics; i++) {
|
||||||
|
free(meter->metrics[i].name);
|
||||||
|
free(meter->metrics[i].label);
|
||||||
|
free(meter->metrics[i].suffix);
|
||||||
|
}
|
||||||
|
free(meter->metrics);
|
||||||
|
free(meter->super.caption);
|
||||||
|
free(meter->super.description);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PCPDynamicMeters_done(Hashtable* table) {
|
||||||
|
Hashtable_foreach(table, PCPDynamicMeter_free, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void PCPDynamicMeter_enable(PCPDynamicMeter* this) {
|
void PCPDynamicMeter_enable(PCPDynamicMeter* this) {
|
||||||
for (size_t i = 0; i < this->totalMetrics; i++)
|
for (size_t i = 0; i < this->totalMetrics; i++)
|
||||||
PCPMetric_enable(this->metrics[i].id, true);
|
PCPMetric_enable(this->metrics[i].id, true);
|
||||||
|
@ -33,6 +33,8 @@ typedef struct PCPDynamicMeters_ {
|
|||||||
|
|
||||||
void PCPDynamicMeters_init(PCPDynamicMeters* meters);
|
void PCPDynamicMeters_init(PCPDynamicMeters* meters);
|
||||||
|
|
||||||
|
void PCPDynamicMeters_done(Hashtable* table);
|
||||||
|
|
||||||
void PCPDynamicMeter_enable(PCPDynamicMeter* this);
|
void PCPDynamicMeter_enable(PCPDynamicMeter* this);
|
||||||
|
|
||||||
void PCPDynamicMeter_updateValues(PCPDynamicMeter* this, Meter* meter);
|
void PCPDynamicMeter_updateValues(PCPDynamicMeter* this, Meter* meter);
|
||||||
|
@ -317,7 +317,7 @@ static void PCPProcessList_updateCmdline(Process* process, int pid, int offset,
|
|||||||
Process_updateComm(process, comm);
|
Process_updateComm(process, comm);
|
||||||
|
|
||||||
if (PCPMetric_instance(PCP_PROC_EXE, pid, offset, &value, PM_TYPE_STRING)) {
|
if (PCPMetric_instance(PCP_PROC_EXE, pid, offset, &value, PM_TYPE_STRING)) {
|
||||||
Process_updateExe(process, value.cp);
|
Process_updateExe(process, value.cp[0] ? value.cp : NULL);
|
||||||
free(value.cp);
|
free(value.cp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -363,6 +363,14 @@ void Platform_init(void) {
|
|||||||
Platform_getMaxPid();
|
Platform_getMaxPid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Platform_dynamicColumnsDone(Hashtable* columns) {
|
||||||
|
PCPDynamicColumns_done(columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_dynamicMetersDone(Hashtable* meters) {
|
||||||
|
PCPDynamicMeters_done(meters);
|
||||||
|
}
|
||||||
|
|
||||||
void Platform_done(void) {
|
void Platform_done(void) {
|
||||||
pmDestroyContext(pcp->context);
|
pmDestroyContext(pcp->context);
|
||||||
if (pcp->result)
|
if (pcp->result)
|
||||||
|
@ -138,6 +138,8 @@ void Platform_gettime_monotonic(uint64_t* msec);
|
|||||||
|
|
||||||
Hashtable* Platform_dynamicMeters(void);
|
Hashtable* Platform_dynamicMeters(void);
|
||||||
|
|
||||||
|
void Platform_dynamicMetersDone(Hashtable* meters);
|
||||||
|
|
||||||
void Platform_dynamicMeterInit(Meter* meter);
|
void Platform_dynamicMeterInit(Meter* meter);
|
||||||
|
|
||||||
void Platform_dynamicMeterUpdateValues(Meter* meter);
|
void Platform_dynamicMeterUpdateValues(Meter* meter);
|
||||||
@ -146,6 +148,8 @@ void Platform_dynamicMeterDisplay(const Meter* meter, RichString* out);
|
|||||||
|
|
||||||
Hashtable* Platform_dynamicColumns(void);
|
Hashtable* Platform_dynamicColumns(void);
|
||||||
|
|
||||||
|
void Platform_dynamicColumnsDone(Hashtable* columns);
|
||||||
|
|
||||||
const char* Platform_dynamicColumnInit(unsigned int key);
|
const char* Platform_dynamicColumnInit(unsigned int key);
|
||||||
|
|
||||||
bool Platform_dynamicColumnWriteField(const Process* proc, RichString* str, unsigned int key);
|
bool Platform_dynamicColumnWriteField(const Process* proc, RichString* str, unsigned int key);
|
||||||
|
@ -1,63 +1,47 @@
|
|||||||
{
|
|
||||||
<ncurses internal memory allocated at startup>
|
|
||||||
Memcheck:Leak
|
|
||||||
match-leak-kinds: reachable
|
|
||||||
...
|
|
||||||
fun:CRT_init
|
|
||||||
fun:main
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
<ncurses internal memory allocated at startup>
|
|
||||||
Memcheck:Leak
|
|
||||||
match-leak-kinds: reachable
|
|
||||||
...
|
|
||||||
fun:CRT_init
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
<ncurses internal memory>
|
<ncurses internal memory>
|
||||||
Memcheck:Leak
|
Memcheck:Leak
|
||||||
match-leak-kinds: reachable
|
match-leak-kinds: possible,reachable
|
||||||
...
|
|
||||||
fun:wgetch
|
|
||||||
fun:ScreenManager_run
|
|
||||||
fun:Action_runSetup
|
|
||||||
fun:actionSetup
|
|
||||||
fun:MainPanel_eventHandler
|
|
||||||
fun:ScreenManager_run
|
|
||||||
fun:main
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
<ncurses internal memory>
|
|
||||||
Memcheck:Leak
|
|
||||||
match-leak-kinds: reachable
|
|
||||||
...
|
|
||||||
fun:wgetch
|
|
||||||
fun:ScreenManager_run
|
|
||||||
fun:main
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
<ncurses internal memory>
|
|
||||||
Memcheck:Leak
|
|
||||||
match-leak-kinds: reachable
|
|
||||||
...
|
|
||||||
fun:wrefresh
|
|
||||||
fun:main
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
<ncurses internal memory>
|
|
||||||
Memcheck:Leak
|
|
||||||
match-leak-kinds: reachable
|
|
||||||
fun:realloc
|
|
||||||
fun:_nc_doalloc
|
|
||||||
fun:_nc_tparm_analyze
|
|
||||||
fun:tparm
|
|
||||||
...
|
...
|
||||||
fun:doupdate_sp
|
fun:doupdate_sp
|
||||||
fun:wrefresh
|
fun:wrefresh
|
||||||
obj:*
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
<ncurses internal memory>
|
||||||
|
Memcheck:Leak
|
||||||
|
match-leak-kinds: possible,reachable
|
||||||
|
...
|
||||||
|
fun:newterm_sp
|
||||||
|
fun:newterm
|
||||||
|
fun:initscr
|
||||||
|
fun:CRT_init
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
<ncurses internal memory>
|
||||||
|
Memcheck:Leak
|
||||||
|
match-leak-kinds: reachable
|
||||||
|
...
|
||||||
|
obj:*/libtinfo*
|
||||||
|
fun:CRT_init
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
<ncurses internal memory>
|
||||||
|
Memcheck:Leak
|
||||||
|
match-leak-kinds: reachable
|
||||||
|
...
|
||||||
|
obj:*/libncurses*
|
||||||
|
fun:CRT_init
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
<ncurses internal memory>
|
||||||
|
Memcheck:Leak
|
||||||
|
match-leak-kinds: possible,reachable
|
||||||
|
...
|
||||||
|
obj:*/libncurses*
|
||||||
|
fun:CRT_setColors
|
||||||
|
fun:CRT_init
|
||||||
}
|
}
|
||||||
|
@ -3,4 +3,4 @@
|
|||||||
SCRIPT=$(readlink -f "$0")
|
SCRIPT=$(readlink -f "$0")
|
||||||
SCRIPTDIR=$(dirname "$SCRIPT")
|
SCRIPTDIR=$(dirname "$SCRIPT")
|
||||||
|
|
||||||
valgrind --leak-check=full --show-reachable=yes --show-leak-kinds=all --track-fds=yes --errors-for-leak-kinds=all --suppressions="${SCRIPTDIR}/htop_suppressions.valgrind" "${SCRIPTDIR}/../htop"
|
valgrind --leak-check=full --show-reachable=yes --show-leak-kinds=all --track-fds=yes --errors-for-leak-kinds=all --track-origins=yes --suppressions="${SCRIPTDIR}/htop_suppressions.valgrind" "${SCRIPTDIR}/../htop"
|
||||||
|
@ -131,6 +131,8 @@ IGNORE_WCASTQUAL_END
|
|||||||
|
|
||||||
static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
|
static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
|
||||||
|
|
||||||
|
static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
|
||||||
|
|
||||||
static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { }
|
static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { }
|
||||||
|
|
||||||
static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { }
|
static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { }
|
||||||
@ -139,6 +141,8 @@ static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter,
|
|||||||
|
|
||||||
static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
|
static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
|
||||||
|
|
||||||
|
static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
|
||||||
|
|
||||||
static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
|
static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
|
||||||
|
|
||||||
static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
|
static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
|
||||||
|
@ -79,6 +79,8 @@ static inline void Platform_gettime_monotonic(uint64_t* msec) {
|
|||||||
|
|
||||||
static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
|
static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
|
||||||
|
|
||||||
|
static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
|
||||||
|
|
||||||
static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { }
|
static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { }
|
||||||
|
|
||||||
static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { }
|
static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { }
|
||||||
@ -87,6 +89,8 @@ static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter,
|
|||||||
|
|
||||||
static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
|
static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
|
||||||
|
|
||||||
|
static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
|
||||||
|
|
||||||
static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
|
static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
|
||||||
|
|
||||||
static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
|
static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
|
||||||
|
Reference in New Issue
Block a user