diff --git a/CMakeLists.txt b/CMakeLists.txt index 037e9dfd9..f3c96e9b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -256,6 +256,7 @@ endif() if(LINUX OR BSD) list(APPEND LIBFASTFETCH_SRC + src/detection/cpuUsage/cpuUsage_linux.c src/detection/host/host_linux.c src/detection/os/os_linux.c src/detection/gpu/gpu_linux.c @@ -272,6 +273,7 @@ endif() if(APPLE) list(APPEND LIBFASTFETCH_SRC + src/detection/cpuUsage/cpuUsage_apple.c src/util/apple/cf_helpers.c src/util/apple/osascript.m src/detection/host/host_apple.c @@ -295,6 +297,7 @@ endif() if(ANDROID) list(APPEND LIBFASTFETCH_SRC + src/detection/cpuUsage/cpuUsage_linux.c src/detection/host/host_android.c src/detection/os/os_android.c src/detection/gpu/gpu_android.c diff --git a/src/detection/cpuUsage/cpuUsage.h b/src/detection/cpuUsage/cpuUsage.h new file mode 100644 index 000000000..577d2a374 --- /dev/null +++ b/src/detection/cpuUsage/cpuUsage.h @@ -0,0 +1,8 @@ +#pragma once + +#ifndef FF_INCLUDED_detection_cpu_cpuUsage +#define FF_INCLUDED_detection_cpu_cpuUsage + +const char* ffGetCpuUsagePercent(double* result); + +#endif diff --git a/src/detection/cpuUsage/cpuUsage_apple.c b/src/detection/cpuUsage/cpuUsage_apple.c new file mode 100644 index 000000000..49f1d34c8 --- /dev/null +++ b/src/detection/cpuUsage/cpuUsage_apple.c @@ -0,0 +1,46 @@ +#include "fastfetch.h" +#include "cpuUsage.h" + +#include +#include +#include + +static const char* getCpuUsageInfo(long* inUseAll, long* totalAll) +{ + natural_t numCPUs = 0U; + processor_info_array_t cpuInfo; + mach_msg_type_number_t numCpuInfo; + + if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numCPUs, &cpuInfo, &numCpuInfo) != KERN_SUCCESS) + return "host_processor_info() failed"; + if (numCPUs * CPU_STATE_MAX != numCpuInfo) + return "Unexpected host_processor_info() result"; + + for (natural_t i = 0U; i < numCPUs; ++i) { + integer_t inUse = cpuInfo[CPU_STATE_MAX * i + CPU_STATE_USER] + + cpuInfo[CPU_STATE_MAX * i + CPU_STATE_SYSTEM] + + cpuInfo[CPU_STATE_MAX * i + CPU_STATE_NICE]; + integer_t total = inUse + cpuInfo[CPU_STATE_MAX * i + CPU_STATE_IDLE]; + *inUseAll += inUse; + *totalAll += total; + } + return NULL; +} + +const char* ffGetCpuUsagePercent(double* result) +{ + long inUseAll1 = 0, totalAll1 = 0; + const char* error = getCpuUsageInfo(&inUseAll1, &totalAll1); + if(error) + return error; + + sleep(1); + + long inUseAll2 = 0, totalAll2 = 0; + error = getCpuUsageInfo(&inUseAll2, &totalAll2); + if(error) + return error; + + *result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100; + return NULL; +} diff --git a/src/detection/cpuUsage/cpuUsage_linux.c b/src/detection/cpuUsage/cpuUsage_linux.c new file mode 100644 index 000000000..499759a82 --- /dev/null +++ b/src/detection/cpuUsage/cpuUsage_linux.c @@ -0,0 +1,46 @@ +#include "fastfetch.h" +#include "cpuUsage.h" + +#include +#include + +static const char* getCpuUsageInfo(FILE* procStat, long* inUseAll, long* totalAll) +{ + long user, nice, system, idle, iowait, irq, softirq; + + if (fscanf(procStat, "cpu%ld%ld%ld%ld%ld%ld%ld", &user, &nice, &system, &idle, &iowait, &irq, &softirq) < 0) + { + fclose(procStat); + return "fscanf() failed"; + } + *inUseAll = user + nice + system; + *totalAll = *inUseAll + idle + iowait + irq + softirq; + return NULL; +} + +const char* ffGetCpuUsagePercent(double* result) +{ + FILE* procStat = fopen("/proc/stat", "r"); + if(procStat == NULL) + return "fopen(\"""/proc/stat\", \"r\") == NULL"; + + const char* error = NULL; + long inUseAll1 = 0, totalAll1 = 0; + error = getCpuUsageInfo(procStat, &inUseAll1, &totalAll1); + if(error) + goto exit; + + sleep(1); + rewind(procStat); + + long inUseAll2 = 0, totalAll2 = 0; + error = getCpuUsageInfo(procStat, &inUseAll2, &totalAll2); + if(error) + goto exit; + + *result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100; + +exit: + fclose(procStat); + return error; +} diff --git a/src/modules/cpuUsage.c b/src/modules/cpuUsage.c index c4b56873d..fe655af99 100644 --- a/src/modules/cpuUsage.c +++ b/src/modules/cpuUsage.c @@ -1,35 +1,20 @@ #include "fastfetch.h" #include "common/printing.h" - -#include +#include "detection/cpuUsage/cpuUsage.h" #define FF_CPU_USAGE_MODULE_NAME "CPU Usage" #define FF_CPU_USAGE_NUM_FORMAT_ARGS 1 void ffPrintCPUUsage(FFinstance* instance) { - long user, nice, system, idle, iowait, irq, softirq; - FILE* procStat = fopen("/proc/stat", "r"); - if(procStat == NULL) + double cpuPercent = 0; + const char* error = ffGetCpuUsagePercent(&cpuPercent); + + if(error) { - ffPrintError(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpu, "fopen(\"""/proc/stat\", \"r\") == NULL"); + ffPrintError(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpu, "%s", error); return; } - if (fscanf(procStat, "cpu%ld%ld%ld%ld%ld%ld%ld", &user, &nice, &system, &idle, &iowait, &irq, &softirq) < 0) goto exit; - long workJiffies1 = user + nice + system; - long totalJiffies1 = workJiffies1 + idle + iowait + irq + softirq; - - sleep(1); - - rewind(procStat); - if (fscanf(procStat, "cpu%ld%ld%ld%ld%ld%ld%ld", &user, &nice, &system, &idle, &iowait, &irq, &softirq) < 0) goto exit; - long workJiffies2 = user + nice + system; - long totalJiffies2 = workJiffies2 + idle + iowait + irq + softirq; - - // https://stackoverflow.com/questions/3017162/how-to-get-total-cpu-usage-in-linux-using-c#answer-3017438 - long workOverPeriod = workJiffies2 - workJiffies1; - long totalOverPeriod = totalJiffies2 - totalJiffies1; - double cpuPercent = (double)workOverPeriod / (double)totalOverPeriod * 100; if(instance->config.cpuUsage.outputFormat.length == 0) { @@ -43,7 +28,4 @@ void ffPrintCPUUsage(FFinstance* instance) {FF_FORMAT_ARG_TYPE_DOUBLE, &cpuPercent} }); } - -exit: - fclose(procStat); }