From fbb68e0d519e22dac4aa559866605dd5eba29832 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Thu, 5 Jan 2023 21:16:37 -0500 Subject: [PATCH] Fix SMT behaviour paper cuts --- backend/src/api/handler.rs | 34 ++++++++++++++++++++++++++++++++-- src/backend.ts | 4 ++-- src/index.tsx | 22 +++++++--------------- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/backend/src/api/handler.rs b/backend/src/api/handler.rs index a1a9354..e7672e6 100644 --- a/backend/src/api/handler.rs +++ b/backend/src/api/handler.rs @@ -60,6 +60,8 @@ pub enum CpuMessage { impl CpuMessage { fn process(self, settings: &mut dyn TCpus) { + // NOTE: "cpu" refers to the Linux kernel definition of a CPU, which is actually a hardware thread + // not to be confused with a CPU chip, which usually has multiple hardware threads (cpu cores/threads) in the chip match self { Self::SetCpuOnline(index, status) => {settings.cpus().get_mut(index).map(|c| *c.online() = status);}, Self::SetCpusOnline(cpus) => { @@ -68,10 +70,38 @@ impl CpuMessage { } }, Self::SetSmt(status, cb) => { - *settings.smt() = status; + if *settings.smt() == status { + // already set, do nothing + } else if status { + // set SMT on + *settings.smt() = true; + let mut should_be_online = false; + let cpu_count = settings.len(); + for i in (0..cpu_count).rev() { + if *settings.cpus()[i].online() && !should_be_online { + should_be_online = true; + // enable the odd-numbered thread right before + // for 1c:2t configs (i.e. anything with SMT2), the highest cpu core is always odd + // (e.g. 4c8t has CPUs 0-7, inclusive) + // this enables the """fake""" (i.e. odd) cpu which is disabled when SMT is set off + if i % 2 == 0 && i+1 != cpu_count { + *(settings.cpus()[i+1].online()) = true; + } + } else { + *settings.cpus()[i].online() = should_be_online; + } + } + } else { + // set SMT off + *settings.smt() = false; + for i in 0..settings.len() { + // this disables the """fake""" (odd) cpu for appearances' sake + // the kernel will automatically disable that same cpu when SMT is changed + *settings.cpus()[i].online() = *settings.cpus()[i].online() && (status || i % 2 == 0); + } + } let mut result = Vec::with_capacity(settings.len()); for i in 0..settings.len() { - *settings.cpus()[i].online() = *settings.cpus()[i].online() && (status || i % 2 == 0); result.push(*settings.cpus()[i].online()); } cb(result); diff --git a/src/backend.ts b/src/backend.ts index 59a4f4d..70f1fee 100644 --- a/src/backend.ts +++ b/src/backend.ts @@ -120,8 +120,8 @@ export async function unsetBatteryChargeMode(): Promise { // CPU -export async function setCpuSmt(status: boolean): Promise { - return (await call_backend("CPU_set_smt", [status]))[0]; +export async function setCpuSmt(status: boolean): Promise { + return await call_backend("CPU_set_smt", [status]); } /*export async function getCpuCount(): Promise { diff --git a/src/index.tsx b/src/index.tsx index ef25c48..4de4a06 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -251,18 +251,10 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { description="Enables odd-numbered CPUs" onChange={(smt: boolean) => { backend.log(backend.LogLevel.Debug, "SMT is now " + smt.toString()); - const cpus = get_value(ONLINE_CPUS); + //const cpus = get_value(ONLINE_CPUS); const smtNow = smt && smtAllowed; - backend.resolve(backend.setCpuSmt(smtNow), (newVal: boolean) => { - set_value(SMT_CPU, newVal); - }); - let onlines: boolean[] = []; - for (let i = 0; i < total_cpus; i++) { - const online = (smtNow? i < cpus : (i % 2 == 0) && (i < cpus * 2)) - || (!smtNow && cpus == 4); - onlines.push(online); - } - backend.resolve(backend.setCpuOnlines(onlines), (statii: boolean[]) => { + backend.resolve(backend.setCpuSmt(smtNow), (statii: boolean[]) => { + set_value(SMT_CPU, smtNow); set_value(ONLINE_STATUS_CPUS, statii); const count = countCpus(statii); set_value(ONLINE_CPUS, count); @@ -276,7 +268,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { label="Threads" value={get_value(ONLINE_CPUS)} step={1} - max={get_value(SMT_CPU) || !smtAllowed ? total_cpus : total_cpus/2} + max={(get_value(SMT_CPU) || !smtAllowed) ? total_cpus : total_cpus/2} min={1} showValue={true} onChange={(cpus: number) => { @@ -411,9 +403,9 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { description="Allow the CPU thread to do work" onChange={(status: boolean) => { backend.log(backend.LogLevel.Debug, "CPU " + advancedCpu.toString() + " is now " + status.toString()); - if (get_value(SMT_CPU)) { - backend.resolve(backend.setCpuSmt(false), (newVal: boolean) => { - set_value(SMT_CPU, newVal); + if (!get_value(SMT_CPU)) { + backend.resolve(backend.setCpuSmt(true), (_newVal: boolean[]) => { + set_value(SMT_CPU, true); }); } backend.resolve(backend.setCpuOnline(advancedCpuIndex, status), (newVal: boolean) => {