build/packages/extras-buildpkgs/htop/debian/patches/avafinger-cpu-monitor.patch

3578 lines
101 KiB
Diff

This patch file contains code from @avafinger's htop_2.2.2 repository.
It is the result of diff between:
https://github.com/avafinger/htop_2.2.2/commit/dc21e5f6
and:
https://github.com/hishamhm/htop/tree/2.2.0
---
diff --git a/Armbian_Meter.c b/Armbian_Meter.c
new file mode 100644
index 0000000..183032b
--- /dev/null
+++ b/Armbian_Meter.c
@@ -0,0 +1,55 @@
+/*
+htop - Armbianversion_Meter.c
+(C) 2018 @lex
+*/
+
+#include "Armbian_Meter.h"
+#include "Platform.h"
+#include "CRT.h"
+
+#include "interfaces.h"
+
+/*{
+#include "Meter.h"
+}*/
+
+
+int Armbianversion_Meter_attributes[] = {
+ ARMBIAN_VERSION
+};
+
+static void Armbianversion_Meter_setValues(Meter* this, char* buffer, int len) {
+ int ret;
+ static char version[256];
+ static unsigned int use_cached = 0;
+
+ if ((use_cached++ % 10)) {
+ xSnprintf(buffer, len, "%s", version);
+ return;
+ }
+
+ ret = ReadKeyValue( "/etc/armbian-release", "VERSION=", version);
+
+ if (ret) {
+ xSnprintf(buffer, len, "%s", version);
+ } else {
+ xSnprintf(buffer, len, "%s", "unknown");
+ }
+}
+
+MeterClass Armbianversion_Meter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = Armbianversion_Meter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 8,
+ .total = 100.0,
+ .attributes = Armbianversion_Meter_attributes,
+ .name = "Armbianversion",
+ .uiName = "Armbian version",
+ .caption = "Armbian : ",
+};
+
+
diff --git a/Armbian_Meter.h b/Armbian_Meter.h
new file mode 100644
index 0000000..146a1ee
--- /dev/null
+++ b/Armbian_Meter.h
@@ -0,0 +1,17 @@
+/* Do not edit this file. It was automatically generated. */
+
+#ifndef HEADER_Armbian_Meter
+#define HEADER_Armbian_Meter
+/*
+htop - Armbianversion_Meter.h
+(C) 2018 @lex
+*/
+
+#include "Meter.h"
+
+extern int Armbianversion_Meter_attributes[];
+
+extern MeterClass Armbianversion_Meter_class;
+
+
+#endif
diff --git a/AvailableMetersPanel.c b/AvailableMetersPanel.c
index ddb5536..01ee3cd 100644
--- a/AvailableMetersPanel.c
+++ b/AvailableMetersPanel.c
@@ -9,6 +9,8 @@ in the source distribution for its full text.
#include "MetersPanel.h"
#include "CPUMeter.h"
+#include "CpuFreqMeter.h"
+#include "CpuTempMeter.h"
#include "Header.h"
#include "ListItem.h"
#include "Platform.h"
@@ -100,6 +102,8 @@ PanelClass AvailableMetersPanel_class = {
};
AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* header, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr, ProcessList* pl) {
+ int i;
+
AvailableMetersPanel* this = AllocThis(AvailableMetersPanel);
Panel* super = (Panel*) this;
FunctionBar* fuBar = FunctionBar_newEnterEsc("Add ", "Done ");
@@ -114,7 +118,7 @@ AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* heade
Panel_setHeader(super, "Available meters");
// Platform_meterTypes[0] should be always (&CPUMeter_class), which we will
// handle separately in the code below.
- for (int i = 1; Platform_meterTypes[i]; i++) {
+ for (i = 1; Platform_meterTypes[i]; i++) {
MeterClass* type = Platform_meterTypes[i];
assert(type != &CPUMeter_class);
const char* label = type->description ? type->description : type->uiName;
@@ -125,7 +129,7 @@ AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* heade
int cpus = pl->cpuCount;
if (cpus > 1) {
Panel_add(super, (Object*) ListItem_new("CPU average", 0));
- for (int i = 1; i <= cpus; i++) {
+ for (i = 1; i <= cpus; i++) {
char buffer[50];
xSnprintf(buffer, 50, "%s %d", type->uiName, i);
Panel_add(super, (Object*) ListItem_new(buffer, i));
diff --git a/BlockDevice_ioStatsMeter.c b/BlockDevice_ioStatsMeter.c
new file mode 100644
index 0000000..9dccbde
--- /dev/null
+++ b/BlockDevice_ioStatsMeter.c
@@ -0,0 +1,711 @@
+/*
+htop - BlockDevice_ioStatsMeter.c
+(C) 2020 @lex
+*/
+
+#include "BlockDevice_ioStatsMeter.h"
+#include "Platform.h"
+#include "CRT.h"
+
+#include "interfaces.h"
+
+/*{
+#include "Meter.h"
+}*/
+
+
+int BlockDevice_ioStatsMeter_attributes[] = {
+ ETH1_INTERFACE
+};
+
+static void BlockDevice_sda_ioStatsMeter_setValues(Meter* this, char* buffer, int len) {
+ int ret;
+ float readspeed;
+ float writespeed;
+ double refreshdelay;
+ char block_device[80];
+ static double old = 0.;
+ static double now = 0.;
+ static int flash = 0;
+ static unsigned long sec_size = 0;
+ FILE *fp;
+
+ if (sec_size == 0) {
+ xSnprintf(block_device, sizeof(block_device), "/sys/block/%s/queue/hw_sector_size", "sda");
+ if ((fp = fopen(block_device, "r")) == NULL) {
+ xSnprintf(buffer, len, "%s", "unavailable");
+ return;
+ }
+ if (fgets(block_device, 79, fp) != NULL) {
+ sscanf(block_device, "%lu", &sec_size);
+ }
+ fclose(fp);
+ if (sec_size == 0)
+ sec_size = 1;
+ }
+
+ now = get_wall_time();
+ refreshdelay = now - old;
+ if (old == 0.)
+ refreshdelay = 1.;
+ old = now;
+
+ ret = Platform_getIO_stats("sda", 0, 0);
+ if (ret) {
+ if (Platform_BlockDevice_sda_stats.read_sectors_comp > Platform_BlockDevice_sda_stats.read_sectors)
+ Platform_BlockDevice_sda_stats.read_sectors_comp = 0;
+ if (Platform_BlockDevice_sda_stats.write_sectors_comp > Platform_BlockDevice_sda_stats.write_sectors)
+ Platform_BlockDevice_sda_stats.write_sectors_comp = 0;
+
+ /* we assume here the refresdelay is 1 sec which sometimes is 1.5, so we have a peak */
+ readspeed = (Platform_BlockDevice_sda_stats.read_sectors - Platform_BlockDevice_sda_stats.read_sectors_comp) / refreshdelay;
+ writespeed = (Platform_BlockDevice_sda_stats.write_sectors - Platform_BlockDevice_sda_stats.write_sectors_comp) / refreshdelay;
+
+ writespeed = writespeed * sec_size / 1000;
+ readspeed = readspeed * sec_size / 1000;
+ if (writespeed >= 1000 || readspeed >= 1000) {
+ writespeed /= 1000;
+ readspeed /= 1000;
+ if (writespeed >= 1000 || readspeed >= 1000) {
+ writespeed /= 1000;
+ readspeed /= 1000;
+ xSnprintf(buffer, len, "%.2f GB/s - %.2f GB/s (R/W)", (float) readspeed, (float) writespeed);
+ } else {
+ xSnprintf(buffer, len, "%.2f MB/s - %.2f MB/s (R/W)", (float) readspeed, (float) writespeed);
+ }
+ } else {
+ xSnprintf(buffer, len, "%.2f KB/s - %.2f KB/s (R/W)", (float) readspeed, (float) writespeed);
+ }
+
+ Platform_BlockDevice_sda_stats.read_sectors_comp = Platform_BlockDevice_sda_stats.read_sectors;
+ Platform_BlockDevice_sda_stats.write_sectors_comp = Platform_BlockDevice_sda_stats.write_sectors;
+
+ } else {
+ if (!(flash % 2))
+ xSnprintf(buffer, len, "%s", "unavailable");
+ else
+ xSnprintf(buffer, len, "%s", "");
+ flash++;
+ }
+}
+
+MeterClass BlockDevice_sda_ioStatsMeter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = BlockDevice_sda_ioStatsMeter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 8,
+ .total = 100.0,
+ .attributes = BlockDevice_ioStatsMeter_attributes,
+ .name = "sdastat",
+ .uiName = "sda speed stat",
+ .caption = "sda stat: ",
+};
+
+static void BlockDevice_sdb_ioStatsMeter_setValues(Meter* this, char* buffer, int len) {
+ int ret;
+ float readspeed;
+ float writespeed;
+ double refreshdelay;
+ char block_device[80];
+ static double old = 0.;
+ static double now = 0.;
+ static int flash = 0;
+ static unsigned long sec_size = 0;
+ FILE *fp;
+
+ if (sec_size == 0) {
+ xSnprintf(block_device, sizeof(block_device), "/sys/block/%s/queue/hw_sector_size", "sdb");
+ if ((fp = fopen(block_device, "r")) == NULL) {
+ xSnprintf(buffer, len, "%s", "unavailable");
+ return;
+ }
+ if (fgets(block_device, 79, fp) != NULL) {
+ sscanf(block_device, "%lu", &sec_size);
+ }
+ fclose(fp);
+ if (sec_size == 0)
+ sec_size = 1;
+ }
+
+ now = get_wall_time();
+ refreshdelay = now - old;
+ if (old == 0.)
+ refreshdelay = 1.;
+ old = now;
+
+ ret = Platform_getIO_stats("sdb", 1, 0);
+ if (ret) {
+ if (Platform_BlockDevice_sdb_stats.read_sectors_comp > Platform_BlockDevice_sdb_stats.read_sectors)
+ Platform_BlockDevice_sdb_stats.read_sectors_comp = 0;
+ if (Platform_BlockDevice_sdb_stats.write_sectors_comp > Platform_BlockDevice_sdb_stats.write_sectors)
+ Platform_BlockDevice_sdb_stats.write_sectors_comp = 0;
+
+ /* we assume here the refresdelay is 1 sec which sometimes is 1.5, so we have a peak */
+ readspeed = (Platform_BlockDevice_sdb_stats.read_sectors - Platform_BlockDevice_sdb_stats.read_sectors_comp) / refreshdelay;
+ writespeed = (Platform_BlockDevice_sdb_stats.write_sectors - Platform_BlockDevice_sdb_stats.write_sectors_comp) / refreshdelay;
+
+ writespeed = writespeed * sec_size / 1000;
+ readspeed = readspeed * sec_size / 1000;
+ if (writespeed >= 1000 || readspeed >= 1000) {
+ writespeed /= 1000;
+ readspeed /= 1000;
+ if (writespeed >= 1000 || readspeed >= 1000) {
+ writespeed /= 1000;
+ readspeed /= 1000;
+ xSnprintf(buffer, len, "%.2f GB/s - %.2f GB/s (R/W)", (float) readspeed, (float) writespeed);
+ } else {
+ xSnprintf(buffer, len, "%.2f MB/s - %.2f MB/s (R/W)", (float) readspeed, (float) writespeed);
+ }
+ } else {
+ xSnprintf(buffer, len, "%.2f KB/s - %.2f KB/s (R/W)", (float) readspeed, (float) writespeed);
+ }
+
+ Platform_BlockDevice_sdb_stats.read_sectors_comp = Platform_BlockDevice_sdb_stats.read_sectors;
+ Platform_BlockDevice_sdb_stats.write_sectors_comp = Platform_BlockDevice_sdb_stats.write_sectors;
+
+ } else {
+ if (!(flash % 2))
+ xSnprintf(buffer, len, "%s", "unavailable");
+ else
+ xSnprintf(buffer, len, "%s", "");
+ flash++;
+ }
+}
+
+MeterClass BlockDevice_sdb_ioStatsMeter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = BlockDevice_sdb_ioStatsMeter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 8,
+ .total = 100.0,
+ .attributes = BlockDevice_ioStatsMeter_attributes,
+ .name = "sdbstat",
+ .uiName = "sdb speed stat",
+ .caption = "sdb stat: ",
+};
+
+static void BlockDevice_sdc_ioStatsMeter_setValues(Meter* this, char* buffer, int len) {
+ int ret;
+ float readspeed;
+ float writespeed;
+ double refreshdelay;
+ char block_device[80];
+ static double old = 0.;
+ static double now = 0.;
+ static int flash = 0;
+ static unsigned long sec_size = 0;
+ FILE *fp;
+
+ if (sec_size == 0) {
+ xSnprintf(block_device, sizeof(block_device), "/sys/block/%s/queue/hw_sector_size", "sdc");
+ if ((fp = fopen(block_device, "r")) == NULL) {
+ xSnprintf(buffer, len, "%s", "unavailable");
+ return;
+ }
+ if (fgets(block_device, 79, fp) != NULL) {
+ sscanf(block_device, "%lu", &sec_size);
+ }
+ fclose(fp);
+ if (sec_size == 0)
+ sec_size = 1;
+ }
+
+ now = get_wall_time();
+ refreshdelay = now - old;
+ if (old == 0.)
+ refreshdelay = 1.;
+ old = now;
+
+ ret = Platform_getIO_stats("sdc", 2, 0);
+ if (ret) {
+ if (Platform_BlockDevice_sdc_stats.read_sectors_comp > Platform_BlockDevice_sdc_stats.read_sectors)
+ Platform_BlockDevice_sdc_stats.read_sectors_comp = 0;
+ if (Platform_BlockDevice_sdc_stats.write_sectors_comp > Platform_BlockDevice_sdc_stats.write_sectors)
+ Platform_BlockDevice_sdc_stats.write_sectors_comp = 0;
+
+ /* we assume here the refresdelay is 1 sec which sometimes is 1.5, so we have a peak */
+ readspeed = (Platform_BlockDevice_sdc_stats.read_sectors - Platform_BlockDevice_sdc_stats.read_sectors_comp) / refreshdelay;
+ writespeed = (Platform_BlockDevice_sdc_stats.write_sectors - Platform_BlockDevice_sdc_stats.write_sectors_comp) / refreshdelay;
+
+ writespeed = writespeed * sec_size / 1000;
+ readspeed = readspeed * sec_size / 1000;
+ if (writespeed >= 1000 || readspeed >= 1000) {
+ writespeed /= 1000;
+ readspeed /= 1000;
+ if (writespeed >= 1000 || readspeed >= 1000) {
+ writespeed /= 1000;
+ readspeed /= 1000;
+ xSnprintf(buffer, len, "%.2f GB/s - %.2f GB/s (R/W)", (float) readspeed, (float) writespeed);
+ } else {
+ xSnprintf(buffer, len, "%.2f MB/s - %.2f MB/s (R/W)", (float) readspeed, (float) writespeed);
+ }
+ } else {
+ xSnprintf(buffer, len, "%.2f KB/s - %.2f KB/s (R/W)", (float) readspeed, (float) writespeed);
+ }
+
+ Platform_BlockDevice_sdc_stats.read_sectors_comp = Platform_BlockDevice_sdc_stats.read_sectors;
+ Platform_BlockDevice_sdc_stats.write_sectors_comp = Platform_BlockDevice_sdc_stats.write_sectors;
+
+ } else {
+ if (!(flash % 2))
+ xSnprintf(buffer, len, "%s", "unavailable");
+ else
+ xSnprintf(buffer, len, "%s", "");
+ flash++;
+ }
+}
+
+MeterClass BlockDevice_sdc_ioStatsMeter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = BlockDevice_sdc_ioStatsMeter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 8,
+ .total = 100.0,
+ .attributes = BlockDevice_ioStatsMeter_attributes,
+ .name = "sdcstat",
+ .uiName = "sdc speed stat",
+ .caption = "sdc stat: ",
+};
+
+static void BlockDevice_sdd_ioStatsMeter_setValues(Meter* this, char* buffer, int len) {
+ int ret;
+ float readspeed;
+ float writespeed;
+ double refreshdelay;
+ char block_device[80];
+ static double old = 0.;
+ static double now = 0.;
+ static int flash = 0;
+ static unsigned long sec_size = 0;
+ FILE *fp;
+
+ if (sec_size == 0) {
+ xSnprintf(block_device, sizeof(block_device), "/sys/block/%s/queue/hw_sector_size", "sdd");
+ if ((fp = fopen(block_device, "r")) == NULL) {
+ xSnprintf(buffer, len, "%s", "unavailable");
+ return;
+ }
+ if (fgets(block_device, 79, fp) != NULL) {
+ sscanf(block_device, "%lu", &sec_size);
+ }
+ fclose(fp);
+ if (sec_size == 0)
+ sec_size = 1;
+ }
+
+ now = get_wall_time();
+ refreshdelay = now - old;
+ if (old == 0.)
+ refreshdelay = 1.;
+ old = now;
+
+ ret = Platform_getIO_stats("sdd", 3, 0);
+ if (ret) {
+ if (Platform_BlockDevice_sdd_stats.read_sectors_comp > Platform_BlockDevice_sdd_stats.read_sectors)
+ Platform_BlockDevice_sdd_stats.read_sectors_comp = 0;
+ if (Platform_BlockDevice_sdd_stats.write_sectors_comp > Platform_BlockDevice_sdd_stats.write_sectors)
+ Platform_BlockDevice_sdd_stats.write_sectors_comp = 0;
+
+ /* we assume here the refresdelay is 1 sec which sometimes is 1.5, so we have a peak */
+ readspeed = (Platform_BlockDevice_sdd_stats.read_sectors - Platform_BlockDevice_sdd_stats.read_sectors_comp) / refreshdelay;
+ writespeed = (Platform_BlockDevice_sdd_stats.write_sectors - Platform_BlockDevice_sdd_stats.write_sectors_comp) / refreshdelay;
+
+ writespeed = writespeed * sec_size / 1000;
+ readspeed = readspeed * sec_size / 1000;
+ if (writespeed >= 1000 || readspeed >= 1000) {
+ writespeed /= 1000;
+ readspeed /= 1000;
+ if (writespeed >= 1000 || readspeed >= 1000) {
+ writespeed /= 1000;
+ readspeed /= 1000;
+ xSnprintf(buffer, len, "%.2f GB/s - %.2f GB/s (R/W)", (float) readspeed, (float) writespeed);
+ } else {
+ xSnprintf(buffer, len, "%.2f MB/s - %.2f MB/s (R/W)", (float) readspeed, (float) writespeed);
+ }
+ } else {
+ xSnprintf(buffer, len, "%.2f KB/s - %.2f KB/s (R/W)", (float) readspeed, (float) writespeed);
+ }
+
+ Platform_BlockDevice_sdd_stats.read_sectors_comp = Platform_BlockDevice_sdd_stats.read_sectors;
+ Platform_BlockDevice_sdd_stats.write_sectors_comp = Platform_BlockDevice_sdd_stats.write_sectors;
+
+ } else {
+ if (!(flash % 2))
+ xSnprintf(buffer, len, "%s", "unavailable");
+ else
+ xSnprintf(buffer, len, "%s", "");
+ flash++;
+ }
+}
+
+MeterClass BlockDevice_sdd_ioStatsMeter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = BlockDevice_sdd_ioStatsMeter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 8,
+ .total = 100.0,
+ .attributes = BlockDevice_ioStatsMeter_attributes,
+ .name = "sddstat",
+ .uiName = "sdd speed stat",
+ .caption = "sdd stat: ",
+};
+
+static void BlockDevice_mmcblk0_ioStatsMeter_setValues(Meter* this, char* buffer, int len) {
+ int ret;
+ float readspeed;
+ float writespeed;
+ double refreshdelay;
+ char block_device[80];
+ static double old = 0.;
+ static double now = 0.;
+ static int flash = 0;
+ static unsigned long sec_size = 0;
+ FILE *fp;
+
+ if (sec_size == 0) {
+ xSnprintf(block_device, sizeof(block_device), "/sys/block/%s/queue/hw_sector_size", "mmcblk0");
+ if ((fp = fopen(block_device, "r")) == NULL) {
+ xSnprintf(buffer, len, "%s", "unavailable");
+ return;
+ }
+ if (fgets(block_device, 79, fp) != NULL) {
+ sscanf(block_device, "%lu", &sec_size);
+ }
+ fclose(fp);
+ if (sec_size == 0)
+ sec_size = 1;
+ }
+
+ now = get_wall_time();
+ refreshdelay = now - old;
+ if (old == 0.)
+ refreshdelay = 1.;
+ old = now;
+
+ ret = Platform_getIO_stats("mmcblk0", 4, 0);
+ if (ret) {
+ if (Platform_BlockDevice_mmcblk0_stats.read_sectors_comp > Platform_BlockDevice_mmcblk0_stats.read_sectors)
+ Platform_BlockDevice_mmcblk0_stats.read_sectors_comp = 0;
+ if (Platform_BlockDevice_mmcblk0_stats.write_sectors_comp > Platform_BlockDevice_mmcblk0_stats.write_sectors)
+ Platform_BlockDevice_mmcblk0_stats.write_sectors_comp = 0;
+
+ /* we assume here the refresdelay is 1 sec which sometimes is 1.5, so we have a peak */
+ readspeed = (Platform_BlockDevice_mmcblk0_stats.read_sectors - Platform_BlockDevice_mmcblk0_stats.read_sectors_comp) / refreshdelay;
+ writespeed = (Platform_BlockDevice_mmcblk0_stats.write_sectors - Platform_BlockDevice_mmcblk0_stats.write_sectors_comp) / refreshdelay;
+
+ writespeed = writespeed * sec_size / 1000;
+ readspeed = readspeed * sec_size / 1000;
+ if (writespeed >= 1000 || readspeed >= 1000) {
+ writespeed /= 1000;
+ readspeed /= 1000;
+ if (writespeed >= 1000 || readspeed >= 1000) {
+ writespeed /= 1000;
+ readspeed /= 1000;
+ xSnprintf(buffer, len, "%.2f GB/s - %.2f GB/s (R/W)", (float) readspeed, (float) writespeed);
+ } else {
+ xSnprintf(buffer, len, "%.2f MB/s - %.2f MB/s (R/W)", (float) readspeed, (float) writespeed);
+ }
+ } else {
+ xSnprintf(buffer, len, "%.2f KB/s - %.2f KB/s (R/W)", (float) readspeed, (float) writespeed);
+ }
+
+ Platform_BlockDevice_mmcblk0_stats.read_sectors_comp = Platform_BlockDevice_mmcblk0_stats.read_sectors;
+ Platform_BlockDevice_mmcblk0_stats.write_sectors_comp = Platform_BlockDevice_mmcblk0_stats.write_sectors;
+
+ } else {
+ if (!(flash % 2))
+ xSnprintf(buffer, len, "%s", "unavailable");
+ else
+ xSnprintf(buffer, len, "%s", "");
+ flash++;
+ }
+}
+
+MeterClass BlockDevice_mmcblk0_ioStatsMeter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = BlockDevice_mmcblk0_ioStatsMeter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 8,
+ .total = 100.0,
+ .attributes = BlockDevice_ioStatsMeter_attributes,
+ .name = "mmcblk0stat",
+ .uiName = "mmcblk0 speed stat",
+ .caption = "mmcblk0 stat: ",
+};
+
+static void BlockDevice_mmcblk1_ioStatsMeter_setValues(Meter* this, char* buffer, int len) {
+ int ret;
+ float readspeed;
+ float writespeed;
+ double refreshdelay;
+ char block_device[80];
+ static double old = 0.;
+ static double now = 0.;
+ static int flash = 0;
+ static unsigned long sec_size = 0;
+ FILE *fp;
+
+ if (sec_size == 0) {
+ xSnprintf(block_device, sizeof(block_device), "/sys/block/%s/queue/hw_sector_size", "mmcblk1");
+ if ((fp = fopen(block_device, "r")) == NULL) {
+ xSnprintf(buffer, len, "%s", "unavailable");
+ return;
+ }
+ if (fgets(block_device, 79, fp) != NULL) {
+ sscanf(block_device, "%lu", &sec_size);
+ }
+ fclose(fp);
+ if (sec_size == 0)
+ sec_size = 1;
+ }
+
+ now = get_wall_time();
+ refreshdelay = now - old;
+ if (old == 0.)
+ refreshdelay = 1.;
+ old = now;
+
+ ret = Platform_getIO_stats("mmcblk1", 5, 0);
+ if (ret) {
+ if (Platform_BlockDevice_mmcblk1_stats.read_sectors_comp > Platform_BlockDevice_mmcblk1_stats.read_sectors)
+ Platform_BlockDevice_mmcblk1_stats.read_sectors_comp = 0;
+ if (Platform_BlockDevice_mmcblk1_stats.write_sectors_comp > Platform_BlockDevice_mmcblk1_stats.write_sectors)
+ Platform_BlockDevice_mmcblk1_stats.write_sectors_comp = 0;
+
+ /* we assume here the refresdelay is 1 sec which sometimes is 1.5, so we have a peak */
+ readspeed = (Platform_BlockDevice_mmcblk1_stats.read_sectors - Platform_BlockDevice_mmcblk1_stats.read_sectors_comp) / refreshdelay;
+ writespeed = (Platform_BlockDevice_mmcblk1_stats.write_sectors - Platform_BlockDevice_mmcblk1_stats.write_sectors_comp) / refreshdelay;
+
+ writespeed = writespeed * sec_size / 1000;
+ readspeed = readspeed * sec_size / 1000;
+ if (writespeed >= 1000 || readspeed >= 1000) {
+ writespeed /= 1000;
+ readspeed /= 1000;
+ if (writespeed >= 1000 || readspeed >= 1000) {
+ writespeed /= 1000;
+ readspeed /= 1000;
+ xSnprintf(buffer, len, "%.2f GB/s - %.2f GB/s (R/W)", (float) readspeed, (float) writespeed);
+ } else {
+ xSnprintf(buffer, len, "%.2f MB/s - %.2f MB/s (R/W)", (float) readspeed, (float) writespeed);
+ }
+ } else {
+ xSnprintf(buffer, len, "%.2f KB/s - %.2f KB/s (R/W)", (float) readspeed, (float) writespeed);
+ }
+
+ Platform_BlockDevice_mmcblk1_stats.read_sectors_comp = Platform_BlockDevice_mmcblk1_stats.read_sectors;
+ Platform_BlockDevice_mmcblk1_stats.write_sectors_comp = Platform_BlockDevice_mmcblk1_stats.write_sectors;
+
+ } else {
+ if (!(flash % 2))
+ xSnprintf(buffer, len, "%s", "unavailable");
+ else
+ xSnprintf(buffer, len, "%s", "");
+ flash++;
+ }
+}
+
+MeterClass BlockDevice_mmcblk1_ioStatsMeter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = BlockDevice_mmcblk1_ioStatsMeter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 8,
+ .total = 100.0,
+ .attributes = BlockDevice_ioStatsMeter_attributes,
+ .name = "mmcblk1stat",
+ .uiName = "mmcblk1 speed stat",
+ .caption = "mmcblk1 stat: ",
+};
+
+static void BlockDevice_mmcblk2_ioStatsMeter_setValues(Meter* this, char* buffer, int len) {
+ int ret;
+ float readspeed;
+ float writespeed;
+ double refreshdelay;
+ char block_device[80];
+ static double old = 0.;
+ static double now = 0.;
+ static int flash = 0;
+ static unsigned long sec_size = 0;
+ FILE *fp;
+
+ if (sec_size == 0) {
+ xSnprintf(block_device, sizeof(block_device), "/sys/block/%s/queue/hw_sector_size", "mmcblk2");
+ if ((fp = fopen(block_device, "r")) == NULL) {
+ xSnprintf(buffer, len, "%s", "unavailable");
+ return;
+ }
+ if (fgets(block_device, 79, fp) != NULL) {
+ sscanf(block_device, "%lu", &sec_size);
+ }
+ fclose(fp);
+ if (sec_size == 0)
+ sec_size = 1;
+ }
+
+ now = get_wall_time();
+ refreshdelay = now - old;
+ if (old == 0.)
+ refreshdelay = 1.;
+ old = now;
+
+ ret = Platform_getIO_stats("mmcblk2", 6, 0);
+ if (ret) {
+ if (Platform_BlockDevice_mmcblk2_stats.read_sectors_comp > Platform_BlockDevice_mmcblk2_stats.read_sectors)
+ Platform_BlockDevice_mmcblk2_stats.read_sectors_comp = 0;
+ if (Platform_BlockDevice_mmcblk2_stats.write_sectors_comp > Platform_BlockDevice_mmcblk2_stats.write_sectors)
+ Platform_BlockDevice_mmcblk2_stats.write_sectors_comp = 0;
+
+ /* we assume here the refresdelay is 1 sec which sometimes is 1.5, so we have a peak */
+ readspeed = (Platform_BlockDevice_mmcblk2_stats.read_sectors - Platform_BlockDevice_mmcblk2_stats.read_sectors_comp) / refreshdelay;
+ writespeed = (Platform_BlockDevice_mmcblk2_stats.write_sectors - Platform_BlockDevice_mmcblk2_stats.write_sectors_comp) / refreshdelay;
+
+ writespeed = writespeed * sec_size / 1000;
+ readspeed = readspeed * sec_size / 1000;
+ if (writespeed >= 1000 || readspeed >= 1000) {
+ writespeed /= 1000;
+ readspeed /= 1000;
+ if (writespeed >= 1000 || readspeed >= 1000) {
+ writespeed /= 1000;
+ readspeed /= 1000;
+ xSnprintf(buffer, len, "%.2f GB/s - %.2f GB/s (R/W)", (float) readspeed, (float) writespeed);
+ } else {
+ xSnprintf(buffer, len, "%.2f MB/s - %.2f MB/s (R/W)", (float) readspeed, (float) writespeed);
+ }
+ } else {
+ xSnprintf(buffer, len, "%.2f KB/s - %.2f KB/s (R/W)", (float) readspeed, (float) writespeed);
+ }
+
+ Platform_BlockDevice_mmcblk2_stats.read_sectors_comp = Platform_BlockDevice_mmcblk2_stats.read_sectors;
+ Platform_BlockDevice_mmcblk2_stats.write_sectors_comp = Platform_BlockDevice_mmcblk2_stats.write_sectors;
+
+ } else {
+ if (!(flash % 2))
+ xSnprintf(buffer, len, "%s", "unavailable");
+ else
+ xSnprintf(buffer, len, "%s", "");
+ flash++;
+ }
+}
+
+MeterClass BlockDevice_mmcblk2_ioStatsMeter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = BlockDevice_mmcblk2_ioStatsMeter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 8,
+ .total = 100.0,
+ .attributes = BlockDevice_ioStatsMeter_attributes,
+ .name = "mmcblk2stat",
+ .uiName = "mmcblk2 speed stat",
+ .caption = "mmcblk2 stat: ",
+};
+
+static void BlockDevice_mmcblk3_ioStatsMeter_setValues(Meter* this, char* buffer, int len) {
+ int ret;
+ float readspeed;
+ float writespeed;
+ double refreshdelay;
+ char block_device[80];
+ static double old = 0.;
+ static double now = 0.;
+ static int flash = 0;
+ static unsigned long sec_size = 0;
+ FILE *fp;
+
+ if (sec_size == 0) {
+ xSnprintf(block_device, sizeof(block_device), "/sys/block/%s/queue/hw_sector_size", "mmcblk3");
+ if ((fp = fopen(block_device, "r")) == NULL) {
+ xSnprintf(buffer, len, "%s", "unavailable");
+ return;
+ }
+ if (fgets(block_device, 79, fp) != NULL) {
+ sscanf(block_device, "%lu", &sec_size);
+ }
+ fclose(fp);
+ if (sec_size == 0)
+ sec_size = 1;
+ }
+
+ now = get_wall_time();
+ refreshdelay = now - old;
+ if (old == 0.)
+ refreshdelay = 1.;
+ old = now;
+
+ ret = Platform_getIO_stats("mmcblk3", 7, 0);
+ if (ret) {
+ if (Platform_BlockDevice_mmcblk3_stats.read_sectors_comp > Platform_BlockDevice_mmcblk3_stats.read_sectors)
+ Platform_BlockDevice_mmcblk3_stats.read_sectors_comp = 0;
+ if (Platform_BlockDevice_mmcblk3_stats.write_sectors_comp > Platform_BlockDevice_mmcblk3_stats.write_sectors)
+ Platform_BlockDevice_mmcblk3_stats.write_sectors_comp = 0;
+
+ /* we assume here the refresdelay is 1 sec which sometimes is 1.5, so we have a peak */
+ readspeed = (Platform_BlockDevice_mmcblk3_stats.read_sectors - Platform_BlockDevice_mmcblk3_stats.read_sectors_comp) / refreshdelay;
+ writespeed = (Platform_BlockDevice_mmcblk3_stats.write_sectors - Platform_BlockDevice_mmcblk3_stats.write_sectors_comp) / refreshdelay;
+
+ writespeed = writespeed * sec_size / 1000;
+ readspeed = readspeed * sec_size / 1000;
+ if (writespeed >= 1000 || readspeed >= 1000) {
+ writespeed /= 1000;
+ readspeed /= 1000;
+ if (writespeed >= 1000 || readspeed >= 1000) {
+ writespeed /= 1000;
+ readspeed /= 1000;
+ xSnprintf(buffer, len, "%.2f GB/s - %.2f GB/s (R/W)", (float) readspeed, (float) writespeed);
+ } else {
+ xSnprintf(buffer, len, "%.2f MB/s - %.2f MB/s (R/W)", (float) readspeed, (float) writespeed);
+ }
+ } else {
+ xSnprintf(buffer, len, "%.2f KB/s - %.2f KB/s (R/W)", (float) readspeed, (float) writespeed);
+ }
+
+ Platform_BlockDevice_mmcblk3_stats.read_sectors_comp = Platform_BlockDevice_mmcblk3_stats.read_sectors;
+ Platform_BlockDevice_mmcblk3_stats.write_sectors_comp = Platform_BlockDevice_mmcblk3_stats.write_sectors;
+
+ } else {
+ if (!(flash % 2))
+ xSnprintf(buffer, len, "%s", "unavailable");
+ else
+ xSnprintf(buffer, len, "%s", "");
+ flash++;
+ }
+}
+
+MeterClass BlockDevice_mmcblk3_ioStatsMeter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = BlockDevice_mmcblk3_ioStatsMeter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 8,
+ .total = 100.0,
+ .attributes = BlockDevice_ioStatsMeter_attributes,
+ .name = "mmcblk3stat",
+ .uiName = "mmcblk3 speed stat",
+ .caption = "mmcblk3 stat: ",
+};
+
+
+
+
diff --git a/BlockDevice_ioStatsMeter.h b/BlockDevice_ioStatsMeter.h
new file mode 100644
index 0000000..ce707c8
--- /dev/null
+++ b/BlockDevice_ioStatsMeter.h
@@ -0,0 +1,31 @@
+/* Do not edit this file. It was automatically generated. */
+
+#ifndef HEADER_BlockDevice_ioStatsMeter
+#define HEADER_BlockDevice_ioStatsMeter
+/*
+htop - BlockDevice_ioStatsMeter.h
+(C) 2020 @lex
+*/
+
+#include "Meter.h"
+
+extern int BlockDevice_ioStatsMeter_attributes[];
+
+extern MeterClass BlockDevice_sda_ioStatsMeter_class;
+
+extern MeterClass BlockDevice_sdb_ioStatsMeter_class;
+
+extern MeterClass BlockDevice_sdc_ioStatsMeter_class;
+
+extern MeterClass BlockDevice_sdd_ioStatsMeter_class;
+
+extern MeterClass BlockDevice_mmcblk0_ioStatsMeter_class;
+
+extern MeterClass BlockDevice_mmcblk1_ioStatsMeter_class;
+
+extern MeterClass BlockDevice_mmcblk2_ioStatsMeter_class;
+
+extern MeterClass BlockDevice_mmcblk3_ioStatsMeter_class;
+
+
+#endif
diff --git a/CPUMeter.c b/CPUMeter.c
index de5490d..0825dba 100644
--- a/CPUMeter.c
+++ b/CPUMeter.c
@@ -6,6 +6,7 @@ in the source distribution for its full text.
*/
#include "CPUMeter.h"
+#include "CpuFreqMeter.h"
#include "CRT.h"
#include "Settings.h"
diff --git a/CRT.c b/CRT.c
index ca9a10d..1fefaff 100644
--- a/CRT.c
+++ b/CRT.c
@@ -128,6 +128,20 @@ typedef enum ColorElements_ {
CPU_SOFTIRQ,
CPU_STEAL,
CPU_GUEST,
+ CPU_TEMP,
+ CPU_FREQ,
+ CPU_VCORE,
+ GPU_TEMP,
+ ETH0_INTERFACE,
+ ETH1_INTERFACE,
+ WLAN0_INTERFACE,
+ WLAN1_INTERFACE,
+ KERNEL_VERSION,
+ DISTRO_VERSION,
+ OS_VERSION,
+ ARMBIAN_VERSION,
+ ETH0_STATS,
+ ETH1_STATS,
LAST_COLORELEMENT
} ColorElements;
@@ -232,6 +246,18 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_SOFTIRQ] = ColorPair(Magenta,Black),
[CPU_STEAL] = ColorPair(Cyan,Black),
[CPU_GUEST] = ColorPair(Cyan,Black),
+ [CPU_FREQ] = A_BOLD | ColorPair(Yellow,Black),
+ [CPU_TEMP] = A_BOLD | ColorPair(Red,Black),
+ [CPU_VCORE] = A_BOLD | ColorPair(Yellow,Black),
+ [GPU_TEMP] = ColorPair(Cyan,Black),
+ [ETH0_INTERFACE] = A_BOLD | ColorPair(Cyan,Black),
+ [ETH1_INTERFACE] = A_BOLD | ColorPair(Cyan,Black),
+ [WLAN0_INTERFACE] = A_BOLD | ColorPair(Cyan,Black),
+ [WLAN1_INTERFACE] = A_BOLD | ColorPair(Cyan,Black),
+ [KERNEL_VERSION] = A_BOLD | ColorPair(Cyan,Black),
+ [DISTRO_VERSION] = A_BOLD | ColorPair(Cyan,Black),
+ [OS_VERSION] = A_BOLD | ColorPair(Cyan,Black),
+ [ARMBIAN_VERSION] = A_BOLD | ColorPair(Cyan,Black),
},
[COLORSCHEME_MONOCHROME] = {
[RESET_COLOR] = A_NORMAL,
@@ -291,6 +317,18 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_SOFTIRQ] = A_BOLD,
[CPU_STEAL] = A_REVERSE,
[CPU_GUEST] = A_REVERSE,
+ [CPU_FREQ] = A_BOLD,
+ [CPU_TEMP] = A_BOLD,
+ [CPU_VCORE] = A_BOLD,
+ [GPU_TEMP] = A_BOLD,
+ [ETH0_INTERFACE] = A_BOLD,
+ [ETH1_INTERFACE] = A_BOLD,
+ [WLAN0_INTERFACE] = A_BOLD,
+ [WLAN1_INTERFACE] = A_BOLD,
+ [KERNEL_VERSION] = A_BOLD,
+ [DISTRO_VERSION] = A_BOLD,
+ [OS_VERSION] = A_BOLD,
+ [ARMBIAN_VERSION] = A_BOLD,
},
[COLORSCHEME_BLACKONWHITE] = {
[RESET_COLOR] = ColorPair(Black,White),
@@ -350,6 +388,18 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_SOFTIRQ] = ColorPair(Blue,White),
[CPU_STEAL] = ColorPair(Cyan,White),
[CPU_GUEST] = ColorPair(Cyan,White),
+ [CPU_FREQ] = A_BOLD | ColorPair(Yellow,White),
+ [CPU_TEMP] = A_BOLD | ColorPair(Yellow,White),
+ [CPU_VCORE] = A_BOLD | ColorPair(Yellow,White),
+ [GPU_TEMP] = A_BOLD | ColorPair(Yellow,White),
+ [ETH0_INTERFACE] = A_BOLD | ColorPair(Yellow,White),
+ [ETH1_INTERFACE] = A_BOLD | ColorPair(Yellow,White),
+ [WLAN0_INTERFACE] = A_BOLD | ColorPair(Yellow,White),
+ [WLAN1_INTERFACE] = A_BOLD | ColorPair(Yellow,White),
+ [KERNEL_VERSION] = A_BOLD | ColorPair(Yellow,White),
+ [DISTRO_VERSION] = A_BOLD | ColorPair(Yellow,White),
+ [OS_VERSION] = A_BOLD | ColorPair(Yellow,White),
+ [ARMBIAN_VERSION] = A_BOLD | ColorPair(Yellow,White),
},
[COLORSCHEME_LIGHTTERMINAL] = {
[RESET_COLOR] = ColorPair(Black,Black),
@@ -409,6 +459,18 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_SOFTIRQ] = ColorPair(Blue,Black),
[CPU_STEAL] = ColorPair(Black,Black),
[CPU_GUEST] = ColorPair(Black,Black),
+ [CPU_FREQ] = A_BOLD | ColorPair(Yellow,Black),
+ [CPU_TEMP] = A_BOLD | ColorPair(Yellow,Black),
+ [CPU_VCORE] = A_BOLD | ColorPair(Yellow,Black),
+ [GPU_TEMP] = A_BOLD | ColorPair(Yellow,Black),
+ [ETH0_INTERFACE] = A_BOLD | ColorPair(Yellow,Black),
+ [ETH1_INTERFACE] = A_BOLD | ColorPair(Yellow,Black),
+ [WLAN0_INTERFACE] = A_BOLD | ColorPair(Yellow,Black),
+ [WLAN1_INTERFACE] = A_BOLD | ColorPair(Yellow,Black),
+ [KERNEL_VERSION] = A_BOLD | ColorPair(Yellow,Black),
+ [DISTRO_VERSION] = A_BOLD | ColorPair(Yellow,Black),
+ [OS_VERSION] = A_BOLD | ColorPair(Yellow,Black),
+ [ARMBIAN_VERSION] = A_BOLD | ColorPair(Yellow,Black),
},
[COLORSCHEME_MIDNIGHT] = {
[RESET_COLOR] = ColorPair(White,Blue),
@@ -468,6 +530,18 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_SOFTIRQ] = ColorPair(Black,Blue),
[CPU_STEAL] = ColorPair(White,Blue),
[CPU_GUEST] = ColorPair(White,Blue),
+ [CPU_FREQ] = A_BOLD | ColorPair(Red,Black),
+ [CPU_TEMP] = A_BOLD | ColorPair(Red,Black),
+ [CPU_VCORE] = A_BOLD | ColorPair(Yellow,Black),
+ [GPU_TEMP] = A_BOLD | ColorPair(Yellow,Black),
+ [ETH0_INTERFACE] = A_BOLD | ColorPair(Cyan,Blue),
+ [ETH1_INTERFACE] = A_BOLD | ColorPair(Cyan,Blue),
+ [WLAN0_INTERFACE] = A_BOLD | ColorPair(Cyan,Blue),
+ [WLAN1_INTERFACE] = A_BOLD | ColorPair(Cyan,Blue),
+ [KERNEL_VERSION] = A_BOLD | ColorPair(Cyan,Black),
+ [DISTRO_VERSION] = A_BOLD | ColorPair(Cyan,Black),
+ [OS_VERSION] = A_BOLD | ColorPair(Cyan,Black),
+ [ARMBIAN_VERSION] = A_BOLD | ColorPair(Cyan,Black),
},
[COLORSCHEME_BLACKNIGHT] = {
[RESET_COLOR] = ColorPair(Cyan,Black),
@@ -527,6 +601,18 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[CPU_SOFTIRQ] = ColorPair(Blue,Black),
[CPU_STEAL] = ColorPair(Cyan,Black),
[CPU_GUEST] = ColorPair(Cyan,Black),
+ [CPU_FREQ] = A_BOLD | ColorPair(Red,Black),
+ [CPU_TEMP] = A_BOLD | ColorPair(Red,Black),
+ [CPU_VCORE] = A_BOLD | ColorPair(Yellow,Black),
+ [GPU_TEMP] = A_BOLD | ColorPair(Yellow,Black),
+ [ETH0_INTERFACE] = A_BOLD | ColorPair(Blue,Black),
+ [ETH1_INTERFACE] = A_BOLD | ColorPair(Blue,Black),
+ [WLAN0_INTERFACE] = A_BOLD | ColorPair(Blue,Black),
+ [WLAN1_INTERFACE] = A_BOLD | ColorPair(Blue,Black),
+ [KERNEL_VERSION] = A_BOLD | ColorPair(Blue,Black),
+ [DISTRO_VERSION] = A_BOLD | ColorPair(Blue,Black),
+ [OS_VERSION] = A_BOLD | ColorPair(Blue,Black),
+ [ARMBIAN_VERSION] = A_BOLD | ColorPair(Blue,Black),
},
[COLORSCHEME_BROKENGRAY] = { 0 } // dynamically generated.
};
@@ -596,6 +682,15 @@ void CRT_restorePrivileges() {
// TODO: pass an instance of Settings instead.
void CRT_init(int delay, int colorScheme) {
+#ifdef DEBUG
+ setenv("TERM", "xterm", 1);
+ CRT_termType = getenv("TERM");
+ if (String_eq(CRT_termType, "linux"))
+ CRT_scrollHAmount = 20;
+ else
+ CRT_scrollHAmount = 5;
+ setenv("TERM", "xterm", 1);
+#endif
initscr();
noecho();
CRT_delay = delay;
diff --git a/CRT.h b/CRT.h
index 933fe06..29ba16b 100644
--- a/CRT.h
+++ b/CRT.h
@@ -116,6 +116,20 @@ typedef enum ColorElements_ {
CPU_SOFTIRQ,
CPU_STEAL,
CPU_GUEST,
+ CPU_TEMP,
+ CPU_FREQ,
+ CPU_VCORE,
+ GPU_TEMP,
+ ETH0_INTERFACE,
+ ETH1_INTERFACE,
+ WLAN0_INTERFACE,
+ WLAN1_INTERFACE,
+ KERNEL_VERSION,
+ DISTRO_VERSION,
+ OS_VERSION,
+ ARMBIAN_VERSION,
+ ETH0_STATS,
+ ETH1_STATS,
LAST_COLORELEMENT
} ColorElements;
diff --git a/CpuFreqMeter.c b/CpuFreqMeter.c
new file mode 100644
index 0000000..6508180
--- /dev/null
+++ b/CpuFreqMeter.c
@@ -0,0 +1,109 @@
+/*
+htop - CpuFreqMeter.c
+(C) 2020 Alexander Finger
+*/
+
+#include "CpuFreqMeter.h"
+#include "Platform.h"
+#include "CRT.h"
+
+/*{
+#include "Meter.h"
+}*/
+
+
+int CpuFreqMeter_attributes[] = {
+ CPU_FREQ
+};
+
+static void CpuFreqMeter_setValues(Meter* this, char* buffer, int len) {
+ int ghz,mhz,roundup;
+ int cpu, Freq;
+ int bigLITTLE;
+ char buf_b[32];
+ char buf_l[32];
+ int ln = sizeof(buf_l);
+ static int pulse = 0;
+
+ memset(buf_l, 0, sizeof(buf_l));
+ memset(buf_b, 0, sizeof(buf_b));
+
+ bigLITTLE = Platform_getCpuBigLITTLE();
+ if (bigLITTLE) {
+ cpu = bigLITTLE;
+ if (cpu < 0)
+ cpu = 0;
+ Freq = Platform_getCpuFreq(this, cpu);
+ if (Freq > 1000) {
+ Freq /= 1000;
+ }
+ if (Freq > 1000) {
+ ghz = Freq / 1000;
+ mhz = Freq % 1000;
+ roundup = ((mhz % 10) > 5);
+ mhz /= 10;
+ mhz += roundup;
+ xSnprintf(buf_b, ln, "%d.%02d GHz", ghz, mhz);
+ } else {
+ xSnprintf(buf_b, ln, "%4d MHz", Freq);
+ }
+
+ cpu--;
+ if (cpu < 0)
+ cpu = 0;
+ Freq = Platform_getCpuFreq(this, cpu);
+ if (Freq > 1000) {
+ Freq /= 1000;
+ }
+ if (Freq > 1000) {
+ ghz = Freq / 1000;
+ mhz = Freq % 1000;
+ roundup = ((mhz % 10) > 5);
+ mhz /= 10;
+ mhz += roundup;
+ xSnprintf(buf_l, ln, "%d.%02d GHz", ghz, mhz);
+ } else {
+ xSnprintf(buf_l, ln, "%4d MHz", Freq);
+ }
+
+ if (pulse)
+ xSnprintf(buffer, len, "%s %s (big.LITTLE)", buf_b, buf_l, pulse);
+ else
+ xSnprintf(buffer, len, "%s %s ", buf_b, buf_l, pulse);
+ pulse = !pulse;
+ return;
+ }
+
+ cpu = 0;
+ Freq = Platform_getCpuFreq(this, cpu);
+ if (Freq > 1000) {
+ Freq /= 1000;
+ }
+ if (Freq > 1000) {
+ ghz = Freq / 1000;
+ mhz = Freq % 1000;
+ roundup = ((mhz % 10) > 5);
+ mhz /= 10;
+ mhz += roundup;
+ xSnprintf(buffer, len, "%d.%02d GHz", ghz, mhz);
+ } else {
+ xSnprintf(buffer, len, "%4d MHz", Freq);
+ }
+ pulse = !pulse;
+}
+
+MeterClass CpuFreqMeter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = CpuFreqMeter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 1,
+ .total = 100.0,
+ .attributes = CpuFreqMeter_attributes,
+ .name = "CpuFreq",
+ .uiName = "CpuFreq",
+ .caption = "Cpu Freq: ",
+};
+
diff --git a/CpuFreqMeter.h b/CpuFreqMeter.h
new file mode 100644
index 0000000..151a58c
--- /dev/null
+++ b/CpuFreqMeter.h
@@ -0,0 +1,17 @@
+/* Do not edit this file. It was automatically generated. */
+
+#ifndef HEADER_CpuFreqMeter
+#define HEADER_CpuFreqMeter
+/*
+htop - CpuFreqMeter.h
+(C) 2020 Alexander Finger
+*/
+
+#include "Meter.h"
+
+extern int CpuFreqMeter_attributes[];
+
+extern MeterClass CpuFreqMeter_class;
+
+
+#endif
diff --git a/CpuTempMeter.c b/CpuTempMeter.c
new file mode 100644
index 0000000..4052256
--- /dev/null
+++ b/CpuTempMeter.c
@@ -0,0 +1,39 @@
+/*
+htop - CpuTempMeter.c
+(C) 2020 @lex
+*/
+
+#include "CpuTempMeter.h"
+#include "Platform.h"
+#include "CRT.h"
+
+/*{
+#include "Meter.h"
+}*/
+
+int CpuTempMeter_attributes[] = {
+ CPU_TEMP
+};
+
+static void CpuTempMeter_setValues(Meter* this, char* buffer, int len) {
+ int Temp = Platform_getCpuTemp(this);
+ if (Temp > 1000) {
+ Temp /= 1000;
+ }
+ xSnprintf(buffer, len, "%4d C", Temp);
+}
+
+MeterClass CpuTempMeter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = CpuTempMeter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 1,
+ .total = 100.0,
+ .attributes = CpuTempMeter_attributes,
+ .name = "CpuTemp",
+ .uiName = "CpuTemp",
+ .caption = "Cpu Temp: "
+};
diff --git a/CpuTempMeter.h b/CpuTempMeter.h
new file mode 100644
index 0000000..3538ac3
--- /dev/null
+++ b/CpuTempMeter.h
@@ -0,0 +1,16 @@
+/* Do not edit this file. It was automatically generated. */
+
+#ifndef HEADER_CpuTempMeter
+#define HEADER_CpuTempMeter
+/*
+htop - CpuTempMeter.h
+(C) 2020 @lex
+*/
+
+#include "Meter.h"
+
+extern int CpuTempMeter_attributes[];
+
+extern MeterClass CpuTempMeter_class;
+
+#endif
diff --git a/CpuVcoreMeter.c b/CpuVcoreMeter.c
new file mode 100644
index 0000000..03adb6d
--- /dev/null
+++ b/CpuVcoreMeter.c
@@ -0,0 +1,84 @@
+/*
+htop - CpuVcoreMeter.c
+(C) 2020 Alexander Finger
+*/
+
+#include "CpuVcoreMeter.h"
+#include "Platform.h"
+#include "CRT.h"
+
+/*{
+#include "Meter.h"
+}*/
+
+
+int CpuVcoreMeter_attributes[] = {
+ CPU_VCORE
+};
+
+static void CpuVcoreMeter_setValues(Meter* this, char* buffer, int len) {
+ int v1,v2;
+ int Vcore, Vcore_l, Vcore_b;
+ char buf1[80], buf2[80];
+ int h;
+
+ if (Platform_getCpuBigLITTLE()) {
+ h = len / 2;
+ if (h > 79)
+ h = 79;
+ Vcore_b = Platform_getCpuVcore_b(this);
+ if (Vcore_b > 1000) {
+ Vcore_b /= 1000;
+ }
+ if (Vcore_b >= 1000) {
+ Vcore_b /= 10;
+ v1 = Vcore_b / 100;
+ v2 = Vcore_b % 100;
+ xSnprintf(buf1, h, "%d.%02d V ", v1, v2);
+ } else {
+ xSnprintf(buf1, h, "%4d mV", Vcore_b);
+ }
+ Vcore_l = Platform_getCpuVcore_l(this);
+ if (Vcore_l > 1000) {
+ Vcore_l /= 1000;
+ }
+ if (Vcore_l >= 1000) {
+ Vcore_l /= 10;
+ v1 = Vcore_l / 100;
+ v2 = Vcore_l % 100;
+ xSnprintf(buf2, h, "%d.%02d V ", v1, v2);
+ } else {
+ xSnprintf(buf2, h, "%4d mV", Vcore_l);
+ }
+ xSnprintf(buffer, len, "%s %s (big.LITTLE)", buf1, buf2);
+ return;
+ }
+
+ Vcore = Platform_getCpuVcore(this);
+ if (Vcore > 1000) {
+ Vcore /= 1000;
+ }
+ if (Vcore >= 1000) {
+ Vcore /= 10;
+ v1 = Vcore / 100;
+ v2 = Vcore % 100;
+ xSnprintf(buffer, len, "%d.%02d V", v1, v2);
+ } else {
+ xSnprintf(buffer, len, "%4d mV", Vcore);
+ }
+}
+
+MeterClass CpuVcoreMeter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = CpuVcoreMeter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 1,
+ .total = 100.0,
+ .attributes = CpuVcoreMeter_attributes,
+ .name = "CpuVcore",
+ .uiName = "CpuVcore",
+ .caption = "Cpu Vcor: "
+};
diff --git a/CpuVcoreMeter.h b/CpuVcoreMeter.h
new file mode 100644
index 0000000..603e8e2
--- /dev/null
+++ b/CpuVcoreMeter.h
@@ -0,0 +1,16 @@
+/* Do not edit this file. It was automatically generated. */
+
+#ifndef HEADER_CpuVcoreMeter
+#define HEADER_CpuVcoreMeter
+/*
+htop - CpuVcoreMeter.h
+(C) 2020 Alexander Finger
+*/
+
+#include "Meter.h"
+
+extern int CpuVcoreMeter_attributes[];
+
+extern MeterClass CpuVcoreMeter_class;
+
+#endif
diff --git a/Eth0_Meter.c b/Eth0_Meter.c
new file mode 100644
index 0000000..90e512a
--- /dev/null
+++ b/Eth0_Meter.c
@@ -0,0 +1,60 @@
+/*
+htop - Eth0_Meter.c
+(C) 2018 @lex
+*/
+
+#include "Eth0_Meter.h"
+#include "Platform.h"
+#include "CRT.h"
+
+#include "interfaces.h"
+
+/*{
+#include "Meter.h"
+}*/
+
+
+int Eth0_Meter_attributes[] = {
+ ETH0_INTERFACE
+};
+
+static void Eth0_Meter_setValues(Meter* this, char* buffer, int len) {
+ int ret;
+ static char szIP[48];
+ static unsigned int use_cached = 0;
+ Settings* settings = this->pl->settings;
+
+ if ((use_cached++ % 2)) {
+ xSnprintf(buffer, len, "%s", szIP);
+ return;
+ }
+
+ if (settings->eth0_alias[0] != 0) {
+ ret = findIP_interface(settings->eth0_alias, szIP, sizeof(szIP));
+ } else {
+ ret = findIP_interface("eth0", szIP, sizeof(szIP));
+ }
+
+ if (ret) {
+ xSnprintf(buffer, len, "%s", szIP);
+ } else {
+ xSnprintf(buffer, len, "%s", "down");
+ }
+}
+
+MeterClass Eth0_Meter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = Eth0_Meter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 8,
+ .total = 100.0,
+ .attributes = Eth0_Meter_attributes,
+ .name = "Eth0",
+ .uiName = "Eth0 IP",
+ .caption = "Eth0 IP: ",
+};
+
+
diff --git a/Eth0_Meter.h b/Eth0_Meter.h
new file mode 100644
index 0000000..5443abc
--- /dev/null
+++ b/Eth0_Meter.h
@@ -0,0 +1,17 @@
+/* Do not edit this file. It was automatically generated. */
+
+#ifndef HEADER_Eth0_Meter
+#define HEADER_Eth0_Meter
+/*
+htop - Eth0_Meter.h
+(C) 2018 @lex
+*/
+
+#include "Meter.h"
+
+extern int Eth0_Meter_attributes[];
+
+extern MeterClass Eth0_Meter_class;
+
+
+#endif
diff --git a/Eth0_StatsMeter.c b/Eth0_StatsMeter.c
new file mode 100644
index 0000000..974c656
--- /dev/null
+++ b/Eth0_StatsMeter.c
@@ -0,0 +1,83 @@
+/*
+htop - Eth0_StatsMeter.c
+(C) 2020 @lex
+*/
+
+#include "Eth0_StatsMeter.h"
+#include "Platform.h"
+#include "CRT.h"
+
+#include "interfaces.h"
+
+/*{
+#include "Meter.h"
+}*/
+
+
+int Eth0_StatsMeter_attributes[] = {
+ ETH0_INTERFACE
+};
+
+/* borrowed from slurm */
+static void Eth0_StatsMeter_setValues(Meter* this, char* buffer, int len) {
+ int ret;
+ float rxspeed;
+ float txspeed;
+ Settings* settings = this->pl->settings;
+ double refreshdelay;
+ static double old = 0.;
+ static double now = 0.;
+ static int flash = 0;
+
+ now = get_wall_time();
+ refreshdelay = now - old;
+ if (old == 0.)
+ refreshdelay = 1.;
+ old = now;
+
+ if (settings->eth0_alias[0] != 0) {
+ ret = Platform_getEth_stats(settings->eth0_alias, 0, 0);
+ } else {
+ ret = Platform_getEth_stats("eth0", 0, 0);
+ }
+
+ if (ret) {
+ if (Platform_Eth0_stats.rx_bytes_comp > Platform_Eth0_stats.rx_bytes)
+ Platform_Eth0_stats.rx_bytes_comp = 0;
+ if (Platform_Eth0_stats.tx_bytes_comp > Platform_Eth0_stats.tx_bytes)
+ Platform_Eth0_stats.tx_bytes_comp = 0;
+
+ /* we assume here the refresdelay is 1 sec which sometimes is 1.5, so we have a peak */
+ rxspeed = (Platform_Eth0_stats.rx_bytes - Platform_Eth0_stats.rx_bytes_comp) / refreshdelay;
+ txspeed = (Platform_Eth0_stats.tx_bytes - Platform_Eth0_stats.tx_bytes_comp) / refreshdelay;
+
+ xSnprintf(buffer, len, "%.2f KB/s - %.2f KB/s (TX/RX)", (float) txspeed / 1024, (float) rxspeed / 1024);
+
+ Platform_Eth0_stats.rx_bytes_comp = Platform_Eth0_stats.rx_bytes;
+ Platform_Eth0_stats.tx_bytes_comp = Platform_Eth0_stats.tx_bytes;
+
+ } else {
+ if (!(flash % 2))
+ xSnprintf(buffer, len, "%s", "unavail");
+ else
+ xSnprintf(buffer, len, "%s", "");
+ flash++;
+ }
+}
+
+MeterClass Eth0_StatsMeter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = Eth0_StatsMeter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 8,
+ .total = 100.0,
+ .attributes = Eth0_StatsMeter_attributes,
+ .name = "Eth0stat",
+ .uiName = "Eth0 stat",
+ .caption = "Eth0 stat: ",
+};
+
+
diff --git a/Eth0_StatsMeter.h b/Eth0_StatsMeter.h
new file mode 100644
index 0000000..e44a5cc
--- /dev/null
+++ b/Eth0_StatsMeter.h
@@ -0,0 +1,18 @@
+/* Do not edit this file. It was automatically generated. */
+
+#ifndef HEADER_Eth0_StatsMeter
+#define HEADER_Eth0_StatsMeter
+/*
+htop - Eth0_StatsMeter.h
+(C) 2020 @lex
+*/
+
+#include "Meter.h"
+
+extern int Eth0_StatsMeter_attributes[];
+
+/* borrowed from slurm */
+extern MeterClass Eth0_StatsMeter_class;
+
+
+#endif
diff --git a/Eth1_Meter.c b/Eth1_Meter.c
new file mode 100644
index 0000000..41cfa05
--- /dev/null
+++ b/Eth1_Meter.c
@@ -0,0 +1,60 @@
+/*
+htop - Eth1_Meter.c
+(C) 2018 @lex
+*/
+
+#include "Eth1_Meter.h"
+#include "Platform.h"
+#include "CRT.h"
+
+#include "interfaces.h"
+
+/*{
+#include "Meter.h"
+}*/
+
+
+int Eth1_Meter_attributes[] = {
+ ETH1_INTERFACE
+};
+
+static void Eth1_Meter_setValues(Meter* this, char* buffer, int len) {
+ int ret;
+ static char szIP[48];
+ static unsigned int use_cached = 0;
+ Settings* settings = this->pl->settings;
+
+ if ((use_cached++ % 2)) {
+ xSnprintf(buffer, len, "%s", szIP);
+ return;
+ }
+
+ if (settings->eth1_alias[0] != 0) {
+ ret = findIP_interface(settings->eth1_alias, szIP, sizeof(szIP));
+ } else {
+ ret = findIP_interface("eth1", szIP, sizeof(szIP));
+ }
+
+ if (ret) {
+ xSnprintf(buffer, len, "%s", szIP);
+ } else {
+ xSnprintf(buffer, len, "%s", "down");
+ }
+}
+
+MeterClass Eth1_Meter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = Eth1_Meter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 8,
+ .total = 100.0,
+ .attributes = Eth1_Meter_attributes,
+ .name = "Eth1",
+ .uiName = "Eth1 IP",
+ .caption = "Eth1 IP: ",
+};
+
+
diff --git a/Eth1_Meter.h b/Eth1_Meter.h
new file mode 100644
index 0000000..7f7f4fc
--- /dev/null
+++ b/Eth1_Meter.h
@@ -0,0 +1,17 @@
+/* Do not edit this file. It was automatically generated. */
+
+#ifndef HEADER_Eth1_Meter
+#define HEADER_Eth1_Meter
+/*
+htop - Eth1_Meter.h
+(C) 2018 @lex
+*/
+
+#include "Meter.h"
+
+extern int Eth1_Meter_attributes[];
+
+extern MeterClass Eth1_Meter_class;
+
+
+#endif
diff --git a/Eth1_StatsMeter.c b/Eth1_StatsMeter.c
new file mode 100644
index 0000000..85e6dc9
--- /dev/null
+++ b/Eth1_StatsMeter.c
@@ -0,0 +1,83 @@
+/*
+htop - Eth1_StatsMeter.c
+(C) 2020 @lex
+*/
+
+#include "Eth1_StatsMeter.h"
+#include "Platform.h"
+#include "CRT.h"
+
+#include "interfaces.h"
+
+/*{
+#include "Meter.h"
+}*/
+
+
+int Eth1_StatsMeter_attributes[] = {
+ ETH1_INTERFACE
+};
+
+/* borrowed from slurm */
+static void Eth1_StatsMeter_setValues(Meter* this, char* buffer, int len) {
+ int ret;
+ float rxspeed;
+ float txspeed;
+ Settings* settings = this->pl->settings;
+ double refreshdelay;
+ static double old = 0.;
+ static double now = 0.;
+ static int flash = 0;
+
+ now = get_wall_time();
+ refreshdelay = now - old;
+ if (old == 0.)
+ refreshdelay = 1.;
+ old = now;
+
+ if (settings->eth1_alias[0] != 0) {
+ ret = Platform_getEth_stats(settings->eth1_alias, 1, 0);
+ } else {
+ ret = Platform_getEth_stats("eth1", 1, 0);
+ }
+
+ if (ret) {
+ if (Platform_Eth1_stats.rx_bytes_comp > Platform_Eth1_stats.rx_bytes)
+ Platform_Eth1_stats.rx_bytes_comp = 0;
+ if (Platform_Eth1_stats.tx_bytes_comp > Platform_Eth1_stats.tx_bytes)
+ Platform_Eth1_stats.tx_bytes_comp = 0;
+
+ /* we assume here the refresdelay is 1 sec which sometimes is 1.5, so we have a peak */
+ rxspeed = (Platform_Eth1_stats.rx_bytes - Platform_Eth1_stats.rx_bytes_comp) / refreshdelay;
+ txspeed = (Platform_Eth1_stats.tx_bytes - Platform_Eth1_stats.tx_bytes_comp) / refreshdelay;
+
+ xSnprintf(buffer, len, "%.2f KB/s - %.2f KB/s (TX/RX)", (float) txspeed / 1024, (float) rxspeed / 1024);
+
+ Platform_Eth1_stats.rx_bytes_comp = Platform_Eth1_stats.rx_bytes;
+ Platform_Eth1_stats.tx_bytes_comp = Platform_Eth1_stats.tx_bytes;
+
+ } else {
+ if (!(flash % 2))
+ xSnprintf(buffer, len, "%s", "unavail");
+ else
+ xSnprintf(buffer, len, "%s", "");
+ flash++;
+ }
+}
+
+MeterClass Eth1_StatsMeter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = Eth1_StatsMeter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 8,
+ .total = 100.0,
+ .attributes = Eth1_StatsMeter_attributes,
+ .name = "Eth1stat",
+ .uiName = "Eth1 stat",
+ .caption = "Eth1 stat: ",
+};
+
+
diff --git a/Eth1_StatsMeter.h b/Eth1_StatsMeter.h
new file mode 100644
index 0000000..c173b15
--- /dev/null
+++ b/Eth1_StatsMeter.h
@@ -0,0 +1,18 @@
+/* Do not edit this file. It was automatically generated. */
+
+#ifndef HEADER_Eth1_StatsMeter
+#define HEADER_Eth1_StatsMeter
+/*
+htop - Eth1_StatsMeter.h
+(C) 2020 @lex
+*/
+
+#include "Meter.h"
+
+extern int Eth1_StatsMeter_attributes[];
+
+/* borrowed from slurm */
+extern MeterClass Eth1_StatsMeter_class;
+
+
+#endif
diff --git a/GpuTempMeter.c b/GpuTempMeter.c
new file mode 100644
index 0000000..92394b3
--- /dev/null
+++ b/GpuTempMeter.c
@@ -0,0 +1,39 @@
+/*
+htop - GpuTempMeter.c
+(C) 2018 @lex
+*/
+
+#include "GpuTempMeter.h"
+#include "Platform.h"
+#include "CRT.h"
+
+/*{
+#include "Meter.h"
+}*/
+
+int GpuTempMeter_attributes[] = {
+ GPU_TEMP
+};
+
+static void GpuTempMeter_setValues(Meter* this, char* buffer, int len) {
+ int Temp = Platform_getGpuTemp(this);
+ if (Temp > 1000) {
+ Temp /= 1000;
+ }
+ xSnprintf(buffer, len, "%4d C", Temp);
+}
+
+MeterClass GpuTempMeter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = GpuTempMeter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 1,
+ .total = 100.0,
+ .attributes = GpuTempMeter_attributes,
+ .name = "GpuTemp",
+ .uiName = "GpuTemp",
+ .caption = "Gpu Temp: "
+};
diff --git a/GpuTempMeter.h b/GpuTempMeter.h
new file mode 100644
index 0000000..40dab90
--- /dev/null
+++ b/GpuTempMeter.h
@@ -0,0 +1,16 @@
+/* Do not edit this file. It was automatically generated. */
+
+#ifndef HEADER_GpuTempMeter
+#define HEADER_GpuTempMeter
+/*
+htop - GpuTempMeter.h
+(C) 2018 @lex
+*/
+
+#include "Meter.h"
+
+extern int GpuTempMeter_attributes[];
+
+extern MeterClass GpuTempMeter_class;
+
+#endif
diff --git a/Kernel_Meter.c b/Kernel_Meter.c
new file mode 100644
index 0000000..45c675f
--- /dev/null
+++ b/Kernel_Meter.c
@@ -0,0 +1,55 @@
+/*
+htop - Kernelversion_Meter.c
+(C) 2018 @lex
+*/
+
+#include "Kernel_Meter.h"
+#include "Platform.h"
+#include "CRT.h"
+
+#include "interfaces.h"
+
+/*{
+#include "Meter.h"
+}*/
+
+
+int Kernelversion_Meter_attributes[] = {
+ KERNEL_VERSION
+};
+
+static void Kernelversion_Meter_setValues(Meter* this, char* buffer, int len) {
+ int ret;
+ static char version[256];
+ static int use_cached = 0;
+
+ if ((use_cached++ % 10)) {
+ xSnprintf(buffer, len, "%s", version);
+ return;
+ }
+
+ ret = ReadTokenValue( "/proc/version", "Linux version", version);
+
+ if (ret) {
+ xSnprintf(buffer, len, "%s", version);
+ } else {
+ xSnprintf(buffer, len, "%s", "down");
+ }
+}
+
+MeterClass Kernelversion_Meter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = Kernelversion_Meter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 8,
+ .total = 100.0,
+ .attributes = Kernelversion_Meter_attributes,
+ .name = "Kernelversion",
+ .uiName = "Kernel version",
+ .caption = "Kernel: ",
+};
+
+
diff --git a/Kernel_Meter.h b/Kernel_Meter.h
new file mode 100644
index 0000000..98f9a1f
--- /dev/null
+++ b/Kernel_Meter.h
@@ -0,0 +1,17 @@
+/* Do not edit this file. It was automatically generated. */
+
+#ifndef HEADER_Kernel_Meter
+#define HEADER_Kernel_Meter
+/*
+htop - Kernelversion_Meter.h
+(C) 2018 @lex
+*/
+
+#include "Meter.h"
+
+extern int Kernelversion_Meter_attributes[];
+
+extern MeterClass Kernelversion_Meter_class;
+
+
+#endif
diff --git a/Makefile.am b/Makefile.am
index cd5209c..6557c6a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,7 +21,9 @@ ClockMeter.c ColorsPanel.c ColumnsPanel.c CPUMeter.c CRT.c MainPanel.c \
DisplayOptionsPanel.c FunctionBar.c Hashtable.c Header.c htop.c ListItem.c \
LoadAverageMeter.c MemoryMeter.c Meter.c MetersPanel.c Object.c Panel.c \
BatteryMeter.c Process.c ProcessList.c RichString.c ScreenManager.c Settings.c \
-SignalsPanel.c StringUtils.c SwapMeter.c TasksMeter.c UptimeMeter.c \
+SignalsPanel.c StringUtils.c SwapMeter.c TasksMeter.c UptimeMeter.c CpuFreqMeter.c CpuTempMeter.c GpuTempMeter.c CpuVcoreMeter.c \
+interfaces.c OS_Meter.c Eth0_Meter.c Eth1_Meter.c Wlan0_Meter.c Wlan1_Meter.c Kernel_Meter.c Armbian_Meter.c \
+Wlan0_StatsMeter.c Eth0_StatsMeter.c Eth1_StatsMeter.c BlockDevice_ioStatsMeter.c \
TraceScreen.c UsersTable.c Vector.c AvailableColumnsPanel.c AffinityPanel.c \
HostnameMeter.c OpenFilesScreen.c Affinity.c IncSet.c Action.c EnvScreen.c \
InfoScreen.c XAlloc.c
@@ -32,7 +34,9 @@ CPUMeter.h CRT.h MainPanel.h DisplayOptionsPanel.h FunctionBar.h \
Hashtable.h Header.h htop.h ListItem.h LoadAverageMeter.h MemoryMeter.h \
BatteryMeter.h Meter.h MetersPanel.h Object.h Panel.h ProcessList.h RichString.h \
ScreenManager.h Settings.h SignalsPanel.h StringUtils.h SwapMeter.h \
-TasksMeter.h UptimeMeter.h TraceScreen.h UsersTable.h Vector.h Process.h \
+TasksMeter.h UptimeMeter.h CpuFreqMeter.h CpuTempMeter.h GpuTempMeter.h CpuVcoreMeter.h TraceScreen.h UsersTable.h Vector.h Process.h \
+interfaces.h OS_Meter.h Eth0_Meter.h Eth1_Meter.h Wlan0_Meter.h Wlan1_Meter.h Kernel_Meter.h Armbian_Meter.h \
+Wlan0_StatsMeter.h Eth0_StatsMeter.h Eth1_StatsMeter.h BlockDevice_ioStatsMeter.h \
AffinityPanel.h HostnameMeter.h OpenFilesScreen.h Affinity.h IncSet.h Action.h \
EnvScreen.h InfoScreen.h XAlloc.h
diff --git a/OS_Meter.c b/OS_Meter.c
new file mode 100644
index 0000000..588c234
--- /dev/null
+++ b/OS_Meter.c
@@ -0,0 +1,55 @@
+/*
+htop - OSversion_Meter.c
+(C) 2018 @lex
+*/
+
+#include "OS_Meter.h"
+#include "Platform.h"
+#include "CRT.h"
+
+#include "interfaces.h"
+
+/*{
+#include "Meter.h"
+}*/
+
+
+int OSversion_Meter_attributes[] = {
+ OS_VERSION
+};
+
+static void OSversion_Meter_setValues(Meter* this, char* buffer, int len) {
+ int ret;
+ static char version[256];
+ static int use_cached = 0;
+
+ if ((use_cached++ % 10)) {
+ xSnprintf(buffer, len, "%s", version);
+ return;
+ }
+
+ ret = ReadKeyValue( "/etc/os-release", "PRETTY_NAME=", version);
+
+ if (ret) {
+ xSnprintf(buffer, len, "%s", version);
+ } else {
+ xSnprintf(buffer, len, "%s", "down");
+ }
+}
+
+MeterClass OSversion_Meter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = OSversion_Meter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 8,
+ .total = 100.0,
+ .attributes = OSversion_Meter_attributes,
+ .name = "OSversion",
+ .uiName = "OS version",
+ .caption = "OS vers: ",
+};
+
+
diff --git a/OS_Meter.h b/OS_Meter.h
new file mode 100644
index 0000000..c5cccb2
--- /dev/null
+++ b/OS_Meter.h
@@ -0,0 +1,17 @@
+/* Do not edit this file. It was automatically generated. */
+
+#ifndef HEADER_OS_Meter
+#define HEADER_OS_Meter
+/*
+htop - OSversion_Meter.h
+(C) 2018 @lex
+*/
+
+#include "Meter.h"
+
+extern int OSversion_Meter_attributes[];
+
+extern MeterClass OSversion_Meter_class;
+
+
+#endif
diff --git a/Process.c b/Process.c
index 471f529..9ac5fa6 100644
--- a/Process.c
+++ b/Process.c
@@ -1,6 +1,7 @@
/*
htop - Process.c
(C) 2004-2015 Hisham H. Muhammad
+(C) 2020 Alexander Finger
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
diff --git a/Process.h b/Process.h
index f702ca0..fbd9ef5 100644
--- a/Process.h
+++ b/Process.h
@@ -5,6 +5,7 @@
/*
htop - Process.h
(C) 2004-2015 Hisham H. Muhammad
+(C) 2020 Alexander Finger
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
diff --git a/ProcessList.c b/ProcessList.c
index 7482b03..4ef1e83 100644
--- a/ProcessList.c
+++ b/ProcessList.c
@@ -69,6 +69,7 @@ typedef struct ProcessList_ {
unsigned long long int freeSwap;
int cpuCount;
+ int cpuBigLITTLE;
} ProcessList;
diff --git a/ProcessList.h b/ProcessList.h
index 572d484..aa0e6c0 100644
--- a/ProcessList.h
+++ b/ProcessList.h
@@ -63,6 +63,7 @@ typedef struct ProcessList_ {
unsigned long long int freeSwap;
int cpuCount;
+ int cpuBigLITTLE;
} ProcessList;
diff --git a/ScreenManager.c b/ScreenManager.c
index 05e1c02..3ae6670 100644
--- a/ScreenManager.c
+++ b/ScreenManager.c
@@ -130,6 +130,7 @@ static void checkRecalculation(ScreenManager* this, double* oldTime, int* sortTi
if (newTime < *oldTime) *rescan = true; // clock was adjusted?
if (*rescan) {
*oldTime = newTime;
+ Header_draw(this->header);
ProcessList_scan(pl);
if (*sortTimeout == 0 || this->settings->treeView) {
ProcessList_sort(pl);
@@ -139,7 +140,7 @@ static void checkRecalculation(ScreenManager* this, double* oldTime, int* sortTi
}
if (*redraw) {
ProcessList_rebuildPanel(pl);
- Header_draw(this->header);
+ // Header_draw(this->header);
}
*rescan = false;
}
diff --git a/Settings.c b/Settings.c
index db2fa06..912ad7d 100644
--- a/Settings.c
+++ b/Settings.c
@@ -59,6 +59,28 @@ typedef struct Settings_ {
bool accountGuestInCPUMeter;
bool headerMargin;
+ char CpuFreq_handler[256];
+ char CpuTemp_handler[256];
+ char CpuVCore_l_handler[256];
+ char CpuVCore_b_handler[256];
+
+ char GpuVCore_handler[256];
+ char GpuTemp_handler[256];
+
+ char BoardName[128];
+ char KernelVersionFull[256];
+ char KernelVersionShort[64];
+
+ char IP_wlan0[32];
+ char IP_wlan1[32];
+ char IP_eth0[32];
+ char IP_eth1[32];
+
+ char eth0_alias[32];
+ char eth1_alias[32];
+ char wlan0_alias[32];
+ char wlan1_alias[32];
+
bool changed;
} Settings;
@@ -141,6 +163,12 @@ static void Settings_defaultMeters(Settings* this) {
this->columns[1].modes[r++] = TEXT_METERMODE;
this->columns[1].names[r] = xStrdup("Uptime");
this->columns[1].modes[r++] = TEXT_METERMODE;
+
+ this->columns[1].names[r] = xStrdup("CpuTemp");
+ this->columns[1].modes[r++] = TEXT_METERMODE;
+ this->columns[1].names[r] = xStrdup("CpuFreq");
+ this->columns[1].modes[r++] = TEXT_METERMODE;
+
}
static void readFields(ProcessField* fields, int* flags, const char* line) {
@@ -244,7 +272,41 @@ static bool Settings_read(Settings* this, const char* fileName) {
} else if (String_eq(option[0], "right_meter_modes")) {
Settings_readMeterModes(this, option[1], 1);
didReadMeters = true;
- }
+ } else if (String_eq(option[0], "BoardName")) {
+ strcpy(this->BoardName,option[1]);
+ didReadMeters = true;
+ } else if (String_eq(option[0], "CpuFreq_handler")) {
+ strcpy(this->CpuFreq_handler,option[1]);
+ didReadMeters = true;
+ } else if (String_eq(option[0], "CpuTemp_handler")) {
+ strcpy(this->CpuTemp_handler,option[1]);
+ didReadMeters = true;
+ } else if (String_eq(option[0], "CpuVCore_l_handler")) {
+ strcpy(this->CpuVCore_l_handler,option[1]);
+ didReadMeters = true;
+ } else if (String_eq(option[0], "CpuVCore_b_handler")) {
+ strcpy(this->CpuVCore_b_handler,option[1]);
+ didReadMeters = true;
+ } else if (String_eq(option[0], "GpuVCore_handler")) {
+ strcpy(this->GpuVCore_handler,option[1]);
+ didReadMeters = true;
+ } else if (String_eq(option[0], "GpuTemp_handler")) {
+ strcpy(this->GpuTemp_handler,option[1]);
+ didReadMeters = true;
+ } else if (String_eq(option[0], "eth0_alias")) {
+ strcpy(this->eth0_alias,option[1]);
+ didReadMeters = true;
+ } else if (String_eq(option[0], "eth1_alias")) {
+ strcpy(this->eth1_alias,option[1]);
+ didReadMeters = true;
+ } else if (String_eq(option[0], "wlan0_alias")) {
+ strcpy(this->wlan0_alias,option[1]);
+ didReadMeters = true;
+ } else if (String_eq(option[0], "wlan1_alias")) {
+ strcpy(this->wlan1_alias,option[1]);
+ didReadMeters = true;
+ }
+
String_freeArray(option);
}
fclose(fd);
@@ -320,6 +382,23 @@ bool Settings_write(Settings* this) {
fprintf(fd, "left_meter_modes="); writeMeterModes(this, fd, 0);
fprintf(fd, "right_meters="); writeMeters(this, fd, 1);
fprintf(fd, "right_meter_modes="); writeMeterModes(this, fd, 1);
+
+ fprintf(fd, "# SBC hardware and Kernel specific path.\n");
+ fprintf(fd, "# Editable manually.\n");
+ fprintf(fd, "BoardName=%s\n", this->BoardName);
+ fprintf(fd, "CpuFreq_handler=%s\n", this->CpuFreq_handler);
+ fprintf(fd, "CpuTemp_handler=%s\n", this->CpuTemp_handler);
+ fprintf(fd, "CpuVCore_l_handler=%s\n", this->CpuVCore_l_handler);
+ fprintf(fd, "CpuVCore_b_handler=%s\n", this->CpuVCore_b_handler);
+ fprintf(fd, "GpuVCore_handler=%s\n", this->GpuVCore_handler);
+ fprintf(fd, "GpuTemp_handler=%s\n", this->GpuTemp_handler);
+
+ fprintf(fd, "# Wlan / Eth alias\n");
+ fprintf(fd, "eth0_alias=%s\n",this->eth0_alias);
+ fprintf(fd, "eth1_alias=%s\n",this->eth1_alias);
+ fprintf(fd, "wlan0_alias=%s\n",this->wlan0_alias);
+ fprintf(fd, "wlan1_alias=%s\n",this->wlan1_alias);
+
fclose(fd);
return true;
}
diff --git a/Settings.h b/Settings.h
index d9dc068..4fcd885 100644
--- a/Settings.h
+++ b/Settings.h
@@ -50,6 +50,28 @@ typedef struct Settings_ {
bool accountGuestInCPUMeter;
bool headerMargin;
+ char CpuFreq_handler[256];
+ char CpuTemp_handler[256];
+ char CpuVCore_l_handler[256];
+ char CpuVCore_b_handler[256];
+
+ char GpuVCore_handler[256];
+ char GpuTemp_handler[256];
+
+ char BoardName[128];
+ char KernelVersionFull[256];
+ char KernelVersionShort[64];
+
+ char IP_wlan0[32];
+ char IP_wlan1[32];
+ char IP_eth0[32];
+ char IP_eth1[32];
+
+ char eth0_alias[32];
+ char eth1_alias[32];
+ char wlan0_alias[32];
+ char wlan1_alias[32];
+
bool changed;
} Settings;
diff --git a/Wlan0_Meter.c b/Wlan0_Meter.c
new file mode 100644
index 0000000..bf75623
--- /dev/null
+++ b/Wlan0_Meter.c
@@ -0,0 +1,58 @@
+/*
+htop - Wlan0_Meter.c
+(C) 2020 @lex
+*/
+
+#include "Wlan0_Meter.h"
+#include "Platform.h"
+#include "CRT.h"
+
+/*{
+#include "Meter.h"
+}*/
+
+
+int Wlan0_Meter_attributes[] = {
+ WLAN0_INTERFACE
+};
+
+static void Wlan0_Meter_setValues(Meter* this, char* buffer, int len) {
+ int ret;
+ static char szIP[48];
+ static unsigned int use_cached = 0;
+ Settings* settings = this->pl->settings;
+
+ if ((use_cached++ % 2)) {
+ xSnprintf(buffer, len, "%s", szIP);
+ return;
+ }
+
+ if (settings->wlan0_alias[0] != 0) {
+ ret = findIP_interface(settings->wlan0_alias, szIP, sizeof(szIP));
+ } else {
+ ret = findIP_interface("wlan0", szIP, sizeof(szIP));
+ }
+
+ if (ret) {
+ xSnprintf(buffer, len, "%s", szIP);
+ } else {
+ xSnprintf(buffer, len, "%s", "down");
+ }
+}
+
+MeterClass Wlan0_Meter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = Wlan0_Meter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 8,
+ .total = 100.0,
+ .attributes = Wlan0_Meter_attributes,
+ .name = "Wlan0",
+ .uiName = "Wlan0 IP",
+ .caption = "Wlan0 IP: ",
+};
+
+
diff --git a/Wlan0_Meter.h b/Wlan0_Meter.h
new file mode 100644
index 0000000..59761ff
--- /dev/null
+++ b/Wlan0_Meter.h
@@ -0,0 +1,17 @@
+/* Do not edit this file. It was automatically generated. */
+
+#ifndef HEADER_Wlan0_Meter
+#define HEADER_Wlan0_Meter
+/*
+htop - Wlan0_Meter.h
+(C) 2020 @lex
+*/
+
+#include "Meter.h"
+
+extern int Wlan0_Meter_attributes[];
+
+extern MeterClass Wlan0_Meter_class;
+
+
+#endif
diff --git a/Wlan0_StatsMeter.c b/Wlan0_StatsMeter.c
new file mode 100644
index 0000000..f920f9c
--- /dev/null
+++ b/Wlan0_StatsMeter.c
@@ -0,0 +1,83 @@
+/*
+htop - Wlan0_StatsMeter.c
+(C) 2020 @lex
+*/
+
+#include "Wlan0_StatsMeter.h"
+#include "Platform.h"
+#include "CRT.h"
+
+#include "interfaces.h"
+
+/*{
+#include "Meter.h"
+}*/
+
+
+int Wlan0_StatsMeter_attributes[] = {
+ ETH0_INTERFACE
+};
+
+/* borrowed from slurm */
+static void Wlan0_StatsMeter_setValues(Meter* this, char* buffer, int len) {
+ int ret;
+ float rxspeed;
+ float txspeed;
+ Settings* settings = this->pl->settings;
+ double refreshdelay;
+ static double old = 0.;
+ static double now = 0.;
+ static int flash = 0;
+
+ now = get_wall_time();
+ refreshdelay = now - old;
+ if (old == 0.)
+ refreshdelay = 1.;
+ old = now;
+
+ if (settings->wlan0_alias[0] != 0) {
+ ret = Platform_getEth_stats(settings->wlan0_alias, 2, 0);
+ } else {
+ ret = Platform_getEth_stats("wlan0", 0, 0);
+ }
+
+ if (ret) {
+ if (Platform_Wlan0_stats.rx_bytes_comp > Platform_Wlan0_stats.rx_bytes)
+ Platform_Wlan0_stats.rx_bytes_comp = 0;
+ if (Platform_Wlan0_stats.tx_bytes_comp > Platform_Wlan0_stats.tx_bytes)
+ Platform_Wlan0_stats.tx_bytes_comp = 0;
+
+ /* we assume here the refresdelay is 1 sec which sometimes is 1.5, so we have a peak */
+ rxspeed = (Platform_Wlan0_stats.rx_bytes - Platform_Wlan0_stats.rx_bytes_comp) / refreshdelay;
+ txspeed = (Platform_Wlan0_stats.tx_bytes - Platform_Wlan0_stats.tx_bytes_comp) / refreshdelay;
+
+ xSnprintf(buffer, len, "%.2f KB/s - %.2f KB/s (TX/RX)", (float) txspeed / 1024, (float) rxspeed / 1024);
+
+ Platform_Wlan0_stats.rx_bytes_comp = Platform_Wlan0_stats.rx_bytes;
+ Platform_Wlan0_stats.tx_bytes_comp = Platform_Wlan0_stats.tx_bytes;
+
+ } else {
+ if (!(flash % 2))
+ xSnprintf(buffer, len, "%s", "unavail");
+ else
+ xSnprintf(buffer, len, "%s", "");
+ flash++;
+ }
+}
+
+MeterClass Wlan0_StatsMeter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = Wlan0_StatsMeter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 8,
+ .total = 100.0,
+ .attributes = Wlan0_StatsMeter_attributes,
+ .name = "Wlan0stat",
+ .uiName = "Wlan0 stat",
+ .caption = "Wlan0 stat: ",
+};
+
+
diff --git a/Wlan0_StatsMeter.h b/Wlan0_StatsMeter.h
new file mode 100644
index 0000000..2880f9d
--- /dev/null
+++ b/Wlan0_StatsMeter.h
@@ -0,0 +1,18 @@
+/* Do not edit this file. It was automatically generated. */
+
+#ifndef HEADER_Wlan0_StatsMeter
+#define HEADER_Wlan0_StatsMeter
+/*
+htop - Wlan0_StatsMeter.h
+(C) 2020 @lex
+*/
+
+#include "Meter.h"
+
+extern int Wlan0_StatsMeter_attributes[];
+
+/* borrowed from slurm */
+extern MeterClass Wlan0_StatsMeter_class;
+
+
+#endif
diff --git a/Wlan1_Meter.c b/Wlan1_Meter.c
new file mode 100644
index 0000000..c5acd69
--- /dev/null
+++ b/Wlan1_Meter.c
@@ -0,0 +1,60 @@
+/*
+htop - Eth0_Meter.c
+(C) 2018 @lex
+*/
+
+#include "Wlan1_Meter.h"
+#include "Platform.h"
+#include "CRT.h"
+
+#include "interfaces.h"
+
+/*{
+#include "Meter.h"
+}*/
+
+
+int Wlan1_Meter_attributes[] = {
+ WLAN1_INTERFACE
+};
+
+static void Wlan1_Meter_setValues(Meter* this, char* buffer, int len) {
+ int ret;
+ static char szIP[48];
+ static unsigned int use_cached = 0;
+ Settings* settings = this->pl->settings;
+
+ if ((use_cached++ % 2)) {
+ xSnprintf(buffer, len, "%s", szIP);
+ return;
+ }
+
+ if (settings->wlan1_alias[0] != 0) {
+ ret = findIP_interface(settings->wlan1_alias, szIP, sizeof(szIP));
+ } else {
+ ret = findIP_interface("wlan1", szIP, sizeof(szIP));
+ }
+
+ if (ret) {
+ xSnprintf(buffer, len, "%s", szIP);
+ } else {
+ xSnprintf(buffer, len, "%s", "down");
+ }
+}
+
+MeterClass Wlan1_Meter_class = {
+ .super = {
+ .extends = Class(Meter),
+ .delete = Meter_delete
+ },
+ .updateValues = Wlan1_Meter_setValues,
+ .defaultMode = TEXT_METERMODE,
+ .maxItems = 8,
+ .total = 100.0,
+ .attributes = Wlan1_Meter_attributes,
+ .name = "Wlan1",
+ .uiName = "Wlan1 IP",
+ .caption = "Wlan1 IP: ",
+};
+
+
diff --git a/Wlan1_Meter.h b/Wlan1_Meter.h
new file mode 100644
index 0000000..4bba228
--- /dev/null
+++ b/Wlan1_Meter.h
@@ -0,0 +1,17 @@
+/* Do not edit this file. It was automatically generated. */
+
+#ifndef HEADER_Wlan1_Meter
+#define HEADER_Wlan1_Meter
+/*
+htop - Eth0_Meter.h
+(C) 2018 @lex
+*/
+
+#include "Meter.h"
+
+extern int Wlan1_Meter_attributes[];
+
+extern MeterClass Wlan1_Meter_class;
+
+
+#endif
diff --git a/htop.c b/htop.c
index 6db81dd..0044eb8 100644
--- a/htop.c
+++ b/htop.c
@@ -1,6 +1,7 @@
/*
htop - htop.c
(C) 2004-2011 Hisham H. Muhammad
+(C) 2020 Alexander Finger
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
@@ -170,7 +171,6 @@ static void millisleep(unsigned long millisec) {
}
int main(int argc, char** argv) {
-
char *lc_ctype = getenv("LC_CTYPE");
if(lc_ctype != NULL)
setlocale(LC_CTYPE, lc_ctype);
@@ -193,6 +193,8 @@ int main(int argc, char** argv) {
UsersTable* ut = UsersTable_new();
ProcessList* pl = ProcessList_new(ut, flags.pidWhiteList, flags.userId);
+ Platform_findCpuBigLITTLE(pl->cpuCount, &pl->cpuBigLITTLE);
+
Settings* settings = Settings_new(pl->cpuCount);
pl->settings = settings;
@@ -243,7 +245,16 @@ int main(int argc, char** argv) {
mvhline(LINES-1, 0, ' ', COLS);
attroff(CRT_colors[RESET_COLOR]);
refresh();
-
+
+ Platform_getEth_stats("", -1, 1);
+ Platform_getIO_stats("", 0, 1);
+ Platform_getIO_stats("", 1, 1);
+ Platform_getIO_stats("", 2, 1);
+ Platform_getIO_stats("", 3, 1);
+ Platform_getIO_stats("", 4, 1);
+ Platform_getIO_stats("", 5, 1);
+ Platform_getIO_stats("", 6, 1);
+ Platform_getIO_stats("", 7, 1);
CRT_done();
if (settings->changed)
Settings_write(settings);
diff --git a/htop.h b/htop.h
index 7faa6c6..05d5fd4 100644
--- a/htop.h
+++ b/htop.h
@@ -5,6 +5,7 @@
/*
htop - htop.h
(C) 2004-2011 Hisham H. Muhammad
+(C) 2020 Alexander Finger
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
diff --git a/interfaces.c b/interfaces.c
new file mode 100644
index 0000000..aa41d2a
--- /dev/null
+++ b/interfaces.c
@@ -0,0 +1,206 @@
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <linux/i2c-dev.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <ifaddrs.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <linux/if_link.h>
+#include <linux/if.h>
+#include <signal.h>
+
+#include "interfaces.h"
+#include "Settings.h"
+
+#define BLEN 256
+/*
+ /etc/armbian-release
+ VERSION=20.02.1
+
+ /etc/debian_version
+ buster/sid
+
+ cat /etc/lsb-release
+ DISTRIB_DESCRIPTION="Ubuntu 18.04.5 LTS"
+
+ cat /etc/os-release
+ PRETTY_NAME="Ubuntu 18.04.5 LTS"
+ VERSION="18.04.5 LTS (Bionic Beaver)"
+ ID=ubuntu
+
+ cat /proc/version
+ Linux version 5.3.0-52-generic (buildd@lgw01-amd64-037) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #46~18.04.1-Ubuntu SMP Thu Apr 30 16:13:51 UTC 2020
+*/
+
+
+int ReadKeyValue( char *fname, char *key, char *value) {
+ FILE* fp;
+ char buffer[BLEN];
+ int fd = 0;
+ int len = strlen(key);
+ char *str;
+ char *str_end;
+
+ fp = fopen(fname, "r");
+ if (fp == NULL)
+ return fd;
+
+ while (fgets(buffer, BLEN, fp) != NULL) {
+ str = strstr(buffer, key);
+ if (str != NULL) {
+ fd = 1;
+ str += len;
+ if (*str == '\"') {
+ str++;
+ len = strlen(str);
+ str_end = str + len;
+ while (*str_end != '\"') {
+ *str_end = 0;
+ str_end--;
+ if (str_end == str)
+ break;
+ }
+ *str_end = 0;
+ strcpy(value, str);
+ fd = 1;
+ } else {
+ strcpy(value, str);
+ fd = 1;
+ }
+ }
+ }
+ fclose(fp);
+ return fd;
+}
+
+int ReadTokenValue( char *fname, char *key, char *value) {
+ FILE* fp;
+ char buffer[BLEN];
+ int fd = 0;
+ int len = strlen(key);
+ char *str;
+ char *str_end;
+
+ fp = fopen(fname, "r");
+ if (fp == NULL)
+ return fd;
+
+ while (fgets(buffer, BLEN, fp) != NULL) {
+ str = strstr(buffer, key);
+ if (str != NULL) {
+ fd = 1;
+ str += len;
+ str++;
+ str_end = str;
+ while (*str_end != ' ' && *str_end != 0) {
+ str_end++;
+ }
+ *str_end = 0;
+ strcpy(value, str);
+ fd = 1;
+ }
+ }
+ fclose(fp);
+ return fd;
+}
+
+char *ltrim(char *str) {
+ while(isspace(*str))
+ str++;
+ return str;
+}
+
+char *rtrim(char *str) {
+ char* end = str + strlen(str);
+ while (isspace(*--end))
+ ;
+ *(end + 1) = '\0';
+ return str;
+}
+
+char *trim(char *str) {
+ return rtrim(ltrim(str));
+}
+
+int FindDataValueFromKey( char *fname, char *key, char *value) {
+ FILE* fp;
+ char buffer[BLEN];
+ int fd = 0;
+ char *str;
+ char *str_end;
+ char *str_start;
+
+ fp = fopen(fname, "r");
+ if (fp == NULL)
+ return fd;
+
+ while (fgets(buffer, BLEN, fp) != NULL) {
+ str_start = buffer;
+ str_end = strchr(buffer, ':');
+ if (str_end != NULL) {
+ *str_end = 0;
+ str_start = trim(str_start);
+ if (strcasecmp(str_start, key) == 0) {
+ str = str_end + 1;
+ str = trim(str);
+ strcpy(value, str);
+ printf("key: %s, value: %s\n", str_start, str);
+ fd = 1;
+ break;
+ }
+ }
+ }
+ fclose(fp);
+ return fd;
+}
+
+
+int findIP_interface(char *dev, char *szIP, int bufsz) {
+ struct ifaddrs *ifaddr, *ifa;
+ int family, s, n;
+ char host[NI_MAXHOST];
+ int found_if = 0;
+ int len = strlen(dev);
+
+ /* get interface information */
+ if (getifaddrs(&ifaddr) != -1) {
+ for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
+ if (ifa->ifa_addr == NULL)
+ continue;
+
+ family = ifa->ifa_addr->sa_family;
+ if ((strncmp (dev, ifa->ifa_name, len ) == 0) && (family == AF_INET || family == AF_INET6)) {
+ s = getnameinfo(ifa->ifa_addr,
+ (ifa->ifa_addr->sa_family == AF_INET) ? sizeof(struct sockaddr_in) :
+ sizeof(struct sockaddr_in6),
+ host, NI_MAXHOST,
+ NULL, 0, NI_NUMERICHOST);
+ if (s != 0) {
+ break;
+ }
+ if ((ifa->ifa_flags & IFF_UP) == 0)
+ continue;
+ if ((ifa->ifa_flags & IFF_RUNNING) == 0)
+ continue;
+ found_if = 1;
+ break;
+ }
+ }
+ if (found_if) {
+ snprintf ( szIP, bufsz, "%s", host );
+ }
+ freeifaddrs(ifaddr);
+ }
+ return found_if;
+}
diff --git a/interfaces.h b/interfaces.h
new file mode 100644
index 0000000..adb4e5b
--- /dev/null
+++ b/interfaces.h
@@ -0,0 +1,40 @@
+/* Do not edit this file. It was automatically generated. */
+
+#ifndef HEADER_interfaces
+#define HEADER_interfaces
+
+#define BLEN 256
+/*
+ /etc/armbian-release
+ VERSION=20.02.1
+
+ /etc/debian_version
+ buster/sid
+
+ cat /etc/lsb-release
+ DISTRIB_DESCRIPTION="Ubuntu 18.04.5 LTS"
+
+ cat /etc/os-release
+ PRETTY_NAME="Ubuntu 18.04.5 LTS"
+ VERSION="18.04.5 LTS (Bionic Beaver)"
+ ID=ubuntu
+
+ cat /proc/version
+ Linux version 5.3.0-52-generic (buildd@lgw01-amd64-037) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #46~18.04.1-Ubuntu SMP Thu Apr 30 16:13:51 UTC 2020
+*/
+
+int ReadKeyValue( char *fname, char *key, char *value);
+
+int ReadTokenValue( char *fname, char *key, char *value);
+
+char *ltrim(char *str);
+
+char *rtrim(char *str);
+
+char *trim(char *str);
+
+int FindDataValueFromKey( char *fname, char *key, char *value);
+
+int findIP_interface(char *dev, char *szIP, int bufsz);
+
+#endif
diff --git a/linux/Platform.c b/linux/Platform.c
index ab90ca7..e87089c 100644
--- a/linux/Platform.c
+++ b/linux/Platform.c
@@ -1,6 +1,7 @@
/*
htop - linux/Platform.c
(C) 2014 Hisham H. Muhammad
+(C) 2020 Alexander Finger
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
@@ -14,6 +15,21 @@ in the source distribution for its full text.
#include "Meter.h"
#include "CPUMeter.h"
+#include "CpuFreqMeter.h"
+#include "CpuTempMeter.h"
+#include "GpuTempMeter.h"
+#include "CpuVcoreMeter.h"
+#include "Eth0_StatsMeter.h"
+#include "Eth1_StatsMeter.h"
+#include "Wlan0_StatsMeter.h"
+#include "BlockDevice_ioStatsMeter.h"
+#include "Eth0_Meter.h"
+#include "Eth1_Meter.h"
+#include "Wlan0_Meter.h"
+#include "Wlan1_Meter.h"
+#include "Armbian_Meter.h"
+#include "OS_Meter.h"
+#include "Kernel_Meter.h"
#include "MemoryMeter.h"
#include "SwapMeter.h"
#include "TasksMeter.h"
@@ -22,12 +38,23 @@ in the source distribution for its full text.
#include "ClockMeter.h"
#include "HostnameMeter.h"
#include "LinuxProcess.h"
+#include "Settings.h"
+#include "interfaces.h"
+
+#ifdef WIN32
+#include <windows.h>
+#elif _POSIX_C_SOURCE >= 199309L
+#include <time.h> /* for nanosleep */
+#else
+#include <unistd.h> /* for usleep */
+#endif
#include <math.h>
#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
+#include <sys/time.h>
/*{
#include "Action.h"
@@ -35,6 +62,50 @@ in the source distribution for its full text.
#include "BatteryMeter.h"
#include "LinuxProcess.h"
#include "SignalsPanel.h"
+#ifdef WIN32
+#include <windows.h>
+#elif _POSIX_C_SOURCE >= 199309L
+#include <time.h>
+#else
+#include <unistd.h>
+#endif
+#include <string.h>
+
+
+typedef enum vendor_id_ {
+ VENDOR_INTEL,
+ VENDOR_AMD,
+ VENDOR_CYRIX,
+ VENDOR_VIA,
+ VENDOR_TRANSMETA,
+ VENDOR_UMC,
+ VENDOR_NEXGEN,
+ VENDOR_RISE,
+ VENDOR_SIS,
+ VENDOR_NSC,
+ VENDOR_VORTEX,
+ VENDOR_RDC,
+ VENDOR_UNKNOWN
+} vendor_id;
+
+typedef struct Stats_ {
+ int rx_over;
+ int tx_over;
+ double rx_bytes;
+ double tx_bytes;
+ double rx_bytes_comp;
+ double tx_bytes_comp;
+} Stats;
+
+typedef struct ioStats_ {
+ int read_over;
+ int write_over;
+ double read_sectors;
+ double write_sectors;
+ double read_sectors_comp;
+ double write_sectors_comp;
+} ioStats;
+
}*/
#ifndef CLAMP
@@ -45,6 +116,7 @@ ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_SIZE, M_R
//static ProcessField defaultIoFields[] = { PID, IO_PRIORITY, USER, IO_READ_RATE, IO_WRITE_RATE, IO_RATE, COMM, 0 };
+int Platform_cpuBigLITTLE = 0;
int Platform_numberOfFields = LAST_PROCESSFIELD;
const SignalItem Platform_signals[] = {
@@ -126,9 +198,270 @@ MeterClass* Platform_meterTypes[] = {
&LeftCPUs2Meter_class,
&RightCPUs2Meter_class,
&BlankMeter_class,
+ &CpuTempMeter_class,
+ &CpuFreqMeter_class,
+ /* --- fix me --- &AllCpuFreqMeter_class, */
+ &CpuVcoreMeter_class,
+ &GpuTempMeter_class,
+ /* interfaces */
+ &Eth0_Meter_class,
+ &Eth1_Meter_class,
+ &Wlan0_Meter_class,
+ &Wlan0_StatsMeter_class,
+ &Wlan1_Meter_class,
+ &OSversion_Meter_class,
+ &Kernelversion_Meter_class,
+ &Armbianversion_Meter_class,
+ &Eth0_StatsMeter_class,
+ &Eth1_StatsMeter_class,
+ &BlockDevice_sda_ioStatsMeter_class,
+ &BlockDevice_sdb_ioStatsMeter_class,
+ &BlockDevice_sdc_ioStatsMeter_class,
+ &BlockDevice_sdd_ioStatsMeter_class,
+ &BlockDevice_mmcblk0_ioStatsMeter_class,
+ &BlockDevice_mmcblk1_ioStatsMeter_class,
+ &BlockDevice_mmcblk2_ioStatsMeter_class,
+ &BlockDevice_mmcblk3_ioStatsMeter_class,
NULL
};
+/* cross-platform sleep function */
+void sleep_ms(int milliseconds) {
+#ifdef WIN32
+ Sleep(milliseconds);
+#elif _POSIX_C_SOURCE >= 199309L
+ struct timespec ts;
+ ts.tv_sec = milliseconds / 1000;
+ ts.tv_nsec = (milliseconds % 1000) * 1000000;
+ nanosleep(&ts, NULL);
+#else
+ usleep(milliseconds * 1000);
+#endif
+}
+
+int Platform_getGpuTemp(Meter* this) {
+ int Temp = 0;
+ char szbuf[256];
+ Settings* settings = this->pl->settings;
+ char *handler;
+ char *cpu_core_policy;
+
+ handler = settings->GpuTemp_handler;
+ if (handler[0] != 0) {
+ cpu_core_policy = strchr(handler, '%');
+ if (cpu_core_policy) {
+ xSnprintf(szbuf, sizeof(szbuf), "%s", "/sys/class/thermal/thermal_zone1/temp");
+ } else {
+ xSnprintf(szbuf, sizeof(szbuf), "%s", handler);
+ }
+ } else {
+ xSnprintf(szbuf, sizeof(szbuf), "%s", "/sys/class/thermal/thermal_zone1/temp");
+ }
+
+ FILE* fd = fopen(szbuf, "r");
+ if (!fd) {
+ fd = fopen("/sys/devices/virtual/thermal/thermal_zone1/temp", "r");
+ }
+ if (fd) {
+ int n = fscanf(fd, "%d", &Temp);
+ fclose(fd);
+ if (n <= 0) return 0;
+ }
+ return Temp;
+}
+
+int Platform_getCpuTemp(Meter* this) {
+ int Temp = 0;
+ char szbuf[256];
+ Settings* settings = this->pl->settings;
+ char *handler;
+ char *cpu_core_policy;
+
+ handler = settings->CpuTemp_handler;
+ if (handler[0] != 0) {
+ cpu_core_policy = strchr(handler, '%');
+ if (cpu_core_policy) {
+ xSnprintf(szbuf, sizeof(szbuf), "%s", "/sys/class/thermal/thermal_zone0/temp");
+ } else {
+ xSnprintf(szbuf, sizeof(szbuf), "%s", handler);
+ }
+ } else {
+ // sleep_ms(30);
+ // xSnprintf(szbuf, sizeof(szbuf), "/sys/devices/system/cpu/cpufreq/policy%d/cpuinfo_cur_freq", cpu);
+ xSnprintf(szbuf, sizeof(szbuf), "%s", "/sys/class/thermal/thermal_zone0/temp");
+ }
+ FILE *fd = fopen(szbuf, "r");
+ if (!fd) {
+ fd = fopen("/sys/devices/virtual/thermal/thermal_zone0/temp", "r");
+ }
+ if (fd) {
+ int n = fscanf(fd, "%d", &Temp);
+ fclose(fd);
+ if (n <= 0) return 0;
+ }
+ return Temp;
+}
+
+int Platform_getCpuFreq(Meter* this, int cpu) {
+ int Freq = 0;
+ FILE* fd;
+ char szbuf[256];
+ Settings* settings = this->pl->settings;
+ char *handler;
+ char *cpu_core_policy;
+
+ handler = settings->CpuFreq_handler;
+ if (handler[0] != 0) {
+ cpu_core_policy = strchr(handler, '%');
+ if (cpu_core_policy) {
+ xSnprintf(szbuf, sizeof(szbuf), handler, cpu);
+ } else {
+ xSnprintf(szbuf, sizeof(szbuf), "%s", handler);
+ }
+ } else {
+ // sleep_ms(30);
+ // xSnprintf(szbuf, sizeof(szbuf), "/sys/devices/system/cpu/cpufreq/policy%d/cpuinfo_cur_freq", cpu);
+ xSnprintf(szbuf, sizeof(szbuf), "%s", "/sys/devices/system/cpu/cpufreq/policy0/cpuinfo_cur_freq");
+ }
+ fd = fopen(szbuf, "r");
+ if (fd) {
+ int n;
+ n = fscanf(fd, "%d", &Freq);
+ fclose(fd);
+ if (n <= 0) return 0;
+ }
+ return Freq;
+}
+
+int Platform_getCpuVcore(Meter* this) {
+ int Vcore = 0;
+ FILE* fd;
+ char szbuf[256];
+ Settings* settings = this->pl->settings;
+ char *handler;
+ char *cpu_core_policy;
+ handler = settings->CpuVCore_l_handler;
+ if (handler[0] != 0) {
+ cpu_core_policy = strchr(handler, '%');
+ if (cpu_core_policy) {
+ xSnprintf(szbuf, sizeof(szbuf), "%s", "/sys/devices/platform/ff3c0000.i2c/i2c-0/0-001b/regulator/regulator.13/microvolts");
+ } else {
+ xSnprintf(szbuf, sizeof(szbuf), "%s", handler);
+ }
+ } else {
+ xSnprintf(szbuf, sizeof(szbuf), "%s", "/sys/devices/platform/ff3c0000.i2c/i2c-0/0-001b/regulator/regulator.13/microvolts");
+ }
+
+ // sleep_ms(10);
+ fd = fopen(szbuf, "r");
+ if (fd) {
+ int n;
+ n = fscanf(fd, "%d", &Vcore);
+ fclose(fd);
+ if (n <= 0) return 0;
+ }
+ return Vcore;
+}
+
+int Platform_getCpuVcore_l(Meter* this) {
+ int Vcore = 0;
+ FILE* fd;
+ char szbuf[256];
+ Settings* settings = this->pl->settings;
+ char *handler;
+ char *cpu_core_policy;
+ handler = settings->CpuVCore_l_handler;
+ if (handler[0] != 0) {
+ cpu_core_policy = strchr(handler, '%');
+ if (cpu_core_policy) {
+ strcpy(szbuf, "/sys/devices/platform/ff3c0000.i2c/i2c-0/0-001b/regulator/regulator.13/microvolts");
+ } else {
+ strcpy(szbuf, handler);
+ }
+ } else {
+ strcpy(szbuf, "/sys/devices/platform/ff3c0000.i2c/i2c-0/0-001b/regulator/regulator.13/microvolts");
+ }
+
+ // sleep_ms(10);
+ fd = fopen(szbuf, "r");
+ if (fd) {
+ int n;
+ n = fscanf(fd, "%d", &Vcore);
+ fclose(fd);
+ if (n <= 0) return 0;
+ }
+ return Vcore;
+}
+
+int Platform_getCpuVcore_b(Meter* this) {
+ int Vcore = 0;
+ FILE* fd;
+ char szbuf[256];
+ Settings* settings = this->pl->settings;
+ char *handler;
+ char *cpu_core_policy;
+ handler = settings->CpuVCore_b_handler;
+ if (handler[0] != 0) {
+ cpu_core_policy = strchr(handler, '%');
+ if (cpu_core_policy) {
+ strcpy(szbuf, "/sys/devices/platform/ff3c0000.i2c/i2c-0/0-0040/regulator/regulator.10/microvolts");
+ } else {
+ strcpy(szbuf, handler);
+ }
+ } else {
+ strcpy(szbuf, "/sys/devices/platform/ff3c0000.i2c/i2c-0/0-0040/regulator/regulator.10/microvolts");
+ }
+ // sleep_ms(10);
+ fd = fopen(szbuf, "r");
+ if (fd) {
+ int n;
+ n = fscanf(fd, "%d", &Vcore);
+ fclose(fd);
+ if (n <= 0) return 0;
+ }
+ return Vcore;
+}
+
+
+int Platform_getCpuBigLITTLE() {
+ return Platform_cpuBigLITTLE;
+}
+
+int Platform_findCpuBigLITTLE(int cpucount, int *cpuBigLITTLE) {
+ char buf[256];
+ int n, prev, next;
+ FILE* fd;
+
+ *cpuBigLITTLE = 0;
+ prev = next = -1;
+ int cpu = 0;
+ while (cpu < cpucount) {
+ xSnprintf(buf, sizeof(buf), "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", cpu);
+ fd = fopen(buf, "r");
+ if (fd) {
+ n = fscanf(fd, "%d", &next);
+ fclose(fd);
+ if (n <= 0)
+ break;
+ if (prev == -1) {
+ prev = next;
+ } else {
+ if (prev != next) {
+ if (prev < next) {
+ Platform_cpuBigLITTLE = cpu;
+ } else {
+ Platform_cpuBigLITTLE = cpu * -1; /* fix me */
+ }
+ *cpuBigLITTLE = Platform_cpuBigLITTLE;
+ break;
+ }
+ }
+ }
+ cpu++;
+ }
+ return cpu;
+}
+
int Platform_getUptime() {
double uptime = 0;
FILE* fd = fopen(PROCDIR "/uptime", "r");
@@ -237,3 +570,177 @@ char* Platform_getProcessEnv(pid_t pid) {
}
return env;
}
+
+Stats Platform_Eth0_stats;
+Stats Platform_Eth1_stats;
+Stats Platform_Wlan0_stats;
+
+int Platform_getEth_stats(char *devname, int id, int close_fp) {
+ char buffer[BLEN];
+ char *str;
+ char *str_end;
+ char *str_start;
+ unsigned long dump;
+ int ifound;
+ unsigned long rx_o, tx_o;
+ Stats *Platform_Eth_stats;
+ static FILE *fp_proc_net_dev = NULL;
+
+ if (close_fp) {
+ if (fp_proc_net_dev)
+ fclose(fp_proc_net_dev);
+ return 0;
+ }
+
+ if (fp_proc_net_dev == NULL) {
+ if ((fp_proc_net_dev = fopen("/proc/net/dev", "r")) == NULL) {
+ return 0;
+ }
+ }
+ if (id == 0) {
+ Platform_Eth_stats = &Platform_Eth0_stats;
+ } else {
+ if (id == 1) {
+ Platform_Eth_stats = &Platform_Eth1_stats;
+ } else {
+ Platform_Eth_stats = &Platform_Wlan0_stats;
+ }
+ }
+
+ /* save rx/tx values */
+ rx_o = Platform_Eth_stats->rx_bytes;
+ tx_o = Platform_Eth_stats->tx_bytes;
+
+ /* do not parse the first two lines as they only contain static garbage */
+ fseek(fp_proc_net_dev, 0, SEEK_SET);
+ fgets(buffer, BLEN, fp_proc_net_dev);
+ fgets(buffer, BLEN, fp_proc_net_dev);
+
+ ifound = 0;
+ while (fgets(buffer, BLEN, fp_proc_net_dev) != NULL) {
+ str_start = buffer;
+ str_end = strchr(buffer, ':');
+ if (str_end != NULL) {
+ *str_end = 0;
+ str_start = trim(str_start);
+ if (strcasecmp(str_start, devname) == 0) {
+ str = str_end + 1;
+ str = ltrim(str);
+ sscanf(str,
+ "%lg %lu %lu %lu %lu %lu %lu %lu %lg %lu %lu %lu %lu %lu %lu %lu",
+ &Platform_Eth_stats->rx_bytes, &dump, &dump,
+ &dump, &dump, &dump, &dump, &dump, &Platform_Eth_stats->tx_bytes,
+ &dump, &dump, &dump, &dump, &dump, &dump, &dump);
+ ifound = 1;
+ continue;
+ }
+ }
+ }
+ if (ifound) {
+ if (rx_o > Platform_Eth_stats->rx_bytes)
+ Platform_Eth_stats->rx_over++;
+ if (tx_o > Platform_Eth_stats->tx_bytes)
+ Platform_Eth_stats->tx_over++;
+ }
+ return ifound;
+}
+
+double get_wall_time(void) {
+ struct timeval time;
+ if (gettimeofday(&time, NULL))
+ return 0.;
+ return (double) time.tv_sec + (double) time.tv_usec * .000001;
+}
+
+ioStats Platform_BlockDevice_sda_stats;
+ioStats Platform_BlockDevice_sdb_stats;
+ioStats Platform_BlockDevice_sdc_stats;
+ioStats Platform_BlockDevice_sdd_stats;
+ioStats Platform_BlockDevice_mmcblk0_stats;
+ioStats Platform_BlockDevice_mmcblk1_stats;
+ioStats Platform_BlockDevice_mmcblk2_stats;
+ioStats Platform_BlockDevice_mmcblk3_stats;
+
+FILE *fp_block_dev_a[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+
+int Platform_getIO_stats(char *devname, int idx, int close_fp) {
+ char block_device[80] = {0};
+ char buffer[BLEN] = {0};
+ unsigned long dump;
+ unsigned long read_o, write_o;
+ ioStats *Platform_io_stats;
+ FILE *fp_block_dev = NULL;
+
+ if (idx > 7)
+ idx = 0;
+
+ fp_block_dev = fp_block_dev_a[idx];
+
+ if (close_fp) {
+ if (fp_block_dev)
+ fclose(fp_block_dev);
+ return 0;
+ }
+ if (devname && *devname == 0)
+ return 0;
+
+ if (fp_block_dev == NULL) {
+ xSnprintf(block_device, sizeof(block_device), "/sys/block/%s/stat", devname);
+ if ((fp_block_dev = fopen(block_device, "r")) == NULL) {
+ return 0;
+ }
+ fp_block_dev_a[idx] = fp_block_dev;
+ }
+
+ switch(idx) {
+ case 0:
+ Platform_io_stats = &Platform_BlockDevice_sda_stats;
+ break;
+ case 1:
+ Platform_io_stats = &Platform_BlockDevice_sdb_stats;
+ break;
+ case 2:
+ Platform_io_stats = &Platform_BlockDevice_sdc_stats;
+ break;
+ case 3:
+ Platform_io_stats = &Platform_BlockDevice_sdd_stats;
+ break;
+ case 4:
+ Platform_io_stats = &Platform_BlockDevice_mmcblk0_stats;
+ break;
+ case 5:
+ Platform_io_stats = &Platform_BlockDevice_mmcblk1_stats;
+ break;
+ case 6:
+ Platform_io_stats = &Platform_BlockDevice_mmcblk2_stats;
+ break;
+ case 7:
+ Platform_io_stats = &Platform_BlockDevice_mmcblk3_stats;
+ break;
+ default:
+ Platform_io_stats = &Platform_BlockDevice_sda_stats;
+ break;
+ }
+ /* save read/write values */
+ read_o = Platform_io_stats->read_sectors;
+ write_o = Platform_io_stats->write_sectors;
+ fseek(fp_block_dev, 0, SEEK_SET);
+ if (fgets(buffer, BLEN - 1, fp_block_dev) != NULL) {
+ sscanf(buffer,
+ "%lu %lu %lg %lu %lu %lu %lg %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
+ &dump, &dump, &Platform_io_stats->read_sectors, &dump, &dump,
+ &dump, &Platform_io_stats->write_sectors, &dump, &dump, &dump, &dump,
+ &dump, &dump, &dump, &dump, &dump, &dump);
+ } else {
+ return 0;
+ }
+
+ while (fgets(buffer, BLEN - 1, fp_block_dev) != NULL)
+ ;
+
+ if (read_o > Platform_io_stats->read_sectors)
+ Platform_io_stats->read_over++;
+ if (write_o > Platform_io_stats->write_sectors)
+ Platform_io_stats->write_over++;
+ return 1;
+}
diff --git a/linux/Platform.h b/linux/Platform.h
index b0456e5..54dbf80 100644
--- a/linux/Platform.h
+++ b/linux/Platform.h
@@ -5,15 +5,65 @@
/*
htop - linux/Platform.h
(C) 2014 Hisham H. Muhammad
+(C) 2020 Alexander Finger
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
+#ifdef WIN32
+#elif _POSIX_C_SOURCE >= 199309L
+#else
+#endif
+
#include "Action.h"
#include "MainPanel.h"
#include "BatteryMeter.h"
#include "LinuxProcess.h"
#include "SignalsPanel.h"
+#ifdef WIN32
+#include <windows.h>
+#elif _POSIX_C_SOURCE >= 199309L
+#include <time.h>
+#else
+#include <unistd.h>
+#endif
+#include <string.h>
+
+
+typedef enum vendor_id_ {
+ VENDOR_INTEL,
+ VENDOR_AMD,
+ VENDOR_CYRIX,
+ VENDOR_VIA,
+ VENDOR_TRANSMETA,
+ VENDOR_UMC,
+ VENDOR_NEXGEN,
+ VENDOR_RISE,
+ VENDOR_SIS,
+ VENDOR_NSC,
+ VENDOR_VORTEX,
+ VENDOR_RDC,
+ VENDOR_UNKNOWN
+} vendor_id;
+
+typedef struct Stats_ {
+ int rx_over;
+ int tx_over;
+ double rx_bytes;
+ double tx_bytes;
+ double rx_bytes_comp;
+ double tx_bytes_comp;
+} Stats;
+
+typedef struct ioStats_ {
+ int read_over;
+ int write_over;
+ double read_sectors;
+ double write_sectors;
+ double read_sectors_comp;
+ double write_sectors_comp;
+} ioStats;
+
#ifndef CLAMP
#define CLAMP(x,low,high) (((x)>(high))?(high):(((x)<(low))?(low):(x)))
@@ -21,6 +71,7 @@ in the source distribution for its full text.
extern ProcessField Platform_defaultFields[];
+extern int Platform_cpuBigLITTLE;
extern int Platform_numberOfFields;
extern const SignalItem Platform_signals[];
@@ -31,6 +82,25 @@ void Platform_setBindings(Htop_Action* keys);
extern MeterClass* Platform_meterTypes[];
+/* cross-platform sleep function */
+void sleep_ms(int milliseconds);
+
+int Platform_getGpuTemp(Meter* this);
+
+int Platform_getCpuTemp(Meter* this);
+
+int Platform_getCpuFreq(Meter* this, int cpu);
+
+int Platform_getCpuVcore(Meter* this);
+
+int Platform_getCpuVcore_l(Meter* this);
+
+int Platform_getCpuVcore_b(Meter* this);
+
+int Platform_getCpuBigLITTLE();
+
+int Platform_findCpuBigLITTLE(int cpucount, int *cpuBigLITTLE);
+
int Platform_getUptime();
void Platform_getLoadAverage(double* one, double* five, double* fifteen);
@@ -45,4 +115,25 @@ void Platform_setSwapValues(Meter* this);
char* Platform_getProcessEnv(pid_t pid);
+Stats Platform_Eth0_stats;
+Stats Platform_Eth1_stats;
+Stats Platform_Wlan0_stats;
+
+int Platform_getEth_stats(char *devname, int id, int close_fp);
+
+double get_wall_time(void);
+
+ioStats Platform_BlockDevice_sda_stats;
+ioStats Platform_BlockDevice_sdb_stats;
+ioStats Platform_BlockDevice_sdc_stats;
+ioStats Platform_BlockDevice_sdd_stats;
+ioStats Platform_BlockDevice_mmcblk0_stats;
+ioStats Platform_BlockDevice_mmcblk1_stats;
+ioStats Platform_BlockDevice_mmcblk2_stats;
+ioStats Platform_BlockDevice_mmcblk3_stats;
+
+extern FILE *fp_block_dev_a[8];
+
+int Platform_getIO_stats(char *devname, int idx, int close_fp);
+
#endif