aboutsummaryrefslogtreecommitdiffstats
path: root/linux/Platform.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/Platform.c')
-rw-r--r--linux/Platform.c176
1 files changed, 115 insertions, 61 deletions
diff --git a/linux/Platform.c b/linux/Platform.c
index 64f25c4..8dc8bb5 100644
--- a/linux/Platform.c
+++ b/linux/Platform.c
@@ -5,12 +5,11 @@ Released under the GNU GPLv2+, see the COPYING file
in the source distribution for its full text.
*/
-#include "config.h"
+#include "config.h" // IWYU pragma: keep
#include "linux/Platform.h"
#include <assert.h>
-#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@@ -31,9 +30,11 @@ in the source distribution for its full text.
#include "DateMeter.h"
#include "DateTimeMeter.h"
#include "DiskIOMeter.h"
+#include "FileDescriptorMeter.h"
#include "HostnameMeter.h"
#include "HugePageMeter.h"
#include "LoadAverageMeter.h"
+#include "Machine.h"
#include "Macros.h"
#include "MainPanel.h"
#include "Meter.h"
@@ -43,9 +44,7 @@ in the source distribution for its full text.
#include "Object.h"
#include "Panel.h"
#include "PressureStallMeter.h"
-#include "ProcessList.h"
#include "ProvideCurses.h"
-#include "linux/SELinuxMeter.h"
#include "Settings.h"
#include "SwapMeter.h"
#include "SysArchMeter.h"
@@ -54,17 +53,18 @@ in the source distribution for its full text.
#include "XUtils.h"
#include "linux/IOPriority.h"
#include "linux/IOPriorityPanel.h"
+#include "linux/LinuxMachine.h"
#include "linux/LinuxProcess.h"
-#include "linux/LinuxProcessList.h"
+#include "linux/SELinuxMeter.h"
#include "linux/SystemdMeter.h"
#include "linux/ZramMeter.h"
#include "linux/ZramStats.h"
+#include "linux/ZswapStats.h"
#include "zfs/ZfsArcMeter.h"
#include "zfs/ZfsArcStats.h"
#include "zfs/ZfsCompressedArcMeter.h"
#ifdef HAVE_LIBCAP
-#include <errno.h>
#include <sys/capability.h>
#endif
@@ -163,7 +163,7 @@ static Htop_Reaction Platform_actionSetIOPriority(State* st) {
const void* set = Action_pickFromVector(st, ioprioPanel, 20, true);
if (set) {
IOPriority ioprio2 = IOPriorityPanel_getIOPriority(ioprioPanel);
- bool ok = MainPanel_foreachProcess(st->mainPanel, LinuxProcess_setIOPriority, (Arg) { .i = ioprio2 }, NULL);
+ bool ok = MainPanel_foreachRow(st->mainPanel, LinuxProcess_rowSetIOPriority, (Arg) { .i = ioprio2 }, NULL);
if (!ok) {
beep();
}
@@ -178,7 +178,7 @@ static bool Platform_changeAutogroupPriority(MainPanel* panel, int delta) {
return false;
}
bool anyTagged;
- bool ok = MainPanel_foreachProcess(panel, LinuxProcess_changeAutogroupPriorityBy, (Arg) { .i = delta }, &anyTagged);
+ bool ok = MainPanel_foreachRow(panel, LinuxProcess_rowChangeAutogroupPriorityBy, (Arg) { .i = delta }, &anyTagged);
if (!ok)
beep();
return anyTagged;
@@ -240,6 +240,7 @@ const MeterClass* const Platform_meterTypes[] = {
&PressureStallCPUSomeMeter_class,
&PressureStallIOSomeMeter_class,
&PressureStallIOFullMeter_class,
+ &PressureStallIRQFullMeter_class,
&PressureStallMemorySomeMeter_class,
&PressureStallMemoryFullMeter_class,
&ZfsArcMeter_class,
@@ -249,6 +250,8 @@ const MeterClass* const Platform_meterTypes[] = {
&NetworkIOMeter_class,
&SELinuxMeter_class,
&SystemdMeter_class,
+ &SystemdUserMeter_class,
+ &FileDescriptorMeter_class,
NULL
};
@@ -287,12 +290,12 @@ err:
*fifteen = NAN;
}
-int Platform_getMaxPid(void) {
+pid_t Platform_getMaxPid(void) {
+ pid_t maxPid = 4194303;
FILE* file = fopen(PROCDIR "/sys/kernel/pid_max", "r");
if (!file)
- return -1;
+ return maxPid;
- int maxPid = 4194303;
int match = fscanf(file, "%32d", &maxPid);
(void) match;
fclose(file);
@@ -300,8 +303,9 @@ int Platform_getMaxPid(void) {
}
double Platform_setCPUValues(Meter* this, unsigned int cpu) {
- const LinuxProcessList* pl = (const LinuxProcessList*) this->pl;
- const CPUData* cpuData = &(pl->cpuData[cpu]);
+ const LinuxMachine* lhost = (const LinuxMachine*) this->host;
+ const Settings* settings = this->host->settings;
+ const CPUData* cpuData = &(lhost->cpuData[cpu]);
double total = (double) ( cpuData->totalPeriod == 0 ? 1 : cpuData->totalPeriod);
double percent;
double* v = this->values;
@@ -313,28 +317,30 @@ double Platform_setCPUValues(Meter* this, unsigned int cpu) {
v[CPU_METER_NICE] = cpuData->nicePeriod / total * 100.0;
v[CPU_METER_NORMAL] = cpuData->userPeriod / total * 100.0;
- if (this->pl->settings->detailedCPUTime) {
+ if (settings->detailedCPUTime) {
v[CPU_METER_KERNEL] = cpuData->systemPeriod / total * 100.0;
v[CPU_METER_IRQ] = cpuData->irqPeriod / total * 100.0;
v[CPU_METER_SOFTIRQ] = cpuData->softIrqPeriod / total * 100.0;
+ this->curItems = 5;
+
v[CPU_METER_STEAL] = cpuData->stealPeriod / total * 100.0;
v[CPU_METER_GUEST] = cpuData->guestPeriod / total * 100.0;
- v[CPU_METER_IOWAIT] = cpuData->ioWaitPeriod / total * 100.0;
- this->curItems = 8;
- if (this->pl->settings->accountGuestInCPUMeter) {
- percent = v[0] + v[1] + v[2] + v[3] + v[4] + v[5] + v[6];
- } else {
- percent = v[0] + v[1] + v[2] + v[3] + v[4];
+ if (settings->accountGuestInCPUMeter) {
+ this->curItems = 7;
}
+
+ v[CPU_METER_IOWAIT] = cpuData->ioWaitPeriod / total * 100.0;
} else {
- v[2] = cpuData->systemAllPeriod / total * 100.0;
- v[3] = (cpuData->stealPeriod + cpuData->guestPeriod) / total * 100.0;
+ v[CPU_METER_KERNEL] = cpuData->systemAllPeriod / total * 100.0;
+ v[CPU_METER_IRQ] = (cpuData->stealPeriod + cpuData->guestPeriod) / total * 100.0;
this->curItems = 4;
- percent = v[0] + v[1] + v[2] + v[3];
}
- percent = CLAMP(percent, 0.0, 100.0);
- if (isnan(percent)) {
- percent = 0.0;
+
+ percent = sumPositiveValues(v, this->curItems);
+ percent = MINIMUM(percent, 100.0);
+
+ if (settings->detailedCPUTime) {
+ this->curItems = 8;
}
v[CPU_METER_FREQUENCY] = cpuData->frequency;
@@ -349,51 +355,81 @@ double Platform_setCPUValues(Meter* this, unsigned int cpu) {
}
void Platform_setMemoryValues(Meter* this) {
- const ProcessList* pl = this->pl;
- const LinuxProcessList* lpl = (const LinuxProcessList*) pl;
-
- this->total = pl->totalMem;
- this->values[MEMORY_METER_USED] = pl->usedMem;
- this->values[MEMORY_METER_BUFFERS] = pl->buffersMem;
- this->values[MEMORY_METER_SHARED] = pl->sharedMem;
- this->values[MEMORY_METER_CACHE] = pl->cachedMem;
- this->values[MEMORY_METER_AVAILABLE] = pl->availableMem;
-
- if (lpl->zfs.enabled != 0 && !Running_containerized) {
+ const Machine* host = this->host;
+ const LinuxMachine* lhost = (const LinuxMachine*) host;
+
+ this->total = host->totalMem;
+ this->values[MEMORY_METER_USED] = host->usedMem;
+ this->values[MEMORY_METER_SHARED] = host->sharedMem;
+ this->values[MEMORY_METER_COMPRESSED] = 0; /* compressed */
+ this->values[MEMORY_METER_BUFFERS] = host->buffersMem;
+ this->values[MEMORY_METER_CACHE] = host->cachedMem;
+ this->values[MEMORY_METER_AVAILABLE] = host->availableMem;
+
+ if (lhost->zfs.enabled != 0 && !Running_containerized) {
// ZFS does not shrink below the value of zfs_arc_min.
unsigned long long int shrinkableSize = 0;
- if (lpl->zfs.size > lpl->zfs.min)
- shrinkableSize = lpl->zfs.size - lpl->zfs.min;
+ if (lhost->zfs.size > lhost->zfs.min)
+ shrinkableSize = lhost->zfs.size - lhost->zfs.min;
this->values[MEMORY_METER_USED] -= shrinkableSize;
this->values[MEMORY_METER_CACHE] += shrinkableSize;
this->values[MEMORY_METER_AVAILABLE] += shrinkableSize;
}
+
+ if (lhost->zswap.usedZswapOrig > 0 || lhost->zswap.usedZswapComp > 0) {
+ this->values[MEMORY_METER_USED] -= lhost->zswap.usedZswapComp;
+ this->values[MEMORY_METER_COMPRESSED] += lhost->zswap.usedZswapComp;
+ }
}
void Platform_setSwapValues(Meter* this) {
- const ProcessList* pl = this->pl;
- this->total = pl->totalSwap;
- this->values[0] = pl->usedSwap;
- this->values[1] = pl->cachedSwap;
+ const Machine* host = this->host;
+ const LinuxMachine* lhost = (const LinuxMachine*) host;
+
+ this->total = host->totalSwap;
+ this->values[SWAP_METER_USED] = host->usedSwap;
+ this->values[SWAP_METER_CACHE] = host->cachedSwap;
+ this->values[SWAP_METER_FRONTSWAP] = 0; /* frontswap -- memory that is accounted to swap but resides elsewhere */
+
+ if (lhost->zswap.usedZswapOrig > 0 || lhost->zswap.usedZswapComp > 0) {
+ /*
+ * FIXME: Zswapped pages can be both SwapUsed and SwapCached, and we do not know which.
+ *
+ * Apparently, it is possible that Zswapped > SwapUsed. This means that some of Zswapped pages
+ * were actually SwapCached, nor SwapUsed. Unfortunately, we cannot tell what exactly portion
+ * of Zswapped pages were SwapCached.
+ *
+ * For now, subtract Zswapped from SwapUsed and only if Zswapped > SwapUsed, subtract the
+ * overflow from SwapCached.
+ */
+ this->values[SWAP_METER_USED] -= lhost->zswap.usedZswapOrig;
+ if (this->values[SWAP_METER_USED] < 0) {
+ /* subtract the overflow from SwapCached */
+ this->values[SWAP_METER_CACHE] += this->values[SWAP_METER_USED];
+ this->values[SWAP_METER_USED] = 0;
+ }
+ this->values[SWAP_METER_FRONTSWAP] += lhost->zswap.usedZswapOrig;
+ }
}
void Platform_setZramValues(Meter* this) {
- const LinuxProcessList* lpl = (const LinuxProcessList*) this->pl;
- this->total = lpl->zram.totalZram;
- this->values[0] = lpl->zram.usedZramComp;
- this->values[1] = lpl->zram.usedZramOrig;
+ const LinuxMachine* lhost = (const LinuxMachine*) this->host;
+
+ this->total = lhost->zram.totalZram;
+ this->values[ZRAM_METER_COMPRESSED] = lhost->zram.usedZramComp;
+ this->values[ZRAM_METER_UNCOMPRESSED] = lhost->zram.usedZramOrig - lhost->zram.usedZramComp;
}
void Platform_setZfsArcValues(Meter* this) {
- const LinuxProcessList* lpl = (const LinuxProcessList*) this->pl;
+ const LinuxMachine* lhost = (const LinuxMachine*) this->host;
- ZfsArcMeter_readStats(this, &(lpl->zfs));
+ ZfsArcMeter_readStats(this, &(lhost->zfs));
}
void Platform_setZfsCompressedArcValues(Meter* this) {
- const LinuxProcessList* lpl = (const LinuxProcessList*) this->pl;
+ const LinuxMachine* lhost = (const LinuxMachine*) this->host;
- ZfsCompressedArcMeter_readStats(this, &(lpl->zfs));
+ ZfsCompressedArcMeter_readStats(this, &(lhost->zfs));
}
char* Platform_getProcessEnv(pid_t pid) {
@@ -456,16 +492,16 @@ FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
continue;
errno = 0;
- char *end = de->d_name;
+ char* end = de->d_name;
int file = strtoull(de->d_name, &end, 10);
if (errno || *end)
continue;
int fd = openat(dfd, de->d_name, O_RDONLY | O_CLOEXEC);
- if(fd == -1)
+ if (fd == -1)
continue;
- FILE *f = fdopen(fd, "r");
- if(!f) {
+ FILE* f = fdopen(fd, "r");
+ if (!f) {
close(fd);
continue;
}
@@ -474,7 +510,7 @@ FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
if (!strchr(buffer, '\n'))
continue;
- if (strncmp(buffer, "lock:\t", strlen("lock:\t")))
+ if (!String_startsWith(buffer, "lock:\t"))
continue;
FileLocks_Data data = {.fd = file};
@@ -537,6 +573,24 @@ void Platform_getPressureStall(const char* file, bool some, double* ten, double*
fclose(fd);
}
+void Platform_getFileDescriptors(double* used, double* max) {
+ *used = NAN;
+ *max = 65536;
+
+ FILE* fd = fopen(PROCDIR "/sys/fs/file-nr", "r");
+ if (!fd)
+ return;
+
+ unsigned long long v1, v2, v3;
+ int total = fscanf(fd, "%llu %llu %llu", &v1, &v2, &v3);
+ if (total == 3) {
+ *used = v1;
+ *max = v3;
+ }
+
+ fclose(fd);
+}
+
bool Platform_getDiskIO(DiskIOData* data) {
FILE* fd = fopen(PROCDIR "/diskstats", "r");
if (!fd)
@@ -790,7 +844,7 @@ static void Platform_Battery_getSysData(double* percent, ACPresence* isOnAC) {
}
}
- if (!now && full && !isnan(capacityLevel))
+ if (!now && full && isNonnegative(capacityLevel))
totalRemain += capacityLevel * fullCharge;
} else if (type == AC) {
@@ -830,12 +884,12 @@ void Platform_getBattery(double* percent, ACPresence* isOnAC) {
if (Platform_Battery_method == BAT_PROC) {
Platform_Battery_getProcData(percent, isOnAC);
- if (isnan(*percent))
+ if (!isNonnegative(*percent))
Platform_Battery_method = BAT_SYS;
}
if (Platform_Battery_method == BAT_SYS) {
Platform_Battery_getSysData(percent, isOnAC);
- if (isnan(*percent))
+ if (!isNonnegative(*percent))
Platform_Battery_method = BAT_ERR;
}
if (Platform_Battery_method == BAT_ERR) {
@@ -874,7 +928,7 @@ CommandLineStatus Platform_getLongOption(int opt, int argc, char** argv) {
case 160: {
const char* mode = optarg;
if (!mode && optind < argc && argv[optind] != NULL &&
- (argv[optind][0] != '\0' && argv[optind][0] != '-')) {
+ (argv[optind][0] != '\0' && argv[optind][0] != '-')) {
mode = argv[optind++];
}
@@ -1015,7 +1069,7 @@ bool Platform_init(void) {
char lineBuffer[256];
while (fgets(lineBuffer, sizeof(lineBuffer), fd)) {
// detect lxc or overlayfs and guess that this means we are running containerized
- if (String_startsWith(lineBuffer, "lxcfs /proc") || String_startsWith(lineBuffer, "overlay ")) {
+ if (String_startsWith(lineBuffer, "lxcfs /proc") || String_startsWith(lineBuffer, "overlay / overlay")) {
Running_containerized = true;
break;
}

© 2014-2024 Faster IT GmbH | imprint | privacy policy