Skip to content

Commit

Permalink
OpenBSD: support offline CPUs and hot-swapping
Browse files Browse the repository at this point in the history
  • Loading branch information
cgzones committed Jun 13, 2021
1 parent cb8c42e commit 5ff6d27
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 66 deletions.
123 changes: 68 additions & 55 deletions openbsd/OpenBSDProcessList.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,33 +36,74 @@ static long fscale;
static int pageSize;
static int pageSizeKB;

ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId) {
static void OpenBSDProcessList_updateCPUcount(ProcessList* super) {
OpenBSDProcessList* opl = (OpenBSDProcessList*) super;
const int nmib[] = { CTL_HW, HW_NCPU };
const int mib[] = { CTL_HW, HW_NCPUONLINE };
const int fmib[] = { CTL_KERN, KERN_FSCALE };
int r;
unsigned int cpu_index_c = 0;
unsigned int value;
size_t size;
char errbuf[_POSIX2_LINE_MAX];
bool change = false;

OpenBSDProcessList* opl = xCalloc(1, sizeof(OpenBSDProcessList));
ProcessList* pl = (ProcessList*) opl;
ProcessList_init(pl, Class(OpenBSDProcess), usersTable, pidMatchList, userId);
size = sizeof(value);
r = sysctl(mib, 2, &value, &size, NULL, 0);
if (r < 0 || value < 1) {
value = 1;
}

if (value != super->activeCPUs) {
super->activeCPUs = value;
change = true;
}

// TODO: test offline CPUs and hot swapping
size = sizeof(value);
r = sysctl(nmib, 2, &value, &size, NULL, 0);
if (r < 0 || value < 1) {
value = super->activeCPUs;
}

size = sizeof(pl->activeCPUs);
r = sysctl(mib, 2, &pl->activeCPUs, &size, NULL, 0);
if (r < 0 || pl->activeCPUs < 1) {
pl->activeCPUs = 1;
if (value != super->existingCPUs) {
opl->cpuData = xReallocArray(opl->cpuData, value + 1, sizeof(CPUData));
super->existingCPUs = value;
change = true;
}
opl->cpus = xCalloc(pl->activeCPUs + 1, sizeof(CPUData));

size = sizeof(int);
r = sysctl(nmib, 2, &pl->existingCPUs, &size, NULL, 0);
if (r < 0) {
pl->existingCPUs = pl->activeCPUs;
if (change) {
CPUData* dAvg = &opl->cpuData[0];
memset(dAvg, '\0', sizeof(CPUData));
dAvg->totalTime = 1;
dAvg->totalPeriod = 1;
dAvg->online = true;

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;

const int ncmib[] = { CTL_KERN, KERN_CPUSTATS, i };
struct cpustats cpu_stats;

size = sizeof(cpu_stats);
if (sysctl(ncmib, 3, &cpu_stats, &size, NULL, 0) < 0) {
CRT_fatalError("ncmib sysctl call failed");
}
d->online = (cpu_stats.cs_flags & CPUSTATS_ONLINE);
}
}
}


ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId) {
const int fmib[] = { CTL_KERN, KERN_FSCALE };
size_t size;
char errbuf[_POSIX2_LINE_MAX];

OpenBSDProcessList* opl = xCalloc(1, sizeof(OpenBSDProcessList));
ProcessList* pl = (ProcessList*) opl;
ProcessList_init(pl, Class(OpenBSDProcess), usersTable, pidMatchList, userId);

OpenBSDProcessList_updateCPUcount(pl);

size = sizeof(fscale);
if (sysctl(fmib, 2, &fscale, &size, NULL, 0) < 0) {
Expand All @@ -73,36 +114,13 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui
CRT_fatalError("pagesize sysconf call failed");
pageSizeKB = pageSize / ONE_K;

for (unsigned int i = 0; i <= pl->activeCPUs; i++) {
CPUData* d = opl->cpus + i;
d->totalTime = 1;
d->totalPeriod = 1;
}

opl->kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
if (opl->kd == NULL) {
CRT_fatalError("kvm_openfiles() failed");
}

opl->cpuSpeed = -1;

for (unsigned int i = 0; i < pl->existingCPUs; i++) {
const int ncmib[] = { CTL_KERN, KERN_CPUSTATS, i };
struct cpustats cpu_stats;

size = sizeof(cpu_stats);
if (sysctl(ncmib, 3, &cpu_stats, &size, NULL, 0) < 0) {
CRT_fatalError("ncmib sysctl call failed");
}
if (cpu_stats.cs_flags & CPUSTATS_ONLINE) {
opl->cpus[cpu_index_c].cpuIndex = i;
cpu_index_c++;
}

if (cpu_index_c == pl->activeCPUs)
break;
}

return pl;
}

Expand All @@ -113,7 +131,7 @@ void ProcessList_delete(ProcessList* this) {
kvm_close(opl->kd);
}

free(opl->cpus);
free(opl->cpuData);

ProcessList_done(this);
free(this);
Expand Down Expand Up @@ -275,8 +293,6 @@ static void OpenBSDProcessList_scanProcs(OpenBSDProcessList* this) {
Process* proc = ProcessList_getProcess(&this->super, (kproc->p_tid == -1) ? kproc->p_pid : kproc->p_tid, &preExisting, OpenBSDProcess_new);
OpenBSDProcess* fp = (OpenBSDProcess*) proc;

proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) || (hideUserlandThreads && Process_isUserlandThread(proc)));

if (!preExisting) {
proc->ppid = kproc->p_ppid;
proc->tpgid = kproc->p_tpgid;
Expand Down Expand Up @@ -345,6 +361,8 @@ static void OpenBSDProcessList_scanProcs(OpenBSDProcessList* this) {
if (proc->state == 'R') {
this->super.runningTasks++;
}

proc->show = ! ((hideKernelThreads && Process_isKernelThread(proc)) || (hideUserlandThreads && Process_isUserlandThread(proc)));
proc->updated = true;
}
}
Expand All @@ -353,7 +371,7 @@ static unsigned long long saturatingSub(unsigned long long a, unsigned long long
return a > b ? a - b : 0;
}

static void getKernelCPUTimes(int cpuId, u_int64_t* times) {
static void getKernelCPUTimes(unsigned int cpuId, u_int64_t* times) {
const int mib[] = { CTL_KERN, KERN_CPTIME2, cpuId };
size_t length = sizeof(*times) * CPUSTATES;
if (sysctl(mib, 3, times, &length, NULL, 0) == -1 || length != sizeof(*times) * CPUSTATES) {
Expand Down Expand Up @@ -402,9 +420,9 @@ static void OpenBSDProcessList_scanCPUTime(OpenBSDProcessList* this) {
u_int64_t kernelTimes[CPUSTATES] = {0};
u_int64_t avg[CPUSTATES] = {0};

for (unsigned int i = 0; i < this->super.activeCPUs; i++) {
getKernelCPUTimes(this->cpus[i].cpuIndex, kernelTimes);
CPUData* cpu = this->cpus + i + 1;
for (unsigned int i = 0; i < this->super.existingCPUs; i++) {
getKernelCPUTimes(i, kernelTimes);
CPUData* cpu = &this->cpuData[i + 1];
kernelCPUTimesToHtop(kernelTimes, cpu);

avg[CP_USER] += cpu->userTime;
Expand All @@ -421,7 +439,7 @@ static void OpenBSDProcessList_scanCPUTime(OpenBSDProcessList* this) {
avg[i] /= this->super.activeCPUs;
}

kernelCPUTimesToHtop(avg, this->cpus);
kernelCPUTimesToHtop(avg, &this->cpuData[0]);

{
const int mib[] = { CTL_HW, HW_CPUSPEED };
Expand All @@ -438,6 +456,7 @@ static void OpenBSDProcessList_scanCPUTime(OpenBSDProcessList* this) {
void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
OpenBSDProcessList* opl = (OpenBSDProcessList*) super;

OpenBSDProcessList_updateCPUcount(super);
OpenBSDProcessList_scanMemoryInfo(super);
OpenBSDProcessList_scanCPUTime(opl);

Expand All @@ -453,11 +472,5 @@ bool ProcessList_isCPUonline(const ProcessList* super, unsigned int id) {
assert(id < super->existingCPUs);

const OpenBSDProcessList* opl = (const OpenBSDProcessList*) super;

for (unsigned int i = 0; i < super->activeCPUs; i++) {
if (opl->cpus[i].cpuIndex == id)
return true;
}

return false;
return opl->cpuData[id + 1].online;
}
4 changes: 2 additions & 2 deletions openbsd/OpenBSDProcessList.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ typedef struct CPUData_ {
unsigned long long int intrPeriod;
unsigned long long int idlePeriod;

unsigned int cpuIndex;
bool online;
} CPUData;

typedef struct OpenBSDProcessList_ {
ProcessList super;
kvm_t* kd;

CPUData* cpus;
CPUData* cpuData;
int cpuSpeed;

} OpenBSDProcessList;
Expand Down
11 changes: 2 additions & 9 deletions openbsd/Platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,19 +169,12 @@ int Platform_getMaxPid() {

double Platform_setCPUValues(Meter* this, unsigned int cpu) {
const OpenBSDProcessList* pl = (const OpenBSDProcessList*) this->pl;
const CPUData* cpuData = NULL;
const CPUData* cpuData = &(pl->cpuData[cpu]);
double total;
double totalPercent;
double* v = this->values;

for (unsigned int i = 0; i < pl->super.activeCPUs; i++) {
if (pl->cpus[i].cpuIndex == cpu) {
cpuData = &(pl->cpus[i]);
break;
}
}

if (!cpuData) {
if (!cpuData->online) {
this->curItems = 0;
return NAN;
}
Expand Down

0 comments on commit 5ff6d27

Please sign in to comment.