[gnome-battery-bench] System info: refactoring of cpu information
- From: Christian Kellner <gicmo src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-battery-bench] System info: refactoring of cpu information
- Date: Wed, 5 Jul 2017 14:19:20 +0000 (UTC)
commit 6fbb9ab4c76c72138c9789543657617fdadb09b7
Author: Christian Kellner <gicmo gnome org>
Date: Wed Jul 5 15:46:03 2017 +0200
System info: refactoring of cpu information
src/system-info.c | 501 +++++++++++++++++++++++++++++++++++++++++++----------
src/system-info.h | 2 +
2 files changed, 411 insertions(+), 92 deletions(-)
---
diff --git a/src/system-info.c b/src/system-info.c
index 7b763a4..e1f0db0 100644
--- a/src/system-info.c
+++ b/src/system-info.c
@@ -13,14 +13,18 @@
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
+#include <sys/utsname.h>
#include "util-sysfs.h"
-
#include "power-supply.h"
#include "config.h"
+static void value_set_string_or_unknown(GValue *value, const char *str);
+static char *gbb_strdup_clean(const char *input);
+
+
G_DEFINE_BOXED_TYPE (GbbPciClass, gbb_pci_class, gbb_pci_class_copy, gbb_pci_class_free)
GbbPciClass *
@@ -326,6 +330,361 @@ gbb_pci_device_discover(GUdevClient *client, int code, int sub, int progif)
return devices;
}
+/* *************************************************************************** */
+
+struct _GbbCpuClass
+{
+ GObjectClass parent_class;
+
+ gpointer padding[13];
+};
+
+
+typedef struct _GbbCpu {
+ GObject parent;
+
+ char *model_name;
+ char *architecture;
+
+ char *model;
+
+ char *vendor_id;
+ char *vendor_name;
+
+ guint number;
+ guint threads;
+ guint cores;
+ guint packages;
+
+} GbbCpu;
+
+enum {
+ PROP_CPU_0,
+ PROP_CPU_MODEL_NAME,
+ PROP_CPU_ARCHITECTURE,
+
+ PROP_CPU_VENDOR_ID,
+ PROP_CPU_VENDOR_NAME,
+
+ PROP_CPU_NUMBER,
+ PROP_CPU_THREADS,
+ PROP_CPU_CORES,
+ PROP_CPU_PACKAGES,
+
+ PROP_CPU_LAST
+};
+
+static GParamSpec *cpu_props[PROP_CPU_LAST] = { NULL, };
+
+G_DEFINE_TYPE(GbbCpu,
+ gbb_cpu,
+ G_TYPE_OBJECT);
+
+static void
+gbb_cpu_finalize(GObject *object)
+{
+ GbbCpu *cpu = GBB_CPU(object);
+
+ g_free(cpu->model_name);
+ g_free(cpu->architecture);
+
+ g_free(cpu->model);
+
+ g_free(cpu->vendor_id);
+ g_free(cpu->vendor_name);
+}
+
+
+static void
+gbb_cpu_get_property(GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbbCpu *cpu = GBB_CPU(object);
+
+ switch (prop_id) {
+ case PROP_CPU_MODEL_NAME:
+ value_set_string_or_unknown(value, cpu->model_name);
+ break;
+
+ case PROP_CPU_ARCHITECTURE:
+ value_set_string_or_unknown(value, cpu->architecture);
+ break;
+
+ case PROP_CPU_VENDOR_ID:
+ value_set_string_or_unknown(value, cpu->vendor_id);
+ break;
+
+ case PROP_CPU_VENDOR_NAME:
+ if (!cpu->vendor_name) {
+ value_set_string_or_unknown(value, cpu->vendor_id);
+ } else {
+ g_value_set_string(value, cpu->vendor_name);
+ }
+ break;
+
+ case PROP_CPU_NUMBER:
+ g_value_set_uint(value, cpu->number);
+ break;
+
+ case PROP_CPU_THREADS:
+ g_value_set_uint(value, cpu->threads);
+ break;
+
+ case PROP_CPU_CORES:
+ g_value_set_uint(value, cpu->cores);
+ break;
+
+ case PROP_CPU_PACKAGES:
+ g_value_set_uint(value, cpu->packages);
+ break;
+ }
+}
+
+
+static void
+gbb_cpu_class_init(GbbCpuClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = gbb_cpu_finalize;
+ gobject_class->get_property = gbb_cpu_get_property;
+
+ cpu_props[PROP_CPU_MODEL_NAME] =
+ g_param_spec_string("model-name",
+ NULL, NULL,
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ cpu_props[PROP_CPU_ARCHITECTURE] =
+ g_param_spec_string("architecture",
+ NULL, NULL,
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+
+ cpu_props[PROP_CPU_VENDOR_ID] =
+ g_param_spec_string("vendor",
+ NULL, NULL,
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ cpu_props[PROP_CPU_VENDOR_NAME] =
+ g_param_spec_string("vendor-name",
+ NULL, NULL,
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ cpu_props[PROP_CPU_NUMBER] =
+ g_param_spec_uint("number",
+ NULL, NULL,
+ 0, G_MAXUINT, 1,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ cpu_props[PROP_CPU_THREADS] =
+ g_param_spec_uint("threads",
+ NULL, NULL,
+ 0, G_MAXUINT, 1,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ cpu_props[PROP_CPU_CORES] =
+ g_param_spec_uint("cores",
+ NULL, NULL,
+ 0, G_MAXUINT, 1,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ cpu_props[PROP_CPU_PACKAGES] =
+ g_param_spec_uint("packages",
+ NULL, NULL,
+ 0, G_MAXUINT, 1,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ g_object_class_install_properties(gobject_class,
+ PROP_CPU_LAST,
+ cpu_props);
+}
+
+
+static gsize
+_cpu_block_handle(GHashTable *values, GStrv kv, gsize *mark)
+{
+ gsize i;
+
+ for (i = *mark; i < g_strv_length(kv); i++) {
+ char *entry = kv[i];
+ char *pos;
+
+ entry = g_strchomp(entry);
+ if (strlen(entry) == 0) {
+ return i;
+ }
+
+ pos = g_strstr_len(entry, -1, ":");
+ if (pos == NULL) {
+ g_warning("cpu block: unexpected k, v pair [%s]\n", entry);
+ continue;
+ }
+ *pos = '\0';
+ pos++;
+
+ while (*pos == ' ' && *pos != '\n') {
+ pos++;
+ }
+
+ entry = g_strchomp(entry);
+ g_hash_table_insert(values, (void *) entry, (void *) pos);
+ }
+
+ return i;
+}
+
+static gboolean
+fill_field_string(GHashTable *kv,
+ const char *key,
+ char **field)
+{
+ const char *value = g_hash_table_lookup(kv, key);
+
+ if (value == NULL) {
+ return FALSE;
+ }
+
+ *field = gbb_strdup_clean(value);
+ return TRUE;
+}
+
+static gboolean
+fill_value_uint(GHashTable *kv,
+ const char *key,
+ guint *field)
+{
+ const char *value = g_hash_table_lookup(kv, key);
+ char *end = NULL;
+ guint64 ival;
+
+ if (value == NULL) {
+ return FALSE;
+ }
+
+ ival = g_ascii_strtoull(value, &end, 10);
+ if (end == value || ival > G_MAXUINT) {
+ return FALSE;
+ }
+
+ *field = (guint) ival;
+ return TRUE;
+}
+
+static GbbCpu *
+cpus_fill_data(GbbCpu *cpu, GHashTable *kv)
+{
+ struct utsname un_info;
+ int un_res;
+
+ /* fill in the basic data */
+ un_res = uname(&un_info);
+
+ if (un_res != -1) {
+ cpu->architecture = gbb_strdup_clean(un_info.machine);
+ }
+
+ fill_field_string(kv, "model name", &cpu->model_name);
+ fill_field_string(kv, "model", &cpu->model);
+ fill_field_string(kv, "vendor_id", &cpu->vendor_id);
+
+ return cpu;
+}
+
+static gboolean
+cpu_load_info(GbbCpu *cpu, GError **error)
+{
+ g_autofree char *data;
+ g_autoptr(GHashTable) values = NULL;
+ g_auto(GStrv) kv = NULL;
+ gsize i;
+ gboolean ok;
+
+ ok = g_file_get_contents("/proc/cpuinfo", &data, NULL, error);
+
+ if (!ok) {
+ return FALSE;
+ }
+
+ kv = g_strsplit(data, "\n", -1);
+ values = g_hash_table_new(g_str_hash, g_str_equal);
+
+ for (i = 0; i < g_strv_length(kv); i++) {
+ GbbCpu *cur;
+ guint num;
+
+ g_hash_table_remove_all(values);
+ gsize p = _cpu_block_handle(values, kv, &i);
+ if (p == i)
+ break;
+ i = p;
+
+ cur = cpus_fill_data(cpu, values);
+
+ if (fill_value_uint(values, "processor", &num)) {
+ cur->number = num + 1;
+ }
+
+ if (fill_value_uint(values, "cpu cores", &num)) {
+ cur->cores = num;
+ } else if (fill_value_uint(values, "core id", &num)) {
+ cur->cores = num + 1;
+ }
+
+ if (fill_value_uint(values, "physical id", &num)) {
+ cur->packages = num + 1;
+ }
+ }
+
+ cpu->threads = cpu->number / (cpu->cores * cpu->packages);
+
+ if (cpu->vendor_id) {
+ const char *v = cpu->vendor_id;
+ if (g_str_equal(v, "GenuineIntel")) {
+ cpu->vendor_name = g_strdup("Intel");
+ } else if (g_str_equal(v, "AMDisbetter!") ||
+ g_str_equal(v, "AuthenticAMD")) {
+ cpu->vendor_name = g_strdup("AMD");
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+gbb_cpu_init(GbbCpu *cpu)
+{
+}
+
+static GbbCpu *
+gbb_cpu_discover(GError **error)
+{
+ GbbCpu *cpu = g_object_new(GBB_TYPE_CPU, NULL);
+ gboolean ok = cpu_load_info(cpu, error);
+
+ if (!ok) {
+ g_object_unref(cpu);
+ return NULL;
+ }
+
+ return cpu;
+}
+
+/* *************************************************************************** */
+
struct _GbbSystemInfo {
GObject parent;
@@ -341,8 +700,7 @@ struct _GbbSystemInfo {
char *bios_vendor;
/* CPU*/
- guint cpu_number;
- GStrv cpu_info;
+ GbbCpu *cpu;
guint64 mem_total;
@@ -392,8 +750,7 @@ enum {
PROP_BIOS_VENDOR,
PROP_BIOS_DATE,
- PROP_CPU_NUMBER,
- PROP_CPU_INFO,
+ PROP_CPU,
PROP_MEM_TOTAL,
PROP_BATTERIES,
@@ -445,7 +802,7 @@ gbb_system_info_finalize(GbbSystemInfo *info)
g_free(info->bios_date);
g_free(info->bios_vendor);
- g_strfreev(info->cpu_info);
+ g_object_unref(info->cpu);
g_ptr_array_unref(info->batteries);
@@ -508,12 +865,8 @@ gbb_system_info_get_property (GObject *object, guint prop_id, GValue *value, GPa
value_set_string_or_unknown(value, info->bios_vendor);
break;
- case PROP_CPU_NUMBER:
- g_value_set_uint(value, info->cpu_number);
- break;
-
- case PROP_CPU_INFO:
- g_value_set_boxed(value, info->cpu_info);
+ case PROP_CPU:
+ g_value_set_object(value, info->cpu);
break;
case PROP_MEM_TOTAL:
@@ -629,18 +982,12 @@ gbb_system_info_class_init (GbbSystemInfoClass *klass)
NULL, NULL,
NULL,
G_PARAM_READABLE);
+ props[PROP_CPU] =
+ g_param_spec_object("cpu",
+ NULL, NULL,
+ GBB_TYPE_CPU,
+ G_PARAM_READABLE);
- props[PROP_CPU_NUMBER] =
- g_param_spec_uint("cpu-number",
- NULL, NULL,
- 0, G_MAXUINT, 0,
- G_PARAM_READABLE);
-
- props[PROP_CPU_INFO] =
- g_param_spec_boxed("cpu-info",
- NULL, NULL,
- G_TYPE_STRV,
- G_PARAM_READABLE);
props[PROP_MEM_TOTAL] =
g_param_spec_uint64("mem-total",
NULL, NULL,
@@ -862,65 +1209,6 @@ report_format_error(const char *filename, const char *message)
#endif
}
-static GStrv
-read_cpu_info(guint *ncpus)
-{
- g_autofree char *data = read_sysfs_string("/proc/cpuinfo");
- g_autoptr(GHashTable) cpus = NULL;
- g_auto(GStrv) kv = NULL;
- GStrv models = NULL;
- gsize i, n = 0;
- gpointer key, val;
- GHashTableIter iter;
-
- if (data == NULL) {
- return NULL;
- }
-
- cpus = g_hash_table_new (g_str_hash, g_str_equal);
-
- kv = g_strsplit(data, "\n", -1);
- for (i = 0; i < g_strv_length(kv); i++) {
- const char *entry = kv[i];
- const char *pos;
- if (!g_str_has_prefix(entry, "model name")) {
- continue;
- }
-
- pos = g_strstr_len(entry, -1, ":");
- if (pos == NULL) {
- report_format_error("/proc/cpuinfo", "expected a ':'");
- continue;
- }
- pos++;
-
- while (*pos == ' ' && *pos != '\n') {
- pos++;
- }
-
- val = g_hash_table_lookup(cpus, pos);
- if (val == NULL) {
- g_hash_table_insert(cpus, (gpointer) pos, GINT_TO_POINTER(1));
- } else {
- val = GINT_TO_POINTER(GPOINTER_TO_INT(val) + 1);
- g_hash_table_replace(cpus, (gpointer) pos, val);
- }
- }
-
- n = i = 0;
- g_hash_table_iter_init (&iter, cpus);
- models = (GStrv) g_new(char *, g_hash_table_size(cpus) + 1);
- while (g_hash_table_iter_next (&iter, &key, &val)) {
- int k = GPOINTER_TO_INT(val);
- models[i] = g_strdup_printf("%s [%d]", (char *) key, k);
- n += k;
- i++;
- }
- models[i] = NULL;
- *ncpus = n;
- return models;
-}
-
static guint64
read_mem_info(void)
{
@@ -1169,7 +1457,7 @@ static void gbb_system_info_init (GbbSystemInfo *info)
info->os_type = get_os_type();
info->os_kernel = read_kernel_version();
- info->cpu_info = read_cpu_info(&info->cpu_number);
+ info->cpu = gbb_cpu_discover(NULL);
info->mem_total = read_mem_info();
info->batteries = get_batteries();
info->gpus = gbb_pci_device_discover(NULL, 3, -1, -1);
@@ -1240,18 +1528,47 @@ gbb_system_info_to_json (const GbbSystemInfo *info, JsonBuilder *builder)
json_builder_end_object(builder);
}
- if (info->cpu_number > 0) {
- json_builder_set_member_name(builder, "cpu");
+ if (info->cpu > 0) {
+ g_autofree char *model_name = NULL;
+ g_autofree char *arch = NULL;
+ g_autofree char *vendor = NULL;
+ g_autofree char *vendor_name = NULL;
+ guint number, threads, cores, packages;
+
+ g_object_get(info->cpu,
+ "model-name", &model_name,
+ "architecture", &arch,
+ "vendor", &vendor,
+ "vendor-name", &vendor_name,
+ "number", &number,
+ "threads", &threads,
+ "cores", &cores,
+ "packages", &packages,
+ NULL);
+
+ json_builder_set_member_name(builder, "cpu");
json_builder_begin_object(builder);
+
+ jsb_add_kv_string(builder, "model-name", model_name);
+
+ jsb_add_kv_string(builder, "vendor-name", vendor_name);
+ jsb_add_kv_string(builder, "vendor", vendor);
+ jsb_add_kv_string(builder, "architecture", arch);
+
json_builder_set_member_name(builder, "number");
- json_builder_add_int_value(builder, info->cpu_number);
- json_builder_set_member_name(builder, "info");
- json_builder_begin_array(builder);
- for (i = 0; i < g_strv_length(info->cpu_info); i++) {
- json_builder_add_string_value(builder, info->cpu_info[i]);
- }
- json_builder_end_array(builder);
+ json_builder_add_int_value(builder, number);
+
+ json_builder_set_member_name(builder, "threads");
+ json_builder_add_int_value(builder, threads);
+
+ json_builder_set_member_name(builder, "cores");
+ json_builder_add_int_value(builder, cores);
+
+ json_builder_set_member_name(builder, "packages");
+ json_builder_add_int_value(builder, packages);
+
+
json_builder_end_object(builder);
}
diff --git a/src/system-info.h b/src/system-info.h
index d331641..c8ce62b 100644
--- a/src/system-info.h
+++ b/src/system-info.h
@@ -21,6 +21,8 @@ void gbb_pci_class_free (GbbPciClass *klass);
#define GBB_TYPE_PCI_DEVICE gbb_pci_device_get_type()
G_DECLARE_DERIVABLE_TYPE(GbbPciDevice, gbb_pci_device, GBB, PCI_DEVICE, GObject)
+#define GBB_TYPE_CPU gbb_cpu_get_type()
+G_DECLARE_FINAL_TYPE(GbbCpu, gbb_cpu, GBB, CPU, GObject)
#define GBB_TYPE_SYSTEM_INFO gbb_system_info_get_type()
G_DECLARE_FINAL_TYPE(GbbSystemInfo, gbb_system_info, GBB, SYSTEM_INFO, GObject)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]