hyperoptimized file reading
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
#ifndef LINUXSMARTIE_SYS_H
|
||||
#define LINUXSMARTIE_SYS_H
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SYS_GET_TIME_STR(t) sys_get_time_string((char[16]){0}, 16, t)
|
||||
@@ -20,6 +22,8 @@ struct disk_t {
|
||||
struct network_t {
|
||||
uint32_t download;
|
||||
uint32_t upload;
|
||||
sensor_file_t f_rx;
|
||||
sensor_file_t f_tx;
|
||||
char device[16];
|
||||
};
|
||||
|
||||
@@ -41,8 +45,10 @@ void sys_get_disk(struct disk_t *disk);
|
||||
|
||||
void sys_get_network(struct network_t *network);
|
||||
|
||||
void sys_netdev_detect(struct network_t *network);
|
||||
|
||||
void sys_detect(struct syssensors_t *s, const char *platform);
|
||||
|
||||
void sys_update_sensors(struct syssensors_t *s);
|
||||
void sys_update_sensors(const struct syssensors_t *s);
|
||||
|
||||
#endif // LINUXSMARTIE_SYS_H
|
||||
@@ -2,7 +2,7 @@
|
||||
#define LINUXSMARTIE_UTILS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/types.h> // NOLINT yes its, needed for ssize_t
|
||||
|
||||
#if __STDC_VERSION__ >= 202000L
|
||||
#define C_STD "C23"
|
||||
@@ -22,17 +22,20 @@
|
||||
#define P_BYTES(bytes, start) pretty_bytes((bytes), (start), (char[16]){0}, 16)
|
||||
#define P_NUM(num) pretty_num((num), (char[16]){0}, 16)
|
||||
|
||||
typedef enum {
|
||||
typedef enum : uint8_t {
|
||||
SENSOR_I16,
|
||||
SENSOR_U8,
|
||||
SENSOR_U16,
|
||||
SENSOR_U64,
|
||||
SENSOR_FLOAT,
|
||||
} sensor_type_t;
|
||||
|
||||
typedef struct {
|
||||
char path[256];
|
||||
sensor_type_t type;
|
||||
int fd;
|
||||
void* value;
|
||||
uint32_t divider;
|
||||
sensor_type_t type;
|
||||
} sensor_t;
|
||||
} sensor_file_t;
|
||||
|
||||
int get_instance_lock();
|
||||
|
||||
@@ -46,22 +49,12 @@ char *pretty_bytes(uint64_t bytes, int8_t start_suffix, char *buf, size_t bufsz)
|
||||
|
||||
int get_hwmon_dir(char *path, size_t bufsz);
|
||||
|
||||
ssize_t read_file(const char *dir, const char *file, char *buffer, size_t n);
|
||||
void open_sensor(sensor_file_t* s, const char* dir, const char *file, void* value, uint32_t divider, sensor_type_t type);
|
||||
|
||||
void fast_read_num_u64(const char *dir, const char *file, char *buf, uint64_t *result, uint32_t divider);
|
||||
void fast_read_sensor_into_mem(const sensor_file_t *s, void* val);
|
||||
|
||||
void fast_read_num_u16(const char *dir, const char *file, char *buf, uint16_t *result, uint32_t divider);
|
||||
void fast_read_sensor(const sensor_file_t *s);
|
||||
|
||||
void fast_read_num_u8(const char *dir, const char *file, char *buf, uint8_t *result, uint32_t divider);
|
||||
|
||||
void fast_read_num_i16(const char *dir, const char *file, char *buf, int16_t *result, uint32_t divider);
|
||||
|
||||
void fast_read_num_f(const char *dir, const char *file, char *buf, float *result, uint32_t divider);
|
||||
|
||||
void open_sensor(sensor_t* s, const char* dir, const char *file, void* value, uint32_t divider, sensor_type_t type);
|
||||
|
||||
void fast_read_sensor_i16(const sensor_t *s);
|
||||
|
||||
void close_sensor(const sensor_t* s);
|
||||
void close_sensor(const sensor_file_t* s);
|
||||
|
||||
#endif
|
||||
|
||||
49
src/cpu.c
49
src/cpu.c
@@ -3,10 +3,13 @@
|
||||
#include "utils.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static uint64_t max_energy_range_uj = 0;
|
||||
static sensor_file_t* sensors;
|
||||
static sensor_file_t* cpu_freqs;
|
||||
static constexpr uint64_t max_energy_range_uj = 65532610987;
|
||||
|
||||
void cpu_detect(struct cpu_sensors_t *t, const char *pci_dev) {
|
||||
t->module = unknown;
|
||||
@@ -20,14 +23,34 @@ void cpu_detect(struct cpu_sensors_t *t, const char *pci_dev) {
|
||||
return;
|
||||
}
|
||||
|
||||
static char buf[32];
|
||||
fast_read_num_u64("/sys/class/powercap/intel-rapl:0/", "max_energy_range_uj", buf, &max_energy_range_uj, 1);
|
||||
t->module = read_file(t->hwmon, "/in1_input", nullptr, 0) ? zenpower : k10temp; // if we can read zenpower file then zenpower. idk if this is reliable, we're trying to avoid just reading the name
|
||||
// fast_read_num_u64("/sys/class/powercap/intel-rapl:0/", "max_energy_range_uj", buf, &max_energy_range_uj, 1);
|
||||
// t->module = read_file(t->hwmon, "/in1_input", nullptr, 0) ? zenpower : k10temp; // if we can read zenpower file then zenpower. idk if this is reliable, we're trying to avoid just reading the name
|
||||
t->module = k10temp; // just assume its k10temp until we figure out a better way to detect it
|
||||
applog(LOG_INF, "Detected %d cores, module enum #%d in path %s", t->num_cores, t->module, t->hwmon);
|
||||
|
||||
cpu_freqs = malloc(sizeof(sensor_file_t) * t->num_cores);
|
||||
sensors = malloc(sizeof(sensor_file_t) * (t->module == zenpower ? 4 : 3));
|
||||
|
||||
for (uint8_t i = 0; i < t->num_cores; i++) {
|
||||
char p[128];
|
||||
sprintf(p, "/sys/devices/system/cpu/cpu%d/cpufreq/", i);
|
||||
open_sensor(&cpu_freqs[i], p, "cpuinfo_avg_freq", nullptr, 1000, SENSOR_U64);
|
||||
}
|
||||
|
||||
if (max_energy_range_uj != 0)
|
||||
open_sensor(&sensors[0], "/sys/class/powercap/intel-rapl:0/", "energy_uj", nullptr, 1, SENSOR_U64);
|
||||
|
||||
if (t->module == k10temp) {
|
||||
open_sensor(&sensors[1], t->hwmon, "/temp1_input", &t->tctl, 1000, SENSOR_I16);
|
||||
open_sensor(&sensors[2], t->hwmon, "/temp3_input", &t->tccd1, 1000, SENSOR_I16);
|
||||
} else if (t->module == zenpower) {
|
||||
open_sensor(&sensors[1], t->hwmon, "/temp1_input", &t->tdie, 1000, SENSOR_I16);
|
||||
open_sensor(&sensors[2], t->hwmon, "/temp2_input", &t->tctl, 1000, SENSOR_I16);
|
||||
open_sensor(&sensors[3], t->hwmon, "/temp3_input", &t->tccd1, 1000, SENSOR_I16);
|
||||
}
|
||||
}
|
||||
|
||||
void cpu_update(struct cpu_sensors_t *c) {
|
||||
static char buf[32];
|
||||
struct energy_t {
|
||||
struct timespec ts;
|
||||
uint64_t energy;
|
||||
@@ -40,7 +63,7 @@ void cpu_update(struct cpu_sensors_t *c) {
|
||||
// read power from intel-rapl? works on amd too, btop uses this trick, seems accurate
|
||||
// it tracks with "socket power" in hwinfo on windows, its actually the same thing i had in lcdsmartie
|
||||
clock_gettime(CLOCK_MONOTONIC, &curr.ts);
|
||||
fast_read_num_u64("/sys/class/powercap/intel-rapl:0/", "energy_uj", buf, &curr.energy, 1);
|
||||
fast_read_sensor_into_mem(&sensors[0], &curr.energy);
|
||||
|
||||
if (curr.energy >= prev.energy)
|
||||
energy_delta = curr.energy - prev.energy;
|
||||
@@ -56,11 +79,9 @@ void cpu_update(struct cpu_sensors_t *c) {
|
||||
|
||||
// lots of reads but still faster than reading /proc/cpuinfo
|
||||
c->avg_freq = 0;
|
||||
char p[128];
|
||||
for (uint8_t i = 0; i < c->num_cores; i++) {
|
||||
uint64_t t = 0;
|
||||
sprintf(p, "/sys/devices/system/cpu/cpu%d/cpufreq/", i);
|
||||
fast_read_num_u64(p, "cpuinfo_avg_freq", buf, &t, 1000);
|
||||
fast_read_sensor_into_mem(&cpu_freqs[i], &t);
|
||||
c->avg_freq += (uint32_t)t;
|
||||
}
|
||||
c->avg_freq /= (c->num_cores > 1) ? c->num_cores : 1;
|
||||
@@ -69,15 +90,15 @@ void cpu_update(struct cpu_sensors_t *c) {
|
||||
return;
|
||||
|
||||
if (c->module == k10temp) {
|
||||
fast_read_num_i16(c->hwmon, "/temp1_input", buf, &c->tctl, 1000);
|
||||
fast_read_num_i16(c->hwmon, "/temp3_input", buf, &c->tccd1, 1000);
|
||||
fast_read_sensor(&sensors[1]);
|
||||
fast_read_sensor(&sensors[2]);
|
||||
}
|
||||
|
||||
// commented out unused values so its faster
|
||||
if (c->module == zenpower) {
|
||||
fast_read_num_i16(c->hwmon, "/temp1_input", buf, &c->tdie, 1000);
|
||||
fast_read_num_i16(c->hwmon, "/temp2_input", buf, &c->tctl, 1000);
|
||||
fast_read_num_i16(c->hwmon, "/temp3_input", buf, &c->tccd1, 1000);
|
||||
fast_read_sensor(&sensors[1]);
|
||||
fast_read_sensor(&sensors[2]);
|
||||
fast_read_sensor(&sensors[3]);
|
||||
// utils::fastReadNum<1000>(c->hwmon + "/in1_input", buf, c->vcore);
|
||||
// utils::fastReadNum<1000>(c->hwmon + "/in2_input", buf, c->vsoc);
|
||||
}
|
||||
|
||||
74
src/gpu.c
74
src/gpu.c
@@ -6,8 +6,16 @@
|
||||
#include "log.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static constexpr char rel_metrics_path[] = "/../../gpu_metrics"; // gpu_metrics path relative to hwmon path
|
||||
static constexpr uint16_t max_metrics_length = 512; // length of the metrics buffer
|
||||
static constexpr uint16_t max_metrics_length = 512; // length of the metrics buffer
|
||||
|
||||
static sensor_file_t* sensors;
|
||||
static int gpu_metrics_fd;
|
||||
|
||||
void gpu_detect(struct gpu_sensors_t *t, const char *pci) {
|
||||
snprintf(t->hwmon, sizeof(t->hwmon), "/sys/bus/pci/devices/%s/hwmon", pci);
|
||||
@@ -19,43 +27,55 @@ void gpu_detect(struct gpu_sensors_t *t, const char *pci) {
|
||||
}
|
||||
|
||||
t->has_gpu_metrics = false;
|
||||
char raw_metrics[max_metrics_length];
|
||||
if (!read_file(t->hwmon, rel_metrics_path, raw_metrics, sizeof(raw_metrics)))
|
||||
return;
|
||||
const struct metrics_table_header *header = (struct metrics_table_header *)raw_metrics;
|
||||
applog(LOG_INF, "Found gpu_metrics_v%d_%d", header->format_revision, header->content_revision);
|
||||
t->has_gpu_metrics = true;
|
||||
char p[160];
|
||||
char *nt = stpcpy(p, t->hwmon);
|
||||
strcpy(nt, rel_metrics_path);
|
||||
gpu_metrics_fd = open(p, O_RDONLY | O_CLOEXEC);
|
||||
if (gpu_metrics_fd > 0) {
|
||||
t->has_gpu_metrics = true;
|
||||
char raw_metrics[max_metrics_length];
|
||||
read(gpu_metrics_fd, raw_metrics, sizeof(raw_metrics));
|
||||
const struct metrics_table_header *header = (struct metrics_table_header *)raw_metrics;
|
||||
applog(LOG_INF, "Found gpu_metrics_v%d_%d", header->format_revision, header->content_revision);
|
||||
}
|
||||
|
||||
sensors = malloc(sizeof(sensor_file_t) * (t->has_gpu_metrics ? 10 : 5));
|
||||
|
||||
// we always open these
|
||||
open_sensor(&sensors[0], t->hwmon, "/in0_input", &t->vcore, 1000, SENSOR_FLOAT);
|
||||
open_sensor(&sensors[1], t->hwmon, "/fan1_input", &t->fan_speed, 1, SENSOR_U16);
|
||||
open_sensor(&sensors[2], t->hwmon, "/power1_cap", &t->power_cap, 1000000, SENSOR_U16);
|
||||
open_sensor(&sensors[3], t->hwmon, "/power1_average", &t->power_avg, 1000000, SENSOR_U16);
|
||||
open_sensor(&sensors[4], t->hwmon, "/../../mem_info_vram_used", &t->vram_used, 1, SENSOR_U64);
|
||||
|
||||
if (t->has_gpu_metrics == false) {
|
||||
open_sensor(&sensors[5], t->hwmon, "/freq1_input", &t->clock_core, 1000000, SENSOR_U16);
|
||||
open_sensor(&sensors[6], t->hwmon, "/freq2_input", &t->clock_mem, 1000000, SENSOR_U16);
|
||||
open_sensor(&sensors[7], t->hwmon, "/power1_input",&t->power_avg, 1000000, SENSOR_U16);
|
||||
open_sensor(&sensors[8], t->hwmon, "/temp1_input", &t->temp_edge, 1000, SENSOR_U8);
|
||||
open_sensor(&sensors[9], t->hwmon, "/../../gpu_busy_percent", &t->usage_core, 1, SENSOR_U8);
|
||||
}
|
||||
}
|
||||
|
||||
/* some metrics are missing in gpu_metrics, we always fill them from fs, unused metrics are commented out */
|
||||
static void fill_missing_metrics(struct gpu_sensors_t *g) {
|
||||
char buf[32];
|
||||
fast_read_num_f(g->hwmon, "/in0_input", buf, &g->vcore, 1000);
|
||||
static void fill_missing_metrics() {
|
||||
// g->fan_pwm = std::stoi(readFile(g->hwmon + "/pwm1", 4)) * 100 / 256;
|
||||
fast_read_num_u16(g->hwmon, "/fan1_input", buf, &g->fan_speed, 1);
|
||||
fast_read_num_u16(g->hwmon, "/power1_cap", buf, &g->power_cap, 1000000);
|
||||
fast_read_num_u16(g->hwmon, "/power1_average", buf, &g->power_avg, 1000000);
|
||||
// utils::fastReadNum(g->hwmon + "/power1_cap_max", g->power_cap_max) / 1000000;
|
||||
fast_read_num_u64(g->hwmon, "/../../mem_info_vram_used", buf, &g->vram_used, 1);
|
||||
// utils::fastReadNum(g->hwmon + "/../../mem_info_vram_total", g->vram_total);
|
||||
for (uint8_t i = 0; i < 5; i++)
|
||||
fast_read_sensor(&sensors[i]);
|
||||
}
|
||||
|
||||
/* get sensors for pre-vega cards (rx480/580) */
|
||||
static void update_from_fs(struct gpu_sensors_t *g) {
|
||||
char buf[32];
|
||||
fast_read_num_u16(g->hwmon, "/freq1_input", buf, &g->clock_core, 1000000);
|
||||
fast_read_num_u16(g->hwmon, "/freq2_input", buf, &g->clock_mem, 1000000);
|
||||
fast_read_num_u16(g->hwmon, "/power1_input", buf, &g->power_avg, 1000000);
|
||||
fast_read_num_u8(g->hwmon, "/temp1_input", buf, &g->temp_edge, 1000);
|
||||
fast_read_num_u8(g->hwmon, "/../../gpu_busy_percent", buf, &g->usage_core, 1);
|
||||
static void update_from_fs() {
|
||||
for (uint8_t i = 5; i < 10; i++)
|
||||
fast_read_sensor(&sensors[i]);
|
||||
}
|
||||
|
||||
static void update_from_metrics(struct gpu_sensors_t *g) {
|
||||
char raw_metrics[max_metrics_length];
|
||||
|
||||
if (!read_file(g->hwmon, rel_metrics_path, raw_metrics, sizeof(raw_metrics)))
|
||||
return;
|
||||
|
||||
lseek(gpu_metrics_fd, 0, SEEK_SET);
|
||||
read(gpu_metrics_fd, raw_metrics, sizeof(raw_metrics));
|
||||
const struct metrics_table_header *header = (struct metrics_table_header *)raw_metrics;
|
||||
|
||||
switch (header->format_revision * 10 + header->content_revision) {
|
||||
@@ -106,11 +126,11 @@ void gpu_update(struct gpu_sensors_t *g) {
|
||||
const bool hwmon_valid = g->hwmon[0] != '\0';
|
||||
|
||||
if (hwmon_valid)
|
||||
fill_missing_metrics(g);
|
||||
fill_missing_metrics();
|
||||
if (g->has_gpu_metrics)
|
||||
update_from_metrics(g);
|
||||
else if (hwmon_valid)
|
||||
update_from_fs(g);
|
||||
update_from_fs();
|
||||
if (g->fan_speed > 9999)
|
||||
g->fan_speed = 9999; // sanity check fan speed
|
||||
}
|
||||
@@ -10,10 +10,7 @@
|
||||
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
int lcd_open(struct lcd_t *lcd, bool reopen);
|
||||
void lcd_write(struct lcd_t *lcd, const uint8_t *cmdbuf, uint16_t len);
|
||||
|
||||
int lcd_open(struct lcd_t *lcd, const bool reopen) {
|
||||
static int lcd_open(struct lcd_t *lcd, const bool reopen) {
|
||||
applog(LOG_INF, "Opening serial port at %s", lcd->port);
|
||||
if (lcd->fd <= 0 || reopen)
|
||||
lcd->fd = open(lcd->port, O_WRONLY | O_NOCTTY);
|
||||
@@ -36,7 +33,7 @@ void lcd_close(struct lcd_t *lcd) {
|
||||
lcd->fd = -1;
|
||||
}
|
||||
|
||||
void lcd_write(struct lcd_t *lcd, const uint8_t *cmdbuf, const uint16_t len) {
|
||||
static void lcd_write(struct lcd_t *lcd, const uint8_t *cmdbuf, const uint16_t len) {
|
||||
if (write(lcd->fd, cmdbuf, len) <= 0) {
|
||||
applog(LOG_ERR, "failed to execute write(), lost access to port?");
|
||||
lcd_close(lcd);
|
||||
@@ -109,7 +106,7 @@ inline void lcd_clear_buf(struct lcd_t *lcd) {
|
||||
|
||||
|
||||
/* flushes writebuffer to lcd, hyperoptmized, flushes buffer and commands in a single write operation */
|
||||
inline void lcd_flush_buf(struct lcd_t *lcd) {
|
||||
void lcd_flush_buf(struct lcd_t *lcd) {
|
||||
constexpr uint8_t set_disp[] = {254, 71, 1, 1}; // set cursor to char 1, line 1
|
||||
memcpy(&lcd->writebuf.text[0], set_disp, 4);
|
||||
memcpy(&lcd->writebuf.text[2 * LCD_COLS + 4], set_disp, 4);
|
||||
|
||||
@@ -23,13 +23,13 @@ static constexpr char netif[] = "enp4s0f0";
|
||||
static constexpr char cpu_pcidev[] = "0000:00:18.3";
|
||||
static constexpr char gpu_pcidev[] = "0000:0a:00.0";
|
||||
|
||||
struct control_t {
|
||||
static struct {
|
||||
pthread_mutex_t sensors_mtx;
|
||||
pthread_cond_t sensors_ready;
|
||||
atomic_bool running;
|
||||
} control;
|
||||
|
||||
struct sensors_t { // NOLINT yes it is
|
||||
struct sensors_t { // NOLINT stfu
|
||||
time_t ts;
|
||||
struct memory_t ram;
|
||||
struct disk_t home;
|
||||
@@ -56,6 +56,7 @@ static void *sensors_thread(void *arg) {
|
||||
cpu_detect(&sensors->cpu, cpu_pcidev);
|
||||
gpu_detect(&sensors->gpu, gpu_pcidev);
|
||||
sys_detect(&sensors->sys, "nct6775.656");
|
||||
sys_netdev_detect(&sensors->net);
|
||||
aio_detect(&sensors->aio);
|
||||
|
||||
/* main sensor loop */
|
||||
@@ -90,7 +91,7 @@ static void *sensors_thread(void *arg) {
|
||||
|
||||
static void *display_thread(void *arg) {
|
||||
applog(LOG_START, "display thread started");
|
||||
struct sensors_t *sensors = arg;
|
||||
const struct sensors_t *sensors = arg;
|
||||
|
||||
/* lcd setup */
|
||||
struct lcd_t lcd = {
|
||||
@@ -191,7 +192,7 @@ int main() {
|
||||
}
|
||||
|
||||
/* malloc memory for the struct */
|
||||
struct sensors_t *sensors = malloc(sizeof(*sensors)); // no actual point in mallocing and it is ever so sligtly slower to access heap vs stack, but its cool
|
||||
struct sensors_t *sensors = malloc(sizeof(struct sensors_t)); // no actual point in mallocing but its cool
|
||||
if (sensors == nullptr) {
|
||||
applog(LOG_ERR, "can't allocate mem for the sensor struct. You don't got %lu bytes bro?", sizeof(*sensors));
|
||||
free(sensors);
|
||||
|
||||
36
src/sys.c
36
src/sys.c
@@ -8,7 +8,7 @@
|
||||
#include "sys.h"
|
||||
#include "utils.h"
|
||||
|
||||
static sensor_t sensors[1];
|
||||
static sensor_file_t sensors;
|
||||
|
||||
char *sys_get_time_string(char *buf, const size_t bufsz, const time_t t) {
|
||||
const struct tm *tm = localtime(&t);
|
||||
@@ -61,26 +61,30 @@ void sys_get_network(struct network_t *network) {
|
||||
uint64_t tx;
|
||||
};
|
||||
|
||||
static char path[128];
|
||||
static char buf[32];
|
||||
static struct _net_t prev;
|
||||
struct _net_t current = {};
|
||||
snprintf(path, sizeof(path), "/sys/class/net/%s/statistics/", network->device);
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, ¤t.ts);
|
||||
fast_read_num_u64(path, "rx_bytes", buf, ¤t.rx, 1);
|
||||
fast_read_num_u64(path, "tx_bytes", buf, ¤t.tx, 1);
|
||||
fast_read_sensor_into_mem(&network->f_rx, ¤t.rx);
|
||||
fast_read_sensor_into_mem(&network->f_tx, ¤t.tx);
|
||||
const int64_t diff_us = timespec_diff_us(¤t.ts, &prev.ts);
|
||||
const uint64_t rx_delta = current.rx >= prev.rx ? current.rx - prev.rx : 0;
|
||||
const uint64_t tx_delta = current.tx >= prev.tx ? current.tx - prev.tx : 0;
|
||||
const double diff_s = (double)diff_us / 1000000.0;
|
||||
network->download = (uint32_t)((double)rx_delta / diff_s);
|
||||
network->upload = (uint32_t)((double)tx_delta / diff_s);
|
||||
if (rx_delta < 2000000000ULL && tx_delta < 2000000000ULL)
|
||||
prev = current;
|
||||
prev = current;
|
||||
// still fucky?
|
||||
}
|
||||
|
||||
void sys_netdev_detect(struct network_t *network) {
|
||||
applog(LOG_INF, "Opening netdev %s", network->device);
|
||||
static char path[128];
|
||||
snprintf(path, sizeof(path), "/sys/class/net/%s/statistics/", network->device);
|
||||
open_sensor(&network->f_rx, path, "rx_bytes", nullptr, 1, SENSOR_U64);
|
||||
open_sensor(&network->f_tx, path, "tx_bytes", nullptr, 1, SENSOR_U64);
|
||||
}
|
||||
|
||||
void sys_detect(struct syssensors_t *s, const char *platform) {
|
||||
snprintf(s->hwmon, sizeof(s->hwmon), "/sys/devices/platform/%s/hwmon", platform);
|
||||
const int ret = get_hwmon_dir(s->hwmon, sizeof(s->hwmon));
|
||||
@@ -90,22 +94,12 @@ void sys_detect(struct syssensors_t *s, const char *platform) {
|
||||
return;
|
||||
}
|
||||
applog(LOG_INF, "Detected system sensors in %s", s->hwmon);
|
||||
|
||||
open_sensor(&sensors[0], s->hwmon, "/temp5_input", &s->t_sensor, 1000, SENSOR_I16);
|
||||
open_sensor(&sensors, s->hwmon, "/temp5_input", &s->t_sensor, 1000, SENSOR_I16);
|
||||
}
|
||||
|
||||
void sys_update_sensors(struct syssensors_t *s) {
|
||||
void sys_update_sensors(const struct syssensors_t *s) {
|
||||
if (!s->hwmon[0])
|
||||
return;
|
||||
|
||||
static size_t num_sensors = 0;
|
||||
if (num_sensors == 0)
|
||||
num_sensors = sizeof(sensors) / sizeof(sensors[0]);
|
||||
|
||||
// static char buf[8];
|
||||
// fast_read_num_u16(s->hwmon, "/fan2_input", buf, &s->fan_speed[0], 1); // cpu fan, aka aio pump now
|
||||
// fast_read_num_u16(s->hwmon, "/fan7_input", buf, &s->fan_speed[1], 1); // cpu opt
|
||||
// fast_read_num_i16(s->hwmon, "/temp5_input", buf, &s->t_sensor, 1000);
|
||||
for (size_t i = 0; i < num_sensors; i++)
|
||||
fast_read_sensor_i16(&sensors[i]);
|
||||
fast_read_sensor(&sensors);
|
||||
}
|
||||
|
||||
106
src/utils.c
106
src/utils.c
@@ -13,7 +13,7 @@
|
||||
#include "log.h"
|
||||
#include "utils.h"
|
||||
|
||||
int get_instance_lock(void) {
|
||||
int get_instance_lock() {
|
||||
const char *xdg_runtime_dir = getenv("XDG_RUNTIME_DIR");
|
||||
char tmp_dir[256];
|
||||
snprintf(tmp_dir, sizeof(tmp_dir), "%s/linuxSmartie.lock", xdg_runtime_dir);
|
||||
@@ -80,82 +80,72 @@ int get_hwmon_dir(char *path, const size_t bufsz) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* instead of building the path here we could build it once in *_detect funcs for each sensor, but thats a lot of paths damn
|
||||
* actual slowdown is in the syscalls anyway, open(), read(), close () */
|
||||
|
||||
/* read n bytes from path into buffer */
|
||||
// file descriptors shouldnt change once opened, so we could open once, cache them, just call read() in the loop, then close all of them on program exit?
|
||||
inline ssize_t read_file(const char *dir, const char *file, char *buffer, const size_t n) {
|
||||
char path[160]; // bug alert
|
||||
void open_sensor(sensor_file_t* s, const char* dir, const char *file, void* value, const uint32_t divider, const sensor_type_t type) {
|
||||
char path[256];
|
||||
char *nt = stpcpy(path, dir); // nt is a pointer to the null terminator of the copied string
|
||||
strcpy(nt, file); // copy to the null terminator of prev copy, append basically
|
||||
const int fd = open(path, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
if (buffer != nullptr) // if its null means we're just checking if it exists at all, so dont log it
|
||||
applog(LOG_ERR, "Error reading %s", path);
|
||||
return 0;
|
||||
}
|
||||
const ssize_t len = read(fd, buffer, n);
|
||||
if (len > 0 && buffer)
|
||||
buffer[len] = '\0';
|
||||
close(fd);
|
||||
return len;
|
||||
}
|
||||
|
||||
inline void fast_read_num_u64(const char *dir, const char *file, char *buf, uint64_t *result, const uint32_t divider) {
|
||||
read_file(dir, file, buf, 32);
|
||||
*result = strtoull(buf, nullptr, 10) / divider;
|
||||
}
|
||||
|
||||
inline void fast_read_num_u16(const char *dir, const char *file, char *buf, uint16_t *result, const uint32_t divider) {
|
||||
read_file(dir, file, buf, 32);
|
||||
*result = (uint16_t)(strtol(buf, nullptr, 10) / divider);
|
||||
}
|
||||
|
||||
inline void fast_read_num_u8(const char *dir, const char *file, char *buf, uint8_t *result, const uint32_t divider) {
|
||||
read_file(dir, file, buf, 32);
|
||||
*result = (uint8_t)(strtol(buf, nullptr, 10) / divider);
|
||||
}
|
||||
|
||||
inline void fast_read_num_i16(const char *dir, const char *file, char *buf, int16_t *result, const uint32_t divider) {
|
||||
read_file(dir, file, buf, 32);
|
||||
*result = (int16_t)(strtol(buf, nullptr, 10) / divider);
|
||||
}
|
||||
|
||||
inline void fast_read_num_f(const char *dir, const char *file, char *buf, float *result, const uint32_t divider) {
|
||||
read_file(dir, file, buf, 32);
|
||||
const uint64_t val = strtoull(buf, nullptr, 10);
|
||||
*result = (float)val / (float)divider;
|
||||
}
|
||||
|
||||
void open_sensor(sensor_t* s, const char* dir, const char *file, void* value, const uint32_t divider, const sensor_type_t type) {
|
||||
char *nt = stpcpy(s->path, dir); // nt is a pointer to the null terminator of the copied string
|
||||
strcpy(nt, file); // copy to the null terminator of prev copy, append basically
|
||||
s->divider = divider;
|
||||
s->value = value;
|
||||
s->type = type;
|
||||
s->fd = open(s->path, O_RDONLY | O_CLOEXEC);
|
||||
s->fd = open(path, O_RDONLY | O_CLOEXEC);
|
||||
if (s->fd < 0)
|
||||
applog(LOG_ERR, "couldn't open %s", path);
|
||||
}
|
||||
|
||||
inline void fast_read_sensor_i16(const sensor_t *s) {
|
||||
inline void fast_read_sensor_into_mem(const sensor_file_t *s, void* val) {
|
||||
if (s->fd < 0) {
|
||||
applog(LOG_ERR, "invalid sensor fd %d", s->fd);
|
||||
return;
|
||||
}
|
||||
|
||||
char buf[32];
|
||||
lseek(s->fd, 0, SEEK_SET);
|
||||
const ssize_t len = read(s->fd, buf, sizeof(buf));
|
||||
if (len > 0)
|
||||
buf[len] = '\0';
|
||||
// return if read failed
|
||||
|
||||
if (len <= 0) {
|
||||
applog(LOG_ERR, "error reading sensor");
|
||||
return;
|
||||
}
|
||||
|
||||
buf[len] = '\0';
|
||||
|
||||
switch (s->type) {
|
||||
case SENSOR_I16:
|
||||
*(int16_t*)s->value = (int16_t)(strtol(buf, nullptr, 10) / s->divider);
|
||||
*(int16_t*)val = (int16_t)(strtol(buf, nullptr, 10) / s->divider);
|
||||
break;
|
||||
|
||||
case SENSOR_U8:
|
||||
*(uint8_t*)val = (uint8_t)(strtol(buf, nullptr, 10) / s->divider);
|
||||
break;
|
||||
|
||||
case SENSOR_U16:
|
||||
*(uint16_t*)val = (uint16_t)(strtol(buf, nullptr, 10) / s->divider);
|
||||
break;
|
||||
|
||||
case SENSOR_U64:
|
||||
*(uint64_t*)val = strtoull(buf, nullptr, 10) / s->divider;
|
||||
break;
|
||||
|
||||
case SENSOR_FLOAT:
|
||||
const uint64_t t = strtoull(buf, nullptr, 10);
|
||||
*(float*)val = (float)t / (float)s->divider;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
applog(LOG_ERR, "unknown sensor type %d", s->type);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void close_sensor(const sensor_t* s) {
|
||||
inline void fast_read_sensor(const sensor_file_t *s) {
|
||||
if (s->value != nullptr) {
|
||||
fast_read_sensor_into_mem(s, s->value);
|
||||
return;
|
||||
}
|
||||
applog(LOG_ERR, "attempted to read into nullptr");
|
||||
}
|
||||
|
||||
void close_sensor(const sensor_file_t* s) {
|
||||
close(s->fd);
|
||||
}
|
||||
Reference in New Issue
Block a user