version 1.21, 2007/09/02 15:19:35 |
version 1.22, 2008/06/12 22:26:01 |
|
|
* SUCH DAMAGE. |
* SUCH DAMAGE. |
*/ |
*/ |
|
|
#ifndef lint |
|
#if 0 |
|
static char sccsid[] = "@(#)pigs.c 8.2 (Berkeley) 9/23/93"; |
|
#endif |
|
static char rcsid[] = "$OpenBSD$"; |
|
#endif /* not lint */ |
|
|
|
/* |
/* |
* Pigs display from Bill Reeves at Lucasfilm |
* Pigs display from Bill Reeves at Lucasfilm |
*/ |
*/ |
|
|
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
|
|
#include "extern.h" |
|
#include "systat.h" |
#include "systat.h" |
|
|
int compar(const void *, const void *); |
int compar(const void *, const void *); |
|
void print_pg(void); |
|
int read_pg(void); |
|
int select_pg(void); |
|
void showpigs(int k); |
|
|
static int nproc; |
static struct kinfo_proc2 *procbase = NULL; |
static struct p_times { |
static int nproc, pigs_cnt, *pb_indices = NULL; |
float pt_pctcpu; |
static int onproc = -1; |
struct kinfo_proc2 *pt_kp; |
|
} *pt; |
|
|
|
static long stime[CPUSTATES]; |
static long stime[CPUSTATES]; |
static double lccpu; |
static double lccpu; |
|
struct loadavg sysload; |
|
|
WINDOW * |
|
openpigs(void) |
|
{ |
|
return (subwin(stdscr, LINES-1-2, 0, 2, 0)); |
|
} |
|
|
|
void |
|
closepigs(WINDOW *w) |
|
{ |
|
if (w == NULL) |
|
return; |
|
wclear(w); |
|
wrefresh(w); |
|
delwin(w); |
|
} |
|
|
|
|
field_def fields_pg[] = { |
|
{"USER", 6, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, |
|
{"NAME", 10, 24, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, |
|
{"PID", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
|
{"CPU", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, |
|
{"", 30, 60, 1, FLD_ALIGN_BAR, -1, 0, 0, 100}, |
|
}; |
|
|
void |
#define FIELD_ADDR(x) (&fields_pg[x]) |
showpigs(void) |
|
{ |
|
int i, j, y, k; |
|
struct kinfo_proc2 *kp; |
|
float total; |
|
int factor; |
|
char *uname, *pname, pidname[30]; |
|
|
|
if (pt == NULL) |
#define FLD_PG_USER FIELD_ADDR(0) |
return; |
#define FLD_PG_NAME FIELD_ADDR(1) |
/* Accumulate the percent of cpu per user. */ |
#define FLD_PG_PID FIELD_ADDR(2) |
total = 0.0; |
#define FLD_PG_VALUE FIELD_ADDR(3) |
for (i = 0; i <= nproc; i++) { |
#define FLD_PG_BAR FIELD_ADDR(4) |
/* Accumulate the percentage. */ |
|
total += pt[i].pt_pctcpu; |
|
} |
|
|
|
if (total < 1.0) |
/* Define views */ |
total = 1.0; |
field_def *view_pg_0[] = { |
factor = 50.0/total; |
FLD_PG_PID, FLD_PG_USER, FLD_PG_NAME, FLD_PG_VALUE, FLD_PG_BAR, NULL |
|
}; |
|
|
qsort(pt, nproc + 1, sizeof (struct p_times), compar); |
|
y = 1; |
/* Define view managers */ |
i = nproc + 1; |
struct view_manager pigs_mgr = { |
if (i > wnd->_maxy-1) |
"Pigs", select_pg, read_pg, NULL, print_header, |
i = wnd->_maxy-1; |
print_pg, keyboard_callback, NULL, NULL |
for (k = 0; i > 0 && pt[k].pt_pctcpu > 0.01; i--, y++, k++) { |
}; |
kp = pt[k].pt_kp; |
|
if (kp == NULL) { |
field_view views_pg[] = { |
uname = ""; |
{view_pg_0, "pigs", '5', &pigs_mgr}, |
pname = "<idle>"; |
{NULL, NULL, 0, NULL} |
} else { |
}; |
uname = user_from_uid(kp->p_uid, 0); |
|
pname = kp->p_comm; |
|
} |
#ifdef FSCALE |
wmove(wnd, y, 0); |
# define FIXED_LOADAVG FSCALE |
wclrtoeol(wnd); |
# define FIXED_PCTCPU FSCALE |
mvwaddstr(wnd, y, 0, uname); |
#endif |
snprintf(pidname, sizeof pidname, "%10.10s", pname); |
|
mvwaddstr(wnd, y, 9, pidname); |
#ifdef FIXED_PCTCPU |
wmove(wnd, y, 20); |
typedef long pctcpu; |
for (j = pt[k].pt_pctcpu*factor + 0.5; j > 0; j--) |
# define pctdouble(p) ((double)(p) / FIXED_PCTCPU) |
waddch(wnd, 'X'); |
#else |
} |
typedef double pctcpu; |
wmove(wnd, y, 0); wclrtobot(wnd); |
# define pctdouble(p) (p) |
|
#endif |
|
|
|
int |
|
select_pg(void) |
|
{ |
|
num_disp = pigs_cnt; |
|
return (0); |
} |
} |
|
|
struct loadavg sysload; |
|
|
|
int |
int |
initpigs(void) |
getprocs(void) |
{ |
{ |
static int sysload_mib[] = {CTL_VM, VM_LOADAVG}; |
|
static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME }; |
|
static int ccpu_mib[] = { CTL_KERN, KERN_CCPU }; |
|
size_t size; |
size_t size; |
fixpt_t ccpu; |
int mib[6] = {CTL_KERN, KERN_PROC2, KERN_PROC_KTHREAD, 0, sizeof(struct kinfo_proc2), 0}; |
|
|
|
int st; |
|
|
size = sizeof(stime); |
free(procbase); |
(void) sysctl(cp_time_mib, 2, &stime, &size, NULL, 0); |
procbase = NULL; |
|
|
size = sizeof(sysload); |
st = sysctl(mib, 6, NULL, &size, NULL, 0); |
(void) sysctl(sysload_mib, 2, &sysload, &size, NULL, 0); |
if (st == -1) |
|
return (1); |
|
|
size = sizeof(ccpu); |
size = 5 * size / 4; /* extra slop */ |
(void) sysctl(ccpu_mib, 2, &ccpu, &size, NULL, 0); |
if ((procbase = malloc(size + 1)) == NULL) |
|
return (1); |
|
|
lccpu = log((double) ccpu / sysload.fscale); |
mib[5] = (int)(size / sizeof(struct kinfo_proc2)); |
|
st = sysctl(mib, 6, procbase, &size, NULL, 0); |
|
if (st == -1) |
|
return (1); |
|
|
return(1); |
nproc = (int)(size / sizeof(struct kinfo_proc2)); |
|
return (0); |
} |
} |
|
|
void |
|
fetchpigs(void) |
int |
|
read_pg(void) |
{ |
{ |
static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME }; |
static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME }; |
static int lastnproc = 0; |
|
struct kinfo_proc2 *kpp; |
|
long ctime[CPUSTATES]; |
long ctime[CPUSTATES]; |
double t; |
double t; |
int i; |
int i, k; |
size_t size; |
size_t size; |
float *pctp; |
|
|
|
kpp = kvm_getproc2(kd, KERN_PROC_KTHREAD, 0, sizeof(*kpp), &nproc); |
num_disp = pigs_cnt = 0; |
if (kpp == NULL) { |
|
error("%s", kvm_geterr(kd)); |
if (getprocs()) { |
if (pt) |
error("Failed to read process info!"); |
free(pt); |
return 1; |
return; |
|
} |
} |
if (nproc > lastnproc) { |
|
free(pt); |
if (nproc > onproc) { |
if ((pt = calloc(nproc + 1, sizeof(struct p_times))) == NULL) { |
int *p; |
error("Out of memory"); |
p = realloc(pb_indices, (nproc + 1) * sizeof(int)); |
die(); |
if (p == NULL) { |
|
error("Out of Memory!"); |
|
return 1; |
} |
} |
|
pb_indices = p; |
|
onproc = nproc; |
} |
} |
lastnproc = nproc; |
|
|
memset(&procbase[nproc], 0, sizeof(*procbase)); |
|
|
|
for (i = 0; i <= nproc; i++) |
|
pb_indices[i] = i; |
|
|
/* |
/* |
* calculate %cpu for each proc |
|
*/ |
|
for (i = 0; i < nproc; i++) { |
|
pt[i].pt_kp = &kpp[i]; |
|
pctp = &pt[i].pt_pctcpu; |
|
if (kpp->p_swtime == 0) |
|
*pctp = 0; |
|
else |
|
*pctp = ((double) kpp->p_pctcpu / sysload.fscale) / |
|
(1.0 - exp(kpp->p_swtime * lccpu)); |
|
} |
|
/* |
|
* and for the imaginary "idle" process |
* and for the imaginary "idle" process |
*/ |
*/ |
size = sizeof(ctime); |
size = sizeof(ctime); |
(void) sysctl(cp_time_mib, 2, &ctime, &size, NULL, 0); |
sysctl(cp_time_mib, 2, &ctime, &size, NULL, 0); |
|
|
t = 0; |
t = 0; |
for (i = 0; i < CPUSTATES; i++) |
for (i = 0; i < CPUSTATES; i++) |
t += ctime[i] - stime[i]; |
t += ctime[i] - stime[i]; |
if (t == 0.0) |
if (t == 0.0) |
t = 1.0; |
t = 1.0; |
pt[nproc].pt_kp = NULL; |
|
pt[nproc].pt_pctcpu = (ctime[CP_IDLE] - stime[CP_IDLE]) / t; |
procbase[nproc].p_pctcpu = (ctime[CP_IDLE] - stime[CP_IDLE]) / t / pctdouble(1); |
for (i = 0; i < CPUSTATES; i++) |
for (i = 0; i < CPUSTATES; i++) |
stime[i] = ctime[i]; |
stime[i] = ctime[i]; |
|
|
|
qsort(pb_indices, nproc + 1, sizeof (int), compar); |
|
|
|
pigs_cnt = 0; |
|
for (k = 0; k < nproc + 1; k++) { |
|
int i = pb_indices[k]; |
|
if (pctdouble(procbase[i].p_pctcpu) < 0.01) |
|
break; |
|
pigs_cnt++; |
|
} |
|
|
|
num_disp = pigs_cnt; |
|
return 0; |
} |
} |
|
|
|
|
void |
void |
labelpigs(void) |
print_pg(void) |
{ |
{ |
wmove(wnd, 0, 0); |
int n, count = 0; |
wclrtoeol(wnd); |
|
mvwaddstr(wnd, 0, 20, |
for (n = dispstart; n < num_disp; n++) { |
"/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100"); |
showpigs(pb_indices[n]); |
|
count++; |
|
if (maxprint > 0 && count >= maxprint) |
|
break; |
|
} |
} |
} |
|
|
int |
int |
|
initpigs(void) |
|
{ |
|
static int sysload_mib[] = {CTL_VM, VM_LOADAVG}; |
|
static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME }; |
|
static int ccpu_mib[] = { CTL_KERN, KERN_CCPU }; |
|
field_view *v; |
|
size_t size; |
|
fixpt_t ccpu; |
|
|
|
size = sizeof(stime); |
|
sysctl(cp_time_mib, 2, &stime, &size, NULL, 0); |
|
|
|
size = sizeof(sysload); |
|
sysctl(sysload_mib, 2, &sysload, &size, NULL, 0); |
|
|
|
size = sizeof(ccpu); |
|
sysctl(ccpu_mib, 2, &ccpu, &size, NULL, 0); |
|
|
|
lccpu = log((double) ccpu / sysload.fscale); |
|
|
|
for (v = views_pg; v->name != NULL; v++) |
|
add_view(v); |
|
|
|
return(1); |
|
} |
|
|
|
void |
|
showpigs(int k) |
|
{ |
|
struct kinfo_proc2 *kp; |
|
double value; |
|
char *uname, *pname; |
|
|
|
if (procbase == NULL) |
|
return; |
|
|
|
value = pctdouble(procbase[k].p_pctcpu) * 100; |
|
|
|
kp = &procbase[k]; |
|
if (kp->p_comm[0] == '\0') { |
|
uname = ""; |
|
pname = "<idle>"; |
|
} else { |
|
uname = user_from_uid(kp->p_uid, 0); |
|
pname = kp->p_comm; |
|
print_fld_uint(FLD_PG_PID, kp->p_pid); |
|
} |
|
|
|
tb_start(); |
|
tbprintf("%.2f", value); |
|
print_fld_tb(FLD_PG_VALUE); |
|
|
|
print_fld_str(FLD_PG_NAME, pname); |
|
print_fld_str(FLD_PG_USER, uname); |
|
print_fld_bar(FLD_PG_BAR, value); |
|
|
|
end_line(); |
|
} |
|
|
|
|
|
int |
compar(const void *a, const void *b) |
compar(const void *a, const void *b) |
{ |
{ |
return (((struct p_times *)a)->pt_pctcpu > |
int i1 = *((int *)a); |
((struct p_times *)b)->pt_pctcpu) ? -1 : 1; |
int i2 = *((int *)b); |
|
|
|
return procbase[i1].p_pctcpu > |
|
procbase[i2].p_pctcpu ? -1 : 1; |
} |
} |
|
|