KCPULoad – a small CPU meter for Kicker
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

200 lines
5.0 KiB

/***************************************************************************
* *
* KCPULoad is copyright (c) 1999-2000, Markus Gustavsson *
* (c) 2002, Ben Burton *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "kcpuproc.h"
#include <cstdlib>
#include <cstring>
// BSD-specific includes.
#ifdef Q_OS_BSD4
#include <sys/param.h>
#if defined(__FreeBSD__) && __FreeBSD_version >= 500101
#include <sys/resource.h>
#else
#include <sys/dkstat.h>
#endif
#include <sys/sysctl.h>
#include <string.h>
#include <kvm.h>
#ifdef Q_OS_NETBSD
#include <sys/sched.h>
#endif
#endif
/**
* Linux
* -----
*
* System information is read from /proc/stat.
*
* We assume /proc/stat is in one of the following formats:
*
* cpu %d %d %d %d
* ....
*
* cpu %d %d %d %d
* cpu0 %d %d %d %d
* ....
*
* cpu %d %d %d %d
* cpu0 %d %d %d %d
* cpu1 %d %d %d %d
* ....
*
* where each set of four numbers is of the form:
*
* user_ticks nice_ticks system_ticks idle_ticks
*
* We also allow sets of seven numbers instead of four (as provided by
* the 2.6 kernel); the last three of these numbers are ignored.
*
* BSD
* ---
*
* Currently only uni-processor mode is supported for BSD.
*
* BSD code by Andy Fawcett <andy@athame.co.uk> and
* Robbie Ward <linuxphreak@gmx.co.uk>, licensed under GPL2.
*
* Other Operating Systems
* -----------------------
*
* Please, send in a patch!
*
* The KCPULoad maintainer is currently Ben Burton <bab@debian.org>, or
* you could submit a patch through the KDE bug tracking system
* (bugs.kde.org).
*/
KCPUProc::CPU::Ticks::Ticks() :
U(0), S(0), N(0), I(0)
{ }
KCPUProc::KCPUProc() {
smp = false;
// Look for SMP support and take a current tick reading.
// ========== BSD-specific (begin) ==========
#ifdef Q_OS_BSD4
readLoad();
return;
#endif
// ========== BSD-specific (end) ==========
// ========== Linux-specific (begin) ==========
#ifdef Q_OS_LINUX
if ((fd = fopen("/proc/stat", "r")) == 0)
return;
if (!all.parse(fd))
return;
CPU c;
while (c.parse(fd))
cpu.push_back(c);
smp = cpu.size() > 1;
#endif
// ========== Linux-specific (end) ==========
}
void KCPUProc::readLoad() {
// OS-specific local variables.
// ========== Linux-specific (begin) ==========
#ifdef Q_OS_LINUX
// Prepare to take the readings.
if ((fd = fopen("/proc/stat", "r")) == 0)
return;
// Take a fresh set of current readings (SMP mode).
all.parse(fd);
for (int i = 0; i < cpu.size(); i++) {
if (!cpu[i].parse(fd))
break;
}
// Clean up after taking readings.
fclose(fd);
#endif
// ========== Linux-specific (end) ==========
// ========== BSD-specific (begin) ==========
#ifdef Q_OS_BSD4
static int name2oid[2] = { 0, 3 };
static int oidCpuTime[CTL_MAXNAME + 2];
static size_t oidCpuTimeLen = sizeof(oidCpuTime);
long cpuTime[CPUSTATES];
size_t cpuTimeLen = sizeof(cpuTime);
static char *name = "kern.cp_time";
static int initialized = 0;
if(smp) {
// Take a fresh set of current readings (SMP mode).
// TODO: Add SMP support for BSD.
} else {
// Take a fresh set of current readings (uni-processor mode).
// The current readings must now become the previous readings.
all.p = all.c;
if (! initialized) {
if (sysctl(name2oid, 2, oidCpuTime, &oidCpuTimeLen, name,
strlen(name)) < 0)
return;
oidCpuTimeLen /= sizeof(int);
initialized = 1;
}
if (sysctl(oidCpuTime, oidCpuTimeLen, cpuTime, &cpuTimeLen, 0, 0) < 0)
return;
all.c.U = cpuTime[CP_USER];
all.c.N = cpuTime[CP_NICE];
all.c.S = cpuTime[CP_SYS];
all.c.I = cpuTime[CP_IDLE];
}
#endif
// ========== BSD-specific (end) ==========
}
// ========== Linux-specific (begin) ==========
#ifdef Q_OS_LINUX
bool KCPUProc::CPU::parse(FILE* fd) {
char tagbuffer[32+1];
Ticks n; // new ticks
if (fscanf(fd, "%32s%d%d%d%d", tagbuffer, &n.U, &n.N, &n.S, &n.I) != 5) {
return false; // failure
}
if (strncmp(tagbuffer, "cpu", 3) != 0) {
return false; // tag mismatch
}
// shift readings
p = c;
c = n;
// ignore the rest of the line
int ch;
do {
ch = getc(fd);
} while (ch != '\n' && ch != EOF);
return true;
}
#endif
// ========== Linux-specific (end) ==========