33 Commits

Author SHA1 Message Date
a516e0852e Update configure to reflect rc2 in the version 2021-09-05 19:07:29 +02:00
556d7c03e8 Add a Process_printPercentage helper routine
Replace several open-coded variants of percentage formatting.
This function has been ported from Hishams old 'next' branch.
2021-09-05 18:47:07 +02:00
0925c54caa Drop redundant semicolons 2021-09-04 14:17:37 +02:00
d0f5b61aa5 hwloc: use int in hwloc_bitmap_foreach_begin loop
Affinity.c:67:10: runtime error: implicit conversion from type 'int' of value -1 (32-bit, signed) to type 'unsigned int' changed the value to 4294967295 (32-bit, unsigned)
2021-09-04 09:48:53 +02:00
284f8c5e0b configure: output vserver as implied if ancient-vserver is enabled
The build time configuration ancient-vserver implies the configuration
vserver; say so in the configure status report if only ancient-vserver
has been specified.

Also indent with 3 spaces.
2021-09-04 09:48:53 +02:00
11b65a2861 Header: use upper case floating point suffix 2021-09-04 09:48:53 +02:00
b85b718e69 Settings: enclose casted macro argument in parenthesis 2021-09-04 09:48:53 +02:00
7891cdc552 Reduce variable scope
Also avoid declaring variables of different type, pointer and array, in
the same line.
2021-09-04 09:48:53 +02:00
b9fdf1c2a1 ColumnsPanel: drop unused struct declaration 2021-09-04 09:48:53 +02:00
2844429f15 NetBSD: scale CPU frequencies
Use a value type of 'long int' to avoid ENOMEM failures of sysctl(3).

Also check for "machdep.tsc_freq", scaled in MHz.
2021-09-03 12:17:45 +02:00
3834f2a68f NetBSD: misc const additions 2021-09-03 12:17:45 +02:00
343c2e58be NetBSD: update process fields
Populate fields to ttyname, minflt, majflt and processor.
2021-09-03 12:17:45 +02:00
fd2c4f5ddd NetBSD: fix reading environment variables of processes
kvm_getenvv(3) seems not to work with kvm_openfiles(..., KVM_NO_FILES,
...)
2021-09-03 12:17:45 +02:00
7f95ed8528 NetBSD: simplify Platform_setMemoryValues 2021-09-03 12:17:45 +02:00
9579d9b7aa NetBSD: silence dropping const qualifier on define_key(3)
On NetBSD define_key(3) has the prototype

    int define_key(char *sequence, int key_symbol);
2021-09-03 12:17:45 +02:00
0580dbb202 NetBSD: color process state P as running
On NetBSD state 'R' means runnable not running.

Improve the color identifier name accordingly.
2021-09-03 12:17:45 +02:00
c0c2bb98a2 Add completion handling for dynamic meters and columns
Be sure to free dynamic memory allocated for meters and
columns strings, no-op on platforms other than pcp.

Closes #774
2021-09-03 09:47:01 +02:00
9b30870eec Merge pull request #775 from cgzones/pcp
PCP: do not set exe to empty string
2021-09-03 12:08:00 +10:00
25c945e2ef PCP: do not set exe to empty string
In case the executable is an empty string, e.g. if pcp is run by an
unprivileged user, do not set procExe to an empty value, which breaks
the formatting of the PROCEXE column and the merged-cmdline logic.
2021-09-02 23:37:53 +02:00
f94934472f Linux: rework disk-io parsing
Generalize sub-diskname handling, like sdb1/sdb2, to not count the
usage twice with the aggregate top-diskname, like sdb.
Rely on /proc/diskstats being ordered, e.g. no sub-diskname precedes its
top-diskname.

Closes: #675
2021-09-02 22:12:58 +02:00
becd33795c Settings: create default meters on no existing config file
If htop is started for the first time and no configuration file exists
the header is empty cause no meters are added as a default.

Add the default meters if parsing all available configuration paths
failed.
2021-09-02 08:03:21 +02:00
74f99e3693 linux: simplify recheck condition
`recheck` is calculated modulo 2048, so its maximum value is 2047.
Drop the quite similar (up to 27 milliseconds) explicit check against
2000.
2021-09-02 08:03:21 +02:00
e1f4645bd1 Process: drop unused merged-command bit fields 2021-09-02 08:03:21 +02:00
0afd0fe572 linux: color void delay accounting values gray
Use the color gray, similar to other process fields, if the delay
accounting value is either 0 (or very small) or cannot be accessed, e.g.
by an unprivileged user.
2021-09-02 08:03:21 +02:00
ff336b652c linux: drop unused macro IOPriority_error 2021-09-02 08:03:21 +02:00
58a59c11f4 linux: drop dead process field column DIRTY
The field for dirty pages in /proc/[pid]/statm is always 0 since Linux
2.6 (see man:proc(5)).
2021-09-02 08:03:21 +02:00
3f806368e0 CPUMeter: use correct buffer size 2021-09-02 08:03:21 +02:00
4855d92469 travis-ci: update
Drop explicit CFLAGS specification as `-Wno-c11-extensions` is enabled
on FreeBSD by the configure script.

Run and check `make install` and `make installcheck`.
2021-09-02 08:03:21 +02:00
b81bb9038c Fix resource leaks dealing with unrecognised config file version
Plug leaks of an open file descriptor and dynamically allocated
'option' when we bail out early reading unknown config version.
2021-08-31 08:08:01 +02:00
1f2f567ca1 Fix meterPanels size calculation for dynamic array allocation 2021-08-31 08:08:01 +02:00
393330239e Small editorial fixes to ChangeLog 2021-08-27 09:31:06 +02:00
d2c34259b4 Remove trailing whitespace in changelog for CI checks 2021-08-27 12:19:50 +10:00
858ad8029d Update configure to reflect rc1 in the version 2021-08-27 12:14:23 +10:00
43 changed files with 263 additions and 175 deletions

View File

@ -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

View File

@ -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();
} }
} }

View File

@ -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++) {

View File

@ -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) {

20
CRT.c
View File

@ -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),
@ -886,6 +886,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 +910,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
View File

@ -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,

View File

@ -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];

View File

@ -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

View File

@ -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) {

View File

@ -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;
} }

View File

@ -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);
} }

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -86,8 +86,9 @@ static void Header_addMeterByName(Header* this, const char* name, MeterModeId mo
if (paren) { if (paren) {
int ok = sscanf(paren, "(%10u)", &param); // CPUMeter int ok = sscanf(paren, "(%10u)", &param); // 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,16 +196,16 @@ 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++) {
@ -213,7 +214,7 @@ void Header_draw(const Header* this) {
float actualWidth = colWidth; float actualWidth = colWidth;
if (meter->mode == TEXT_METERMODE) { if (meter->mode == TEXT_METERMODE) {
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;
} }
} }

View File

@ -707,6 +707,24 @@ 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) {
xSnprintf(buffer, n, "%3d. ", (int)val);
} else {
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 +839,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 +861,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];

View File

@ -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);

View File

@ -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';
@ -182,6 +183,8 @@ static bool Settings_read(Settings* this, const char* fileName, unsigned int ini
// 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.", 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");
@ -541,6 +544,9 @@ Settings* Settings_new(unsigned int initialCpuCount, Hashtable* dynamicColumns)
this->changed = true; this->changed = true;
Settings_read(this, SYSCONFDIR "/htoprc", initialCpuCount); Settings_read(this, SYSCONFDIR "/htoprc", initialCpuCount);
} }
if (!ok) {
Settings_defaultMeters(this, initialCpuCount);
}
return this; return this;
} }

View File

@ -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])
@ -482,6 +482,9 @@ 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
if test "x$enable_vserver" != xyes; then
enable_vserver=implied
fi
AC_DEFINE([HAVE_VSERVER], [1], [Define if VServer support enabled.]) AC_DEFINE([HAVE_VSERVER], [1], [Define if VServer support enabled.])
AC_DEFINE([HAVE_ANCIENT_VSERVER], [1], [Define if ancient vserver support enabled.]) AC_DEFINE([HAVE_ANCIENT_VSERVER], [1], [Define if ancient vserver support enabled.])
fi fi

View File

@ -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; }

View File

@ -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; }

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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, },
@ -88,7 +87,7 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
#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:

View File

@ -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;

View File

@ -678,7 +678,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 +687,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) {
@ -1433,7 +1433,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
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);
} }

View File

@ -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;

View File

@ -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; }

View File

@ -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, \

View File

@ -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;
} }

View File

@ -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;

View File

@ -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; }

View File

@ -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; }

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);
} }
} }

View File

@ -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)

View File

@ -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);

View File

@ -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; }

View File

@ -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; }