From 33aa3d1133f1adf1c7e3331514aa2efe31d75cc4 Mon Sep 17 00:00:00 2001 From: Prashant Vaibhav Date: Thu, 5 Mar 2026 21:45:30 +0530 Subject: [PATCH 1/2] Replace userspace CPU governor with kernel scaling governors Remove all manual CPU frequency control via the userspace governor and scaling_setspeed. Instead, three shell scripts (auto_governor.sh, powersave_governor.sh, performance_governor.sh) configure the kernel governor and frequency range dynamically at runtime. - auto: ondemand, min to one step below max frequency - powersave: conservative, min to midpoint frequency - performance: schedutil, min to max frequency The minarch CPU Speed menu is reduced from four options (Powersave, Normal, Performance, Auto) to three (Auto, Performance, Powersave). Selecting a profile executes the corresponding script via an absolute path constructed from SYSTEM_PATH. The auto governor is always restored on minarch exit, including early-exit paths. The userspace PLAT_cpu_monitor frequency-scaling loop is removed from both tg5040 and tg5050 platform.c; the thread is retained for CPU usage measurement only. PLAT_setCPUSpeed and PLAT_setCustomCPUSpeed are now no-ops so existing callers (ledcontrol, bootlogo, etc.) are unaffected. --- skeleton/SYSTEM/tg5040/bin/auto_governor.sh | 11 ++ .../SYSTEM/tg5040/bin/performance_governor.sh | 11 ++ .../SYSTEM/tg5040/bin/powersave_governor.sh | 13 ++ .../SYSTEM/tg5040/paks/MinUI.pak/launch.sh | 5 +- skeleton/SYSTEM/tg5050/bin/auto_governor.sh | 11 ++ .../SYSTEM/tg5050/bin/performance_governor.sh | 11 ++ .../SYSTEM/tg5050/bin/powersave_governor.sh | 13 ++ .../SYSTEM/tg5050/paks/MinUI.pak/launch.sh | 16 +-- workspace/all/common/api.h | 2 - workspace/all/minarch/minarch.c | 77 +++++------ workspace/desktop/platform/platform.c | 1 - workspace/tg5040/platform/platform.c | 124 +++-------------- workspace/tg5050/platform/platform.c | 128 +++--------------- 13 files changed, 141 insertions(+), 282 deletions(-) create mode 100644 skeleton/SYSTEM/tg5040/bin/auto_governor.sh create mode 100644 skeleton/SYSTEM/tg5040/bin/performance_governor.sh create mode 100644 skeleton/SYSTEM/tg5040/bin/powersave_governor.sh create mode 100644 skeleton/SYSTEM/tg5050/bin/auto_governor.sh create mode 100644 skeleton/SYSTEM/tg5050/bin/performance_governor.sh create mode 100644 skeleton/SYSTEM/tg5050/bin/powersave_governor.sh diff --git a/skeleton/SYSTEM/tg5040/bin/auto_governor.sh b/skeleton/SYSTEM/tg5040/bin/auto_governor.sh new file mode 100644 index 000000000..86b33256d --- /dev/null +++ b/skeleton/SYSTEM/tg5040/bin/auto_governor.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# auto_governor.sh - ondemand governor, min freq to one step below max +for CPU_PATH in /sys/devices/system/cpu/cpu*/cpufreq; do + [ -f "$CPU_PATH/scaling_available_frequencies" ] || continue + FREQS=$(cat "$CPU_PATH/scaling_available_frequencies" | tr ' ' '\n' | grep -v '^$' | sort -n) + MIN_FREQ=$(echo "$FREQS" | head -1) + SECOND_MAX=$(echo "$FREQS" | tail -2 | head -1) + echo ondemand > "$CPU_PATH/scaling_governor" 2>/dev/null || true + echo "$MIN_FREQ" > "$CPU_PATH/scaling_min_freq" + echo "$SECOND_MAX" > "$CPU_PATH/scaling_max_freq" +done diff --git a/skeleton/SYSTEM/tg5040/bin/performance_governor.sh b/skeleton/SYSTEM/tg5040/bin/performance_governor.sh new file mode 100644 index 000000000..9627b7791 --- /dev/null +++ b/skeleton/SYSTEM/tg5040/bin/performance_governor.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# performance_governor.sh - schedutil governor, min freq to max freq +for CPU_PATH in /sys/devices/system/cpu/cpu*/cpufreq; do + [ -f "$CPU_PATH/scaling_available_frequencies" ] || continue + FREQS=$(cat "$CPU_PATH/scaling_available_frequencies" | tr ' ' '\n' | grep -v '^$' | sort -n) + MIN_FREQ=$(echo "$FREQS" | head -1) + MAX_FREQ=$(echo "$FREQS" | tail -1) + echo schedutil > "$CPU_PATH/scaling_governor" 2>/dev/null || true + echo "$MIN_FREQ" > "$CPU_PATH/scaling_min_freq" + echo "$MAX_FREQ" > "$CPU_PATH/scaling_max_freq" +done diff --git a/skeleton/SYSTEM/tg5040/bin/powersave_governor.sh b/skeleton/SYSTEM/tg5040/bin/powersave_governor.sh new file mode 100644 index 000000000..eb364b6bb --- /dev/null +++ b/skeleton/SYSTEM/tg5040/bin/powersave_governor.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# powersave_governor.sh - conservative governor, min freq to midpoint max +for CPU_PATH in /sys/devices/system/cpu/cpu*/cpufreq; do + [ -f "$CPU_PATH/scaling_available_frequencies" ] || continue + FREQS=$(cat "$CPU_PATH/scaling_available_frequencies" | tr ' ' '\n' | grep -v '^$' | sort -n) + COUNT=$(echo "$FREQS" | wc -l) + MID=$(( (COUNT + 1) / 2 )) + MIN_FREQ=$(echo "$FREQS" | head -1) + MID_FREQ=$(echo "$FREQS" | sed -n "${MID}p") + echo conservative > "$CPU_PATH/scaling_governor" 2>/dev/null || true + echo "$MIN_FREQ" > "$CPU_PATH/scaling_min_freq" + echo "$MID_FREQ" > "$CPU_PATH/scaling_max_freq" +done diff --git a/skeleton/SYSTEM/tg5040/paks/MinUI.pak/launch.sh b/skeleton/SYSTEM/tg5040/paks/MinUI.pak/launch.sh index 09528cf3a..b3272ff4d 100755 --- a/skeleton/SYSTEM/tg5040/paks/MinUI.pak/launch.sh +++ b/skeleton/SYSTEM/tg5040/paks/MinUI.pak/launch.sh @@ -111,10 +111,7 @@ fi # start stock gpio input daemon trimui_inputd & -echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor -CPU_PATH=/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed -CPU_SPEED_PERF=2000000 -echo $CPU_SPEED_PERF > $CPU_PATH +sh "$SYSTEM_PATH/bin/auto_governor.sh" keymon.elf & # &> $SDCARD_PATH/keymon.txt & batmon.elf & # &> $SDCARD_PATH/batmon.txt & diff --git a/skeleton/SYSTEM/tg5050/bin/auto_governor.sh b/skeleton/SYSTEM/tg5050/bin/auto_governor.sh new file mode 100644 index 000000000..86b33256d --- /dev/null +++ b/skeleton/SYSTEM/tg5050/bin/auto_governor.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# auto_governor.sh - ondemand governor, min freq to one step below max +for CPU_PATH in /sys/devices/system/cpu/cpu*/cpufreq; do + [ -f "$CPU_PATH/scaling_available_frequencies" ] || continue + FREQS=$(cat "$CPU_PATH/scaling_available_frequencies" | tr ' ' '\n' | grep -v '^$' | sort -n) + MIN_FREQ=$(echo "$FREQS" | head -1) + SECOND_MAX=$(echo "$FREQS" | tail -2 | head -1) + echo ondemand > "$CPU_PATH/scaling_governor" 2>/dev/null || true + echo "$MIN_FREQ" > "$CPU_PATH/scaling_min_freq" + echo "$SECOND_MAX" > "$CPU_PATH/scaling_max_freq" +done diff --git a/skeleton/SYSTEM/tg5050/bin/performance_governor.sh b/skeleton/SYSTEM/tg5050/bin/performance_governor.sh new file mode 100644 index 000000000..9627b7791 --- /dev/null +++ b/skeleton/SYSTEM/tg5050/bin/performance_governor.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# performance_governor.sh - schedutil governor, min freq to max freq +for CPU_PATH in /sys/devices/system/cpu/cpu*/cpufreq; do + [ -f "$CPU_PATH/scaling_available_frequencies" ] || continue + FREQS=$(cat "$CPU_PATH/scaling_available_frequencies" | tr ' ' '\n' | grep -v '^$' | sort -n) + MIN_FREQ=$(echo "$FREQS" | head -1) + MAX_FREQ=$(echo "$FREQS" | tail -1) + echo schedutil > "$CPU_PATH/scaling_governor" 2>/dev/null || true + echo "$MIN_FREQ" > "$CPU_PATH/scaling_min_freq" + echo "$MAX_FREQ" > "$CPU_PATH/scaling_max_freq" +done diff --git a/skeleton/SYSTEM/tg5050/bin/powersave_governor.sh b/skeleton/SYSTEM/tg5050/bin/powersave_governor.sh new file mode 100644 index 000000000..eb364b6bb --- /dev/null +++ b/skeleton/SYSTEM/tg5050/bin/powersave_governor.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# powersave_governor.sh - conservative governor, min freq to midpoint max +for CPU_PATH in /sys/devices/system/cpu/cpu*/cpufreq; do + [ -f "$CPU_PATH/scaling_available_frequencies" ] || continue + FREQS=$(cat "$CPU_PATH/scaling_available_frequencies" | tr ' ' '\n' | grep -v '^$' | sort -n) + COUNT=$(echo "$FREQS" | wc -l) + MID=$(( (COUNT + 1) / 2 )) + MIN_FREQ=$(echo "$FREQS" | head -1) + MID_FREQ=$(echo "$FREQS" | sed -n "${MID}p") + echo conservative > "$CPU_PATH/scaling_governor" 2>/dev/null || true + echo "$MIN_FREQ" > "$CPU_PATH/scaling_min_freq" + echo "$MID_FREQ" > "$CPU_PATH/scaling_max_freq" +done diff --git a/skeleton/SYSTEM/tg5050/paks/MinUI.pak/launch.sh b/skeleton/SYSTEM/tg5050/paks/MinUI.pak/launch.sh index d73b92a2a..97707073d 100755 --- a/skeleton/SYSTEM/tg5050/paks/MinUI.pak/launch.sh +++ b/skeleton/SYSTEM/tg5050/paks/MinUI.pak/launch.sh @@ -98,21 +98,7 @@ echo 0 > /sys/class/led_anim/max_scale # start gpio input daemon trimui_inputd & -echo userspace > /sys/devices/system/cpu/cpu4/cpufreq/scaling_governor -echo 408000 > /sys/devices/system/cpu/cpu4/cpufreq/scaling_min_freq -echo 2160000 > /sys/devices/system/cpu/cpu4/cpufreq/scaling_max_freq - -BIG_PATH=/sys/devices/system/cpu/cpu4/cpufreq/scaling_setspeed -CPU_SPEED_PERF=2160000 -echo $CPU_SPEED_PERF > $BIG_PATH - -echo schedutil > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor -echo 408000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq -echo 2000000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq - -#LITTLE_PATH=/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed -#CPU_SPEED_PERF_LITTLE=2000000 -#echo $CPU_SPEED_PERF_LITTLE > $LITTLE_PATH +sh "$SYSTEM_PATH/bin/auto_governor.sh" echo performance > /sys/devices/platform/soc@3000000/1800000.gpu/devfreq/1800000.gpu/governor diff --git a/workspace/all/common/api.h b/workspace/all/common/api.h index 1cef108f1..d68461bbf 100644 --- a/workspace/all/common/api.h +++ b/workspace/all/common/api.h @@ -113,8 +113,6 @@ extern int currentshaderdsth; extern int currentshadertexw; extern int currentshadertexh; extern int should_rotate; -extern volatile int useAutoCpu; - enum { ASSET_WHITE_PILL, ASSET_BLACK_PILL, diff --git a/workspace/all/minarch/minarch.c b/workspace/all/minarch/minarch.c index ed2f92abd..76b4d2410 100644 --- a/workspace/all/minarch/minarch.c +++ b/workspace/all/minarch/minarch.c @@ -97,7 +97,7 @@ static int rewind_cfg_granularity = MINARCH_DEFAULT_REWIND_GRANULARITY; static int rewind_cfg_audio = MINARCH_DEFAULT_REWIND_AUDIO; static int rewind_cfg_compress = 1; static int rewind_cfg_lz4_acceleration = MINARCH_DEFAULT_REWIND_LZ4_ACCELERATION; -static int overclock = 3; // auto +static int overclock = 0; // auto static int has_custom_controllers = 0; static int gamepad_type = 0; // index in gamepad_labels/gamepad_values @@ -2490,10 +2490,9 @@ static char* button_labels[] = { NULL, }; static char* overclock_labels[] = { - "Powersave", - "Normal", - "Performance", "Auto", + "Performance", + "Powersave", NULL, }; @@ -2640,10 +2639,10 @@ static struct Config { [FE_OPT_OVERCLOCK] = { .key = "minarch_cpu_speed", .name = "CPU Speed", - .desc = "Over- or underclock the CPU to prioritize\npure performance or power savings.", - .default_value = 3, - .value = 3, - .count = 4, + .desc = "Select the CPU governor profile.\nAuto uses ondemand scaling, Performance\nallows max frequency, Powersave limits\nto a conservative midpoint.", + .default_value = 0, + .value = 0, + .count = 3, .values = overclock_labels, .labels = overclock_labels, }, @@ -2990,30 +2989,29 @@ static int Config_getValue(char* cfg, const char* key, char* out_value, int* loc +static void run_governor_script(const char* script_name) { + const char* system_path = getenv("SYSTEM_PATH"); + if (!system_path) { + LOG_info("WARNING: SYSTEM_PATH not set, cannot run governor script\n"); + return; + } + char cmd[512]; + int n = snprintf(cmd, sizeof(cmd), "sh \"%s/bin/%s\"", system_path, script_name); + if (n < 0 || n >= (int)sizeof(cmd)) { + LOG_info("WARNING: SYSTEM_PATH too long for governor script path\n"); + return; + } + int ret = system(cmd); + if (ret != 0) LOG_info("WARNING: governor script '%s' exited with status %d\n", script_name, ret); +} + static void setOverclock(int i) { - overclock = i; - switch (i) { - case 0: { - useAutoCpu = 0; - PWR_setCPUSpeed(CPU_SPEED_POWERSAVE); - break; - } - case 1: { - useAutoCpu = 0; - PWR_setCPUSpeed(CPU_SPEED_NORMAL); - break; - } - case 2: { - useAutoCpu = 0; - PWR_setCPUSpeed(CPU_SPEED_PERFORMANCE); - break; - } - case 3: { - PWR_setCPUSpeed(CPU_SPEED_NORMAL); - useAutoCpu = 1; - break; - } - } + overclock = i; + switch (i) { + case 0: run_governor_script("auto_governor.sh"); break; + case 1: run_governor_script("performance_governor.sh"); break; + case 2: run_governor_script("powersave_governor.sh"); break; + } } static void Config_syncFrontend(char* key, int value) { int i = -1; @@ -6270,8 +6268,6 @@ void Menu_beforeSleep() { RTC_write(); State_autosave(); putFile(AUTO_RESUME_PATH, game.path + strlen(SDCARD_PATH)); - - PWR_setCPUSpeed(CPU_SPEED_MENU); } void Menu_afterSleep() { unlink(AUTO_RESUME_PATH); @@ -8503,7 +8499,6 @@ static void Menu_loop(void) { SRAM_write(); RTC_write(); if (!HAS_POWER_BUTTON) PWR_enableSleep(); - PWR_setCPUSpeed(CPU_SPEED_MENU); // set Hz directly GFX_setEffect(EFFECT_NONE); @@ -8973,16 +8968,16 @@ int main(int argc , char* argv[]) { pthread_create(&cpucheckthread, &attr, PLAT_cpu_monitor, NULL); pthread_attr_destroy(&attr); - setOverclock(2); // start up in performance mode, faster init + if(argc < 2) + return EXIT_FAILURE; + + setOverclock(1); // start up in performance mode, faster init PWR_pinToCores(CPU_CORE_PERFORMANCE); // thread affinity - + char core_path[MAX_PATH]; - char rom_path[MAX_PATH]; + char rom_path[MAX_PATH]; char tag_name[MAX_PATH]; - if(argc < 2) - return EXIT_FAILURE; - strcpy(core_path, argv[1]); strcpy(rom_path, argv[2]); getEmuName(rom_path, tag_name); @@ -9186,6 +9181,8 @@ int main(int argc , char* argv[]) { finish: + run_governor_script("auto_governor.sh"); // restore auto governor on return to menu + // Unload game and shutdown RetroAchievements before Core_quit RA_unloadGame(); RA_quit(); diff --git a/workspace/desktop/platform/platform.c b/workspace/desktop/platform/platform.c index bdf3f65d5..ab9fe52c0 100644 --- a/workspace/desktop/platform/platform.c +++ b/workspace/desktop/platform/platform.c @@ -62,7 +62,6 @@ void PLAT_powerOff(int reboot) { /////////////////////////////// -volatile int useAutoCpu = 0; void PLAT_setCPUSpeed(int speed) { // buh } diff --git a/workspace/tg5040/platform/platform.c b/workspace/tg5040/platform/platform.c index 07b915b55..0d60426a6 100644 --- a/workspace/tg5040/platform/platform.c +++ b/workspace/tg5040/platform/platform.c @@ -243,140 +243,48 @@ static pthread_mutex_t currentcpuinfo; // a roling average for the display values of about 2 frames, otherwise they are unreadable jumping too fast up and down and stuff to read #define ROLLING_WINDOW 120 -volatile int useAutoCpu = 1; void *PLAT_cpu_monitor(void *arg) { - struct timespec start_time, curr_time; - clock_gettime(CLOCK_MONOTONIC_RAW, &start_time); - - long clock_ticks_per_sec = sysconf(_SC_CLK_TCK); - double prev_real_time = get_time_sec(); double prev_cpu_time = get_process_cpu_time_sec(); - // big Cortex-A53 CPUx4 - 408Mhz to 2160Mhz - // 408000 600000 816000 1008000 1200000 1416000 1608000 1800000 2000000 - const int cpu_frequencies[] = {408,600,816,1008,1200,1416,1608,1800,2000}; - const int num_freqs = sizeof(cpu_frequencies) / sizeof(cpu_frequencies[0]); - int current_index = 1; - double cpu_usage_history[ROLLING_WINDOW] = {0}; - double cpu_speed_history[ROLLING_WINDOW] = {0}; int history_index = 0; - int history_count = 0; + int history_count = 0; while (true) { + double curr_real_time = get_time_sec(); + double curr_cpu_time = get_process_cpu_time_sec(); - double curr_real_time = get_time_sec(); - double curr_cpu_time = get_process_cpu_time_sec(); + double elapsed_real_time = curr_real_time - prev_real_time; + double elapsed_cpu_time = curr_cpu_time - prev_cpu_time; - double elapsed_real_time = curr_real_time - prev_real_time; - double elapsed_cpu_time = curr_cpu_time - prev_cpu_time; - - if (useAutoCpu) { - double cpu_usage = 0; - - if (elapsed_real_time > 0) { - cpu_usage = (elapsed_cpu_time / elapsed_real_time) * 100.0; - } + if (elapsed_real_time > 0) { + double cpu_usage = (elapsed_cpu_time / elapsed_real_time) * 100.0; pthread_mutex_lock(¤tcpuinfo); - // the goal here is is to keep cpu usage between 75% and 85% at the lowest possible speed so device stays cool and battery usage is at a minimum - // if usage falls out of this range it will either scale a step down or up - // but if usage hits above 95% we need that max boost and we instant scale up to 2000mhz as long as needed - // all this happens very fast like 60 times per second, so i'm applying roling averages to display values, so debug screen is readable and gives a good estimate on whats happening cpu wise - // the roling averages are purely for displaying, the actual scaling is happening realtime each run. - if (cpu_usage > 95) { - current_index = num_freqs - 1; // Instant power needed, cpu is above 95% Jump directly to max boost 2000MHz - } - else if (cpu_usage > 85 && current_index < num_freqs - 1) { // otherwise try to keep between 75 and 85 at lowest clock speed - current_index++; - } - else if (cpu_usage < 75 && current_index > 0) { - current_index--; - } - - PLAT_setCustomCPUSpeed(cpu_frequencies[current_index] * 1000); - cpu_usage_history[history_index] = cpu_usage; - cpu_speed_history[history_index] = cpu_frequencies[current_index]; - history_index = (history_index + 1) % ROLLING_WINDOW; - if (history_count < ROLLING_WINDOW) { - history_count++; - } - - double sum_cpu_usage = 0, sum_cpu_speed = 0; - for (int i = 0; i < history_count; i++) { - sum_cpu_usage += cpu_usage_history[i]; - sum_cpu_speed += cpu_speed_history[i]; - } + if (history_count < ROLLING_WINDOW) history_count++; + double sum_cpu_usage = 0; + for (int i = 0; i < history_count; i++) sum_cpu_usage += cpu_usage_history[i]; perf.cpu_usage = sum_cpu_usage / history_count; - //perf.cpu_speed = sum_cpu_speed / history_count; pthread_mutex_unlock(¤tcpuinfo); - - prev_real_time = curr_real_time; - prev_cpu_time = curr_cpu_time; - // 20ms really seems lowest i can go, anything lower it becomes innacurate, maybe one day I will find another even more granual way to calculate usage accurately and lower this shit to 1ms haha, altough anything lower than 10ms causes cpu usage in itself so yeah - // Anyways screw it 20ms is pretty much on a frame by frame basis anyways, so will anything lower really make a difference specially if that introduces cpu usage by itself? - // Who knows, maybe some CPU engineer will find my comment here one day and can explain, maybe this is looking for the limits of C and needs Assambler or whatever to call CPU instructions directly to go further, but all I know is PUSH and MOV, how did the orignal Roller Coaster Tycoon developer wrote a whole game like this anyways? Its insane.. - usleep(20000); - - } else { - // Just measure CPU usage without changing frequency - - if (elapsed_real_time > 0) { - double cpu_usage = (elapsed_cpu_time / elapsed_real_time) * 100.0; - - pthread_mutex_lock(¤tcpuinfo); - - cpu_usage_history[history_index] = cpu_usage; - - history_index = (history_index + 1) % ROLLING_WINDOW; - if (history_count < ROLLING_WINDOW) { - history_count++; - } - - double sum_cpu_usage = 0; - for (int i = 0; i < history_count; i++) { - sum_cpu_usage += cpu_usage_history[i]; - } - - perf.cpu_usage = sum_cpu_usage / history_count; - - pthread_mutex_unlock(¤tcpuinfo); - } - - prev_real_time = curr_real_time; - prev_cpu_time = curr_cpu_time; - usleep(100000); } + + prev_real_time = curr_real_time; + prev_cpu_time = curr_cpu_time; + usleep(100000); } } - -#define GOVERNOR_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed" void PLAT_setCustomCPUSpeed(int speed) { - FILE *fp = fopen(GOVERNOR_PATH, "w"); - if (fp == NULL) { - perror("Failed to open scaling_setspeed"); - return; - } - - fprintf(fp, "%d\n", speed); - fclose(fp); + // Frequency control is now handled by kernel governor scripts } void PLAT_setCPUSpeed(int speed) { - int freq = 0; - switch (speed) { - case CPU_SPEED_MENU: freq = 600000; perf.cpu_speed = 600; break; - case CPU_SPEED_POWERSAVE: freq = 1200000; perf.cpu_speed = 1200; break; - case CPU_SPEED_NORMAL: freq = 1608000; perf.cpu_speed = 1600; break; - case CPU_SPEED_PERFORMANCE: freq = 2000000; perf.cpu_speed = 2000; break; - } - putInt(GOVERNOR_PATH, freq); + // Frequency control is now handled by kernel governor scripts } #define MAX_STRENGTH 0xFFFF diff --git a/workspace/tg5050/platform/platform.c b/workspace/tg5050/platform/platform.c index cef0e80d0..850856ff5 100644 --- a/workspace/tg5050/platform/platform.c +++ b/workspace/tg5050/platform/platform.c @@ -288,144 +288,48 @@ void PLAT_pinToCores(int core_type) LOG_error("Failed to pin: Are all cores sleeping?\n"); } -volatile int useAutoCpu = 1; void *PLAT_cpu_monitor(void *arg) { - struct timespec start_time, curr_time; - clock_gettime(CLOCK_MONOTONIC_RAW, &start_time); - - long clock_ticks_per_sec = sysconf(_SC_CLK_TCK); - double prev_real_time = get_time_sec(); double prev_cpu_time = get_process_cpu_time_sec(); - // big Cortex-A55 CPU4 - 408Mhz to 2160Mhz - // 408000 672000 840000 1008000 1200000 1344000 1488000 1584000 1680000 1800000 1992000 2088000 2160000 - const int big_cpu_frequencies[] = {408,672,840,1008,1200,1344,1488,1584,1680,1800,1992,2088,2160}; - const int big_num_freqs = sizeof(big_cpu_frequencies) / sizeof(big_cpu_frequencies[0]); - int big_index = 1; // 672Mhz start - // little Cortex-A55 CPU0 - 408Mhz to 1416Mhz - // 408000 672000 792000 936000 1032000 1128000 1224000 1320000 1416000 - const int little_cpu_frequencies[] = {408,672,792,936,1032,1128,1224,1320,1416}; - const int little_num_freqs = sizeof(little_cpu_frequencies) / sizeof(little_cpu_frequencies[0]); - int little_index = 1; // 672Mhz start - double cpu_usage_history[ROLLING_WINDOW] = {0}; - double cpu_speed_history[ROLLING_WINDOW] = {0}; int history_index = 0; - int history_count = 0; + int history_count = 0; while (true) { + double curr_real_time = get_time_sec(); + double curr_cpu_time = get_process_cpu_time_sec(); - double curr_real_time = get_time_sec(); - double curr_cpu_time = get_process_cpu_time_sec(); + double elapsed_real_time = curr_real_time - prev_real_time; + double elapsed_cpu_time = curr_cpu_time - prev_cpu_time; - double elapsed_real_time = curr_real_time - prev_real_time; - double elapsed_cpu_time = curr_cpu_time - prev_cpu_time; - - if (useAutoCpu) { - double cpu_usage = 0; - - if (elapsed_real_time > 0) { - cpu_usage = (elapsed_cpu_time / elapsed_real_time) * 100.0; - } + if (elapsed_real_time > 0) { + double cpu_usage = (elapsed_cpu_time / elapsed_real_time) * 100.0; pthread_mutex_lock(¤tcpuinfo); - // the goal here is is to keep cpu usage between 75% and 85% at the lowest possible speed so device stays cool and battery usage is at a minimum - // if usage falls out of this range it will either scale a step down or up - // but if usage hits above 95% we need that max boost and we instant scale up to 2000mhz as long as needed - // all this happens very fast like 60 times per second, so i'm applying roling averages to display values, so debug screen is readable and gives a good estimate on whats happening cpu wise - // the roling averages are purely for displaying, the actual scaling is happening realtime each run. - if (cpu_usage > 95) { - big_index = big_num_freqs - 1; // Instant power needed, cpu is above 95% Jump directly to max boost 2000MHz - } - else if (cpu_usage > 85 && big_index < big_num_freqs - 1) { // otherwise try to keep between 75 and 85 at lowest clock speed - big_index++; - } - else if (cpu_usage < 75 && big_index > 0) { - big_index--; - } - - PLAT_setCustomCPUSpeed(big_cpu_frequencies[big_index] * 1000); - cpu_usage_history[history_index] = cpu_usage; - cpu_speed_history[history_index] = big_cpu_frequencies[big_index]; - history_index = (history_index + 1) % ROLLING_WINDOW; - if (history_count < ROLLING_WINDOW) { - history_count++; - } - - double sum_cpu_usage = 0, sum_cpu_speed = 0; - for (int i = 0; i < history_count; i++) { - sum_cpu_usage += cpu_usage_history[i]; - sum_cpu_speed += cpu_speed_history[i]; - } + if (history_count < ROLLING_WINDOW) history_count++; + double sum_cpu_usage = 0; + for (int i = 0; i < history_count; i++) sum_cpu_usage += cpu_usage_history[i]; perf.cpu_usage = sum_cpu_usage / history_count; - //perf.cpu_speed = sum_cpu_speed / history_count; pthread_mutex_unlock(¤tcpuinfo); - - prev_real_time = curr_real_time; - prev_cpu_time = curr_cpu_time; - // 20ms really seems lowest i can go, anything lower it becomes innacurate, maybe one day I will find another even more granual way to calculate usage accurately and lower this shit to 1ms haha, altough anything lower than 10ms causes cpu usage in itself so yeah - // Anyways screw it 20ms is pretty much on a frame by frame basis anyways, so will anything lower really make a difference specially if that introduces cpu usage by itself? - // Who knows, maybe some CPU engineer will find my comment here one day and can explain, maybe this is looking for the limits of C and needs Assambler or whatever to call CPU instructions directly to go further, but all I know is PUSH and MOV, how did the orignal Roller Coaster Tycoon developer wrote a whole game like this anyways? Its insane.. - usleep(20000); - } else { - // Just measure CPU usage without changing frequency - - if (elapsed_real_time > 0) { - double cpu_usage = (elapsed_cpu_time / elapsed_real_time) * 100.0; - - pthread_mutex_lock(¤tcpuinfo); - - cpu_usage_history[history_index] = cpu_usage; - - history_index = (history_index + 1) % ROLLING_WINDOW; - if (history_count < ROLLING_WINDOW) { - history_count++; - } - - double sum_cpu_usage = 0; - for (int i = 0; i < history_count; i++) { - sum_cpu_usage += cpu_usage_history[i]; - } - - perf.cpu_usage = sum_cpu_usage / history_count; - - pthread_mutex_unlock(¤tcpuinfo); - } - - prev_real_time = curr_real_time; - prev_cpu_time = curr_cpu_time; - usleep(100000); } + + prev_real_time = curr_real_time; + prev_cpu_time = curr_cpu_time; + usleep(100000); } } - -#define GOVERNOR_PATH "/sys/devices/system/cpu/cpu4/cpufreq/scaling_setspeed" void PLAT_setCustomCPUSpeed(int speed) { - FILE *fp = fopen(GOVERNOR_PATH, "w"); - if (fp == NULL) { - perror("Failed to open scaling_setspeed"); - return; - } - - fprintf(fp, "%d\n", speed); - fclose(fp); + // Frequency control is now handled by kernel governor scripts } void PLAT_setCPUSpeed(int speed) { - int freq = 0; - switch (speed) { - case CPU_SPEED_MENU: freq = 672000; perf.cpu_speed = 672; break; - case CPU_SPEED_POWERSAVE: freq = 1200000; perf.cpu_speed = 1200; break; - case CPU_SPEED_NORMAL: freq = 1680000; perf.cpu_speed = 1680; break; - case CPU_SPEED_PERFORMANCE: freq = 2160000; perf.cpu_speed = 2160; break; - } - putInt(GOVERNOR_PATH, freq); + // Frequency control is now handled by kernel governor scripts } #define MAX_STRENGTH 0xFFFF From 4bcf0bb04fbe68787909f9c773e447e2e8d99a6a Mon Sep 17 00:00:00 2001 From: Prashant Vaibhav Date: Thu, 26 Mar 2026 04:25:03 +0530 Subject: [PATCH 2/2] fix: address kernel-cpu-governor review feedback * Simplify the CPU Speed description in MinArch * Switch the governor scripts to the shared policy0 path * Remove the unrelated diff about rom_path Also stop running the CPU monitor when it is not needed by gating it behind the Debug HUD setting and removing the NextUI-side thread launch. Previously, nextui.c was launching this thread in teh back- ground and detaching from it. Now, it's launched conditionally in minarch.c only when the Debug HUD switch is turned on. The platform monitor loop now checks the shared enabled state so the sampling work shuts down when the HUD is off. Hope this squeezes a little more performance out of the cpu. --- skeleton/SYSTEM/tg5040/bin/auto_governor.sh | 18 ++++---- .../SYSTEM/tg5040/bin/performance_governor.sh | 18 ++++---- .../SYSTEM/tg5040/bin/powersave_governor.sh | 22 ++++----- skeleton/SYSTEM/tg5050/bin/auto_governor.sh | 18 ++++---- .../SYSTEM/tg5050/bin/performance_governor.sh | 18 ++++---- .../SYSTEM/tg5050/bin/powersave_governor.sh | 22 ++++----- workspace/all/common/api.c | 45 ++++++++++++++++++- workspace/all/common/api.h | 5 +++ workspace/all/minarch/minarch.c | 29 ++++++++---- workspace/all/nextui/nextui.c | 5 --- workspace/tg5040/platform/platform.c | 7 ++- workspace/tg5050/platform/platform.c | 7 ++- 12 files changed, 139 insertions(+), 75 deletions(-) diff --git a/skeleton/SYSTEM/tg5040/bin/auto_governor.sh b/skeleton/SYSTEM/tg5040/bin/auto_governor.sh index 86b33256d..ed63fc372 100644 --- a/skeleton/SYSTEM/tg5040/bin/auto_governor.sh +++ b/skeleton/SYSTEM/tg5040/bin/auto_governor.sh @@ -1,11 +1,11 @@ #!/bin/sh # auto_governor.sh - ondemand governor, min freq to one step below max -for CPU_PATH in /sys/devices/system/cpu/cpu*/cpufreq; do - [ -f "$CPU_PATH/scaling_available_frequencies" ] || continue - FREQS=$(cat "$CPU_PATH/scaling_available_frequencies" | tr ' ' '\n' | grep -v '^$' | sort -n) - MIN_FREQ=$(echo "$FREQS" | head -1) - SECOND_MAX=$(echo "$FREQS" | tail -2 | head -1) - echo ondemand > "$CPU_PATH/scaling_governor" 2>/dev/null || true - echo "$MIN_FREQ" > "$CPU_PATH/scaling_min_freq" - echo "$SECOND_MAX" > "$CPU_PATH/scaling_max_freq" -done +# All cpu*/cpufreq entries point at this same shared policy0 path. +CPU_PATH=/sys/devices/system/cpu/cpufreq/policy0 +[ -f "$CPU_PATH/scaling_available_frequencies" ] || exit 0 +FREQS=$(cat "$CPU_PATH/scaling_available_frequencies" | tr ' ' '\n' | grep -v '^$' | sort -n) +MIN_FREQ=$(echo "$FREQS" | head -1) +SECOND_MAX=$(echo "$FREQS" | tail -2 | head -1) +echo ondemand > "$CPU_PATH/scaling_governor" 2>/dev/null || true +echo "$MIN_FREQ" > "$CPU_PATH/scaling_min_freq" +echo "$SECOND_MAX" > "$CPU_PATH/scaling_max_freq" diff --git a/skeleton/SYSTEM/tg5040/bin/performance_governor.sh b/skeleton/SYSTEM/tg5040/bin/performance_governor.sh index 9627b7791..d1f36441a 100644 --- a/skeleton/SYSTEM/tg5040/bin/performance_governor.sh +++ b/skeleton/SYSTEM/tg5040/bin/performance_governor.sh @@ -1,11 +1,11 @@ #!/bin/sh # performance_governor.sh - schedutil governor, min freq to max freq -for CPU_PATH in /sys/devices/system/cpu/cpu*/cpufreq; do - [ -f "$CPU_PATH/scaling_available_frequencies" ] || continue - FREQS=$(cat "$CPU_PATH/scaling_available_frequencies" | tr ' ' '\n' | grep -v '^$' | sort -n) - MIN_FREQ=$(echo "$FREQS" | head -1) - MAX_FREQ=$(echo "$FREQS" | tail -1) - echo schedutil > "$CPU_PATH/scaling_governor" 2>/dev/null || true - echo "$MIN_FREQ" > "$CPU_PATH/scaling_min_freq" - echo "$MAX_FREQ" > "$CPU_PATH/scaling_max_freq" -done +# All cpu*/cpufreq entries point at this same shared policy0 path. +CPU_PATH=/sys/devices/system/cpu/cpufreq/policy0 +[ -f "$CPU_PATH/scaling_available_frequencies" ] || exit 0 +FREQS=$(cat "$CPU_PATH/scaling_available_frequencies" | tr ' ' '\n' | grep -v '^$' | sort -n) +MIN_FREQ=$(echo "$FREQS" | head -1) +MAX_FREQ=$(echo "$FREQS" | tail -1) +echo schedutil > "$CPU_PATH/scaling_governor" 2>/dev/null || true +echo "$MIN_FREQ" > "$CPU_PATH/scaling_min_freq" +echo "$MAX_FREQ" > "$CPU_PATH/scaling_max_freq" diff --git a/skeleton/SYSTEM/tg5040/bin/powersave_governor.sh b/skeleton/SYSTEM/tg5040/bin/powersave_governor.sh index eb364b6bb..5496df8e8 100644 --- a/skeleton/SYSTEM/tg5040/bin/powersave_governor.sh +++ b/skeleton/SYSTEM/tg5040/bin/powersave_governor.sh @@ -1,13 +1,13 @@ #!/bin/sh # powersave_governor.sh - conservative governor, min freq to midpoint max -for CPU_PATH in /sys/devices/system/cpu/cpu*/cpufreq; do - [ -f "$CPU_PATH/scaling_available_frequencies" ] || continue - FREQS=$(cat "$CPU_PATH/scaling_available_frequencies" | tr ' ' '\n' | grep -v '^$' | sort -n) - COUNT=$(echo "$FREQS" | wc -l) - MID=$(( (COUNT + 1) / 2 )) - MIN_FREQ=$(echo "$FREQS" | head -1) - MID_FREQ=$(echo "$FREQS" | sed -n "${MID}p") - echo conservative > "$CPU_PATH/scaling_governor" 2>/dev/null || true - echo "$MIN_FREQ" > "$CPU_PATH/scaling_min_freq" - echo "$MID_FREQ" > "$CPU_PATH/scaling_max_freq" -done +# All cpu*/cpufreq entries point at this same shared policy0 path. +CPU_PATH=/sys/devices/system/cpu/cpufreq/policy0 +[ -f "$CPU_PATH/scaling_available_frequencies" ] || exit 0 +FREQS=$(cat "$CPU_PATH/scaling_available_frequencies" | tr ' ' '\n' | grep -v '^$' | sort -n) +COUNT=$(echo "$FREQS" | wc -l) +MID=$(( (COUNT + 1) / 2 )) +MIN_FREQ=$(echo "$FREQS" | head -1) +MID_FREQ=$(echo "$FREQS" | sed -n "${MID}p") +echo conservative > "$CPU_PATH/scaling_governor" 2>/dev/null || true +echo "$MIN_FREQ" > "$CPU_PATH/scaling_min_freq" +echo "$MID_FREQ" > "$CPU_PATH/scaling_max_freq" diff --git a/skeleton/SYSTEM/tg5050/bin/auto_governor.sh b/skeleton/SYSTEM/tg5050/bin/auto_governor.sh index 86b33256d..ed63fc372 100644 --- a/skeleton/SYSTEM/tg5050/bin/auto_governor.sh +++ b/skeleton/SYSTEM/tg5050/bin/auto_governor.sh @@ -1,11 +1,11 @@ #!/bin/sh # auto_governor.sh - ondemand governor, min freq to one step below max -for CPU_PATH in /sys/devices/system/cpu/cpu*/cpufreq; do - [ -f "$CPU_PATH/scaling_available_frequencies" ] || continue - FREQS=$(cat "$CPU_PATH/scaling_available_frequencies" | tr ' ' '\n' | grep -v '^$' | sort -n) - MIN_FREQ=$(echo "$FREQS" | head -1) - SECOND_MAX=$(echo "$FREQS" | tail -2 | head -1) - echo ondemand > "$CPU_PATH/scaling_governor" 2>/dev/null || true - echo "$MIN_FREQ" > "$CPU_PATH/scaling_min_freq" - echo "$SECOND_MAX" > "$CPU_PATH/scaling_max_freq" -done +# All cpu*/cpufreq entries point at this same shared policy0 path. +CPU_PATH=/sys/devices/system/cpu/cpufreq/policy0 +[ -f "$CPU_PATH/scaling_available_frequencies" ] || exit 0 +FREQS=$(cat "$CPU_PATH/scaling_available_frequencies" | tr ' ' '\n' | grep -v '^$' | sort -n) +MIN_FREQ=$(echo "$FREQS" | head -1) +SECOND_MAX=$(echo "$FREQS" | tail -2 | head -1) +echo ondemand > "$CPU_PATH/scaling_governor" 2>/dev/null || true +echo "$MIN_FREQ" > "$CPU_PATH/scaling_min_freq" +echo "$SECOND_MAX" > "$CPU_PATH/scaling_max_freq" diff --git a/skeleton/SYSTEM/tg5050/bin/performance_governor.sh b/skeleton/SYSTEM/tg5050/bin/performance_governor.sh index 9627b7791..d1f36441a 100644 --- a/skeleton/SYSTEM/tg5050/bin/performance_governor.sh +++ b/skeleton/SYSTEM/tg5050/bin/performance_governor.sh @@ -1,11 +1,11 @@ #!/bin/sh # performance_governor.sh - schedutil governor, min freq to max freq -for CPU_PATH in /sys/devices/system/cpu/cpu*/cpufreq; do - [ -f "$CPU_PATH/scaling_available_frequencies" ] || continue - FREQS=$(cat "$CPU_PATH/scaling_available_frequencies" | tr ' ' '\n' | grep -v '^$' | sort -n) - MIN_FREQ=$(echo "$FREQS" | head -1) - MAX_FREQ=$(echo "$FREQS" | tail -1) - echo schedutil > "$CPU_PATH/scaling_governor" 2>/dev/null || true - echo "$MIN_FREQ" > "$CPU_PATH/scaling_min_freq" - echo "$MAX_FREQ" > "$CPU_PATH/scaling_max_freq" -done +# All cpu*/cpufreq entries point at this same shared policy0 path. +CPU_PATH=/sys/devices/system/cpu/cpufreq/policy0 +[ -f "$CPU_PATH/scaling_available_frequencies" ] || exit 0 +FREQS=$(cat "$CPU_PATH/scaling_available_frequencies" | tr ' ' '\n' | grep -v '^$' | sort -n) +MIN_FREQ=$(echo "$FREQS" | head -1) +MAX_FREQ=$(echo "$FREQS" | tail -1) +echo schedutil > "$CPU_PATH/scaling_governor" 2>/dev/null || true +echo "$MIN_FREQ" > "$CPU_PATH/scaling_min_freq" +echo "$MAX_FREQ" > "$CPU_PATH/scaling_max_freq" diff --git a/skeleton/SYSTEM/tg5050/bin/powersave_governor.sh b/skeleton/SYSTEM/tg5050/bin/powersave_governor.sh index eb364b6bb..5496df8e8 100644 --- a/skeleton/SYSTEM/tg5050/bin/powersave_governor.sh +++ b/skeleton/SYSTEM/tg5050/bin/powersave_governor.sh @@ -1,13 +1,13 @@ #!/bin/sh # powersave_governor.sh - conservative governor, min freq to midpoint max -for CPU_PATH in /sys/devices/system/cpu/cpu*/cpufreq; do - [ -f "$CPU_PATH/scaling_available_frequencies" ] || continue - FREQS=$(cat "$CPU_PATH/scaling_available_frequencies" | tr ' ' '\n' | grep -v '^$' | sort -n) - COUNT=$(echo "$FREQS" | wc -l) - MID=$(( (COUNT + 1) / 2 )) - MIN_FREQ=$(echo "$FREQS" | head -1) - MID_FREQ=$(echo "$FREQS" | sed -n "${MID}p") - echo conservative > "$CPU_PATH/scaling_governor" 2>/dev/null || true - echo "$MIN_FREQ" > "$CPU_PATH/scaling_min_freq" - echo "$MID_FREQ" > "$CPU_PATH/scaling_max_freq" -done +# All cpu*/cpufreq entries point at this same shared policy0 path. +CPU_PATH=/sys/devices/system/cpu/cpufreq/policy0 +[ -f "$CPU_PATH/scaling_available_frequencies" ] || exit 0 +FREQS=$(cat "$CPU_PATH/scaling_available_frequencies" | tr ' ' '\n' | grep -v '^$' | sort -n) +COUNT=$(echo "$FREQS" | wc -l) +MID=$(( (COUNT + 1) / 2 )) +MIN_FREQ=$(echo "$FREQS" | head -1) +MID_FREQ=$(echo "$FREQS" | sed -n "${MID}p") +echo conservative > "$CPU_PATH/scaling_governor" 2>/dev/null || true +echo "$MIN_FREQ" > "$CPU_PATH/scaling_min_freq" +echo "$MID_FREQ" > "$CPU_PATH/scaling_max_freq" diff --git a/workspace/all/common/api.c b/workspace/all/common/api.c index af9fef268..91661f39c 100644 --- a/workspace/all/common/api.c +++ b/workspace/all/common/api.c @@ -215,6 +215,49 @@ int currentshadertexh = 0; int should_rotate = 0; +static pthread_mutex_t perf_cpu_monitor_mutex = PTHREAD_MUTEX_INITIALIZER; +static int perf_cpu_monitor_enabled = 0; +static int perf_cpu_monitor_running = 0; + +void Perf_setCPUMonitorEnabled(int enabled) +{ + pthread_mutex_lock(&perf_cpu_monitor_mutex); + perf_cpu_monitor_enabled = enabled; + pthread_mutex_unlock(&perf_cpu_monitor_mutex); +} + +int Perf_isCPUMonitorEnabled(void) +{ + int enabled; + + pthread_mutex_lock(&perf_cpu_monitor_mutex); + enabled = perf_cpu_monitor_enabled; + pthread_mutex_unlock(&perf_cpu_monitor_mutex); + + return enabled; +} + +int Perf_tryBeginCPUMonitor(void) +{ + int should_run = 0; + + pthread_mutex_lock(&perf_cpu_monitor_mutex); + if (perf_cpu_monitor_enabled && !perf_cpu_monitor_running) { + perf_cpu_monitor_running = 1; + should_run = 1; + } + pthread_mutex_unlock(&perf_cpu_monitor_mutex); + + return should_run; +} + +void Perf_endCPUMonitor(void) +{ + pthread_mutex_lock(&perf_cpu_monitor_mutex); + perf_cpu_monitor_running = 0; + pthread_mutex_unlock(&perf_cpu_monitor_mutex); +} + FALLBACK_IMPLEMENTATION void PLAT_pinToCores(int core_type) { // no-op @@ -4393,4 +4436,4 @@ FALLBACK_IMPLEMENTATION void PLAT_bluetoothStreamBegin(int buffersize) {} FALLBACK_IMPLEMENTATION void PLAT_bluetoothStreamEnd() {} FALLBACK_IMPLEMENTATION void PLAT_bluetoothStreamQuit() {} FALLBACK_IMPLEMENTATION int PLAT_bluetoothVolume() { return 100; } -FALLBACK_IMPLEMENTATION void PLAT_bluetoothSetVolume(int vol) {} \ No newline at end of file +FALLBACK_IMPLEMENTATION void PLAT_bluetoothSetVolume(int vol) {} diff --git a/workspace/all/common/api.h b/workspace/all/common/api.h index d68461bbf..48f8ff65e 100644 --- a/workspace/all/common/api.h +++ b/workspace/all/common/api.h @@ -677,6 +677,11 @@ int PLAT_supportsDeepSleep(void); int PLAT_deepSleep(void); void PLAT_powerOff(int reboot); +void Perf_setCPUMonitorEnabled(int enabled); +int Perf_isCPUMonitorEnabled(void); +int Perf_tryBeginCPUMonitor(void); +void Perf_endCPUMonitor(void); + void *PLAT_cpu_monitor(void *arg); void PLAT_setCPUSpeed(int speed); // enum void PLAT_setCustomCPUSpeed(int speed); diff --git a/workspace/all/minarch/minarch.c b/workspace/all/minarch/minarch.c index 76b4d2410..ffca254aa 100644 --- a/workspace/all/minarch/minarch.c +++ b/workspace/all/minarch/minarch.c @@ -2639,7 +2639,7 @@ static struct Config { [FE_OPT_OVERCLOCK] = { .key = "minarch_cpu_speed", .name = "CPU Speed", - .desc = "Select the CPU governor profile.\nAuto uses ondemand scaling, Performance\nallows max frequency, Powersave limits\nto a conservative midpoint.", + .desc = "Choose how the CPU scales.\nAuto is recommended for most users.", .default_value = 0, .value = 0, .count = 3, @@ -3005,6 +3005,21 @@ static void run_governor_script(const char* script_name) { if (ret != 0) LOG_info("WARNING: governor script '%s' exited with status %d\n", script_name, ret); } +static void updateCPUMonitor(void) { + Perf_setCPUMonitorEnabled(show_debug); + if (!show_debug) return; + + pthread_t cpucheckthread; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + if (pthread_create(&cpucheckthread, &attr, PLAT_cpu_monitor, NULL) != 0) { + LOG_info("WARNING: failed to start CPU monitor thread\n"); + Perf_setCPUMonitorEnabled(0); + } + pthread_attr_destroy(&attr); +} + static void setOverclock(int i) { overclock = i; switch (i) { @@ -3078,7 +3093,9 @@ static void Config_syncFrontend(char* key, int value) { i = FE_OPT_OVERCLOCK; } else if (exactMatch(key,config.frontend.options[FE_OPT_DEBUG].key)) { - show_debug = value; + int prev_show_debug = show_debug; + show_debug = value; + if (prev_show_debug != show_debug) updateCPUMonitor(); i = FE_OPT_DEBUG; } else if (exactMatch(key,config.frontend.options[FE_OPT_MAXFF].key)) { @@ -8961,13 +8978,6 @@ int main(int argc , char* argv[]) { //else // LOG_info("asoundrc does not exist at %s\n", asoundpath); - pthread_t cpucheckthread; - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&cpucheckthread, &attr, PLAT_cpu_monitor, NULL); - pthread_attr_destroy(&attr); - if(argc < 2) return EXIT_FAILURE; @@ -9181,6 +9191,7 @@ int main(int argc , char* argv[]) { finish: + Perf_setCPUMonitorEnabled(0); run_governor_script("auto_governor.sh"); // restore auto governor on return to menu // Unload game and shutdown RetroAchievements before Core_quit diff --git a/workspace/all/nextui/nextui.c b/workspace/all/nextui/nextui.c index 4b943b835..20c14b725 100644 --- a/workspace/all/nextui/nextui.c +++ b/workspace/all/nextui/nextui.c @@ -2269,11 +2269,6 @@ int main (int argc, char *argv[]) { int had_bt = PLAT_btIsConnected(); int had_sink = GetAudioSink(); - pthread_t cpucheckthread = 0; - if (pthread_create(&cpucheckthread, NULL, PLAT_cpu_monitor, NULL) == 0) { - pthread_detach(cpucheckthread); - } - int selected_row = top->selected - top->start; float targetY; float previousY; diff --git a/workspace/tg5040/platform/platform.c b/workspace/tg5040/platform/platform.c index 0d60426a6..18075a49c 100644 --- a/workspace/tg5040/platform/platform.c +++ b/workspace/tg5040/platform/platform.c @@ -244,6 +244,8 @@ static pthread_mutex_t currentcpuinfo; #define ROLLING_WINDOW 120 void *PLAT_cpu_monitor(void *arg) { + if (!Perf_tryBeginCPUMonitor()) return NULL; + double prev_real_time = get_time_sec(); double prev_cpu_time = get_process_cpu_time_sec(); @@ -251,7 +253,7 @@ void *PLAT_cpu_monitor(void *arg) { int history_index = 0; int history_count = 0; - while (true) { + while (Perf_isCPUMonitorEnabled()) { double curr_real_time = get_time_sec(); double curr_cpu_time = get_process_cpu_time_sec(); @@ -278,6 +280,9 @@ void *PLAT_cpu_monitor(void *arg) { prev_cpu_time = curr_cpu_time; usleep(100000); } + + Perf_endCPUMonitor(); + return NULL; } void PLAT_setCustomCPUSpeed(int speed) { diff --git a/workspace/tg5050/platform/platform.c b/workspace/tg5050/platform/platform.c index 850856ff5..38cf8cc39 100644 --- a/workspace/tg5050/platform/platform.c +++ b/workspace/tg5050/platform/platform.c @@ -289,6 +289,8 @@ void PLAT_pinToCores(int core_type) } void *PLAT_cpu_monitor(void *arg) { + if (!Perf_tryBeginCPUMonitor()) return NULL; + double prev_real_time = get_time_sec(); double prev_cpu_time = get_process_cpu_time_sec(); @@ -296,7 +298,7 @@ void *PLAT_cpu_monitor(void *arg) { int history_index = 0; int history_count = 0; - while (true) { + while (Perf_isCPUMonitorEnabled()) { double curr_real_time = get_time_sec(); double curr_cpu_time = get_process_cpu_time_sec(); @@ -323,6 +325,9 @@ void *PLAT_cpu_monitor(void *arg) { prev_cpu_time = curr_cpu_time; usleep(100000); } + + Perf_endCPUMonitor(); + return NULL; } void PLAT_setCustomCPUSpeed(int speed) {