From 2e3f34f5c1f7cff7621fa453e2315b3af62554e7 Mon Sep 17 00:00:00 2001 From: fraggerfox Date: Tue, 3 Aug 2021 08:35:02 +0530 Subject: [PATCH] NetBSD: Rework CPU counting. --- netbsd/NetBSDProcessList.c | 104 +++++++++++++++++++++++++++---------- netbsd/NetBSDProcessList.h | 2 +- netbsd/Platform.c | 2 +- 3 files changed, 78 insertions(+), 30 deletions(-) diff --git a/netbsd/NetBSDProcessList.c b/netbsd/NetBSDProcessList.c index 47bfeb23..e295c6e5 100644 --- a/netbsd/NetBSDProcessList.c +++ b/netbsd/NetBSDProcessList.c @@ -49,10 +49,62 @@ static char const *freqSysctls[] = { NULL }; -ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId) { - const int mib[] = { CTL_HW, HW_NCPU }; - const int fmib[] = { CTL_KERN, KERN_FSCALE }; +static void NetBSDProcessList_updateCPUcount(ProcessList* super) { + NetBSDProcessList* opl = (NetBSDProcessList*) super; + + // Definitions for sysctl(3), cf. https://nxr.netbsd.org/xref/src/sys/sys/sysctl.h#813 + const int mib_ncpu_existing[] = { CTL_HW, HW_NCPU }; // Number of existing CPUs + const int mib_ncpu_online[] = { CTL_HW, HW_NCPUONLINE }; // Number of online/active CPUs + int r; + unsigned int value; + size_t size; + + bool change = false; + + // Query the number of active/online CPUs. + size = sizeof(value); + r = sysctl(mib_ncpu_online, 2, &value, &size, NULL, 0); + if (r < 0 || value < 1) { + value = 1; + } + + if (value != super->activeCPUs) { + super->activeCPUs = value; + change = true; + } + + // Query the total number of CPUs. + size = sizeof(value); + r = sysctl(mib_ncpu_existing, 2, &value, &size, NULL, 0); + if (r < 0 || value < 1) { + value = super->activeCPUs; + } + + if (value != super->existingCPUs) { + opl->cpuData = xReallocArray(opl->cpuData, value + 1, sizeof(CPUData)); + super->existingCPUs = value; + change = true; + } + + // Reset CPU stats when number of online/existing CPU cores changed + if (change) { + CPUData* dAvg = &opl->cpuData[0]; + memset(dAvg, '\0', sizeof(CPUData)); + dAvg->totalTime = 1; + dAvg->totalPeriod = 1; + + for (unsigned int i = 0; i < super->existingCPUs; i++) { + CPUData* d = &opl->cpuData[i + 1]; + memset(d, '\0', sizeof(CPUData)); + d->totalTime = 1; + d->totalPeriod = 1; + } + } +} + +ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* pidMatchList, uid_t userId) { + const int fmib[] = { CTL_KERN, KERN_FSCALE }; size_t size; char errbuf[_POSIX2_LINE_MAX]; @@ -60,12 +112,7 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, H ProcessList* pl = (ProcessList*) npl; ProcessList_init(pl, Class(NetBSDProcess), usersTable, dynamicMeters, pidMatchList, userId); - size = sizeof(pl->cpuCount); - r = sysctl(mib, 2, &pl->cpuCount, &size, NULL, 0); - if (r < 0 || pl->cpuCount < 1) { - pl->cpuCount = 1; - } - npl->cpus = xCalloc(pl->cpuCount + 1, sizeof(CPUData)); + NetBSDProcessList_updateCPUcount(pl); size = sizeof(fscale); if (sysctl(fmib, 2, &fscale, &size, NULL, 0) < 0) { @@ -76,12 +123,6 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, H CRT_fatalError("pagesize sysconf call failed"); pageSizeKB = pageSize / ONE_K; - for (unsigned int i = 0; i <= pl->cpuCount; i++) { - CPUData* d = npl->cpus + i; - d->totalTime = 1; - d->totalPeriod = 1; - } - npl->kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf); if (npl->kd == NULL) { CRT_fatalError("kvm_openfiles() failed"); @@ -97,7 +138,7 @@ void ProcessList_delete(ProcessList* this) { kvm_close(npl->kd); } - free(npl->cpus); + free(npl->cpuData); ProcessList_done(this); free(this); @@ -266,7 +307,7 @@ static void NetBSDProcessList_scanProcs(NetBSDProcessList* this) { proc->m_virt = kproc->p_vm_vsize; proc->m_resident = kproc->p_vm_rssize; proc->percent_mem = (proc->m_resident * pageSizeKB) / (double)(this->super.totalMem) * 100.0; - proc->percent_cpu = CLAMP(getpcpu(kproc), 0.0, this->super.cpuCount * 100.0); + proc->percent_cpu = CLAMP(getpcpu(kproc), 0.0, this->super.activeCPUs * 100.0); proc->nlwp = kproc->p_nlwps; proc->nice = kproc->p_nice - 20; proc->time = 100 * (kproc->p_rtime_sec + ((kproc->p_rtime_usec + 500000) / 1000000)); @@ -353,9 +394,9 @@ static void NetBSDProcessList_scanCPUTime(NetBSDProcessList* this) { u_int64_t kernelTimes[CPUSTATES] = {0}; u_int64_t avg[CPUSTATES] = {0}; - for (unsigned int i = 0; i < this->super.cpuCount; i++) { + for (unsigned int i = 0; i < this->super.existingCPUs; i++) { getKernelCPUTimes(i, kernelTimes); - CPUData* cpu = this->cpus + i + 1; + CPUData* cpu = &this->cpuData[i + 1]; kernelCPUTimesToHtop(kernelTimes, cpu); avg[CP_USER] += cpu->userTime; @@ -366,29 +407,29 @@ static void NetBSDProcessList_scanCPUTime(NetBSDProcessList* this) { } for (int i = 0; i < CPUSTATES; i++) { - avg[i] /= this->super.cpuCount; + avg[i] /= this->super.activeCPUs; } - kernelCPUTimesToHtop(avg, this->cpus); + kernelCPUTimesToHtop(avg, &this->cpuData[0]); } static void NetBSDProcessList_scanCPUFrequency(NetBSDProcessList* this) { - unsigned int cpus = this->super.cpuCount; + unsigned int cpus = this->super.existingCPUs; bool match = false; char name[64]; int freq = 0; size_t freqSize; - for (unsigned int i = 0; i <= cpus; i++) { - this->cpus[i].frequency = NAN; + for (unsigned int i = 0; i < cpus; i++) { + this->cpuData[i + 1].frequency = NAN; } /* newer hardware supports per-core frequency, for e.g. ARM big.LITTLE */ - for (unsigned int i = 0; i <= cpus; i++) { + for (unsigned int i = 0; i < cpus; i++) { xSnprintf(name, sizeof(name), "machdep.cpufreq.cpu%u.current", i); freqSize = sizeof(freq); if (sysctlbyname(name, &freq, &freqSize, NULL, 0) != -1) { - this->cpus[i].frequency = freq; + this->cpuData[i + 1].frequency = freq; match = true; } } @@ -410,8 +451,8 @@ static void NetBSDProcessList_scanCPUFrequency(NetBSDProcessList* this) { } if (match) { - for (unsigned int i = 0; i <= cpus; i++) { - this->cpus[i].frequency = freq; + for (unsigned int i = 0; i < cpus; i++) { + this->cpuData[i + 1].frequency = freq; } } } @@ -433,3 +474,10 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { NetBSDProcessList_scanProcs(npl); } + +bool ProcessList_isCPUonline(const ProcessList* super, unsigned int id) { + assert(id < super->existingCPUs); + + // TODO: Support detecting online / offline CPUs. + return true; +} diff --git a/netbsd/NetBSDProcessList.h b/netbsd/NetBSDProcessList.h index c5e60444..1d1407d8 100644 --- a/netbsd/NetBSDProcessList.h +++ b/netbsd/NetBSDProcessList.h @@ -45,7 +45,7 @@ typedef struct NetBSDProcessList_ { ProcessList super; kvm_t* kd; - CPUData* cpus; + CPUData* cpuData; } NetBSDProcessList; diff --git a/netbsd/Platform.c b/netbsd/Platform.c index 25db2d84..d3840ad1 100644 --- a/netbsd/Platform.c +++ b/netbsd/Platform.c @@ -200,7 +200,7 @@ int Platform_getMaxPid() { double Platform_setCPUValues(Meter* this, int cpu) { const NetBSDProcessList* npl = (const NetBSDProcessList*) this->pl; - const CPUData* cpuData = &npl->cpus[cpu]; + const CPUData* cpuData = &npl->cpuData[cpu]; double total = cpuData->totalPeriod == 0 ? 1 : cpuData->totalPeriod; double totalPercent; double* v = this->values;