From c014c21462482779b217c5b0c367cddd9a910a13 Mon Sep 17 00:00:00 2001 From: p-sam Date: Fri, 20 Sep 2019 15:46:19 +0000 Subject: [PATCH] CSV context export at custom interval --- README.md | 17 +++++++----- common/include/sysclk/config.h | 5 ++++ sysmodule/src/clock_manager.cpp | 15 +++++++++-- sysmodule/src/clock_manager.h | 1 + sysmodule/src/file_utils.cpp | 47 +++++++++++++++++++++++++++++++++ sysmodule/src/file_utils.h | 3 +++ 6 files changed, 80 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 52927834..7d3cfe61 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Copy the `atmosphere` folder at the root of your sdcard, overwriting files if pr `/config/sys-clk/config.ini` -* Log file where the log are written if enabled +* Log file where the logs are written if enabled `/config/sys-clk/log.txt` @@ -21,6 +21,10 @@ Copy the `atmosphere` folder at the root of your sdcard, overwriting files if pr `/config/sys-clk/log.flag` +* CSV file where the title id, profile, clocks and temperatures are written if enabled + + `/config/sys-clk/context.csv` + ## Config Presets can be customized by adding them to the ini config file located at `/config/sys-clk/config.ini`, using the following template for each app @@ -80,12 +84,13 @@ handheld_mem=800 ### Advanced -The `[values]` section allows you to alter timings in sys-clk, you should not need to edit any of these. Possible values are: +The `[values]` section allows you to alter timings in sys-clk, you should not need to edit any of these unless you know what you are doing. Possible values are: -| Key | Desc | Default | -|:----------------------:|------------------------------------------------------------------------------|:-------:| -|**temp_log_interval_ms**| Defines how often sys-clk log temperatures, in milliseconds (`0` to disable) | 3000 ms | -|**poll_interval_ms** | Defines how fast sys-clk checks and applies profiles, in milliseconds | 300 ms | +| Key | Desc | Default | +|:-----------------------:|-------------------------------------------------------------------------------|:-------:| +|**temp_log_interval_ms** | Defines how often sys-clk log temperatures, in milliseconds (`0` to disable) | 0 ms | +|**csv_write_interval_ms**| Defines how often sys-clk writes to the CSV, in milliseconds (`0` to disable) | 0 ms | +|**poll_interval_ms** | Defines how fast sys-clk checks and applies profiles, in milliseconds | 300 ms | ## Capping diff --git a/common/include/sysclk/config.h b/common/include/sysclk/config.h index 9e62b0cb..076a7a1e 100644 --- a/common/include/sysclk/config.h +++ b/common/include/sysclk/config.h @@ -16,6 +16,7 @@ typedef enum { SysClkConfigValue_PollingIntervalMs = 0, SysClkConfigValue_TempLogIntervalMs, + SysClkConfigValue_CsvWriteIntervalMs, SysClkConfigValue_EnumMax, } SysClkConfigValue; @@ -27,6 +28,8 @@ static inline const char* sysClkFormatConfigValue(SysClkConfigValue val, bool pr return pretty ? "Polling Interval (ms)" : "poll_interval_ms"; case SysClkConfigValue_TempLogIntervalMs: return pretty ? "Temperature logging interval (ms)" : "temp_log_interval_ms"; + case SysClkConfigValue_CsvWriteIntervalMs: + return pretty ? "CSV write interval (ms)" : "csv_write_interval_ms"; default: return NULL; } @@ -39,6 +42,7 @@ static inline uint64_t sysClkDefaultConfigValue(SysClkConfigValue val) case SysClkConfigValue_PollingIntervalMs: return 300ULL; case SysClkConfigValue_TempLogIntervalMs: + case SysClkConfigValue_CsvWriteIntervalMs: return 0ULL; default: return 0ULL; @@ -52,6 +56,7 @@ static inline uint64_t sysClkValidConfigValue(SysClkConfigValue val, uint64_t in case SysClkConfigValue_PollingIntervalMs: return input > 0; case SysClkConfigValue_TempLogIntervalMs: + case SysClkConfigValue_CsvWriteIntervalMs: return true; default: return false; diff --git a/sysmodule/src/clock_manager.cpp b/sysmodule/src/clock_manager.cpp index a2c4a685..499cacf6 100644 --- a/sysmodule/src/clock_manager.cpp +++ b/sysmodule/src/clock_manager.cpp @@ -49,6 +49,8 @@ ClockManager::ClockManager() this->context->overrideFreqs[i] = 0; } this->running = false; + this->lastTempLogNs = 0; + this->lastCsvWriteNs = 0; } ClockManager::~ClockManager() @@ -166,8 +168,8 @@ bool ClockManager::RefreshContext() // temperatures do not and should not force a refresh, hasChanged untouched std::uint32_t millis = 0; std::uint64_t ns = armTicksToNs(armGetSystemTick()); - std::uint64_t interval = this->GetConfig()->GetConfigValue(SysClkConfigValue_TempLogIntervalMs) * 1000000ULL; - bool shouldLogTemp = interval && ((ns - this->lastTempLogNs) > interval); + std::uint64_t tempLogInterval = this->GetConfig()->GetConfigValue(SysClkConfigValue_TempLogIntervalMs) * 1000000ULL; + bool shouldLogTemp = tempLogInterval && ((ns - this->lastTempLogNs) > tempLogInterval); for (unsigned int sensor = 0; sensor < SysClkThermalSensor_EnumMax; sensor++) { millis = Clocks::GetTemperatureMilli((SysClkThermalSensor)sensor); @@ -177,11 +179,20 @@ bool ClockManager::RefreshContext() } this->context->temps[sensor] = millis; } + if(shouldLogTemp) { this->lastTempLogNs = ns; } + std::uint64_t csvWriteInterval = this->GetConfig()->GetConfigValue(SysClkConfigValue_CsvWriteIntervalMs) * 1000000ULL; + + if(csvWriteInterval && ((ns - this->lastCsvWriteNs) > csvWriteInterval)) + { + FileUtils::WriteContextToCsv(this->context); + this->lastCsvWriteNs = ns; + } + return hasChanged; } diff --git a/sysmodule/src/clock_manager.h b/sysmodule/src/clock_manager.h index abde0204..3eecb21c 100644 --- a/sysmodule/src/clock_manager.h +++ b/sysmodule/src/clock_manager.h @@ -43,4 +43,5 @@ class ClockManager Config *config; SysClkContext *context; std::uint64_t lastTempLogNs; + std::uint64_t lastCsvWriteNs; }; diff --git a/sysmodule/src/file_utils.cpp b/sysmodule/src/file_utils.cpp index 262c8e35..c59b5e53 100644 --- a/sysmodule/src/file_utils.cpp +++ b/sysmodule/src/file_utils.cpp @@ -12,6 +12,7 @@ #include static LockableMutex g_log_mutex; +static LockableMutex g_csv_mutex; static std::atomic_bool g_has_initialized = false; static bool g_log_enabled = false; static std::uint64_t g_last_flag_check = 0; @@ -60,6 +61,52 @@ void FileUtils::LogLine(const char *format, ...) va_end(args); } +void FileUtils::WriteContextToCsv(const SysClkContext* context) +{ + std::scoped_lock lock{g_csv_mutex}; + + FILE *file = fopen(FILE_CONTEXT_CSV_PATH, "a"); + + if (file) + { + // Print header + if(!ftell(file)) + { + fprintf(file, "timestamp,profile,app_tid"); + + for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) + { + fprintf(file, ",%s_hz", sysClkFormatModule((SysClkModule)module, false)); + } + + for (unsigned int sensor = 0; sensor < SysClkThermalSensor_EnumMax; sensor++) + { + fprintf(file, ",%s_milliC", sysClkFormatThermalSensor((SysClkThermalSensor)sensor, false)); + } + + fprintf(file, "\n"); + } + + struct timespec now; + clock_gettime(CLOCK_REALTIME, &now); + + fprintf(file, "%ld%03ld,%s,%016lx", now.tv_sec, now.tv_nsec / 1000000UL, sysClkFormatProfile(context->profile, false), context->applicationTid); + + for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) + { + fprintf(file, ",%d", context->freqs[module]); + } + + for (unsigned int sensor = 0; sensor < SysClkThermalSensor_EnumMax; sensor++) + { + fprintf(file, ",%d", context->temps[sensor]); + } + + fprintf(file, "\n"); + fclose(file); + } +} + void FileUtils::RefreshFlags(bool force) { std::uint64_t now = armTicksToNs(armGetSystemTick()); diff --git a/sysmodule/src/file_utils.h b/sysmodule/src/file_utils.h index 75c43832..4f1642e3 100644 --- a/sysmodule/src/file_utils.h +++ b/sysmodule/src/file_utils.h @@ -15,9 +15,11 @@ #include #include #include +#include #define FILE_CONFIG_DIR "/config/" TARGET #define FILE_FLAG_CHECK_INTERVAL_NS 5000000000ULL +#define FILE_CONTEXT_CSV_PATH FILE_CONFIG_DIR "/context.csv" #define FILE_LOG_FLAG_PATH FILE_CONFIG_DIR "/log.flag" #define FILE_LOG_FILE_PATH FILE_CONFIG_DIR "/log.txt" @@ -30,6 +32,7 @@ class FileUtils static bool IsLogEnabled(); static void InitializeAsync(); static void LogLine(const char *format, ...); + static void WriteContextToCsv(const SysClkContext* context); protected: static void RefreshFlags(bool force); };