File: [local] / src / usr.bin / systat / pigs.c (download)
Revision 1.24, Wed Mar 2 06:48:17 2011 UTC (13 years, 3 months ago) by jasper
Branch: MAIN
Changes since 1.23: +6 -8 lines
- use a common FIELD_ADDR macro, instead of rolling 78 identical copies.
ok canacar@
|
/* $OpenBSD: pigs.c,v 1.24 2011/03/02 06:48:17 jasper Exp $ */
/* $NetBSD: pigs.c,v 1.3 1995/04/29 05:54:50 cgd Exp $ */
/*-
* Copyright (c) 1980, 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Pigs display from Bill Reeves at Lucasfilm
*/
#include <sys/param.h>
#include <sys/dkstat.h>
#include <sys/resource.h>
#include <sys/dir.h>
#include <sys/time.h>
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <curses.h>
#include <math.h>
#include <pwd.h>
#include <err.h>
#include <stdlib.h>
#include <string.h>
#include "systat.h"
int compar(const void *, const void *);
void print_pg(void);
int read_pg(void);
int select_pg(void);
void showpigs(int k);
static struct kinfo_proc2 *procbase = NULL;
static int nproc, pigs_cnt, *pb_indices = NULL;
static int onproc = -1;
static long stime[CPUSTATES];
static double lccpu;
struct loadavg sysload;
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},
};
#define FLD_PG_USER FIELD_ADDR(fields_pg,0)
#define FLD_PG_NAME FIELD_ADDR(fields_pg,1)
#define FLD_PG_PID FIELD_ADDR(fields_pg,2)
#define FLD_PG_VALUE FIELD_ADDR(fields_pg,3)
#define FLD_PG_BAR FIELD_ADDR(fields_pg,4)
/* Define views */
field_def *view_pg_0[] = {
FLD_PG_PID, FLD_PG_USER, FLD_PG_NAME, FLD_PG_VALUE, FLD_PG_BAR, NULL
};
/* Define view managers */
struct view_manager pigs_mgr = {
"Pigs", select_pg, read_pg, NULL, print_header,
print_pg, keyboard_callback, NULL, NULL
};
field_view views_pg[] = {
{view_pg_0, "pigs", '5', &pigs_mgr},
{NULL, NULL, 0, NULL}
};
#ifdef FSCALE
# define FIXED_LOADAVG FSCALE
# define FIXED_PCTCPU FSCALE
#endif
#ifdef FIXED_PCTCPU
typedef long pctcpu;
# define pctdouble(p) ((double)(p) / FIXED_PCTCPU)
#else
typedef double pctcpu;
# define pctdouble(p) (p)
#endif
int
select_pg(void)
{
num_disp = pigs_cnt;
return (0);
}
int
getprocs(void)
{
size_t size;
int mib[6] = {CTL_KERN, KERN_PROC2, KERN_PROC_KTHREAD, 0, sizeof(struct kinfo_proc2), 0};
int st;
free(procbase);
procbase = NULL;
st = sysctl(mib, 6, NULL, &size, NULL, 0);
if (st == -1)
return (1);
size = 5 * size / 4; /* extra slop */
if ((procbase = malloc(size + 1)) == NULL)
return (1);
mib[5] = (int)(size / sizeof(struct kinfo_proc2));
st = sysctl(mib, 6, procbase, &size, NULL, 0);
if (st == -1)
return (1);
nproc = (int)(size / sizeof(struct kinfo_proc2));
return (0);
}
int
read_pg(void)
{
static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME };
long ctimes[CPUSTATES];
double t;
int i, k;
size_t size;
num_disp = pigs_cnt = 0;
if (getprocs()) {
error("Failed to read process info!");
return 1;
}
if (nproc > onproc) {
int *p;
p = realloc(pb_indices, (nproc + 1) * sizeof(int));
if (p == NULL) {
error("Out of Memory!");
return 1;
}
pb_indices = p;
onproc = nproc;
}
memset(&procbase[nproc], 0, sizeof(*procbase));
for (i = 0; i <= nproc; i++)
pb_indices[i] = i;
/*
* and for the imaginary "idle" process
*/
size = sizeof(ctimes);
sysctl(cp_time_mib, 2, &ctimes, &size, NULL, 0);
t = 0;
for (i = 0; i < CPUSTATES; i++)
t += ctimes[i] - stime[i];
if (t == 0.0)
t = 1.0;
procbase[nproc].p_pctcpu = (ctimes[CP_IDLE] - stime[CP_IDLE]) / t / pctdouble(1);
for (i = 0; i < CPUSTATES; i++)
stime[i] = ctimes[i];
qsort(pb_indices, nproc + 1, sizeof (int), compar);
pigs_cnt = 0;
for (k = 0; k < nproc + 1; k++) {
int j = pb_indices[k];
if (pctdouble(procbase[j].p_pctcpu) < 0.01)
break;
pigs_cnt++;
}
num_disp = pigs_cnt;
return 0;
}
void
print_pg(void)
{
int n, count = 0;
for (n = dispstart; n < num_disp; n++) {
showpigs(pb_indices[n]);
count++;
if (maxprint > 0 && count >= maxprint)
break;
}
}
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)
{
int i1 = *((int *)a);
int i2 = *((int *)b);
return procbase[i1].p_pctcpu >
procbase[i2].p_pctcpu ? -1 : 1;
}