From c55320e9e2a8916e911bcd39ab37b79e3a7d03b2 Mon Sep 17 00:00:00 2001 From: Daniel Lange Date: Mon, 11 Jan 2021 20:43:27 +0100 Subject: New upstream version 3.0.5 --- linux/IOPriorityPanel.c | 2 +- linux/LibSensors.c | 81 +++++++++++++++++++-- linux/LibSensors.h | 2 +- linux/LinuxProcess.c | 177 +++++++++++++++++++++------------------------ linux/LinuxProcess.h | 97 ++++--------------------- linux/LinuxProcessList.c | 164 +++++++++++++++++++---------------------- linux/Platform.c | 4 +- linux/Platform.h | 4 +- linux/PressureStallMeter.c | 18 +++-- linux/ProcessField.h | 53 ++++++++++++++ linux/SELinuxMeter.c | 2 +- linux/SystemdMeter.c | 20 ++--- linux/ZramMeter.c | 14 ++-- 13 files changed, 331 insertions(+), 307 deletions(-) create mode 100644 linux/ProcessField.h (limited to 'linux') diff --git a/linux/IOPriorityPanel.c b/linux/IOPriorityPanel.c index c5a4a4c..25d2199 100644 --- a/linux/IOPriorityPanel.c +++ b/linux/IOPriorityPanel.c @@ -17,7 +17,7 @@ in the source distribution for its full text. Panel* IOPriorityPanel_new(IOPriority currPrio) { - Panel* this = Panel_new(1, 1, 1, 1, true, Class(ListItem), FunctionBar_newEnterEsc("Set ", "Cancel ")); + Panel* this = Panel_new(1, 1, 1, 1, Class(ListItem), true, FunctionBar_newEnterEsc("Set ", "Cancel ")); Panel_setHeader(this, "IO Priority:"); Panel_add(this, (Object*) ListItem_new("None (based on nice)", IOPriority_None)); diff --git a/linux/LibSensors.c b/linux/LibSensors.c index a30e21b..158829a 100644 --- a/linux/LibSensors.c +++ b/linux/LibSensors.c @@ -4,6 +4,7 @@ #include #include +#include #include #include "XUtils.h" @@ -16,12 +17,19 @@ static int (*sym_sensors_snprintf_chip_name)(char*, size_t, const sensors_chip_n static const sensors_feature* (*sym_sensors_get_features)(const sensors_chip_name*, int*); static const sensors_subfeature* (*sym_sensors_get_subfeature)(const sensors_chip_name*, const sensors_feature*, sensors_subfeature_type); static int (*sym_sensors_get_value)(const sensors_chip_name*, int, double*); +static char* (*sym_sensors_get_label)(const sensors_chip_name*, const sensors_feature*); static void* dlopenHandle = NULL; int LibSensors_init(FILE* input) { if (!dlopenHandle) { + /* Find the unversioned libsensors.so (symlink) and prefer that, but Debian has .so.5 and Fedora .so.4 without + matching symlinks (unless people install the -dev packages) */ dlopenHandle = dlopen("libsensors.so", RTLD_LAZY); + if (!dlopenHandle) + dlopenHandle = dlopen("libsensors.so.5", RTLD_LAZY); + if (!dlopenHandle) + dlopenHandle = dlopen("libsensors.so.4", RTLD_LAZY); if (!dlopenHandle) goto dlfailure; @@ -41,6 +49,7 @@ int LibSensors_init(FILE* input) { resolve(sensors_get_features); resolve(sensors_get_subfeature); resolve(sensors_get_value); + resolve(sensors_get_label); #undef resolve } @@ -64,17 +73,23 @@ void LibSensors_cleanup(void) { } } -int LibSensors_getCPUTemperatures(CPUData* cpus, int cpuCount) { +void LibSensors_getCPUTemperatures(CPUData* cpus, unsigned int cpuCount) { + for (unsigned int i = 0; i <= cpuCount; i++) + cpus[i].temperature = NAN; + if (!dlopenHandle) - return -ENOTSUP; + return; - int tempCount = 0; + unsigned int coreTempCount = 0; int n = 0; for (const sensors_chip_name *chip = sym_sensors_get_detected_chips(NULL, &n); chip; chip = sym_sensors_get_detected_chips(NULL, &n)) { char buffer[32]; sym_sensors_snprintf_chip_name(buffer, sizeof(buffer), chip); - if (!String_startsWith(buffer, "coretemp") && !String_startsWith(buffer, "cpu_thermal")) + if (!String_startsWith(buffer, "coretemp") && + !String_startsWith(buffer, "cpu_thermal") && + !String_startsWith(buffer, "k10temp") && + !String_startsWith(buffer, "zenpower")) continue; int m = 0; @@ -82,7 +97,27 @@ int LibSensors_getCPUTemperatures(CPUData* cpus, int cpuCount) { if (feature->type != SENSORS_FEATURE_TEMP) continue; - if (feature->number > cpuCount) + char* label = sym_sensors_get_label(chip, feature); + if (!label) + continue; + + unsigned int tempId; + if (String_startsWith(label, "Package ")) { + tempId = 0; + } else if (String_startsWith(label, "temp")) { + /* Raspberry Pi has only temp1 */ + tempId = 0; + } else if (String_startsWith(label, "Tdie")) { + tempId = 0; + } else if (String_startsWith(label, "Core ")) { + tempId = 1 + atoi(label + strlen("Core ")); + } else { + tempId = UINT_MAX; + } + + free(label); + + if (tempId > cpuCount) continue; const sensors_subfeature *sub_feature = sym_sensors_get_subfeature(chip, feature, SENSORS_SUBFEATURE_TEMP_INPUT); @@ -92,13 +127,43 @@ int LibSensors_getCPUTemperatures(CPUData* cpus, int cpuCount) { if (r != 0) continue; - cpus[feature->number].temperature = temp; - tempCount++; + cpus[tempId].temperature = temp; + if (tempId > 0) + coreTempCount++; } } } - return tempCount; + const double packageTemp = cpus[0].temperature; + + /* Only package temperature - copy to all cpus */ + if (coreTempCount == 0 && !isnan(packageTemp)) { + for (unsigned int i = 1; i <= cpuCount; i++) + cpus[i].temperature = packageTemp; + + return; + } + + /* No package temperature - set to max core temperature */ + if (isnan(packageTemp) && coreTempCount != 0) { + double maxTemp = NAN; + for (unsigned int i = 1; i <= cpuCount; i++) { + const double coreTemp = cpus[i].temperature; + if (isnan(coreTemp)) + continue; + + maxTemp = MAXIMUM(maxTemp, coreTemp); + } + + cpus[0].temperature = maxTemp; + } + + /* Half the temperatures, probably HT/SMT - copy to second half */ + const unsigned int delta = cpuCount / 2; + if (coreTempCount == delta) { + for (unsigned int i = 1; i <= delta; i++) + cpus[i + delta].temperature = cpus[i].temperature; + } } #endif /* HAVE_SENSORS_SENSORS_H */ diff --git a/linux/LibSensors.h b/linux/LibSensors.h index ed9be7b..cceeedb 100644 --- a/linux/LibSensors.h +++ b/linux/LibSensors.h @@ -11,6 +11,6 @@ int LibSensors_init(FILE* input); void LibSensors_cleanup(void); -int LibSensors_getCPUTemperatures(CPUData* cpus, int cpuCount); +void LibSensors_getCPUTemperatures(CPUData* cpus, unsigned int cpuCount); #endif /* HEADER_LibSensors */ diff --git a/linux/LinuxProcess.c b/linux/LinuxProcess.c index 8298000..ce6d34d 100644 --- a/linux/LinuxProcess.c +++ b/linux/LinuxProcess.c @@ -24,22 +24,22 @@ in the source distribution for its full text. /* semi-global */ -long long btime; +int pageSize; +int pageSizeKB; /* Used to identify kernel threads in Comm and Exe columns */ static const char *const kthreadID = "KTHREAD"; -ProcessFieldData Process_fields[] = { +const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { [0] = { .name = "", .title = NULL, .description = NULL, .flags = 0, }, - [PID] = { .name = "PID", .title = " PID ", .description = "Process/thread ID", .flags = 0, }, + [PID] = { .name = "PID", .title = "PID", .description = "Process/thread ID", .flags = 0, .pidColumn = true, }, [COMM] = { .name = "Command", .title = "Command ", .description = "Command line", .flags = 0, }, [STATE] = { .name = "STATE", .title = "S ", .description = "Process state (S sleeping, R running, D disk, Z zombie, T traced, W paging, I idle)", .flags = 0, }, - [PPID] = { .name = "PPID", .title = " PPID ", .description = "Parent process ID", .flags = 0, }, - [PGRP] = { .name = "PGRP", .title = " PGRP ", .description = "Process group ID", .flags = 0, }, - [SESSION] = { .name = "SESSION", .title = " SID ", .description = "Process's session ID", .flags = 0, }, + [PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, }, + [PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, }, + [SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, }, [TTY_NR] = { .name = "TTY_NR", .title = "TTY ", .description = "Controlling terminal", .flags = 0, }, - [TPGID] = { .name = "TPGID", .title = " TPGID ", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, }, - [FLAGS] = { .name = "FLAGS", .title = NULL, .description = NULL, .flags = 0, }, + [TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, }, [MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, }, [CMINFLT] = { .name = "CMINFLT", .title = " CMINFLT ", .description = "Children processes' minor faults", .flags = 0, }, [MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, }, @@ -50,24 +50,7 @@ ProcessFieldData Process_fields[] = { [CSTIME] = { .name = "CSTIME", .title = " CSTIME+ ", .description = "Children processes' system CPU time", .flags = 0, }, [PRIORITY] = { .name = "PRIORITY", .title = "PRI ", .description = "Kernel's internal priority for the process", .flags = 0, }, [NICE] = { .name = "NICE", .title = " NI ", .description = "Nice value (the higher the value, the more it lets other processes take priority)", .flags = 0, }, - [ITREALVALUE] = { .name = "ITREALVALUE", .title = NULL, .description = NULL, .flags = 0, }, [STARTTIME] = { .name = "STARTTIME", .title = "START ", .description = "Time the process was started", .flags = 0, }, - [VSIZE] = { .name = "VSIZE", .title = NULL, .description = NULL, .flags = 0, }, - [RSS] = { .name = "RSS", .title = NULL, .description = NULL, .flags = 0, }, - [RLIM] = { .name = "RLIM", .title = NULL, .description = NULL, .flags = 0, }, - [STARTCODE] = { .name = "STARTCODE", .title = NULL, .description = NULL, .flags = 0, }, - [ENDCODE] = { .name = "ENDCODE", .title = NULL, .description = NULL, .flags = 0, }, - [STARTSTACK] = { .name = "STARTSTACK", .title = NULL, .description = NULL, .flags = 0, }, - [KSTKESP] = { .name = "KSTKESP", .title = NULL, .description = NULL, .flags = 0, }, - [KSTKEIP] = { .name = "KSTKEIP", .title = NULL, .description = NULL, .flags = 0, }, - [SIGNAL] = { .name = "SIGNAL", .title = NULL, .description = NULL, .flags = 0, }, - [BLOCKED] = { .name = "BLOCKED", .title = NULL, .description = NULL, .flags = 0, }, - [SSIGIGNORE] = { .name = "SIGIGNORE", .title = NULL, .description = NULL, .flags = 0, }, - [SIGCATCH] = { .name = "SIGCATCH", .title = NULL, .description = NULL, .flags = 0, }, - [WCHAN] = { .name = "WCHAN", .title = NULL, .description = NULL, .flags = 0, }, - [NSWAP] = { .name = "NSWAP", .title = NULL, .description = NULL, .flags = 0, }, - [CNSWAP] = { .name = "CNSWAP", .title = NULL, .description = NULL, .flags = 0, }, - [EXIT_SIGNAL] = { .name = "EXIT_SIGNAL", .title = NULL, .description = NULL, .flags = 0, }, [PROCESSOR] = { .name = "PROCESSOR", .title = "CPU ", .description = "Id of the CPU the process last executed on", .flags = 0, }, [M_VIRT] = { .name = "M_VIRT", .title = " VIRT ", .description = "Total program size in virtual memory", .flags = 0, }, [M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, }, @@ -83,10 +66,10 @@ ProcessFieldData Process_fields[] = { [USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, }, [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, }, [NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, }, - [TGID] = { .name = "TGID", .title = " TGID ", .description = "Thread group ID (i.e. process ID)", .flags = 0, }, + [TGID] = { .name = "TGID", .title = "TGID", .description = "Thread group ID (i.e. process ID)", .flags = 0, .pidColumn = true, }, #ifdef HAVE_OPENVZ [CTID] = { .name = "CTID", .title = " CTID ", .description = "OpenVZ container ID (a.k.a. virtual environment ID)", .flags = PROCESS_FLAG_LINUX_OPENVZ, }, - [VPID] = { .name = "VPID", .title = " VPID ", .description = "OpenVZ process ID", .flags = PROCESS_FLAG_LINUX_OPENVZ, }, + [VPID] = { .name = "VPID", .title = "VPID", .description = "OpenVZ process ID", .flags = PROCESS_FLAG_LINUX_OPENVZ, .pidColumn = true, }, #endif #ifdef HAVE_VSERVER [VXID] = { .name = "VXID", .title = " VXID ", .description = "VServer process ID", .flags = PROCESS_FLAG_LINUX_VSERVER, }, @@ -105,9 +88,9 @@ ProcessFieldData Process_fields[] = { [OOM] = { .name = "OOM", .title = " OOM ", .description = "OOM (Out-of-Memory) killer score", .flags = PROCESS_FLAG_LINUX_OOM, }, [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 = 0, }, - [PERCENT_IO_DELAY] = { .name = "PERCENT_IO_DELAY", .title = "IOD% ", .description = "Block I/O delay %", .flags = 0, }, - [PERCENT_SWAP_DELAY] = { .name = "PERCENT_SWAP_DELAY", .title = "SWAPD% ", .description = "Swapin delay %", .flags = 0, }, + [PERCENT_CPU_DELAY] = { .name = "PERCENT_CPU_DELAY", .title = "CPUD% ", .description = "CPU delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, }, + [PERCENT_IO_DELAY] = { .name = "PERCENT_IO_DELAY", .title = "IOD% ", .description = "Block I/O delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, }, + [PERCENT_SWAP_DELAY] = { .name = "PERCENT_SWAP_DELAY", .title = "SWAPD% ", .description = "Swapin delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, }, #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, }, [M_SWAP] = { .name = "M_SWAP", .title = " SWAP ", .description = "Size of the process's swapped pages", .flags = PROCESS_FLAG_LINUX_SMAPS, }, @@ -117,20 +100,6 @@ ProcessFieldData Process_fields[] = { [PROC_COMM] = { .name = "COMM", .title = "COMM ", .description = "comm string of the process from /proc/[pid]/comm", .flags = 0, }, [PROC_EXE] = { .name = "EXE", .title = "EXE ", .description = "Basename of exe of the process from /proc/[pid]/exe", .flags = 0, }, [CWD] = { .name ="CWD", .title = "CWD ", .description = "The current working directory of the process", .flags = PROCESS_FLAG_LINUX_CWD, }, - [LAST_PROCESSFIELD] = { .name = "*** report bug! ***", .title = NULL, .description = NULL, .flags = 0, }, -}; - -ProcessPidColumn Process_pidColumns[] = { - { .id = PID, .label = "PID" }, - { .id = PPID, .label = "PPID" }, - #ifdef HAVE_OPENVZ - { .id = VPID, .label = "VPID" }, - #endif - { .id = TPGID, .label = "TPGID" }, - { .id = TGID, .label = "TGID" }, - { .id = PGRP, .label = "PGRP" }, - { .id = SESSION, .label = "SID" }, - { .id = 0, .label = NULL }, }; /* This function returns the string displayed in Command column, so that sorting @@ -183,6 +152,11 @@ static int LinuxProcess_effectiveIOPriority(const LinuxProcess* this) { return this->ioPriority; } +#ifdef __ANDROID__ +#define SYS_ioprio_get __NR_ioprio_get +#define SYS_ioprio_set __NR_ioprio_set +#endif + IOPriority LinuxProcess_updateIOPriority(LinuxProcess* this) { IOPriority ioprio = 0; // Other OSes masquerading as Linux (NetBSD?) don't have this syscall @@ -224,12 +198,11 @@ static bool findCommInCmdline(const char *comm, const char *cmdline, int cmdline /* Try to find procComm in tokenized cmdline - this might in rare cases * mis-identify a string or fail, if comm or cmdline had been unsuitably * modified by the process */ - const char *token; const char *tokenBase; size_t tokenLen; const size_t commLen = strlen(comm); - for (token = cmdline + cmdlineBasenameOffset; *token; ) { + for (const char *token = cmdline + cmdlineBasenameOffset; *token; ) { for (tokenBase = token; *token && *token != '\n'; ++token) { if (*token == '/') { tokenBase = token + 1; @@ -394,6 +367,16 @@ void LinuxProcess_makeCommandStr(Process* this) { char *str = strStart; int cmdlineBasenameOffset = lp->procCmdlineBasenameOffset; + int cmdlineBasenameEnd = lp->procCmdlineBasenameEnd; + + if (!cmdline) { + cmdlineBasenameOffset = 0; + cmdlineBasenameEnd = 0; + cmdline = "(zombie)"; + } + + assert(cmdlineBasenameOffset >= 0); + assert(cmdlineBasenameOffset <= (int)strlen(cmdline)); if (!showMergedCommand || !procExe || !procComm) { /* fall back to cmdline */ if (showMergedCommand && !procExe && procComm && strlen(procComm)) { /* Prefix column with comm */ @@ -411,11 +394,11 @@ void LinuxProcess_makeCommandStr(Process* this) { if (showProgramPath) { (void) stpcpyWithNewlineConversion(str, cmdline); mc->baseStart = cmdlineBasenameOffset; - mc->baseEnd = lp->procCmdlineBasenameEnd; + mc->baseEnd = cmdlineBasenameEnd; } else { (void) stpcpyWithNewlineConversion(str, cmdline + cmdlineBasenameOffset); mc->baseStart = 0; - mc->baseEnd = lp->procCmdlineBasenameEnd - cmdlineBasenameOffset; + mc->baseEnd = cmdlineBasenameEnd - cmdlineBasenameOffset; } if (mc->sep1) { @@ -430,6 +413,9 @@ void LinuxProcess_makeCommandStr(Process* this) { int exeBasenameOffset = lp->procExeBasenameOffset; int exeBasenameLen = exeLen - exeBasenameOffset; + assert(exeBasenameOffset >= 0); + assert(exeBasenameOffset <= (int)strlen(procExe)); + /* Start with copying exe */ if (showProgramPath) { str = stpcpy(str, procExe); @@ -536,36 +522,36 @@ static void LinuxProcess_writeCommand(const Process* this, int attr, int baseAtt if(lp->procExeDeleted) baseAttr = CRT_colors[FAILED_READ]; - RichString_append(str, attr, lp->mergedCommand.str); + RichString_appendWide(str, attr, lp->mergedCommand.str); if (lp->mergedCommand.commEnd) { if (!lp->mergedCommand.separateComm && commStart == baseStart && highlightBaseName) { /* If it was matched with procExe's basename, make it bold if needed */ if (commEnd > baseEnd) { - RichString_setAttrn(str, A_BOLD | baseAttr, baseStart, baseEnd - 1); - RichString_setAttrn(str, A_BOLD | commAttr, baseEnd, commEnd - 1); + RichString_setAttrn(str, A_BOLD | baseAttr, baseStart, baseEnd - baseStart); + RichString_setAttrn(str, A_BOLD | commAttr, baseEnd, commEnd - baseEnd); } else if (commEnd < baseEnd) { - RichString_setAttrn(str, A_BOLD | commAttr, commStart, commEnd - 1); - RichString_setAttrn(str, A_BOLD | baseAttr, commEnd, baseEnd - 1); + RichString_setAttrn(str, A_BOLD | commAttr, commStart, commEnd - commStart); + RichString_setAttrn(str, A_BOLD | baseAttr, commEnd, baseEnd - commEnd); } else { // Actually should be highlighted commAttr, but marked baseAttr to reduce visual noise - RichString_setAttrn(str, A_BOLD | baseAttr, commStart, commEnd - 1); + RichString_setAttrn(str, A_BOLD | baseAttr, commStart, commEnd - commStart); } baseStart = baseEnd; } else { - RichString_setAttrn(str, commAttr, commStart, commEnd - 1); + RichString_setAttrn(str, commAttr, commStart, commEnd - commStart); } } if (baseStart < baseEnd && highlightBaseName) { - RichString_setAttrn(str, baseAttr, baseStart, baseEnd - 1); + RichString_setAttrn(str, baseAttr, baseStart, baseEnd - baseStart); } if (mc->sep1) - RichString_setAttrn(str, CRT_colors[FAILED_READ], strStart + mc->sep1, strStart + mc->sep1); + RichString_setAttrn(str, CRT_colors[FAILED_READ], strStart + mc->sep1, 1); if (mc->sep2) - RichString_setAttrn(str, CRT_colors[FAILED_READ], strStart + mc->sep2, strStart + mc->sep2); + RichString_setAttrn(str, CRT_colors[FAILED_READ], strStart + mc->sep2, 1); } static void LinuxProcess_writeCommandField(const Process *this, RichString *str, char *buffer, int n, int attr) { @@ -605,10 +591,11 @@ static void LinuxProcess_writeCommandField(const Process *this, RichString *str, buf = stpcpy(buf, " "); } } + n -= (buf - buffer); - const char* draw = CRT_treeStr[lastItem ? (this->settings->direction == 1 ? TREE_STR_BEND : TREE_STR_TEND) : TREE_STR_RTEE]; + const char* draw = CRT_treeStr[lastItem ? TREE_STR_BEND : TREE_STR_RTEE]; xSnprintf(buf, n, "%s%s ", draw, this->showChildren ? CRT_treeStr[TREE_STR_SHUT] : CRT_treeStr[TREE_STR_OPEN] ); - RichString_append(str, CRT_colors[PROCESS_TREE], buffer); + RichString_appendWide(str, CRT_colors[PROCESS_TREE], buffer); LinuxProcess_writeCommand(this, attr, baseattr, str); } } @@ -619,7 +606,7 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces char buffer[256]; buffer[255] = '\0'; int attr = CRT_colors[DEFAULT_COLOR]; size_t n = sizeof(buffer) - 1; - switch ((int)field) { + switch (field) { case TTY_NR: { if (lp->ttyDevice) { xSnprintf(buffer, n, "%-9s", lp->ttyDevice + 5 /* skip "/dev/" */); @@ -631,19 +618,19 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces } case CMINFLT: Process_colorNumber(str, lp->cminflt, coloring); return; case CMAJFLT: Process_colorNumber(str, lp->cmajflt, coloring); return; - case M_DRS: Process_humanNumber(str, lp->m_drs * CRT_pageSizeKB, coloring); return; - case M_DT: Process_humanNumber(str, lp->m_dt * CRT_pageSizeKB, coloring); return; + case M_DRS: Process_humanNumber(str, lp->m_drs * pageSizeKB, coloring); return; + case M_DT: Process_humanNumber(str, lp->m_dt * pageSizeKB, coloring); return; case M_LRS: if (lp->m_lrs) { - Process_humanNumber(str, lp->m_lrs * CRT_pageSizeKB, coloring); + Process_humanNumber(str, lp->m_lrs * pageSizeKB, coloring); return; } attr = CRT_colors[PROCESS_SHADOW]; xSnprintf(buffer, n, " N/A "); break; - case M_TRS: Process_humanNumber(str, lp->m_trs * CRT_pageSizeKB, coloring); return; - case M_SHARE: Process_humanNumber(str, lp->m_share * CRT_pageSizeKB, coloring); return; + case M_TRS: Process_humanNumber(str, lp->m_trs * pageSizeKB, coloring); return; + case M_SHARE: Process_humanNumber(str, lp->m_share * pageSizeKB, coloring); return; case M_PSS: Process_humanNumber(str, lp->m_pss, coloring); return; case M_SWAP: Process_humanNumber(str, lp->m_swap, coloring); return; case M_PSSWP: Process_humanNumber(str, lp->m_psswp, coloring); return; @@ -674,7 +661,7 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces } #ifdef HAVE_OPENVZ case CTID: xSnprintf(buffer, n, "%-8s ", lp->ctid ? lp->ctid : ""); break; - case VPID: xSnprintf(buffer, n, Process_pidFormat, lp->vpid); break; + case VPID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, lp->vpid); break; #endif #ifdef HAVE_VSERVER case VXID: xSnprintf(buffer, n, "%5u ", lp->vxid); break; @@ -720,59 +707,58 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces return; } case PROC_COMM: { + const char* procComm; if (lp->procComm) { attr = CRT_colors[Process_isUserlandThread(this) ? PROCESS_THREAD_COMM : PROCESS_COMM]; - /* 15 being (TASK_COMM_LEN - 1) */ - xSnprintf(buffer, n, "%-15.15s ", lp->procComm); + procComm = lp->procComm; } else { attr = CRT_colors[PROCESS_SHADOW]; - xSnprintf(buffer, n, "%-15.15s ", Process_isKernelThread(lp) ? kthreadID : "N/A"); + procComm = Process_isKernelThread(lp) ? kthreadID : "N/A"; } - break; + /* 15 being (TASK_COMM_LEN - 1) */ + Process_printLeftAlignedField(str, attr, procComm, 15); + return; } case PROC_EXE: { + const char* procExe; if (lp->procExe) { attr = CRT_colors[Process_isUserlandThread(this) ? PROCESS_THREAD_BASENAME : PROCESS_BASENAME]; if (lp->procExeDeleted) attr = CRT_colors[FAILED_READ]; - xSnprintf(buffer, n, "%-15.15s ", lp->procExe + lp->procExeBasenameOffset); + procExe = lp->procExe + lp->procExeBasenameOffset; } else { attr = CRT_colors[PROCESS_SHADOW]; - xSnprintf(buffer, n, "%-15.15s ", Process_isKernelThread(lp) ? kthreadID : "N/A"); + procExe = Process_isKernelThread(lp) ? kthreadID : "N/A"; } - break; + Process_printLeftAlignedField(str, attr, procExe, 15); + return; } - case CWD: + case CWD: { + const char* cwd; if (!lp->cwd) { - xSnprintf(buffer, n, "%-25s ", "N/A"); attr = CRT_colors[PROCESS_SHADOW]; + cwd = "N/A"; } else if (String_startsWith(lp->cwd, "/proc/") && strstr(lp->cwd, " (deleted)") != NULL) { - xSnprintf(buffer, n, "%-25s ", "main thread terminated"); attr = CRT_colors[PROCESS_SHADOW]; + cwd = "main thread terminated"; } else { - xSnprintf(buffer, n, "%-25.25s ", lp->cwd); + cwd = lp->cwd; } - break; + Process_printLeftAlignedField(str, attr, cwd, 25); + return; + } default: Process_writeField(this, str, field); return; } - RichString_append(str, attr, buffer); + RichString_appendWide(str, attr, buffer); } -static long LinuxProcess_compare(const void* v1, const void* v2) { - const LinuxProcess *p1, *p2; - const Settings *settings = ((const Process*)v1)->settings; - - if (settings->direction == 1) { - p1 = (const LinuxProcess*)v1; - p2 = (const LinuxProcess*)v2; - } else { - p2 = (const LinuxProcess*)v1; - p1 = (const LinuxProcess*)v2; - } +static int LinuxProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) { + const LinuxProcess* p1 = (const LinuxProcess*)v1; + const LinuxProcess* p2 = (const LinuxProcess*)v2; - switch ((int)settings->sortKey) { + switch (key) { case M_DRS: return SPACESHIP_NUMBER(p2->m_drs, p1->m_drs); case M_DT: @@ -858,7 +844,7 @@ static long LinuxProcess_compare(const void* v1, const void* v2) { case CWD: return SPACESHIP_NULLSTR(p1->cwd, p2->cwd); default: - return Process_compare(v1, v2); + return Process_compareByKey_Base(v1, v2, key); } } @@ -871,8 +857,9 @@ const ProcessClass LinuxProcess_class = { .extends = Class(Process), .display = Process_display, .delete = Process_delete, - .compare = LinuxProcess_compare + .compare = Process_compare }, .writeField = LinuxProcess_writeField, - .getCommandStr = LinuxProcess_getCommandStr + .getCommandStr = LinuxProcess_getCommandStr, + .compareByKey = LinuxProcess_compareByKey }; diff --git a/linux/LinuxProcess.h b/linux/LinuxProcess.h index ad396fb..2e9a9d1 100644 --- a/linux/LinuxProcess.h +++ b/linux/LinuxProcess.h @@ -18,85 +18,18 @@ in the source distribution for its full text. #include "Settings.h" -#define PROCESS_FLAG_LINUX_IOPRIO 0x00000100 -#define PROCESS_FLAG_LINUX_OPENVZ 0x00000200 -#define PROCESS_FLAG_LINUX_VSERVER 0x00000400 -#define PROCESS_FLAG_LINUX_CGROUP 0x00000800 -#define PROCESS_FLAG_LINUX_OOM 0x00001000 -#define PROCESS_FLAG_LINUX_SMAPS 0x00002000 -#define PROCESS_FLAG_LINUX_CTXT 0x00004000 -#define PROCESS_FLAG_LINUX_SECATTR 0x00008000 -#define PROCESS_FLAG_LINUX_LRS_FIX 0x00010000 -#define PROCESS_FLAG_LINUX_CWD 0x00020000 - -typedef enum UnsupportedProcessFields { - FLAGS = 9, - ITREALVALUE = 20, - VSIZE = 22, - RSS = 23, - RLIM = 24, - STARTCODE = 25, - ENDCODE = 26, - STARTSTACK = 27, - KSTKESP = 28, - KSTKEIP = 29, - SIGNAL = 30, - BLOCKED = 31, - SSIGIGNORE = 32, - SIGCATCH = 33, - WCHAN = 34, - NSWAP = 35, - CNSWAP = 36, - EXIT_SIGNAL = 37, -} UnsupportedProcessField; - -typedef enum LinuxProcessFields { - CMINFLT = 11, - CMAJFLT = 13, - UTIME = 14, - STIME = 15, - CUTIME = 16, - CSTIME = 17, - M_SHARE = 41, - M_TRS = 42, - M_DRS = 43, - M_LRS = 44, - M_DT = 45, - #ifdef HAVE_OPENVZ - CTID = 100, - VPID = 101, - #endif - #ifdef HAVE_VSERVER - VXID = 102, - #endif - RCHAR = 103, - WCHAR = 104, - SYSCR = 105, - SYSCW = 106, - RBYTES = 107, - WBYTES = 108, - CNCLWB = 109, - IO_READ_RATE = 110, - IO_WRITE_RATE = 111, - IO_RATE = 112, - CGROUP = 113, - OOM = 114, - IO_PRIORITY = 115, - #ifdef HAVE_DELAYACCT - PERCENT_CPU_DELAY = 116, - PERCENT_IO_DELAY = 117, - PERCENT_SWAP_DELAY = 118, - #endif - M_PSS = 119, - M_SWAP = 120, - M_PSSWP = 121, - CTXT = 122, - SECATTR = 123, - PROC_COMM = 124, - PROC_EXE = 125, - CWD = 126, - LAST_PROCESSFIELD = 127, -} LinuxProcessField; +#define PROCESS_FLAG_LINUX_IOPRIO 0x00000100 +#define PROCESS_FLAG_LINUX_OPENVZ 0x00000200 +#define PROCESS_FLAG_LINUX_VSERVER 0x00000400 +#define PROCESS_FLAG_LINUX_CGROUP 0x00000800 +#define PROCESS_FLAG_LINUX_OOM 0x00001000 +#define PROCESS_FLAG_LINUX_SMAPS 0x00002000 +#define PROCESS_FLAG_LINUX_CTXT 0x00004000 +#define PROCESS_FLAG_LINUX_SECATTR 0x00008000 +#define PROCESS_FLAG_LINUX_LRS_FIX 0x00010000 +#define PROCESS_FLAG_LINUX_CWD 0x00020000 +#define PROCESS_FLAG_LINUX_DELAYACCT 0x00040000 + /* LinuxProcessMergedCommand is populated by LinuxProcess_makeCommandStr: It * contains the merged Command string, and the information needed by @@ -191,11 +124,11 @@ static inline bool Process_isUserlandThread(const Process* this) { return this->pid != this->tgid; } -extern long long btime; +extern int pageSize; -extern ProcessFieldData Process_fields[]; +extern int pageSizeKB; -extern ProcessPidColumn Process_pidColumns[]; +extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; extern const ProcessClass LinuxProcess_class; diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c index b9ba247..434d070 100644 --- a/linux/LinuxProcessList.c +++ b/linux/LinuxProcessList.c @@ -57,6 +57,16 @@ in the source distribution for its full text. #endif +// CentOS 6's kernel doesn't provide a definition of O_PATH +// based on definition taken from uapi/asm-generic/fcnth.h in Linux kernel tree +#ifndef O_PATH +# define O_PATH 010000000 +#endif + +static long long btime; + +static long jiffy; + static FILE* fopenat(openat_arg_t openatArg, const char* pathname, const char* mode) { assert(String_eq(mode, "r")); /* only currently supported mode */ @@ -92,7 +102,7 @@ static void LinuxProcessList_initTtyDrivers(LinuxProcessList* this) { int numDrivers = 0; int allocd = 10; - ttyDrivers = xMalloc(sizeof(TtyDriver) * allocd); + ttyDrivers = xMallocArray(allocd, sizeof(TtyDriver)); char* at = buf; while (*at != '\0') { at = strchr(at, ' '); // skip first token @@ -126,7 +136,7 @@ static void LinuxProcessList_initTtyDrivers(LinuxProcessList* this) { numDrivers++; if (numDrivers == allocd) { allocd += 10; - ttyDrivers = xRealloc(ttyDrivers, sizeof(TtyDriver) * allocd); + ttyDrivers = xReallocArray(ttyDrivers, allocd, sizeof(TtyDriver)); } } numDrivers++; @@ -198,39 +208,39 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui ProcessList_init(pl, Class(LinuxProcess), usersTable, pidMatchList, userId); LinuxProcessList_initTtyDrivers(this); - #ifdef HAVE_DELAYACCT - LinuxProcessList_initNetlinkSocket(this); - #endif + // Initialize page size + pageSize = sysconf(_SC_PAGESIZE); + if (pageSize == -1) + CRT_fatalError("Cannot get pagesize by sysconf(_SC_PAGESIZE)"); + pageSizeKB = pageSize / ONE_K; - // Check for /proc/*/smaps_rollup availability (improves smaps parsing speed, Linux 4.14+) - FILE* file = fopen(PROCDIR "/self/smaps_rollup", "r"); - if (file != NULL) { - this->haveSmapsRollup = true; - fclose(file); - } else { - this->haveSmapsRollup = false; - } + // Initialize clock ticks + jiffy = sysconf(_SC_CLK_TCK); + if (jiffy == -1) + CRT_fatalError("Cannot get clock ticks by sysconf(_SC_CLK_TCK)"); + + // Test /proc/PID/smaps_rollup availability (faster to parse, Linux 4.14+) + this->haveSmapsRollup = (access(PROCDIR "/self/smaps_rollup", R_OK) == 0); - // Read btime + // Read btime (the kernel boot time, as number of seconds since the epoch) { FILE* statfile = fopen(PROCSTATFILE, "r"); - if (statfile == NULL) { + if (statfile == NULL) CRT_fatalError("Cannot open " PROCSTATFILE); - } - while (true) { char buffer[PROC_LINE_LENGTH + 1]; - if (fgets(buffer, sizeof(buffer), statfile) == NULL) { - CRT_fatalError("No btime in " PROCSTATFILE); - } else if (String_startsWith(buffer, "btime ")) { - if (sscanf(buffer, "btime %lld\n", &btime) != 1) { - CRT_fatalError("Failed to parse btime from " PROCSTATFILE); - } + if (fgets(buffer, sizeof(buffer), statfile) == NULL) break; - } + if (String_startsWith(buffer, "btime ") == false) + continue; + if (sscanf(buffer, "btime %lld\n", &btime) == 1) + break; + CRT_fatalError("Failed to parse btime from " PROCSTATFILE); } - fclose(statfile); + + if (!btime) + CRT_fatalError("No btime in " PROCSTATFILE); } // Initialize CPU count @@ -267,16 +277,7 @@ void ProcessList_delete(ProcessList* pl) { free(this); } -static inline unsigned long long LinuxProcess_adjustTime(unsigned long long t) { - static long jiffy = -1; - if (jiffy == -1) { - errno = 0; - jiffy = sysconf(_SC_CLK_TCK); - if (errno || -1 == jiffy) { - jiffy = -1; - return t; // Assume 100Hz clock - } - } +static inline unsigned long long LinuxProcessList_adjustTime(unsigned long long t) { return t * 100 / jiffy; } @@ -329,13 +330,13 @@ static bool LinuxProcessList_readStatFile(Process* process, openat_arg_t procFd, location += 1; lp->cmajflt = strtoull(location, &location, 10); location += 1; - lp->utime = LinuxProcess_adjustTime(strtoull(location, &location, 10)); + lp->utime = LinuxProcessList_adjustTime(strtoull(location, &location, 10)); location += 1; - lp->stime = LinuxProcess_adjustTime(strtoull(location, &location, 10)); + lp->stime = LinuxProcessList_adjustTime(strtoull(location, &location, 10)); location += 1; - lp->cutime = LinuxProcess_adjustTime(strtoull(location, &location, 10)); + lp->cutime = LinuxProcessList_adjustTime(strtoull(location, &location, 10)); location += 1; - lp->cstime = LinuxProcess_adjustTime(strtoull(location, &location, 10)); + lp->cstime = LinuxProcessList_adjustTime(strtoull(location, &location, 10)); location += 1; process->priority = strtol(location, &location, 10); location += 1; @@ -345,7 +346,7 @@ static bool LinuxProcessList_readStatFile(Process* process, openat_arg_t procFd, location += 1; location = strchr(location, ' ') + 1; if (process->starttime_ctime == 0) { - process->starttime_ctime = btime + LinuxProcess_adjustTime(strtoll(location, &location, 10)) / 100; + process->starttime_ctime = btime + LinuxProcessList_adjustTime(strtoll(location, &location, 10)) / 100; } else { location = strchr(location, ' ') + 1; } @@ -483,7 +484,7 @@ static inline uint64_t fast_strtoull_hex(char **str, int maxlen) { return result; } -static void LinuxProcessList_calcLibSize_helper(ATTR_UNUSED hkey_t key, void* value, void* data) { +static void LinuxProcessList_calcLibSize_helper(ATTR_UNUSED ht_key_t key, void* value, void* data) { if (!data) return; @@ -573,7 +574,7 @@ static uint64_t LinuxProcessList_calcLibSize(openat_arg_t procFd) { Hashtable_delete(ht); - return total_size / CRT_pageSize; + return total_size / pageSize; } static bool LinuxProcessList_readStatmFile(LinuxProcess* process, openat_arg_t procFd, bool performLookup, unsigned long long now) { @@ -593,6 +594,9 @@ static bool LinuxProcessList_readStatmFile(LinuxProcess* process, openat_arg_t p fclose(statmfile); if (r == 7) { + process->super.m_virt *= pageSizeKB; + process->super.m_resident *= pageSizeKB; + if (tmp_m_lrs) { process->m_lrs = tmp_m_lrs; } else if (performLookup) { @@ -947,12 +951,19 @@ static int handleNetlinkMsg(struct nl_msg* nlmsg, void* linuxProcess) { static void LinuxProcessList_readDelayAcctData(LinuxProcessList* this, LinuxProcess* process) { struct nl_msg* msg; + if (!this->netlink_socket) { + LinuxProcessList_initNetlinkSocket(this); + if (!this->netlink_socket) { + goto delayacct_failure; + } + } + if (nl_socket_modify_cb(this->netlink_socket, NL_CB_VALID, NL_CB_CUSTOM, handleNetlinkMsg, process) < 0) { - return; + goto delayacct_failure; } if (! (msg = nlmsg_alloc())) { - return; + goto delayacct_failure; } if (! genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, this->netlink_family, 0, NLM_F_REQUEST, TASKSTATS_CMD_GET, TASKSTATS_VERSION)) { @@ -964,15 +975,19 @@ static void LinuxProcessList_readDelayAcctData(LinuxProcessList* this, LinuxProc } if (nl_send_sync(this->netlink_socket, msg) < 0) { - process->swapin_delay_percent = NAN; - process->blkio_delay_percent = NAN; - process->cpu_delay_percent = NAN; - return; + goto delayacct_failure; } if (nl_recvmsgs_default(this->netlink_socket) < 0) { - return; + goto delayacct_failure; } + + return; + +delayacct_failure: + process->swapin_delay_percent = NAN; + process->blkio_delay_percent = NAN; + process->cpu_delay_percent = NAN; } #endif @@ -1363,9 +1378,9 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_ } /* period might be 0 after system sleep */ - float percent_cpu = (period < 1e-6) ? 0.0f : ((lp->utime + lp->stime - lasttimes) / period * 100.0); - proc->percent_cpu = CLAMP(percent_cpu, 0.0f, cpus * 100.0f); - proc->percent_mem = (proc->m_resident * CRT_pageSizeKB) / (double)(pl->totalMem) * 100.0; + float percent_cpu = (period < 1E-6) ? 0.0F : ((lp->utime + lp->stime - lasttimes) / period * 100.0); + proc->percent_cpu = CLAMP(percent_cpu, 0.0F, cpus * 100.0F); + proc->percent_mem = proc->m_resident / (double)(pl->totalMem) * 100.0; if (!preExisting) { @@ -1411,7 +1426,9 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_ } #ifdef HAVE_DELAYACCT - LinuxProcessList_readDelayAcctData(this, lp); + if (settings->flags & PROCESS_FLAG_LINUX_DELAYACCT) { + LinuxProcessList_readDelayAcctData(this, lp); + } #endif if (settings->flags & PROCESS_FLAG_LINUX_CGROUP) { @@ -1785,7 +1802,9 @@ static void scanCPUFreqencyFromCPUinfo(LinuxProcessList* this) { continue; } else if ( (sscanf(buffer, "cpu MHz : %lf", &frequency) == 1) || - (sscanf(buffer, "cpu MHz: %lf", &frequency) == 1) + (sscanf(buffer, "cpu MHz: %lf", &frequency) == 1) || + (sscanf(buffer, "clock : %lfMHz", &frequency) == 1) || + (sscanf(buffer, "clock: %lfMHz", &frequency) == 1) ) { if (cpuid < 0 || cpuid > (cpus - 1)) { continue; @@ -1824,41 +1843,6 @@ static void LinuxProcessList_scanCPUFrequency(LinuxProcessList* this) { scanCPUFreqencyFromCPUinfo(this); } -#ifdef HAVE_SENSORS_SENSORS_H -static void LinuxProcessList_scanCPUTemperature(LinuxProcessList* this) { - const int cpuCount = this->super.cpuCount; - - for (int i = 0; i <= cpuCount; i++) { - this->cpus[i].temperature = NAN; - } - - int r = LibSensors_getCPUTemperatures(this->cpus, cpuCount); - - /* No temperature - nothing to do */ - if (r <= 0) - return; - - /* Only package temperature - copy to all cpus */ - if (r == 1 && !isnan(this->cpus[0].temperature)) { - double packageTemp = this->cpus[0].temperature; - for (int i = 1; i <= cpuCount; i++) { - this->cpus[i].temperature = packageTemp; - } - - return; - } - - /* Half the temperatures, probably HT/SMT - copy to second half */ - if (r >= 2 && (r - 1) == (cpuCount / 2)) { - for (int i = cpuCount / 2 + 1; i <= cpuCount; i++) { - this->cpus[i].temperature = this->cpus[i/2].temperature; - } - - return; - } -} -#endif - void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { LinuxProcessList* this = (LinuxProcessList*) super; const Settings* settings = super->settings; @@ -1876,7 +1860,7 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { #ifdef HAVE_SENSORS_SENSORS_H if (settings->showCPUTemperature) - LinuxProcessList_scanCPUTemperature(this); + LibSensors_getCPUTemperatures(this->cpus, this->super.cpuCount); #endif // in pause mode only gather global data for meters (CPU/memory/...) diff --git a/linux/Platform.c b/linux/Platform.c index 590fc7a..dd80ded 100644 --- a/linux/Platform.c +++ b/linux/Platform.c @@ -65,9 +65,7 @@ in the source distribution for its full text. #endif -ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_VIRT, M_RESIDENT, (int)M_SHARE, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; - -int Platform_numberOfFields = LAST_PROCESSFIELD; +const ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_VIRT, M_RESIDENT, M_SHARE, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 }; const SignalItem Platform_signals[] = { { .name = " 0 Cancel", .number = 0 }, diff --git a/linux/Platform.h b/linux/Platform.h index 280b997..fe81448 100644 --- a/linux/Platform.h +++ b/linux/Platform.h @@ -18,9 +18,7 @@ in the source distribution for its full text. #include "ProcessLocksScreen.h" #include "SignalsPanel.h" -extern ProcessField Platform_defaultFields[]; - -extern int Platform_numberOfFields; +extern const ProcessField Platform_defaultFields[]; extern const SignalItem Platform_signals[]; diff --git a/linux/PressureStallMeter.c b/linux/PressureStallMeter.c index 745068c..7486968 100644 --- a/linux/PressureStallMeter.c +++ b/linux/PressureStallMeter.c @@ -43,18 +43,22 @@ static void PressureStallMeter_updateValues(Meter* this, char* buffer, size_t le } Platform_getPressureStall(file, some, &this->values[0], &this->values[1], &this->values[2]); - xSnprintf(buffer, len, "%s %s %.2lf%% %.2lf%% %.2lf%%", some ? "some" : "full", file, this->values[0], this->values[1], this->values[2]); + + /* only print bar for ten (not sixty and threehundred), cause the sum is meaningless */ + this->curItems = 1; + + xSnprintf(buffer, len, "%s %s %5.2lf%% %5.2lf%% %5.2lf%%", some ? "some" : "full", file, this->values[0], this->values[1], this->values[2]); } static void PressureStallMeter_display(const Object* cast, RichString* out) { const Meter* this = (const Meter*)cast; char buffer[20]; - xSnprintf(buffer, sizeof(buffer), "%.2lf%% ", this->values[0]); - RichString_write(out, CRT_colors[PRESSURE_STALL_TEN], buffer); - xSnprintf(buffer, sizeof(buffer), "%.2lf%% ", this->values[1]); - RichString_append(out, CRT_colors[PRESSURE_STALL_SIXTY], buffer); - xSnprintf(buffer, sizeof(buffer), "%.2lf%% ", this->values[2]); - RichString_append(out, CRT_colors[PRESSURE_STALL_THREEHUNDRED], buffer); + xSnprintf(buffer, sizeof(buffer), "%5.2lf%% ", this->values[0]); + RichString_writeAscii(out, CRT_colors[PRESSURE_STALL_TEN], buffer); + xSnprintf(buffer, sizeof(buffer), "%5.2lf%% ", this->values[1]); + RichString_appendAscii(out, CRT_colors[PRESSURE_STALL_SIXTY], buffer); + xSnprintf(buffer, sizeof(buffer), "%5.2lf%% ", this->values[2]); + RichString_appendAscii(out, CRT_colors[PRESSURE_STALL_THREEHUNDRED], buffer); } const MeterClass PressureStallCPUSomeMeter_class = { diff --git a/linux/ProcessField.h b/linux/ProcessField.h new file mode 100644 index 0000000..6e2eff3 --- /dev/null +++ b/linux/ProcessField.h @@ -0,0 +1,53 @@ +#ifndef HEADER_LinuxProcessField +#define HEADER_LinuxProcessField +/* +htop - linux/ProcessField.h +(C) 2020 htop dev team +Released under the GNU GPLv2, see the COPYING file +in the source distribution for its full text. +*/ + + +#define PLATFORM_PROCESS_FIELDS \ + CMINFLT = 11, \ + CMAJFLT = 13, \ + UTIME = 14, \ + STIME = 15, \ + CUTIME = 16, \ + CSTIME = 17, \ + M_SHARE = 41, \ + M_TRS = 42, \ + M_DRS = 43, \ + M_LRS = 44, \ + M_DT = 45, \ + CTID = 100, \ + VPID = 101, \ + VXID = 102, \ + RCHAR = 103, \ + WCHAR = 104, \ + SYSCR = 105, \ + SYSCW = 106, \ + RBYTES = 107, \ + WBYTES = 108, \ + CNCLWB = 109, \ + IO_READ_RATE = 110, \ + IO_WRITE_RATE = 111, \ + IO_RATE = 112, \ + CGROUP = 113, \ + OOM = 114, \ + IO_PRIORITY = 115, \ + PERCENT_CPU_DELAY = 116, \ + PERCENT_IO_DELAY = 117, \ + PERCENT_SWAP_DELAY = 118, \ + M_PSS = 119, \ + M_SWAP = 120, \ + M_PSSWP = 121, \ + CTXT = 122, \ + SECATTR = 123, \ + PROC_COMM = 124, \ + PROC_EXE = 125, \ + CWD = 126, \ + // End of list + + +#endif /* HEADER_LinuxProcessField */ diff --git a/linux/SELinuxMeter.c b/linux/SELinuxMeter.c index 64a3f2a..892f1e8 100644 --- a/linux/SELinuxMeter.c +++ b/linux/SELinuxMeter.c @@ -35,7 +35,7 @@ static bool hasSELinuxMount(void) { return false; } - if (sfbuf.f_type != SELINUX_MAGIC) { + if ((uint32_t)sfbuf.f_type != (uint32_t)SELINUX_MAGIC) { return false; } diff --git a/linux/SystemdMeter.c b/linux/SystemdMeter.c index 4350d26..61bb59b 100644 --- a/linux/SystemdMeter.c +++ b/linux/SystemdMeter.c @@ -267,9 +267,9 @@ static void SystemdMeter_display(ATTR_UNUSED const Object* cast, RichString* out char buffer[16]; int color = (systemState && 0 == strcmp(systemState, "running")) ? METER_VALUE_OK : METER_VALUE_ERROR; - RichString_write(out, CRT_colors[color], systemState ? systemState : "???"); + RichString_writeAscii(out, CRT_colors[color], systemState ? systemState : "N/A"); - RichString_append(out, CRT_colors[METER_TEXT], " ("); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " ("); if (nFailedUnits == INVALID_VALUE) { buffer[0] = '?'; @@ -277,9 +277,9 @@ static void SystemdMeter_display(ATTR_UNUSED const Object* cast, RichString* out } else { xSnprintf(buffer, sizeof(buffer), "%u", nFailedUnits); } - RichString_append(out, zeroDigitColor(nFailedUnits), buffer); + RichString_appendAscii(out, zeroDigitColor(nFailedUnits), buffer); - RichString_append(out, CRT_colors[METER_TEXT], "/"); + RichString_appendAscii(out, CRT_colors[METER_TEXT], "/"); if (nNames == INVALID_VALUE) { buffer[0] = '?'; @@ -287,9 +287,9 @@ static void SystemdMeter_display(ATTR_UNUSED const Object* cast, RichString* out } else { xSnprintf(buffer, sizeof(buffer), "%u", nNames); } - RichString_append(out, valueDigitColor(nNames), buffer); + RichString_appendAscii(out, valueDigitColor(nNames), buffer); - RichString_append(out, CRT_colors[METER_TEXT], " failed) ("); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " failed) ("); if (nJobs == INVALID_VALUE) { buffer[0] = '?'; @@ -297,9 +297,9 @@ static void SystemdMeter_display(ATTR_UNUSED const Object* cast, RichString* out } else { xSnprintf(buffer, sizeof(buffer), "%u", nJobs); } - RichString_append(out, zeroDigitColor(nJobs), buffer); + RichString_appendAscii(out, zeroDigitColor(nJobs), buffer); - RichString_append(out, CRT_colors[METER_TEXT], "/"); + RichString_appendAscii(out, CRT_colors[METER_TEXT], "/"); if (nInstalledJobs == INVALID_VALUE) { buffer[0] = '?'; @@ -307,9 +307,9 @@ static void SystemdMeter_display(ATTR_UNUSED const Object* cast, RichString* out } else { xSnprintf(buffer, sizeof(buffer), "%u", nInstalledJobs); } - RichString_append(out, valueDigitColor(nInstalledJobs), buffer); + RichString_appendAscii(out, valueDigitColor(nInstalledJobs), buffer); - RichString_append(out, CRT_colors[METER_TEXT], " jobs)"); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " jobs)"); } static const int SystemdMeter_attributes[] = { diff --git a/linux/ZramMeter.c b/linux/ZramMeter.c index e6b6937..723de0a 100644 --- a/linux/ZramMeter.c +++ b/linux/ZramMeter.c @@ -37,17 +37,19 @@ static void ZramMeter_updateValues(Meter* this, char* buffer, size_t size) { static void ZramMeter_display(const Object* cast, RichString* out) { char buffer[50]; const Meter* this = (const Meter*)cast; - RichString_write(out, CRT_colors[METER_TEXT], ":"); + + RichString_writeAscii(out, CRT_colors[METER_TEXT], ":"); + Meter_humanUnit(buffer, this->total, sizeof(buffer)); + RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); - RichString_append(out, CRT_colors[METER_VALUE], buffer); Meter_humanUnit(buffer, this->values[0], sizeof(buffer)); - RichString_append(out, CRT_colors[METER_TEXT], " used:"); - RichString_append(out, CRT_colors[METER_VALUE], buffer); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " used:"); + RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); Meter_humanUnit(buffer, this->values[1], sizeof(buffer)); - RichString_append(out, CRT_colors[METER_TEXT], " uncompressed:"); - RichString_append(out, CRT_colors[METER_VALUE], buffer); + RichString_appendAscii(out, CRT_colors[METER_TEXT], " uncompressed:"); + RichString_appendAscii(out, CRT_colors[METER_VALUE], buffer); } const MeterClass ZramMeter_class = { -- cgit v1.2.3