From adf5c8b7e727f436992ebc1cbcc75df651bc627f Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Thu, 26 Mar 2026 07:31:54 -0500 Subject: [PATCH] only display online CPUs in output coreCount now reflects only the schedulable CPUs. With hw.smt=0 on a 4-core/8-thread machine, coreCount becomes 4, so btop allocates 4 display slots instead of 8. The collect loop now also checks CPUSTATS_ONLINE for each CPU and skips offline CPUs, such as disabled hyperthreads. --- src/openbsd/btop_collect.cpp | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/openbsd/btop_collect.cpp b/src/openbsd/btop_collect.cpp index 263cfd58..b250d027 100644 --- a/src/openbsd/btop_collect.cpp +++ b/src/openbsd/btop_collect.cpp @@ -127,7 +127,7 @@ namespace Shared { //? Shared global variables init int mib[2]; mib[0] = CTL_HW; - mib[1] = HW_NCPU; + mib[1] = HW_NCPUONLINE; int ncpu; size_t len = sizeof(ncpu); if (sysctl(mib, 2, &ncpu, &len, nullptr, 0) == -1) { @@ -392,12 +392,21 @@ namespace Cpu { Logger::error("failed to get load averages"); } + //? Read total physical CPU count for sysctl iteration + //? (may differ from coreCount when SMT is disabled via hw.smt=0). + int ncpu_total = Shared::coreCount; + { + int mib[] = {CTL_HW, HW_NCPU}; + size_t len = sizeof(ncpu_total); + sysctl(mib, 2, &ncpu_total, &len, nullptr, 0); + } + auto cp_time = std::unique_ptr{ - new struct cpustats[Shared::coreCount] + new struct cpustats[ncpu_total] }; size_t size = sizeof(struct cpustats); static int cpustats_mib[] = {CTL_KERN, KERN_CPUSTATS, /*fillme*/0}; - for (int i = 0; i < Shared::coreCount; i++) { + for (int i = 0; i < ncpu_total; i++) { cpustats_mib[2] = i; if (sysctl(cpustats_mib, 3, &cp_time[i], &size, NULL, 0) == -1) { Logger::error("sysctl kern.cpustats failed"); @@ -407,11 +416,16 @@ namespace Cpu { long long global_idles = 0; vector times_summed = {0, 0, 0, 0}; - for (long i = 0; i < Shared::coreCount; i++) { + //? j iterates all physical CPUs; offline ones are skipped + //? i is the display slot index, incremented only for online CPUs + for (long i = 0, j = 0; j < ncpu_total; j++) { + if (!(cp_time[j].cs_flags & CPUSTATS_ONLINE)) + continue; + vector times; //? 0=user, 1=nice, 2=system, 3=idle for (int x = 0; const unsigned int c_state : {CP_USER, CP_NICE, CP_SYS, CP_IDLE}) { - auto val = cp_time[i].cs_time[c_state]; + auto val = cp_time[j].cs_time[c_state]; times.push_back(val); times_summed.at(x++) += val; } @@ -426,7 +440,6 @@ namespace Cpu { global_idles += idles; //? Calculate cpu total for each core - if (i > Shared::coreCount) break; const long long calc_totals = max(0ll, totals - core_old_totals.at(i)); const long long calc_idles = max(0ll, idles - core_old_idles.at(i)); core_old_totals.at(i) = totals; @@ -441,7 +454,7 @@ namespace Cpu { Logger::error("Cpu::collect() : {}", e.what()); throw std::runtime_error(fmt::format("collect() : {}", e.what())); } - + i++; } const long long calc_totals = max(1ll, global_totals - cpu_old.at("totals")); @@ -1222,7 +1235,7 @@ namespace Proc { } toggle_children = -1; } - + if (auto find_pid = (collapse != -1 ? collapse : expand); find_pid != -1) { auto collapser = rng::find(current_procs, find_pid, &proc_info::pid); if (collapser != current_procs.end()) {