From bae4ecd86731e5a01f93b74af7d5a36787bc0a4e Mon Sep 17 00:00:00 2001 From: Anton Date: Thu, 29 Oct 2026 13:12:51 +0300 Subject: [PATCH] fix: leave run-mode apps unpinned when all cores are selected --- .../overlay/usr/local/bin/droiddeck-session | 1 + tools/tests/test_session_cpu.py | 51 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 tools/tests/test_session_cpu.py diff --git a/tools/linuxfs/overlay/usr/local/bin/droiddeck-session b/tools/linuxfs/overlay/usr/local/bin/droiddeck-session index 0c037af47..9f7747c6a 100755 --- a/tools/linuxfs/overlay/usr/local/bin/droiddeck-session +++ b/tools/linuxfs/overlay/usr/local/bin/droiddeck-session @@ -298,6 +298,7 @@ program_cores() { [ "${BL_PIN_CORES:-1}" = 0 ] && return 0 command -v taskset >/dev/null 2>&1 || return 0 if [ -n "${BL_GAME_CPUS:-}" ]; then echo "$BL_GAME_CPUS"; return 0; fi + [ "$mode" = run ] && return 0 local f n max min= list= for f in /sys/devices/system/cpu/cpu[0-9]*/cpufreq/cpuinfo_max_freq; do max=$(cat "$f" 2>/dev/null) || continue diff --git a/tools/tests/test_session_cpu.py b/tools/tests/test_session_cpu.py new file mode 100644 index 000000000..a5d741d16 --- /dev/null +++ b/tools/tests/test_session_cpu.py @@ -0,0 +1,51 @@ +import os +from pathlib import Path +import re +import subprocess +import unittest + + +SESSION = Path(__file__).resolve().parents[1] / 'linuxfs/overlay/usr/local/bin/droiddeck-session' + + +class SessionCpuTest(unittest.TestCase): + def cores(self, mode, cpus='', pin='1'): + function = re.search(r'^program_cores\(\) \{\n.*?^\}\n', SESSION.read_text(), re.M | re.S).group(0) + script = ''' +set -u +taskset() { echo 'unexpected taskset invocation' >&2; return 1; } +cat() { + case "$1" in + */cpu[0-5]/cpufreq/*) echo 3630000 ;; + */cpu[67]/cpufreq/*) echo 4610000 ;; + *) return 1 ;; + esac +} +''' + paths = ' '.join(f'/sys/devices/system/cpu/cpu{i}/cpufreq/cpuinfo_max_freq' for i in range(8)) + function = function.replace('/sys/devices/system/cpu/cpu[0-9]*/cpufreq/cpuinfo_max_freq', paths) + env = dict(os.environ, mode=mode, BL_GAME_CPUS=cpus, BL_PIN_CORES=pin) + result = subprocess.run(['bash', '-c', script + function + '\nprogram_cores\n'], + env=env, capture_output=True, text=True, timeout=10) + self.assertEqual(0, result.returncode, result.stderr) + self.assertEqual('', result.stderr) + return result.stdout.strip() + + def test_run_with_all_cores_leaves_scheduling_unrestricted(self): + self.assertEqual('', self.cores('run')) + + def test_run_preserves_an_explicit_core_selection(self): + self.assertEqual('1,2,3,4,5,6,7', self.cores('run', '1,2,3,4,5,6,7')) + + def test_disabled_pinning_takes_precedence_over_explicit_cores(self): + self.assertEqual('', self.cores('run', '6,7', pin='0')) + + def test_desktop_keeps_its_fast_core_default(self): + self.assertEqual('6,7', self.cores('lxqt')) + + def test_desktop_preserves_an_explicit_core_selection(self): + self.assertEqual('0,1,2', self.cores('lxqt', '0,1,2')) + + +if __name__ == '__main__': + unittest.main()