#include <net/if.h>
#include <math.h>
+#define SHORTSTAT_TEMPL "%*s %llu %llu %llu"
+#define LONGSTAT_TEMPL "%*s %llu %llu %llu "
+
+
static struct sysinfo s_info;
static int show_nice_processes;
#define CPU_SAMPLE_COUNT 15
struct cpu_info {
- unsigned long cpu_user;
- unsigned long cpu_system;
- unsigned long cpu_nice;
- double last_cpu_sum;
- unsigned long clock_ticks;
+ unsigned long long cpu_user;
+ unsigned long long cpu_system;
+ unsigned long long cpu_nice;
+ unsigned long long cpu_idle;
+ unsigned long long cpu_iowait;
+ unsigned long long cpu_irq;
+ unsigned long long cpu_softirq;
+ unsigned long long cpu_steal;
+ unsigned long long cpu_total;
+ unsigned long long cpu_active_total;
+ unsigned long long cpu_last_total;
+ unsigned long long cpu_last_active_total;
double cpu_val[CPU_SAMPLE_COUNT];
};
static short cpu_setup = 0;
static FILE *stat_fp;
+/*
+ determine if this kernel gives us "extended" statistics information in /proc/stat.
+ Kernels around 2.5 and earlier only reported user, system, nice and idle values in proc stat.
+ Kernels around 2.6 and greater report these PLUS iowait, irq, softirq, and steal
+*/
+void determine_longstat(char * buf) {
+ unsigned long long iowait=0;
+ KFLAG_SETOFF(KFLAG_IS_LONGSTAT);
+ /* scanf will either return -1 or 1 because there is only 1 assignment */
+ if (sscanf(buf, "%*s %*d %*d %*d %*d %llu",&iowait)>0) KFLAG_SETON(KFLAG_IS_LONGSTAT);
+}
+
void get_cpu_count()
{
char buf[256];
break;
if (strncmp(buf, "cpu", 3) == 0 && isdigit(buf[3])) {
+ if (info.cpu_count == 0) {
+ determine_longstat(buf);
+ }
info.cpu_count++;
}
}
info.cpu_usage = malloc((info.cpu_count + 1) * sizeof(float));
+
}
+#define TMPL_LONGSTAT "%*s %llu %llu %llu %llu %llu %llu %llu %llu"
+#define TMPL_SHORTSTAT "%*s %llu %llu %llu %llu"
inline static void update_stat()
{
unsigned int i;
unsigned int index;
double curtmp;
+ char * stat_template=NULL;
+ unsigned int malloc_cpu_size=0;
+
+
if (!cpu_setup) {
get_cpu_count();
cpu_setup = 1;
}
+
+ if (stat_template == NULL) {
+ stat_template = KFLAG_ISSET(KFLAG_IS_LONGSTAT) ? TMPL_LONGSTAT : TMPL_SHORTSTAT ;
+ }
+
if (cpu == NULL) {
- cpu = malloc((info.cpu_count + 1) * sizeof(struct cpu_info));
- for (index = 0; index < info.cpu_count + 1; ++index) {
- cpu[index].clock_ticks = 0;
- cpu[index].last_cpu_sum = 0;
- for (i = 0; i < CPU_SAMPLE_COUNT; ++i) {
- cpu[index].cpu_val[i] = 0;
- }
- }
+ malloc_cpu_size = (info.cpu_count + 1) * sizeof(struct cpu_info);
+ cpu = malloc(malloc_cpu_size);
+ memset(cpu, 0, malloc_cpu_size);
}
+
if (stat_fp == NULL) {
stat_fp = open_file("/proc/stat", &rep);
} else {
break;
if (strncmp(buf, "procs_running ", 14) == 0) {
- sscanf(buf, "%*s %d", &info.run_procs);
+ sscanf(buf, "%*s %hu", &info.run_procs);
info.mask |= (1 << INFO_RUN_PROCS);
- } else if (strncmp(buf, "cpu ", 4) == 0) {
- sscanf(buf, "%*s %lu %lu %lu", &(cpu[index].cpu_user), &(cpu[index].cpu_nice), &(cpu[index].cpu_system));
- index++;
+ } else if (strncmp(buf, "cpu", 3) == 0) {
+ index = isdigit(buf[3]) ? ((int)buf[3]) - 0x2F : 0;
+ sscanf(buf, stat_template
+ , &(cpu[index].cpu_user)
+ , &(cpu[index].cpu_nice)
+ , &(cpu[index].cpu_system)
+ , &(cpu[index].cpu_idle)
+ , &(cpu[index].cpu_iowait)
+ , &(cpu[index].cpu_irq)
+ , &(cpu[index].cpu_softirq)
+ , &(cpu[index].cpu_steal)
+ );
+
+ cpu[index].cpu_total = cpu[index].cpu_user
+ + cpu[index].cpu_nice
+ + cpu[index].cpu_system
+ + cpu[index].cpu_idle
+ + cpu[index].cpu_iowait
+ + cpu[index].cpu_irq
+ + cpu[index].cpu_softirq
+ + cpu[index].cpu_steal
+ ;
+
+ cpu[index].cpu_active_total = cpu[index].cpu_total - (cpu[index].cpu_idle + cpu[index].cpu_iowait);
info.mask |= (1 << INFO_CPU);
- } else if (strncmp(buf, "cpu", 3) == 0 && isdigit(buf[3]) && index <= info.cpu_count) {
- sscanf(buf, "%*s %lu %lu %lu", &(cpu[index].cpu_user), &(cpu[index].cpu_nice), &(cpu[index].cpu_system));
- index++;
- info.mask |= (1 << INFO_CPU);
- }
- }
- for (index = 0; index < info.cpu_count + 1; index++) {
- double delta;
- delta = current_update_time - last_update_time;
- if (delta <= 0.001) {
- return;
- }
- if (cpu[index].clock_ticks == 0) {
- cpu[index].clock_ticks = sysconf(_SC_CLK_TCK);
- }
- curtmp = 0;
- cpu[index].cpu_val[0] =
- (cpu[index].cpu_user + cpu[index].cpu_nice + cpu[index].cpu_system -
- cpu[index].last_cpu_sum) / delta / (double) cpu[index].clock_ticks;
- for (i = 0; i < info.cpu_avg_samples; i++) {
- curtmp += cpu[index].cpu_val[i];
- }
- if (index == 0) {
- info.cpu_usage[index] = curtmp / info.cpu_avg_samples / info.cpu_count;
- } else {
+ double delta = current_update_time - last_update_time;
+ if (delta <= 0.001) return;
+
+ cpu[index].cpu_val[0] = (cpu[index].cpu_active_total - cpu[index].cpu_last_active_total) /
+ (float )(cpu[index].cpu_total - cpu[index].cpu_last_total);
+ curtmp = 0;
+ for (i=0; i < info.cpu_avg_samples; i++ ) {
+ curtmp += cpu[index].cpu_val[i];
+ }
+ /* TESTING -- I've removed this, because I don't think it is right. You shouldn't divide
+ by the cpu count here ... removing for testing */
+ if (index == 0) {
+ info.cpu_usage[index] = curtmp / info.cpu_avg_samples / info.cpu_count;
+ } else {
+ info.cpu_usage[index] = curtmp / info.cpu_avg_samples;
+ }
+ /* TESTING -- this line replaces the prev. "suspect" if/else */
info.cpu_usage[index] = curtmp / info.cpu_avg_samples;
+
+ cpu[index].cpu_last_total = cpu[index].cpu_total;
+ cpu[index].cpu_last_active_total = cpu[index].cpu_active_total;
+ for (i = info.cpu_avg_samples - 1; i > 0; i--) {
+ cpu[index].cpu_val[i] = cpu[index].cpu_val[i - 1];
+ }
}
- cpu[index].last_cpu_sum = cpu[index].cpu_user + cpu[index].cpu_nice + cpu[index].cpu_system;
- for (i = info.cpu_avg_samples; i > 1; i--)
- cpu[index].cpu_val[i - 1] = cpu[index].cpu_val[i - 2];
}
-
-// test code
-// this is for getting proc shit
-// pee pee
-// poo
- //
-
-
-
-
-
-
}
void update_running_processes()
#include "top.h"
-static regex_t *exclusion_expression = 0;
static unsigned long g_time = 0;
-static unsigned long previous_total = 0;
+static unsigned long long previous_total = 0;
static struct process *first_process = 0;
struct process *get_first_process()
static void process_cleanup(void);
static void delete_process(struct process *);
/*inline void draw_processes(void);*/
-static unsigned long calc_cpu_total(void);
-static void calc_cpu_each(unsigned long);
+static unsigned long long calc_cpu_total(void);
+static void calc_cpu_each(unsigned long long);
/******************************************/
/* store only the difference of the user_time here... */
process->user_time = user_time;
process->kernel_time = kernel_time;
-
+
return 0;
}
/*
* Check name against the exclusion list
*/
- if (process->counted && exclusion_expression
+/* if (process->counted && exclusion_expression
&& !regexec(exclusion_expression, process->name, 0, 0, 0))
process->counted = 0;
+*/
return 0;
}
/******************************************/
/* Calculate cpu total */
/******************************************/
+#define TMPL_SHORTPROC "%*s %llu %llu %llu %llu"
+#define TMPL_LONGPROC "%*s %llu %llu %llu %llu %llu %llu %llu %llu"
-static unsigned long calc_cpu_total()
+static unsigned long long calc_cpu_total()
{
- unsigned long total = 0;
- unsigned long t = 0;
+ unsigned long long total = 0;
+ unsigned long long t = 0;
int rc;
int ps;
char line[BUFFER_LEN];
- unsigned long cpu = 0;
- unsigned long nice = 0;
- unsigned long system = 0;
- unsigned long idle = 0;
-
+ unsigned long long cpu = 0;
+ unsigned long long nice = 0;
+ unsigned long long system = 0;
+ unsigned long long idle = 0;
+ unsigned long long iowait = 0;
+ unsigned long long irq = 0;
+ unsigned long long softirq = 0;
+ unsigned long long steal = 0;
+ char * template = KFLAG_ISSET(KFLAG_IS_LONGSTAT) ? TMPL_LONGPROC : TMPL_SHORTPROC;
+
ps = open("/proc/stat", O_RDONLY);
rc = read(ps, line, sizeof(line));
close(ps);
if (rc < 0)
return 0;
- sscanf(line, "%*s %lu %lu %lu %lu", &cpu, &nice, &system, &idle);
- total = cpu + nice + system + idle;
+
+ sscanf(line, template, &cpu, &nice, &system, &idle, &iowait, &irq, &softirq, &steal);
+ total = cpu + nice + system + idle + iowait + irq + softirq + steal;
t = total - previous_total;
previous_total = total;
-
return t;
}
/* Calculate each processes cpu */
/******************************************/
-inline static void calc_cpu_each(unsigned long total)
+inline static void calc_cpu_each(unsigned long long total)
{
struct process *p = first_process;
while (p) {
- /*p->amount = total ?
- (100.0 * (float) (p->user_time + p->kernel_time) /
- total) : 0; */
p->amount =
- 100.0 * ((float)(p->user_time + p->kernel_time) / (float)total);
+ 100.0 * (p->user_time + p->kernel_time) / (float)total;
-/* if (p->amount > 100)
- p->amount = 0;*/
p = p->next;
}
}
/* Find the top processes */
/******************************************/
-//static int tot_struct; //for debugging..uncomment this and the 2 printfs in the next two functs
-
/*
* free a sp_process structure
*/
void free_sp(struct sorted_process * sp) {
free(sp);
-// printf("free: %d structs\n",--tot_struct );
}
/*
sp->greater = NULL;
sp->less = NULL;
sp->proc = proc;
-// printf("malloc: %d structs\n", ++tot_struct);
return(sp);
}
struct sorted_process *spc_head = NULL, *spc_tail = NULL, *spc_cur = NULL;
struct sorted_process *spm_head = NULL, *spm_tail = NULL, *spm_cur = NULL;
struct process *cur_proc = NULL;
- unsigned long total = 0;
+ unsigned long long total = 0;
if (!top_cpu && !top_mem) return;
cur_proc = first_process;
while (cur_proc !=NULL) {
- //printf("\n\n cur_proc: %s %f %f\n",cur_proc->name, cur_proc->totalmem, cur_proc->amount );
if (top_cpu) {
spc_cur = malloc_sp(cur_proc);
insert_sp_element(spc_cur, &spc_head, &spc_tail, MAX_SP, &compare_cpu);