/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2007 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include #include #include #if defined(sun) && defined(__SVR4) #include #include #endif #ifdef HAVE_UNISTD_H #include #endif /* HAVE_UNISTD_H */ #include #include "gpm-common.h" #include "gpm-marshal.h" #include "egg-debug.h" #include "gpm-load.h" static void gpm_load_finalize (GObject *object); struct GpmLoadPrivate { long unsigned old_idle; long unsigned old_total; }; static gpointer gpm_load_object = NULL; G_DEFINE_TYPE_WITH_PRIVATE (GpmLoad, gpm_load, G_TYPE_OBJECT) /** * gpm_load_class_init: * @klass: This class instance **/ static void gpm_load_class_init (GpmLoadClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gpm_load_finalize; } #if defined(sun) && defined(__SVR4) /** * gpm_load_get_cpu_values: * @cpu_idle: The idle time reported by the CPU * @cpu_total: The total time reported by the CPU * Return value: Success of reading /proc/stat. **/ static gboolean gpm_load_get_cpu_values (long unsigned *cpu_idle, long unsigned *cpu_total) { long unsigned cpu_user = 0; long unsigned cpu_kernel = 0; long unsigned cpu_wait = 0; kstat_ctl_t *kc = NULL; kstat_named_t *kn = NULL; kstat_t *ks = NULL; cpu_stat_t data; int ncpus; int count; kc = kstat_open(); if (!kc) { egg_warning ("Cannot open kstat!\n"); return FALSE; } ks = kstat_lookup(kc, "unix", 0, "system_misc"); if (kstat_read(kc, ks, NULL) == -1) { egg_warning ("Cannot read kstat on module unix!\n"); goto out; } kn = kstat_data_lookup (ks, "ncpus"); if (!kn) { egg_warning ("Cannot get number of cpus in current system!\n"); goto out; } ncpus = kn->value.ui32; /* * To aggresive ticks used of all cpus, * traverse kstat chain to access very cpu_stat instane. */ for(count = 0, *cpu_idle =0, *cpu_total = 0; count < ncpus; count++){ ks = kstat_lookup(kc, "cpu_stat", count, NULL); if (ks == NULL) { egg_warning ("Null output for kstat on cpu%d\n", count); goto out; } if (kstat_read(kc, ks, &data) == -1) { egg_warning ("Cannot read kstat entry on cpu%d\n", count); goto out; } egg_debug ("cpu%d:\t%lu\t%lu\t%lu\t%lu\n", count, data.cpu_sysinfo.cpu[CPU_IDLE], data.cpu_sysinfo.cpu[CPU_USER], data.cpu_sysinfo.cpu[CPU_KERNEL], data.cpu_sysinfo.cpu[CPU_WAIT]); *cpu_idle += data.cpu_sysinfo.cpu[CPU_IDLE]; cpu_user += data.cpu_sysinfo.cpu[CPU_USER]; cpu_kernel += data.cpu_sysinfo.cpu[CPU_KERNEL]; cpu_wait += data.cpu_sysinfo.cpu[CPU_WAIT]; } kstat_close(kc); /* * Summing up all these times gives you the system uptime. * This is what the uptime command does. */ *cpu_total = cpu_user + cpu_kernel + cpu_wait + *cpu_idle; return TRUE; out: kstat_close(kc); return FALSE; } #else /** * gpm_load_get_cpu_values: * @cpu_idle: The idle time reported by the CPU * @cpu_total: The total time reported by the CPU * Return value: Success of reading /proc/stat. **/ static gboolean gpm_load_get_cpu_values (long unsigned *cpu_idle, long unsigned *cpu_total) { long unsigned cpu_user; long unsigned cpu_nice; long unsigned cpu_system; int len; char tmp[5]; char str[80]; FILE *fd; char *suc; gboolean ret = FALSE; /* open file */ fd = fopen("/proc/stat", "r"); if (!fd) goto out; /* get data */ suc = fgets (str, 80, fd); if (suc == NULL) goto out; /* parse */ len = sscanf (str, "%s %lu %lu %lu %lu", tmp, &cpu_user, &cpu_nice, &cpu_system, cpu_idle); if (len != 5) goto out; /* summing up all these times gives you the system uptime in jiffies */ *cpu_total = cpu_user + cpu_nice + cpu_system + *cpu_idle; ret = TRUE; out: if (fd) fclose (fd); return ret; } #endif /* sun & __SVR4 */ /** * gpm_load_get_current: * @load: This class instance * Return value: The CPU idle load **/ gdouble gpm_load_get_current (GpmLoad *load) { double percentage_load; long unsigned cpu_idle; long unsigned cpu_total; long unsigned diff_idle; long unsigned diff_total; gboolean ret; /* work out the differences */ ret = gpm_load_get_cpu_values (&cpu_idle, &cpu_total); if (!ret) return 0.0; diff_idle = cpu_idle - load->priv->old_idle; diff_total = cpu_total - load->priv->old_total; /* If we divide the total time by idle time we get the load. */ if (diff_idle > 0) percentage_load = (double) diff_total / (double) diff_idle; else percentage_load = 100; load->priv->old_idle = cpu_idle; load->priv->old_total = cpu_total; return percentage_load; } /** * gpm_load_init: */ static void gpm_load_init (GpmLoad *load) { load->priv = gpm_load_get_instance_private (load); load->priv->old_idle = 0; load->priv->old_total = 0; /* we have to populate the values at startup */ gpm_load_get_cpu_values (&load->priv->old_idle, &load->priv->old_total); } /** * gpm_load_coldplug: * * @object: This load instance */ static void gpm_load_finalize (GObject *object) { GpmLoad *load; g_return_if_fail (object != NULL); g_return_if_fail (GPM_IS_LOAD (object)); load = GPM_LOAD (object); g_return_if_fail (load->priv != NULL); G_OBJECT_CLASS (gpm_load_parent_class)->finalize (object); } /** * gpm_load_new: * Return value: new GpmLoad instance. **/ GpmLoad * gpm_load_new (void) { if (gpm_load_object != NULL) { g_object_ref (gpm_load_object); } else { gpm_load_object = g_object_new (GPM_TYPE_LOAD, NULL); g_object_add_weak_pointer (gpm_load_object, &gpm_load_object); } return GPM_LOAD (gpm_load_object); }