summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Creech <tcreech@umd.edu>2013-11-20 00:28:33 -0500
committerTim Creech <tcreech@umd.edu>2013-11-20 00:28:33 -0500
commit4fde25b4e7a64a07cebf094f8519cc668e72f43b (patch)
tree2429bc5836e8b330392e4634cdc18d232be2cc51
parenta391d71a98a92e2e39a8b24e07588ed466ec27a9 (diff)
downloadhtop-4fde25b4e7a64a07cebf094f8519cc668e72f43b.tar.gz
fill in sysdep_update_cpu_data from kstat
-rw-r--r--sysdeps/solaris.c155
1 files changed, 155 insertions, 0 deletions
diff --git a/sysdeps/solaris.c b/sysdeps/solaris.c
index 8a4b8b3..e0dab3b 100644
--- a/sysdeps/solaris.c
+++ b/sysdeps/solaris.c
@@ -7,9 +7,118 @@
#include <unistd.h>
#include <vm/anon.h>
+#include <kstat.h>
+#include <sys/cpuvar.h>
+#include <stdlib.h>
+
#include "htop-sysdeps.h"
#include "utils.h"
+static kstat_ctl_t *kc = NULL;
+static kid_t kcid = 0;
+static unsigned kstat_initialized = 0;
+
+/*
+ * int kstat_safe_namematch(int num, kstat_t *ksp, char *name, void *buf)
+ *
+ * Safe scan of kstat chain for names starting with "name". Matches
+ * are copied in to "ksp", and kstat_read is called on each match using
+ * "buf" as a buffer of length "size". The actual number of records
+ * found is returned. Up to "num" kstats are copied in to "ksp", but
+ * no more. If any kstat_read indicates that the chain has changed, then
+ * the whole process is restarted.
+ */
+int kstat_safe_namematch(int num, kstat_t **ksparg, char *name, void *buf, int size){
+ kstat_t *ks;
+ kstat_t **ksp;
+ kid_t new_kcid;
+ int namelen;
+ int count;
+ int changed;
+ char *cbuf;
+
+ namelen = strlen(name);
+
+ do {
+ /* initialize before the scan */
+ cbuf = (char *)buf;
+ ksp = ksparg;
+ count = 0;
+ changed = 0;
+
+ /* scan the chain for matching kstats */
+ for (ks = kc->kc_chain; ks != NULL; ks = ks->ks_next) {
+ if (strncmp(ks->ks_name, name, namelen) == 0) {
+ /* this kstat matches: save it if there is room */
+ if (count++ < num) {
+ /* read the kstat */
+ new_kcid = kstat_read(kc, ks, cbuf);
+
+ /* if the chain changed, update it */
+ if (new_kcid != kcid) {
+ changed = 1;
+ kcid = kstat_chain_update(kc);
+
+ /* there's no sense in continuing the scan */
+ /* so break out of the for loop */
+ break;
+ }
+
+ /* move to the next buffers */
+ cbuf += size;
+ *ksp++ = ks;
+ }
+ }
+ }
+ } while(changed);
+
+ return count;
+}
+
+static kstat_t *ks_system_misc = NULL;
+
+int kstat_safe_retrieve(kstat_t **ksp, char *module, int instance, char *name, void *buf){
+ kstat_t *ks;
+ kid_t new_kcid;
+ int changed;
+
+ ks = *ksp;
+ do {
+ changed = 0;
+ /* if we dont already have the kstat, retrieve it */
+ if (ks == NULL) {
+ if ((ks = kstat_lookup(kc, module, instance, name)) == NULL) {
+ return (-1);
+ }
+ *ksp = ks;
+ }
+
+ /* attempt to read it */
+ new_kcid = kstat_read(kc, ks, buf);
+ /* chance for an infinite loop here if kstat_read keeps
+ returning -1 */
+
+ /* if the chain changed, update it */
+ if (new_kcid != kcid) {
+ changed = 1;
+ kcid = kstat_chain_update(kc);
+ }
+ } while (changed);
+
+ return (0);
+}
+
+int get_ncpus(){
+ kstat_named_t *kn;
+ int ret = -1;
+
+ if ((kn = kstat_data_lookup(ks_system_misc, "ncpus")) != NULL) {
+ ret = (int)(kn->value.ui32);
+ }
+
+ return ret;
+}
+
/* dummy */
IOPriority sysdep_get_ioprio(pid_t p)
{
@@ -46,6 +155,44 @@ void sysdep_get_meminfo(ProcessList *this)
/* TODO */
void sysdep_update_cpu_data(ProcessList *this)
{
+ static kstat_t **cpu_ks = NULL;
+ static cpu_stat_t *cpu_stat = NULL;
+ static unsigned int nelems = 0;
+ cpu_stat_t *cpu_stat_p;
+ int i, cpu_num;
+
+ if(!kstat_initialized) {
+ /* open kstat */
+ if ((kc = kstat_open()) == NULL) {
+ fprintf(stderr, "Unable to open kstat.\n");
+ return;
+ }
+ kcid = kc->kc_chain_id;
+ kstat_safe_retrieve(&ks_system_misc, "unix", 0, "system_misc", NULL);
+ kstat_initialized = 1;
+ }
+
+ while (nelems > 0 ?
+ (cpu_num = kstat_safe_namematch(nelems,
+ cpu_ks,
+ "cpu_stat",
+ cpu_stat,
+ sizeof(cpu_stat_t))) > nelems :
+ (cpu_num = get_ncpus()) > 0)
+ {
+ /* reallocate the arrays */
+ nelems = cpu_num;
+ if (cpu_ks != NULL) {
+ free(cpu_ks);
+ }
+ cpu_ks = (kstat_t **)calloc(nelems, sizeof(kstat_t *));
+ if (cpu_stat != NULL) {
+ free(cpu_stat);
+ }
+ cpu_stat = (cpu_stat_t *)malloc(nelems * sizeof(cpu_stat_t));
+ }
+ cpu_stat_p = cpu_stat;
+
unsigned long long int
usertime = 0, nicetime = 0, systemtime = 0,
systemalltime = 0, idlealltime = 0, idletime = 0,
@@ -54,6 +201,12 @@ void sysdep_update_cpu_data(ProcessList *this)
for (int i = 0; i <= this->cpuCount; i++) {
unsigned long long int ioWait, irq, softIrq, steal, guest;
ioWait = irq = softIrq = steal = guest = 0;
+
+ usertime = cpu_stat_p->cpu_sysinfo.cpu[CPU_USER];
+ systemtime = cpu_stat_p->cpu_sysinfo.cpu[CPU_KERNEL];
+ idletime = cpu_stat_p->cpu_sysinfo.cpu[CPU_IDLE];
+ ioWait = cpu_stat_p->cpu_sysinfo.wait[W_IO] + cpu_stat_p->cpu_sysinfo.wait[W_PIO];
+
idlealltime = idletime + ioWait;
systemalltime = systemtime + irq + softIrq;
virtalltime = steal + guest;
@@ -83,6 +236,8 @@ void sysdep_update_cpu_data(ProcessList *this)
cpuData->stealTime = steal;
cpuData->guestTime = guest;
cpuData->totalTime = totaltime;
+
+ cpu_stat_p++;
}
}