hostinfo: actually parse cpu freq details

This commit is contained in:
Christian Hergert
2019-05-23 12:21:21 -07:00
parent a6848d1f4d
commit 5331e8bd7f

View File

@ -22,6 +22,7 @@
#include <ctype.h>
#include <fcntl.h>
#include <glib/gstdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -34,22 +35,23 @@
struct _SysprofHostinfoSource
{
GObject parent_instance;
GObject parent_instance;
guint handler;
gint n_cpu;
gint stat_fd;
guint handler;
gint n_cpu;
gint stat_fd;
GArray *freqs;
SysprofCaptureWriter *writer;
GArray *cpu_info;
gchar *stat_buf;
GArray *cpu_info;
gchar *stat_buf;
};
typedef struct
{
gint counter_base;
gdouble total;
gdouble freq;
glong last_user;
glong last_idle;
glong last_system;
@ -62,6 +64,12 @@ typedef struct
glong last_guest_nice;
} CpuInfo;
typedef struct
{
gint stat_fd;
gint64 max;
} CpuFreq;
static void source_iface_init (SysprofSourceInterface *iface);
G_DEFINE_TYPE_EXTENDED (SysprofHostinfoSource, sysprof_hostinfo_source, G_TYPE_OBJECT, 0,
@ -195,6 +203,40 @@ poll_cpu (SysprofHostinfoSource *self)
}
}
static gdouble
get_cpu_freq (SysprofHostinfoSource *self,
guint cpu)
{
const CpuFreq *freq;
g_assert (SYSPROF_IS_HOSTINFO_SOURCE (self));
g_assert (cpu < self->freqs->len);
freq = &g_array_index (self->freqs, CpuFreq, cpu);
if (freq->stat_fd > -1)
{
gchar buf[128];
gssize len;
lseek (freq->stat_fd, SEEK_SET, 0);
len = read (freq->stat_fd, buf, sizeof buf - 1);
if (len > 0 && len < sizeof buf)
{
gint64 val;
buf[len] = 0;
g_strstrip (buf);
val = g_ascii_strtoll (buf, NULL, 10);
return (gdouble)val / (gdouble)freq->max * 100.0;
}
}
return 0.0;
}
static void
publish_cpu (SysprofHostinfoSource *self)
{
@ -217,16 +259,16 @@ publish_cpu (SysprofHostinfoSource *self)
value++;
*id = info->counter_base + 1;
value->vdbl = info->freq;
value->vdbl = get_cpu_freq (self, i);
}
sysprof_capture_writer_set_counters (self->writer,
SYSPROF_CAPTURE_CURRENT_TIME,
-1,
getpid (),
counter_ids,
counter_values,
self->n_cpu * 2);
SYSPROF_CAPTURE_CURRENT_TIME,
-1,
getpid (),
counter_ids,
counter_values,
self->n_cpu * 2);
}
static gboolean
@ -256,6 +298,7 @@ sysprof_hostinfo_source_finalize (GObject *object)
g_clear_pointer (&self->writer, sysprof_capture_writer_unref);
g_clear_pointer (&self->cpu_info, g_array_unref);
g_clear_pointer (&self->stat_buf, g_free);
g_clear_pointer (&self->freqs, g_array_unref);
G_OBJECT_CLASS (sysprof_hostinfo_source_parent_class)->finalize (object);
}
@ -274,6 +317,7 @@ sysprof_hostinfo_source_init (SysprofHostinfoSource *self)
self->stat_fd = -1;
self->cpu_info = g_array_new (FALSE, TRUE, sizeof (CpuInfo));
self->stat_buf = g_malloc (PROC_STAT_BUF_SIZE);
self->freqs = g_array_new (FALSE, FALSE, sizeof (CpuFreq));
}
static void
@ -316,6 +360,17 @@ sysprof_hostinfo_source_stop (SysprofSource *source)
self->stat_fd = -1;
}
for (guint i = 0; i < self->freqs->len; i++)
{
CpuFreq *freq = &g_array_index (self->freqs, CpuFreq, i);
if (freq->stat_fd != -1)
close (freq->stat_fd);
}
if (self->freqs->len > 0)
g_array_remove_range (self->freqs, 0, self->freqs->len);
sysprof_source_emit_finished (SYSPROF_SOURCE (self));
}
@ -336,8 +391,12 @@ sysprof_hostinfo_source_prepare (SysprofSource *source)
for (guint i = 0; i < self->n_cpu; i++)
{
g_autofree gchar *max_path = NULL;
g_autofree gchar *cur_path = NULL;
g_autofree gchar *maxstr = NULL;
SysprofCaptureCounter *ctr = &counters[i*2];
CpuInfo info = { 0 };
CpuFreq freq = { 0 };
/*
* Request 2 counter values.
@ -358,6 +417,18 @@ sysprof_hostinfo_source_prepare (SysprofSource *source)
ctr++;
max_path = g_strdup_printf ("/sys/devices/system/cpu/cpu%u/cpufreq/scaling_max_freq", i);
cur_path = g_strdup_printf ("/sys/devices/system/cpu/cpu%u/cpufreq/scaling_cur_freq", i);
if (g_file_get_contents (max_path, &maxstr, NULL, NULL))
{
g_strstrip (maxstr);
freq.max = g_ascii_strtoll (maxstr, NULL, 10);
}
freq.stat_fd = g_open (cur_path, O_RDONLY);
g_array_append_val (self->freqs, freq);
ctr->id = info.counter_base + 1;
ctr->type = SYSPROF_CAPTURE_COUNTER_DOUBLE;
ctr->value.vdbl = 0;