mirror of
https://git.freebsd.org/ports.git
synced 2025-04-30 18:46:38 -04:00
Qt-based library to query system information like CPU, memory usage and network traffic. PR: 278905 Approved by: jsm
307 lines
10 KiB
C++
307 lines
10 KiB
C++
--- cpustat.cpp.orig 2021-11-05 10:06:40 UTC
|
|
+++ cpustat.cpp
|
|
@@ -22,16 +22,65 @@
|
|
** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
**
|
|
** END_COMMON_COPYRIGHT_HEADER */
|
|
-
|
|
-
|
|
#include <unistd.h>
|
|
-
|
|
#include "cpustat.h"
|
|
+#ifdef HAVE_SYSCTL_H
|
|
+extern "C"
|
|
+{
|
|
+ #include <stdlib.h>
|
|
+ #include <limits.h>
|
|
+ #include <string.h>
|
|
+ #include <sys/resource.h> /* CPUSTATES */
|
|
+
|
|
+ #include <sys/types.h>
|
|
+ #include <sys/sysctl.h>
|
|
+}
|
|
+#endif
|
|
#include "cpustat_p.h"
|
|
|
|
|
|
namespace SysStat {
|
|
+#ifdef HAVE_SYSCTL_H
|
|
+char *GetFirstFragment(char *string, const char *delim)
|
|
+{
|
|
+ char *token = NULL;
|
|
|
|
+ token = strsep(&string, delim);
|
|
+ if (token != NULL)
|
|
+ {
|
|
+ /* We need only the first fragment, so no loop! */
|
|
+ return token;
|
|
+ }
|
|
+ else
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+int GetCpu(void)
|
|
+{
|
|
+ static int mib[] = { CTL_HW, HW_NCPU };
|
|
+ int buf;
|
|
+ size_t len = sizeof(int);
|
|
+
|
|
+ if (sysctl(mib, 2, &buf, &len, NULL, 0) < 0)
|
|
+ return 0;
|
|
+ else
|
|
+ return buf;
|
|
+}
|
|
+
|
|
+/* Frequence is in MHz */
|
|
+ulong CpuStatPrivate::CurrentFreq(QString mSource)
|
|
+{
|
|
+ ulong freq=0;
|
|
+ size_t len = sizeof(freq);
|
|
+ int i = mSource.mid(3).toInt();
|
|
+ if (sysctl(mib2[i],4,&freq, &len, NULL, 0) < 0) {
|
|
+ perror("sysctl");
|
|
+ return 0;
|
|
+ }
|
|
+ else
|
|
+ return freq;
|
|
+}
|
|
+#endif
|
|
CpuStatPrivate::CpuStatPrivate(CpuStat *parent)
|
|
: BaseStatPrivate(parent)
|
|
, mMonitoring(CpuStat::LoadAndFrequency)
|
|
@@ -39,7 +88,17 @@ CpuStatPrivate::CpuStatPrivate(CpuStat *parent)
|
|
mSource = defaultSource();
|
|
|
|
connect(mTimer, SIGNAL(timeout()), SLOT(timeout()));
|
|
-
|
|
+#ifdef HAVE_SYSCTL_H
|
|
+ size_t flen=2;
|
|
+ size_t alen=4;
|
|
+ sysctlnametomib("kern.cp_times",mib0,&flen);
|
|
+ sysctlnametomib("kern.cp_time",mib1,&flen);
|
|
+ int ncpu = GetCpu();
|
|
+ for (int i=0;i<ncpu;i++) {
|
|
+ QString cpu_sysctl_name = QString::fromLatin1("dev.cpu.%1.freq").arg(i);
|
|
+ sysctlnametomib(cpu_sysctl_name.toStdString().c_str(),mib2[i],&alen);
|
|
+ }
|
|
+#endif
|
|
mUserHz = sysconf(_SC_CLK_TCK);
|
|
|
|
updateSources();
|
|
@@ -47,6 +106,51 @@ CpuStatPrivate::CpuStatPrivate(CpuStat *parent)
|
|
|
|
void CpuStatPrivate::addSource(const QString &source)
|
|
{
|
|
+#ifdef HAVE_SYSCTL_H
|
|
+ char buf[1024];
|
|
+ char *tokens, *t;
|
|
+ ulong min = 0, max = 0;
|
|
+ size_t len = sizeof(buf);
|
|
+
|
|
+ /* The string returned by the dev.cpu.0.freq_levels sysctl
|
|
+ * is a space separated list of MHz/milliwatts.
|
|
+ */
|
|
+ if (source != QStringLiteral("cpu") && source.mid(0,3).toInt() >-1) {
|
|
+
|
|
+ if (sysctlbyname(QString::fromLatin1("dev.cpu.%1.freq_levels").arg(source.mid(0,3).toInt()).toStdString().c_str(), buf, &len, NULL, 0) < 0)
|
|
+ return;
|
|
+ }
|
|
+ t = strndup(buf, len);
|
|
+ if (t == NULL)
|
|
+ {
|
|
+ free(t);
|
|
+ return;
|
|
+ }
|
|
+ while ((tokens = strsep(&t, " ")) != NULL)
|
|
+ {
|
|
+ char *freq;
|
|
+ ulong res;
|
|
+
|
|
+ freq = GetFirstFragment(tokens, "/");
|
|
+ if (freq != NULL)
|
|
+ {
|
|
+ res = strtoul(freq, &freq, 10);
|
|
+ if (res > max)
|
|
+ {
|
|
+ max = res;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if ((min == 0) || (res < min))
|
|
+ min = res;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ }
|
|
+
|
|
+ free(t);
|
|
+ mBounds[source] = qMakePair(min, max);
|
|
+#else
|
|
bool ok = false;
|
|
|
|
uint min = readAllFile(qPrintable(QString::fromLatin1("/sys/devices/system/cpu/%1/cpufreq/scaling_min_freq").arg(source))).toUInt(&ok);
|
|
@@ -56,11 +160,34 @@ void CpuStatPrivate::addSource(const QString &source)
|
|
if (ok)
|
|
mBounds[source] = qMakePair(min, max);
|
|
}
|
|
+#endif
|
|
}
|
|
|
|
void CpuStatPrivate::updateSources()
|
|
{
|
|
mSources.clear();
|
|
+#ifdef HAVE_SYSCTL_H
|
|
+ mBounds.clear();
|
|
+ int cpu;
|
|
+
|
|
+ cpu = GetCpu();
|
|
+ mSources.append(QString::fromLatin1("cpu"));
|
|
+ for (int i =0;i<cpu;i++)
|
|
+ {
|
|
+ mSources.append(QString::fromLatin1("cpu%1").arg(i));
|
|
+ addSource(QString::fromLatin1("cpu%1").arg(i));
|
|
+ }
|
|
+ long max=0;
|
|
+ long min=0;
|
|
+ for (Bounds::ConstIterator I = mBounds.constBegin(); I != mBounds.constEnd(); ++I)
|
|
+ {
|
|
+ min += mBounds[I.key()].first;
|
|
+ max += mBounds[I.key()].second;
|
|
+
|
|
+ }
|
|
+
|
|
+ mBounds[QStringLiteral("cpu")] = qMakePair(min,max);
|
|
+#else
|
|
const QStringList rows = readAllFile("/proc/stat").split(QLatin1Char('\n'), Qt::SkipEmptyParts);
|
|
for (const QString &row : rows)
|
|
{
|
|
@@ -98,6 +225,7 @@ void CpuStatPrivate::updateSources()
|
|
addSource(QString::fromLatin1("cpu%1").arg(number));
|
|
}
|
|
}
|
|
+#endif
|
|
}
|
|
|
|
CpuStatPrivate::~CpuStatPrivate() = default;
|
|
@@ -124,6 +252,113 @@ void CpuStatPrivate::recalculateMinMax()
|
|
|
|
void CpuStatPrivate::timeout()
|
|
{
|
|
+#ifdef HAVE_SYSCTL_H
|
|
+ if ( (mMonitoring == CpuStat::LoadOnly)
|
|
+ || (mMonitoring == CpuStat::LoadAndFrequency) )
|
|
+ {
|
|
+ int cpuNumber=0;
|
|
+ long *cp_times=0;
|
|
+
|
|
+ if(mSource!=QLatin1String("cpu"))
|
|
+ {
|
|
+ size_t cp_size = sizeof(long) * CPUSTATES * GetCpu();
|
|
+ cp_times = (long *)malloc(cp_size);
|
|
+ cpuNumber = mSource.mid(0,3).toInt();
|
|
+ if (sysctl(mib0,2, cp_times, &cp_size, NULL, 0) < 0)
|
|
+ free(cp_times);
|
|
+ } else {
|
|
+ size_t cp_size = sizeof(long)*CPUSTATES;
|
|
+ cp_times = (long *)malloc(cp_size);
|
|
+ if(sysctl(mib1,2,cp_times,&cp_size,NULL,0) < 0)
|
|
+ {
|
|
+ perror("sysctl");
|
|
+ free(cp_times);
|
|
+ }
|
|
+ }
|
|
+ Values current;
|
|
+ current.user = static_cast<ulong>(cp_times[CP_USER+cpuNumber*CPUSTATES]);
|
|
+ current.nice = static_cast<ulong>(cp_times[CP_NICE+cpuNumber*CPUSTATES]);
|
|
+ current.system = static_cast<ulong>(cp_times[CP_SYS+cpuNumber*CPUSTATES]);
|
|
+ current.idle = static_cast<ulong>(cp_times[CP_IDLE+cpuNumber*CPUSTATES]);
|
|
+ current.other = static_cast<ulong>(cp_times[CP_INTR+cpuNumber*CPUSTATES]);
|
|
+ current.total = current.user + current.nice + current.system+current.idle+current.other;
|
|
+ float sumDelta = static_cast<float>(current.total - mPrevious.total);
|
|
+ if ((mPrevious.total != 0) && ((sumDelta < mIntervalMin) || (sumDelta > mIntervalMax)))
|
|
+ {
|
|
+ if (mMonitoring == CpuStat::LoadAndFrequency)
|
|
+ {
|
|
+ float freqRate = 1.0;
|
|
+ ulong freq = CurrentFreq(mSource);
|
|
+
|
|
+ if (mSource == QLatin1String("cpu")) {
|
|
+ freq=0;
|
|
+ for (Bounds::ConstIterator I = mBounds.constBegin(); I != mBounds.constEnd(); ++I) {
|
|
+ if (I.key() != QStringLiteral("cpu"))
|
|
+ {
|
|
+ freq += CurrentFreq(I.key());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (freq > 0)
|
|
+ {
|
|
+ freqRate = static_cast<float>(freq) / static_cast<float>(mBounds[mSource].second);
|
|
+ emit update(0.0, 0.0, 0.0, 0.0, static_cast<float>(freqRate), freq);
|
|
+ }
|
|
+ } else {
|
|
+ emit update(0.0, 0.0, 0.0, 0.0);
|
|
+ }
|
|
+ mPrevious.clear();
|
|
+ } else {
|
|
+ if (mMonitoring == CpuStat::LoadAndFrequency)
|
|
+ {
|
|
+ float freqRate = 1.0;
|
|
+ ulong freq = CurrentFreq(mSource);
|
|
+
|
|
+ if (freq > 0)
|
|
+ {
|
|
+ if (mSource == QLatin1String("cpu")) {
|
|
+ freq=0;
|
|
+ for (Bounds::ConstIterator I = mBounds.constBegin(); I != mBounds.constEnd(); ++I) {
|
|
+ if (I.key() != QStringLiteral("cpu"))
|
|
+ {
|
|
+ freq += CurrentFreq(I.key());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ freqRate = static_cast<float>(freq) / static_cast<float>(mBounds[mSource].second);
|
|
+ emit update(
|
|
+ static_cast<float>(current.user - mPrevious.user ) / sumDelta,
|
|
+ static_cast<float>(current.nice - mPrevious.nice ) / sumDelta,
|
|
+ static_cast<float>(current.system - mPrevious.system) / sumDelta,
|
|
+ static_cast<float>(current.other - mPrevious.other ) / sumDelta,
|
|
+ static_cast<float>(freqRate),
|
|
+ freq);
|
|
+
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ emit update(
|
|
+ static_cast<float>(current.user - mPrevious.user ) / sumDelta,
|
|
+ static_cast<float>(current.nice - mPrevious.nice ) / sumDelta,
|
|
+ static_cast<float>(current.system - mPrevious.system) / sumDelta,
|
|
+ static_cast<float>(current.other - mPrevious.other ) / sumDelta);
|
|
+ }
|
|
+
|
|
+ mPrevious = current;
|
|
+ }
|
|
+ free(cp_times);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ ulong freq = 0;
|
|
+
|
|
+ freq = CurrentFreq(mSource);
|
|
+ if (freq > 0)
|
|
+ emit update(freq);
|
|
+ }
|
|
+#else
|
|
if ( (mMonitoring == CpuStat::LoadOnly)
|
|
|| (mMonitoring == CpuStat::LoadAndFrequency) )
|
|
{
|
|
@@ -258,6 +493,7 @@ void CpuStatPrivate::timeout()
|
|
}
|
|
emit update(freq);
|
|
}
|
|
+#endif
|
|
}
|
|
|
|
QString CpuStatPrivate::defaultSource()
|