mirror of
https://github.com/xzeldon/htop.git
synced 2025-07-15 21:44:36 +03:00
Compare commits
33 Commits
Author | SHA1 | Date | |
---|---|---|---|
a516e0852e | |||
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:
|
||||
- ./autogen.sh
|
||||
# clang might warn about C11 generic selections in isnan()
|
||||
- CFLAGS=-Wno-c11-extensions ./configure --enable-werror
|
||||
- ./configure --enable-werror
|
||||
- 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);
|
||||
}
|
||||
} else {
|
||||
unsigned int id;
|
||||
hwloc_bitmap_foreach_begin(id, cpuset);
|
||||
Affinity_add(affinity, id);
|
||||
int id;
|
||||
hwloc_bitmap_foreach_begin(id, cpuset)
|
||||
Affinity_add(affinity, (unsigned)id);
|
||||
hwloc_bitmap_foreach_end();
|
||||
}
|
||||
}
|
||||
|
@ -425,9 +425,9 @@ Affinity* AffinityPanel_getAffinity(Panel* super, ProcessList* pl) {
|
||||
Affinity* affinity = Affinity_new(pl);
|
||||
|
||||
#ifdef HAVE_LIBHWLOC
|
||||
unsigned int i;
|
||||
int i;
|
||||
hwloc_bitmap_foreach_begin(i, this->workCpuset)
|
||||
Affinity_add(affinity, i);
|
||||
Affinity_add(affinity, (unsigned)i);
|
||||
hwloc_bitmap_foreach_end();
|
||||
#else
|
||||
for (int i = 0; i < Vector_size(this->cpuids); i++) {
|
||||
|
@ -52,9 +52,9 @@ static void CPUMeter_init(Meter* this) {
|
||||
// Custom uiName runtime logic to include the param (processor)
|
||||
static void CPUMeter_getUiName(const Meter* this, char* buffer, size_t length) {
|
||||
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
|
||||
xSnprintf(buffer, sizeof(length), "%s", Meter_uiName(this));
|
||||
xSnprintf(buffer, length, "%s", Meter_uiName(this));
|
||||
}
|
||||
|
||||
static void CPUMeter_updateValues(Meter* this) {
|
||||
|
20
CRT.c
20
CRT.c
@ -138,7 +138,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||
[PROCESS_GIGABYTES] = ColorPair(Green, Black),
|
||||
[PROCESS_BASENAME] = A_BOLD | 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_HIGH_PRIORITY] = ColorPair(Red, Black),
|
||||
[PROCESS_LOW_PRIORITY] = ColorPair(Green, Black),
|
||||
@ -240,7 +240,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||
[PROCESS_GIGABYTES] = A_BOLD,
|
||||
[PROCESS_BASENAME] = A_BOLD,
|
||||
[PROCESS_TREE] = A_BOLD,
|
||||
[PROCESS_R_STATE] = A_BOLD,
|
||||
[PROCESS_RUN_STATE] = A_BOLD,
|
||||
[PROCESS_D_STATE] = A_BOLD,
|
||||
[PROCESS_HIGH_PRIORITY] = A_BOLD,
|
||||
[PROCESS_LOW_PRIORITY] = A_DIM,
|
||||
@ -342,7 +342,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||
[PROCESS_GIGABYTES] = ColorPair(Green, White),
|
||||
[PROCESS_BASENAME] = ColorPair(Blue, 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_HIGH_PRIORITY] = ColorPair(Red, 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_BASENAME] = ColorPair(Green, 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_HIGH_PRIORITY] = ColorPair(Red, 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_BASENAME] = A_BOLD | 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_HIGH_PRIORITY] = ColorPair(Red, 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_COMM] = ColorPair(Magenta, 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_HIGH_PRIORITY] = ColorPair(Red, 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"))) {
|
||||
#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[F", KEY_END);
|
||||
define_key("\033[7~", KEY_HOME);
|
||||
@ -906,6 +910,10 @@ void CRT_init(const Settings* settings, bool allowUnicode) {
|
||||
sequence[1] = c;
|
||||
define_key(sequence, KEY_ALT('A' + (c - 'a')));
|
||||
}
|
||||
#ifdef HTOP_NETBSD
|
||||
IGNORE_WCASTQUAL_END
|
||||
#undef define_key
|
||||
#endif
|
||||
}
|
||||
|
||||
CRT_installSignalHandlers();
|
||||
|
2
CRT.h
2
CRT.h
@ -74,7 +74,7 @@ typedef enum ColorElements_ {
|
||||
PROCESS_MEGABYTES,
|
||||
PROCESS_GIGABYTES,
|
||||
PROCESS_TREE,
|
||||
PROCESS_R_STATE,
|
||||
PROCESS_RUN_STATE,
|
||||
PROCESS_D_STATE,
|
||||
PROCESS_BASENAME,
|
||||
PROCESS_HIGH_PRIORITY,
|
||||
|
@ -40,7 +40,7 @@ static void CategoriesPanel_delete(Object* object) {
|
||||
|
||||
static void CategoriesPanel_makeMetersPage(CategoriesPanel* this) {
|
||||
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++) {
|
||||
char titleBuffer[32];
|
||||
|
18
ChangeLog
18
ChangeLog
@ -1,6 +1,5 @@
|
||||
What's new in version 3.1.0
|
||||
|
||||
|
||||
* Updated COPYING file to remove the PLPA exemption (appendix 2)
|
||||
With this change the license is now GPLv2 without any additional wording.
|
||||
* 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
|
||||
information simplifies the markup of the command line.
|
||||
* 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
|
||||
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)
|
||||
With this change only settings that cannot be parsed properly are
|
||||
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
|
||||
(and PID 2 if kernel threads are shown) (thanks to Krishna Chaitanya)
|
||||
* 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
|
||||
to the thread's parent process. (thanks to Gonzalo, et.al.)
|
||||
* Reorder process scanning to be performed before updating the display
|
||||
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
|
||||
the user field for a process to change at runtime (e.g. due to seteuid
|
||||
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)
|
||||
* Bugfixes related to CPU time display/calculations for darwin on M1 systems
|
||||
(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
|
||||
marked as AC is found in the system.
|
||||
Battery capacity is summed up over all batteries found.
|
||||
This also changes the old behavior that batteries reported by the
|
||||
system after the first AC adapter where sometimes ignored.
|
||||
* Correctly handle multiple batteries on Darwin
|
||||
Resolves a possible memory leak on systems with multiple batteries
|
||||
* Correctly handle multiple batteries on Darwin.
|
||||
Resolves a possible memory leak on systems with multiple batteries.
|
||||
* Handle Linux Shmem being part of Cached in the MemoryMeter
|
||||
* Add SwapCached to the Linux swap meter (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
|
||||
* Support scheduler affinity on platforms beyond Linux
|
||||
* 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.
|
||||
* Print current settings on crash
|
||||
* Reset signal handlers on program exit
|
||||
|
@ -118,12 +118,6 @@ const PanelClass ColumnsPanel_class = {
|
||||
.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) {
|
||||
const char* name;
|
||||
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 */
|
||||
Settings_delete(settings);
|
||||
if (dc)
|
||||
Hashtable_delete(dc);
|
||||
if (dm)
|
||||
Hashtable_delete(dm);
|
||||
DynamicColumns_delete(dc);
|
||||
DynamicMeters_delete(dm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -22,6 +22,13 @@ Hashtable* DynamicColumns_new(void) {
|
||||
return Platform_dynamicColumns();
|
||||
}
|
||||
|
||||
void DynamicColumns_delete(Hashtable* dynamics) {
|
||||
if (dynamics) {
|
||||
Platform_dynamicColumnsDone(dynamics);
|
||||
Hashtable_delete(dynamics);
|
||||
}
|
||||
}
|
||||
|
||||
const char* DynamicColumn_init(unsigned int key) {
|
||||
return Platform_dynamicColumnInit(key);
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ typedef struct DynamicColumn_ {
|
||||
|
||||
Hashtable* DynamicColumns_new(void);
|
||||
|
||||
void DynamicColumns_delete(Hashtable* dynamics);
|
||||
|
||||
const char* DynamicColumn_init(unsigned int key);
|
||||
|
||||
const DynamicColumn* DynamicColumn_lookup(Hashtable* dynamics, unsigned int key);
|
||||
|
@ -38,6 +38,13 @@ Hashtable* DynamicMeters_new(void) {
|
||||
return Platform_dynamicMeters();
|
||||
}
|
||||
|
||||
void DynamicMeters_delete(Hashtable* dynamics) {
|
||||
if (dynamics) {
|
||||
Platform_dynamicMetersDone(dynamics);
|
||||
Hashtable_delete(dynamics);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
unsigned int key;
|
||||
const char* name;
|
||||
|
@ -17,6 +17,8 @@ typedef struct DynamicMeter_ {
|
||||
|
||||
Hashtable* DynamicMeters_new(void);
|
||||
|
||||
void DynamicMeters_delete(Hashtable* dynamics);
|
||||
|
||||
const char* DynamicMeter_lookup(Hashtable* dynamics, unsigned int key);
|
||||
|
||||
bool DynamicMeter_search(Hashtable* dynamics, const char* name, unsigned int* key);
|
||||
|
15
Header.c
15
Header.c
@ -86,8 +86,9 @@ static void Header_addMeterByName(Header* this, const char* name, MeterModeId mo
|
||||
if (paren) {
|
||||
int ok = sscanf(paren, "(%10u)", ¶m); // CPUMeter
|
||||
if (!ok) {
|
||||
char* end, dynamic[32] = {0};
|
||||
char dynamic[32] = {0};
|
||||
if (sscanf(paren, "(%30s)", dynamic)) { // DynamicMeter
|
||||
char* end;
|
||||
if ((end = strrchr(dynamic, ')')) == NULL)
|
||||
return; // htoprc parse failure
|
||||
*end = '\0';
|
||||
@ -195,16 +196,16 @@ void Header_draw(const Header* this) {
|
||||
}
|
||||
const int width = COLS - pad;
|
||||
int x = pad;
|
||||
float roundingLoss = 0.0f;
|
||||
float roundingLoss = 0.0F;
|
||||
|
||||
Header_forEachColumn(this, 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);
|
||||
if (roundingLoss >= 1.0f) {
|
||||
colWidth += 1.0f;
|
||||
roundingLoss -= 1.0f;
|
||||
if (roundingLoss >= 1.0F) {
|
||||
colWidth += 1.0F;
|
||||
roundingLoss -= 1.0F;
|
||||
}
|
||||
|
||||
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;
|
||||
if (meter->mode == TEXT_METERMODE) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
53
Process.c
53
Process.c
@ -707,6 +707,24 @@ void Process_printLeftAlignedField(RichString* str, int attr, const char* conten
|
||||
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) {
|
||||
char buffer[256];
|
||||
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);
|
||||
break;
|
||||
case PERCENT_CPU:
|
||||
case PERCENT_CPU: Process_printPercentage(this->percent_cpu, buffer, n, &attr); break;
|
||||
case PERCENT_NORM_CPU: {
|
||||
float cpuPercentage = this->percent_cpu;
|
||||
if (field == PERCENT_NORM_CPU) {
|
||||
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);
|
||||
}
|
||||
float cpuPercentage = this->percent_cpu / this->processList->activeCPUs;
|
||||
Process_printPercentage(cpuPercentage, buffer, n, &attr);
|
||||
break;
|
||||
}
|
||||
case PERCENT_MEM:
|
||||
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 PERCENT_MEM: Process_printPercentage(this->percent_mem, buffer, n, &attr); break;
|
||||
case PGRP: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->pgrp); break;
|
||||
case PID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, this->pid); 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:
|
||||
xSnprintf(buffer, n, "%c ", this->state);
|
||||
switch (this->state) {
|
||||
#ifdef HTOP_NETBSD
|
||||
case 'P':
|
||||
#else
|
||||
case 'R':
|
||||
attr = CRT_colors[PROCESS_R_STATE];
|
||||
#endif
|
||||
attr = CRT_colors[PROCESS_RUN_STATE];
|
||||
break;
|
||||
case 'D':
|
||||
attr = CRT_colors[PROCESS_D_STATE];
|
||||
|
@ -79,8 +79,6 @@ typedef struct ProcessMergedCommand_ {
|
||||
char* str; /* merged Command string */
|
||||
size_t highlightCount; /* how many 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 exeChanged : 1; /* whether exe 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_printPercentage(float val, char* buffer, int n, int* attr);
|
||||
|
||||
void Process_display(const Object* cast, RichString* out);
|
||||
|
||||
void Process_done(Process* this);
|
||||
|
12
Settings.c
12
Settings.c
@ -134,8 +134,9 @@ static void Settings_readFields(Settings* settings, const char* line) {
|
||||
}
|
||||
|
||||
// Dynamically-defined columns are always stored by-name.
|
||||
char* end, dynamic[32] = {0};
|
||||
char dynamic[32] = {0};
|
||||
if (sscanf(ids[i], "Dynamic(%30s)", dynamic)) {
|
||||
char* end;
|
||||
if ((end = strrchr(dynamic, ')')) == NULL)
|
||||
continue;
|
||||
*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
|
||||
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);
|
||||
String_freeArray(option);
|
||||
fclose(fd);
|
||||
return false;
|
||||
}
|
||||
} else if (String_eq(option[0], "fields")) {
|
||||
@ -355,9 +358,9 @@ int Settings_write(const Settings* this, bool onCrash) {
|
||||
}
|
||||
|
||||
#define printSettingInteger(setting_, value_) \
|
||||
fprintf(fd, setting_ "=%d%c", (int) value_, separator);
|
||||
fprintf(fd, setting_ "=%d%c", (int) (value_), separator)
|
||||
#define printSettingString(setting_, value_) \
|
||||
fprintf(fd, setting_ "=%s%c", value_, separator);
|
||||
fprintf(fd, setting_ "=%s%c", value_, separator)
|
||||
|
||||
if (!onCrash) {
|
||||
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;
|
||||
Settings_read(this, SYSCONFDIR "/htoprc", initialCpuCount);
|
||||
}
|
||||
if (!ok) {
|
||||
Settings_defaultMeters(this, initialCpuCount);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
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_AUX_DIR([build-aux])
|
||||
@ -482,6 +482,9 @@ AC_ARG_ENABLE([ancient_vserver],
|
||||
[],
|
||||
[enable_ancient_vserver=no])
|
||||
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_ANCIENT_VSERVER], [1], [Define if ancient vserver support enabled.])
|
||||
fi
|
||||
|
@ -99,6 +99,8 @@ void Platform_gettime_monotonic(uint64_t* msec);
|
||||
|
||||
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_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 void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
|
||||
|
||||
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; }
|
||||
|
@ -92,6 +92,8 @@ static inline void Platform_gettime_monotonic(uint64_t* msec) {
|
||||
|
||||
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_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 void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
|
||||
|
||||
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; }
|
||||
|
@ -92,6 +92,8 @@ static inline void Platform_gettime_monotonic(uint64_t* msec) {
|
||||
|
||||
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_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 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; }
|
||||
|
||||
#endif
|
||||
|
@ -392,9 +392,6 @@ except the process's executable instructions).
|
||||
.B M_LRS (LIB)
|
||||
The library size of the process.
|
||||
.TP
|
||||
.B M_DT (DIRTY)
|
||||
The size of the dirty pages of the process.
|
||||
.TP
|
||||
.B M_SWAP (SWAP)
|
||||
The size of the process's swapped pages.
|
||||
.TP
|
||||
|
@ -30,8 +30,6 @@ typedef int IOPriority;
|
||||
|
||||
#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_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_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_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, },
|
||||
[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, },
|
||||
@ -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, },
|
||||
[IO_PRIORITY] = { .name = "IO_PRIORITY", .title = "IO ", .description = "I/O priority", .flags = PROCESS_FLAG_LINUX_IOPRIO, },
|
||||
#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_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
|
||||
[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, },
|
||||
@ -190,16 +189,6 @@ bool LinuxProcess_changeAutogroupPriorityBy(Process* this, Arg delta) {
|
||||
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) {
|
||||
const LinuxProcess* lp = (const LinuxProcess*) this;
|
||||
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 CMAJFLT: Process_printCount(str, lp->cmajflt, 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:
|
||||
if (lp->m_lrs) {
|
||||
Process_printBytes(str, lp->m_lrs * pageSize, coloring);
|
||||
@ -279,9 +267,9 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces
|
||||
break;
|
||||
}
|
||||
#ifdef HAVE_DELAYACCT
|
||||
case PERCENT_CPU_DELAY: LinuxProcess_printDelay(lp->cpu_delay_percent, buffer, n); break;
|
||||
case PERCENT_IO_DELAY: LinuxProcess_printDelay(lp->blkio_delay_percent, buffer, n); break;
|
||||
case PERCENT_SWAP_DELAY: LinuxProcess_printDelay(lp->swapin_delay_percent, buffer, n); break;
|
||||
case PERCENT_CPU_DELAY: Process_printPercentage(lp->cpu_delay_percent, buffer, n, &attr); break;
|
||||
case PERCENT_IO_DELAY: Process_printPercentage(lp->blkio_delay_percent, buffer, n, &attr); break;
|
||||
case PERCENT_SWAP_DELAY: Process_printPercentage(lp->swapin_delay_percent, buffer, n, &attr); break;
|
||||
#endif
|
||||
case CTXT:
|
||||
if (lp->ctxt_diff > 1000) {
|
||||
@ -330,8 +318,6 @@ static int LinuxProcess_compareByKey(const Process* v1, const Process* v2, Proce
|
||||
switch (key) {
|
||||
case 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:
|
||||
return SPACESHIP_NUMBER(p1->m_lrs, p2->m_lrs);
|
||||
case M_TRS:
|
||||
|
@ -47,7 +47,6 @@ typedef struct LinuxProcess_ {
|
||||
long m_trs;
|
||||
long m_drs;
|
||||
long m_lrs;
|
||||
long m_dt;
|
||||
|
||||
/* Data read (in bytes) */
|
||||
unsigned long long io_rchar;
|
||||
|
@ -678,7 +678,7 @@ static bool LinuxProcessList_readStatmFile(LinuxProcess* process, openat_arg_t p
|
||||
if (!statmfile)
|
||||
return false;
|
||||
|
||||
long int dummy;
|
||||
long int dummy, dummy2;
|
||||
|
||||
int r = fscanf(statmfile, "%ld %ld %ld %ld %ld %ld %ld",
|
||||
&process->super.m_virt,
|
||||
@ -687,7 +687,7 @@ static bool LinuxProcessList_readStatmFile(LinuxProcess* process, openat_arg_t p
|
||||
&process->m_trs,
|
||||
&dummy, /* unused since Linux 2.6; always 0 */
|
||||
&process->m_drs,
|
||||
&process->m_dt);
|
||||
&dummy2); /* unused since Linux 2.6; always 0 */
|
||||
fclose(statmfile);
|
||||
|
||||
if (r == 7) {
|
||||
@ -1433,7 +1433,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
|
||||
|
||||
uint64_t recheck = ((uint64_t)rand()) % 2048;
|
||||
|
||||
if (passedTimeInMs > 2000 || passedTimeInMs > recheck) {
|
||||
if (passedTimeInMs > recheck) {
|
||||
lp->last_mlrs_calctime = pl->realtimeMs;
|
||||
LinuxProcessList_readMaps(lp, procFd, settings->flags & PROCESS_FLAG_LINUX_LRS_FIX, settings->highlightDeletedExe);
|
||||
}
|
||||
|
@ -543,6 +543,8 @@ bool Platform_getDiskIO(DiskIOData* data) {
|
||||
if (!fd)
|
||||
return false;
|
||||
|
||||
char lastTopDisk[32] = { '\0' };
|
||||
|
||||
unsigned long long int read_sum = 0, write_sum = 0, timeSpend_sum = 0;
|
||||
char lineBuffer[256];
|
||||
while (fgets(lineBuffer, sizeof(lineBuffer), fd)) {
|
||||
@ -556,22 +558,11 @@ bool Platform_getDiskIO(DiskIOData* data) {
|
||||
continue;
|
||||
|
||||
/* only count root disks, e.g. do not count IO from sda and sda1 twice */
|
||||
if ((diskname[0] == 's' || diskname[0] == 'h')
|
||||
&& diskname[1] == 'd'
|
||||
&& isalpha((unsigned char)diskname[2])
|
||||
&& isdigit((unsigned char)diskname[3]))
|
||||
if (lastTopDisk[0] && String_startsWith(diskname, lastTopDisk))
|
||||
continue;
|
||||
|
||||
/* only count root disks, e.g. do not count IO from mmcblk0 and mmcblk0p1 twice */
|
||||
if (diskname[0] == 'm'
|
||||
&& diskname[1] == 'm'
|
||||
&& diskname[2] == 'c'
|
||||
&& diskname[3] == 'b'
|
||||
&& diskname[4] == 'l'
|
||||
&& diskname[5] == 'k'
|
||||
&& isdigit((unsigned char)diskname[6])
|
||||
&& diskname[7] == 'p')
|
||||
continue;
|
||||
/* This assumes disks are listed directly before any of their partitions */
|
||||
String_safeStrncpy(lastTopDisk, diskname, sizeof(lastTopDisk));
|
||||
|
||||
read_sum += read_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 void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
|
||||
|
||||
static inline void Platform_dynamicMeterInit(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 void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
|
||||
|
||||
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; }
|
||||
|
@ -19,7 +19,6 @@ in the source distribution for its full text.
|
||||
M_TRS = 42, \
|
||||
M_DRS = 43, \
|
||||
M_LRS = 44, \
|
||||
M_DT = 45, \
|
||||
CTID = 100, \
|
||||
VPID = 101, \
|
||||
VXID = 102, \
|
||||
|
@ -39,14 +39,17 @@ static long fscale;
|
||||
static int pageSize;
|
||||
static int pageSizeKB;
|
||||
|
||||
static char const *freqSysctls[] = {
|
||||
"machdep.est.frequency.current",
|
||||
"machdep.powernow.frequency.current",
|
||||
"machdep.intrepid.frequency.current",
|
||||
"machdep.loongson.frequency.current",
|
||||
"machdep.cpu.frequency.current",
|
||||
"machdep.frequency.current",
|
||||
NULL
|
||||
static const struct {
|
||||
const char* name;
|
||||
long int scale;
|
||||
} freqSysctls[] = {
|
||||
{ "machdep.est.frequency.current", 1 },
|
||||
{ "machdep.powernow.frequency.current", 1 },
|
||||
{ "machdep.intrepid.frequency.current", 1 },
|
||||
{ "machdep.loongson.frequency.current", 1 },
|
||||
{ "machdep.cpu.frequency.current", 1 },
|
||||
{ "machdep.frequency.current", 1 },
|
||||
{ "machdep.tsc_freq", 1000000 },
|
||||
};
|
||||
|
||||
static void NetBSDProcessList_updateCPUcount(ProcessList* super) {
|
||||
@ -261,7 +264,6 @@ static void NetBSDProcessList_scanProcs(NetBSDProcessList* this) {
|
||||
bool hideKernelThreads = settings->hideKernelThreads;
|
||||
bool hideUserlandThreads = settings->hideUserlandThreads;
|
||||
int count = 0;
|
||||
int nlwps = 0;
|
||||
|
||||
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->tgid = kproc->p_pid;
|
||||
proc->session = kproc->p_sid;
|
||||
proc->tty_nr = kproc->p_tdev;
|
||||
proc->pgrp = kproc->p__pgid;
|
||||
proc->isKernelThread = !!(kproc->p_flag & P_SYSTEM);
|
||||
proc->isUserlandThread = proc->pid != proc->tgid;
|
||||
@ -287,6 +288,15 @@ static void NetBSDProcessList_scanProcs(NetBSDProcessList* this) {
|
||||
Process_fillStarttimeBuffer(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_updateProcessName(this->kd, kproc, proc);
|
||||
} else {
|
||||
@ -312,8 +322,12 @@ static void NetBSDProcessList_scanProcs(NetBSDProcessList* this) {
|
||||
proc->nice = kproc->p_nice - 20;
|
||||
proc->time = 100 * (kproc->p_rtime_sec + ((kproc->p_rtime_usec + 500000) / 1000000));
|
||||
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) {
|
||||
case SIDL: proc->state = 'I'; break;
|
||||
@ -417,7 +431,7 @@ static void NetBSDProcessList_scanCPUFrequency(NetBSDProcessList* this) {
|
||||
unsigned int cpus = this->super.existingCPUs;
|
||||
bool match = false;
|
||||
char name[64];
|
||||
int freq = 0;
|
||||
long int freq = 0;
|
||||
size_t freqSize;
|
||||
|
||||
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);
|
||||
freqSize = sizeof(freq);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -442,9 +456,10 @@ static void NetBSDProcessList_scanCPUFrequency(NetBSDProcessList* this) {
|
||||
* Iterate through legacy sysctl nodes for single-core frequency until
|
||||
* we find a match...
|
||||
*/
|
||||
for (const char** s = freqSysctls; *s != NULL; ++s) {
|
||||
for (size_t i = 0; i < ARRAYSIZE(freqSysctls); i++) {
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
@ -260,14 +260,11 @@ double Platform_setCPUValues(Meter* this, int cpu) {
|
||||
|
||||
void Platform_setMemoryValues(Meter* this) {
|
||||
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->values[0] = usedMem;
|
||||
this->values[1] = buffersMem;
|
||||
this->values[0] = pl->usedMem;
|
||||
this->values[1] = pl->buffersMem;
|
||||
// this->values[2] = "shared memory, like tmpfs and shm"
|
||||
this->values[3] = cachedMem;
|
||||
this->values[3] = pl->cachedMem;
|
||||
// this->values[4] = "available memory"
|
||||
}
|
||||
|
||||
@ -284,19 +281,19 @@ char* Platform_getProcessEnv(pid_t pid) {
|
||||
char** ptr;
|
||||
int count;
|
||||
kvm_t* kt;
|
||||
struct kinfo_proc* kproc;
|
||||
const struct kinfo_proc2* kproc;
|
||||
size_t capacity = 4096, size = 0;
|
||||
|
||||
if ((kt = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == 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);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ptr = kvm_getenvv(kt, kproc, 0)) == NULL) {
|
||||
if ((ptr = kvm_getenvv2(kt, kproc, 0)) == NULL) {
|
||||
(void) kvm_close(kt);
|
||||
return NULL;
|
||||
}
|
||||
@ -393,7 +390,7 @@ bool Platform_getNetworkIO(NetworkIOData* data) {
|
||||
if (getifaddrs(&ifaddrs) != 0)
|
||||
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)
|
||||
continue;
|
||||
if (ifa->ifa_addr->sa_family != AF_LINK)
|
||||
@ -401,7 +398,7 @@ bool Platform_getNetworkIO(NetworkIOData* data) {
|
||||
if (ifa->ifa_flags & IFF_LOOPBACK)
|
||||
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->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 void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
|
||||
|
||||
static inline void Platform_dynamicMeterInit(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 void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
|
||||
|
||||
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; }
|
||||
|
@ -90,6 +90,8 @@ static inline void Platform_gettime_monotonic(uint64_t* msec) {
|
||||
|
||||
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_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 void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
|
||||
|
||||
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; }
|
||||
|
@ -226,6 +226,18 @@ void PCPDynamicColumns_init(PCPDynamicColumns* columns) {
|
||||
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) {
|
||||
const PCPProcess* pp = (const PCPProcess*) proc;
|
||||
unsigned int type = PCPMetric_type(this->id);
|
||||
|
@ -26,6 +26,8 @@ typedef struct PCPDynamicColumns_ {
|
||||
|
||||
void PCPDynamicColumns_init(PCPDynamicColumns* columns);
|
||||
|
||||
void PCPDynamicColumns_done(Hashtable* table);
|
||||
|
||||
void PCPDynamicColumn_writeField(PCPDynamicColumn* this, const Process* proc, RichString* str);
|
||||
|
||||
int PCPDynamicColumn_compareByKey(const PCPProcess* p1, const PCPProcess* p2, ProcessField key);
|
||||
|
@ -283,6 +283,22 @@ void PCPDynamicMeters_init(PCPDynamicMeters* meters) {
|
||||
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) {
|
||||
for (size_t i = 0; i < this->totalMetrics; i++)
|
||||
PCPMetric_enable(this->metrics[i].id, true);
|
||||
|
@ -33,6 +33,8 @@ typedef struct PCPDynamicMeters_ {
|
||||
|
||||
void PCPDynamicMeters_init(PCPDynamicMeters* meters);
|
||||
|
||||
void PCPDynamicMeters_done(Hashtable* table);
|
||||
|
||||
void PCPDynamicMeter_enable(PCPDynamicMeter* this);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -363,6 +363,14 @@ void Platform_init(void) {
|
||||
Platform_getMaxPid();
|
||||
}
|
||||
|
||||
void Platform_dynamicColumnsDone(Hashtable* columns) {
|
||||
PCPDynamicColumns_done(columns);
|
||||
}
|
||||
|
||||
void Platform_dynamicMetersDone(Hashtable* meters) {
|
||||
PCPDynamicMeters_done(meters);
|
||||
}
|
||||
|
||||
void Platform_done(void) {
|
||||
pmDestroyContext(pcp->context);
|
||||
if (pcp->result)
|
||||
|
@ -138,6 +138,8 @@ void Platform_gettime_monotonic(uint64_t* msec);
|
||||
|
||||
Hashtable* Platform_dynamicMeters(void);
|
||||
|
||||
void Platform_dynamicMetersDone(Hashtable* meters);
|
||||
|
||||
void Platform_dynamicMeterInit(Meter* meter);
|
||||
|
||||
void Platform_dynamicMeterUpdateValues(Meter* meter);
|
||||
@ -146,6 +148,8 @@ void Platform_dynamicMeterDisplay(const Meter* meter, RichString* out);
|
||||
|
||||
Hashtable* Platform_dynamicColumns(void);
|
||||
|
||||
void Platform_dynamicColumnsDone(Hashtable* columns);
|
||||
|
||||
const char* Platform_dynamicColumnInit(unsigned int key);
|
||||
|
||||
bool Platform_dynamicColumnWriteField(const Process* proc, RichString* str, unsigned int key);
|
||||
|
@ -131,6 +131,8 @@ IGNORE_WCASTQUAL_END
|
||||
|
||||
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_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 void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
|
||||
|
||||
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; }
|
||||
|
@ -79,6 +79,8 @@ static inline void Platform_gettime_monotonic(uint64_t* msec) {
|
||||
|
||||
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_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 void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
|
||||
|
||||
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; }
|
||||
|
Reference in New Issue
Block a user