代码拉取完成,页面将自动刷新
/*
** ATOP - System & Process Monitor
**
** The program 'atop' offers the possibility to view the activity of
** the system on system-level as well as process-level.
**
** This source-file contains the Linux-specific functions to calculate
** figures to be visualized.
** ==========================================================================
** Author: Gerlof Langeveld
** Original version.
** E-mail: gerlof.langeveld@atoptool.nl
** Date: July 2002
**
** Author: JC van Winkel - AT Computing, Nijmegen, Holland
** Complete redesign.
** Date: November 2009
** --------------------------------------------------------------------------
** Copyright (C) 2009-2010 JC van Winkel
**
** 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
** --------------------------------------------------------------------------
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <signal.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdarg.h>
#include <curses.h>
#include <pwd.h>
#include <grp.h>
#include <regex.h>
#include "atop.h"
#include "cgroups.h"
#include "photoproc.h"
#include "photosyst.h"
#include "showgeneric.h"
#include "showlinux.h"
static void make_proc_dynamicgen(void);
static int get_perc(char *, char *);
static void make_detail_prints(detail_printpair *, int, const char *,
const char *);
/*
** critical percentages for occupation-percentage;
** these defaults can be overruled via the config-file
*/
int cpubadness = 90; /* percentage */
int gpubadness = 100; /* percentage */
int membadness = 90; /* percentage */
int swpbadness = 80; /* percentage */
int dskbadness = 90; /* percentage */
int netbadness = 90; /* percentage */
int pagbadness = 10; /* number per second */
int almostcrit = 80; /* percentage */
/*
* tables with all sys_printdefs
*/
sys_printdef *prcsyspdefs[] = {
&syspdef_PRCSYS,
&syspdef_PRCUSER,
&syspdef_PRCNPROC,
&syspdef_PRCNRUNNING,
&syspdef_PRCNSLEEPING,
&syspdef_PRCNDSLEEPING,
&syspdef_PRCNIDLE,
&syspdef_PRCNZOMBIE,
&syspdef_PRCCLONES,
&syspdef_PRCNNEXIT,
&syspdef_BLANKBOX,
0
};
sys_printdef *cpusyspdefs[] = {
&syspdef_CPUSYS,
&syspdef_CPUUSER,
&syspdef_CPUIRQ,
&syspdef_CPUIDLE,
&syspdef_CPUWAIT,
&syspdef_BLANKBOX,
&syspdef_CPUIPC,
&syspdef_CPUCYCLE,
&syspdef_CPUFREQ,
&syspdef_CPUSCALE,
&syspdef_CPUSTEAL,
&syspdef_CPUGUEST,
&syspdef_BLANKBOX,
0
};
sys_printdef *cpisyspdefs[] = {
&syspdef_CPUISYS,
&syspdef_CPUIUSER,
&syspdef_CPUIIRQ,
&syspdef_CPUIIDLE,
&syspdef_CPUIWAIT,
&syspdef_BLANKBOX,
&syspdef_CPUIIPC,
&syspdef_CPUICYCLE,
&syspdef_CPUIFREQ,
&syspdef_CPUISCALE,
&syspdef_CPUISTEAL,
&syspdef_CPUIGUEST,
&syspdef_BLANKBOX,
0
};
sys_printdef *cplsyspdefs[] = {
&syspdef_CPLNUMCPU,
&syspdef_CPLAVG1,
&syspdef_CPLAVG5,
&syspdef_CPLAVG15,
&syspdef_CPLCSW,
&syspdef_CPLINTR,
&syspdef_BLANKBOX,
0
};
sys_printdef *gpusyspdefs[] = {
&syspdef_GPUBUS,
&syspdef_GPUGPUPERC,
&syspdef_GPUMEMPERC,
&syspdef_GPUMEMOCC,
&syspdef_GPUMEMTOT,
&syspdef_GPUMEMUSE,
&syspdef_GPUMEMAVG,
&syspdef_GPUTYPE,
&syspdef_GPUNRPROC,
&syspdef_BLANKBOX,
0
};
sys_printdef *memsyspdefs1[] = {
&syspdef_MEMTOT,
&syspdef_MEMFREE,
&syspdef_MEMAVAIL,
&syspdef_BLANKBOX,
&syspdef_MEMCACHE,
&syspdef_MEMDIRTY,
&syspdef_MEMBUFFER,
&syspdef_BLANKBOX,
&syspdef_MEMSLAB,
&syspdef_RECSLAB,
&syspdef_BLANKBOX,
&syspdef_HUPTOT,
&syspdef_HUPUSE,
0
};
sys_printdef *memsyspdefs2[] = {
&syspdef_NUMNUMA,
&syspdef_BLANKBOX,
&syspdef_TCPSOCK,
&syspdef_UDPSOCK,
&syspdef_BLANKBOX,
&syspdef_SHMEM,
&syspdef_SHMRSS,
&syspdef_SHMSWP,
&syspdef_BLANKBOX,
&syspdef_PAGETABS,
&syspdef_BLANKBOX,
&syspdef_ANONTHP,
&syspdef_VMWBAL,
&syspdef_BLANKBOX,
&syspdef_ZFSARC,
0
};
sys_printdef *swpsyspdefs[] = {
&syspdef_SWPTOT,
&syspdef_SWPFREE,
&syspdef_SWPCACHE,
&syspdef_BLANKBOX,
&syspdef_ZSWPOOL,
&syspdef_ZSWSTORED,
&syspdef_KSMSHARING,
&syspdef_KSMSHARED,
&syspdef_BLANKBOX,
&syspdef_SWPCOMMITTED,
&syspdef_SWPCOMMITLIM,
&syspdef_BLANKBOX,
0
};
sys_printdef *pagsyspdefs[] = {
&syspdef_PAGSCAN,
&syspdef_PAGSTEAL,
&syspdef_PAGSTALL,
&syspdef_PAGCOMPACT,
&syspdef_PGMIGRATE,
&syspdef_NUMAMIGRATE,
&syspdef_PAGSWIN,
&syspdef_PAGSWOUT,
&syspdef_PAGZSWIN,
&syspdef_PAGZSWOUT,
&syspdef_OOMKILLS,
&syspdef_PAGPGIN,
&syspdef_PAGPGOUT,
&syspdef_BLANKBOX,
0
};
sys_printdef *memnumasyspdefs[] = {
&syspdef_NUMATOT,
&syspdef_NUMAFREE,
&syspdef_NUMAFILEPAGE,
&syspdef_NUMANR,
&syspdef_NUMADIRTY,
&syspdef_NUMAACTIVE,
&syspdef_NUMAINACTIVE,
&syspdef_NUMASLAB,
&syspdef_NUMASLABRECLAIM,
&syspdef_NUMASHMEM,
&syspdef_NUMAFRAG,
&syspdef_NUMAHUPTOT,
&syspdef_NUMAHUPUSE,
0
};
sys_printdef *cpunumasyspdefs[] = {
&syspdef_NUMACPUSYS,
&syspdef_NUMACPUUSER,
&syspdef_NUMACPUNICE,
&syspdef_NUMACPUIRQ,
&syspdef_NUMACPUSOFTIRQ,
&syspdef_NUMACPUIDLE,
&syspdef_NUMACPUWAIT,
&syspdef_NUMACPUSTEAL,
&syspdef_NUMACPUGUEST,
&syspdef_NUMANUMCPU,
0
};
sys_printdef *llcsyspdefs[] = {
&syspdef_LLCMBMTOTAL,
&syspdef_LLCMBMLOCAL,
&syspdef_NUMLLC,
&syspdef_BLANKBOX,
0
};
sys_printdef *psisyspdefs[] = {
&syspdef_PSICPUSTOT,
&syspdef_PSIMEMSTOT,
&syspdef_PSIMEMFTOT,
&syspdef_PSIIOSTOT,
&syspdef_PSIIOFTOT,
&syspdef_PSICPUS,
&syspdef_PSIMEMS,
&syspdef_PSIMEMF,
&syspdef_PSIIOS,
&syspdef_PSIIOF,
&syspdef_BLANKBOX,
0
};
sys_printdef *contsyspdefs[] = {
&syspdef_CONTNAME,
&syspdef_CONTNPROC,
&syspdef_CONTCPU,
&syspdef_CONTMEM,
&syspdef_BLANKBOX,
0
};
sys_printdef *dsksyspdefs[] = {
&syspdef_DSKNAME,
&syspdef_DSKBUSY,
&syspdef_DSKNREAD,
&syspdef_DSKNWRITE,
&syspdef_DSKNDISC,
&syspdef_DSKMBPERSECWR,
&syspdef_DSKMBPERSECRD,
&syspdef_DSKKBPERRD,
&syspdef_DSKKBPERWR,
&syspdef_DSKKBPERDS,
&syspdef_DSKINFLIGHT,
&syspdef_DSKAVQUEUE,
&syspdef_DSKAVIO,
&syspdef_BLANKBOX,
0
};
sys_printdef *nfsmntsyspdefs[] = {
&syspdef_NFMPATH,
&syspdef_NFMSERVER,
&syspdef_NFMTOTREAD,
&syspdef_NFMTOTWRITE,
&syspdef_NFMNREAD,
&syspdef_NFMNWRITE,
&syspdef_NFMDREAD,
&syspdef_NFMDWRITE,
&syspdef_NFMMREAD,
&syspdef_NFMMWRITE,
&syspdef_BLANKBOX,
0
};
sys_printdef *nfcsyspdefs[] = {
&syspdef_NFCRPCCNT,
&syspdef_NFCRPCREAD,
&syspdef_NFCRPCWRITE,
&syspdef_NFCRPCRET,
&syspdef_NFCRPCARF,
&syspdef_BLANKBOX,
0
};
sys_printdef *nfssyspdefs[] = {
&syspdef_NFSRPCCNT,
&syspdef_NFSRPCREAD,
&syspdef_NFSRPCWRITE,
&syspdef_NFSNRBYTES,
&syspdef_NFSNWBYTES,
&syspdef_NFSNETTCP,
&syspdef_NFSNETUDP,
&syspdef_NFSBADFMT,
&syspdef_NFSBADAUT,
&syspdef_NFSBADCLN,
&syspdef_NFSRCHITS,
&syspdef_NFSRCMISS,
&syspdef_NFSRCNOCA,
&syspdef_BLANKBOX,
0
};
sys_printdef *nettranssyspdefs[] = {
&syspdef_NETTRANSPORT,
&syspdef_NETTCPI,
&syspdef_NETTCPO,
&syspdef_NETUDPI,
&syspdef_NETUDPO,
&syspdef_NETTCPACTOPEN,
&syspdef_NETTCPPASVOPEN,
&syspdef_NETTCPRETRANS,
&syspdef_NETTCPINERR,
&syspdef_NETTCPORESET,
&syspdef_NETTCPCSUMERR,
&syspdef_NETUDPNOPORT,
&syspdef_NETUDPINERR,
&syspdef_BLANKBOX,
0
};
sys_printdef *netnetsyspdefs[] = {
&syspdef_NETNETWORK,
&syspdef_NETIPI,
&syspdef_NETIPO,
&syspdef_NETIPFRW,
&syspdef_NETIPDELIV,
&syspdef_NETICMPIN,
&syspdef_NETICMPOUT,
&syspdef_BLANKBOX,
0
};
sys_printdef *netintfsyspdefs[] = {
&syspdef_NETNAME,
&syspdef_NETPCKI,
&syspdef_NETPCKO,
&syspdef_NETSPEEDMAX,
&syspdef_NETSPEEDIN,
&syspdef_NETSPEEDOUT,
&syspdef_NETCOLLIS,
&syspdef_NETMULTICASTIN,
&syspdef_NETRCVERR,
&syspdef_NETSNDERR,
&syspdef_NETRCVDROP,
&syspdef_NETSNDDROP,
&syspdef_BLANKBOX,
0
};
sys_printdef *infinisyspdefs[] = {
&syspdef_IFBNAME,
&syspdef_IFBPCKI,
&syspdef_IFBPCKO,
&syspdef_IFBSPEEDMAX,
&syspdef_IFBSPEEDIN,
&syspdef_IFBSPEEDOUT,
&syspdef_IFBLANES,
&syspdef_BLANKBOX,
0
};
/*
* table with all detail_printdefs
*/
detail_printdef *alldetaildefs[]=
{
&procprt_PID,
&procprt_TID,
&procprt_PPID,
&procprt_SYSCPU,
&procprt_USRCPU,
&procprt_RUNDELAY,
&procprt_BLKDELAY,
&procprt_WCHAN,
&procprt_NVCSW,
&procprt_NIVCSW,
&procprt_VGROW,
&procprt_RGROW,
&procprt_MINFLT,
&procprt_MAJFLT,
&procprt_VSTEXT,
&procprt_VSIZE,
&procprt_RSIZE,
&procprt_PSIZE,
&procprt_VSLIBS,
&procprt_VDATA,
&procprt_VSTACK,
&procprt_SWAPSZ,
&procprt_LOCKSZ,
&procprt_CMD,
&procprt_RUID,
&procprt_EUID,
&procprt_SUID,
&procprt_FSUID,
&procprt_RGID,
&procprt_EGID,
&procprt_SGID,
&procprt_FSGID,
&procprt_CTID,
&procprt_VPID,
&procprt_CID,
&procprt_STDATE,
&procprt_STTIME,
&procprt_ENDATE,
&procprt_ENTIME,
&procprt_THR,
&procprt_TRUN,
&procprt_TSLPI,
&procprt_TSLPU,
&procprt_TIDLE,
&procprt_POLI,
&procprt_NICE,
&procprt_PRI,
&procprt_RTPR,
&procprt_CURCPU,
&procprt_ST,
&procprt_EXC,
&procprt_S,
&procprt_COMMAND_LINE,
&procprt_NPROCS,
&procprt_RDDSK,
&procprt_WRDSK,
&procprt_CWRDSK,
&procprt_WCANCEL,
&procprt_TCPRCV,
&procprt_TCPRASZ,
&procprt_TCPSND,
&procprt_TCPSASZ,
&procprt_UDPRCV,
&procprt_UDPRASZ,
&procprt_UDPSND,
&procprt_UDPSASZ,
&procprt_RNET,
&procprt_SNET,
&procprt_BANDWI,
&procprt_BANDWO,
&procprt_GPULIST,
&procprt_GPUMEMNOW,
&procprt_GPUMEMAVG,
&procprt_GPUGPUBUSY,
&procprt_GPUMEMBUSY,
&procprt_SORTITEM,
&cgroupprt_CGROUP_PATH,
&cgroupprt_CGRNPROCS,
&cgroupprt_CGRNPROCSB,
&cgroupprt_CGRCPUBUSY,
&cgroupprt_CGRCPUPSI,
&cgroupprt_CGRCPUMAX,
&cgroupprt_CGRCPUWGT,
&cgroupprt_CGRMEMORY,
&cgroupprt_CGRMEMPSI,
&cgroupprt_CGRMEMMAX,
&cgroupprt_CGRSWPMAX,
&cgroupprt_CGRDISKIO,
&cgroupprt_CGRDSKPSI,
&cgroupprt_CGRDSKWGT,
&cgroupprt_CGRPID,
&cgroupprt_CGRCMD,
0
};
/*
* table with all detail_printdefs with PID/TID width to be initialized
*/
detail_printdef *idprocpdefs[]=
{
&procprt_PID,
&procprt_TID,
&procprt_PPID,
&procprt_VPID,
&cgroupprt_CGRPID,
0
};
/***************************************************************/
/*
* output definitions for process and cgroups data
* these should be user configurable
*/
detail_printpair userprocs[MAXITEMS];
detail_printpair memprocs[MAXITEMS];
detail_printpair schedprocs[MAXITEMS];
detail_printpair genprocs[MAXITEMS];
detail_printpair dskprocs[MAXITEMS];
detail_printpair netprocs[MAXITEMS];
detail_printpair gpuprocs[MAXITEMS];
detail_printpair varprocs[MAXITEMS];
detail_printpair cmdprocs[MAXITEMS];
detail_printpair ownprocs[MAXITEMS];
detail_printpair totusers[MAXITEMS];
detail_printpair totprocs[MAXITEMS];
detail_printpair totconts[MAXITEMS];
detail_printpair gencgroups[MAXITEMS]; // cgroups data
detail_printpair gencgrprocs[MAXITEMS]; // cgroups process data
/*****************************************************************/
/*
* output definitions for system data
* these should be user configurable
*/
sys_printpair sysprcline[MAXITEMS];
sys_printpair allcpuline[MAXITEMS];
sys_printpair indivcpuline[MAXITEMS];
sys_printpair cplline[MAXITEMS];
sys_printpair gpuline[MAXITEMS];
sys_printpair memline1[MAXITEMS];
sys_printpair memline2[MAXITEMS];
sys_printpair swpline[MAXITEMS];
sys_printpair memnumaline[MAXITEMS];
sys_printpair cpunumaline[MAXITEMS];
sys_printpair llcline[MAXITEMS];
sys_printpair pagline[MAXITEMS];
sys_printpair psiline[MAXITEMS];
sys_printpair contline[MAXITEMS];
sys_printpair dskline[MAXITEMS];
sys_printpair nettransportline[MAXITEMS];
sys_printpair netnetline[MAXITEMS];
sys_printpair netinterfaceline[MAXITEMS];
sys_printpair infinibandline[MAXITEMS];
sys_printpair nfsmountline[MAXITEMS];
sys_printpair nfcline[MAXITEMS];
sys_printpair nfsline[MAXITEMS];
typedef struct {
const char *name;
int prio;
} name_prio;
/*
** make an string,int pair array from a string. chop based on spaces/tabs
** example: input: "ABCD:3 EFG:1 QWE:16"
** output: { { "ABCD", 3 }, {"EFG", 1}, { "QWE", 16}, { 0, 0 } }
*/
static void
makeargv(char *line, const char *linename, name_prio *vec)
{
int i=0;
char *p=line;
char *name=0;
char *prio=0;
// find pair and scan it
while (*p && i<MAXITEMS-1)
{
// skip initial spaces
while (*p && (*p==' ' || *p=='\t'))
{
++p;
}
if (! *p)
{
break;
}
name=p;
// found a new word; let's chop!
while (*p && *p !=':')
{
++p;
}
if (*p==':')
{
*p=0;
}
else
mcleanstop(1, "atoprc - %s: no name:prio pair for "
"`%s'\n", name, linename);
/* now get number */
p++;
prio=p;
errno = 0; /* To distinguish success/failure after call */
long lprio=strtol(p, &p, 10);
if (prio==p || errno == ERANGE || lprio >= INT_MAX || lprio <0)
{
fprintf(stderr,
"atoprc - %s: item `%s` has "
"invalid priority `", linename, name);
while (*prio && *prio !=' ') {
fputc(*prio, stderr);
prio++;
}
fprintf(stderr, "'\n");
cleanstop(1);
}
vec[i].name=name;
vec[i].prio=lprio;
++i;
}
vec[i].name=0;
}
/*
* make_sys_prints: make array of sys_printpairs
* input: string, sys_printpair array, maxentries
*/
static void
make_sys_prints(sys_printpair *ar, int maxn, const char *pairs,
sys_printdef *permissables[], const char *linename,
struct sstat *sstat, extraparam *extra)
{
name_prio items[MAXITEMS];
int i, a, n=strlen(pairs);
char str[n+1];
strcpy(str, pairs);
makeargv(str, linename, items);
for(i=a=0; items[i].name && i<maxn-1; i++)
{
const char *name=items[i].name;
int j;
for (j=0; permissables[j] != 0; ++j)
{
if (strcmp(permissables[j]->configname, name) == 0)
{
// call validate function to see if this
// counter is relevant
//
if (sstat != NULL &&
permissables[j]->dovalidate != NULL &&
permissables[j]->dovalidate(sstat) == 0)
break;
ar[a].f = permissables[j];
ar[a].prio = items[i].prio;
a++;
break;
}
}
if (permissables[j]==0)
{
mcleanstop(1,
"atoprc - own system line: item %s invalid in %s line\n",
name, linename);
}
}
ar[a].f=0;
ar[a].prio=0;
}
/*
* init_proc_prints: determine width of columns that are
* dependent of dynamic values
*/
static void
init_proc_prints(count_t numcpu)
{
char linebuf[64];
int i;
/*
** fill number of digits for various PID/TID columns
** and reformat header to new width
*/
for (i=0; idprocpdefs[i] != 0; i++)
{
idprocpdefs[i]->width = pidwidth;
if ( strlen(idprocpdefs[i]->head) < pidwidth)
{
char *p = malloc(pidwidth+1);
ptrverify(p, "Malloc failed for formatted header\n");
sprintf(p, "%*s", pidwidth, idprocpdefs[i]->head);
idprocpdefs[i]->head = p;
}
}
/*
** fill number of positions for the SORTITEM (percentage),
** depending on the number of CPUs (e.g. with 10+ CPUs a process
** can reach a CPU percentage of 1000% and with 100+ CPUs a
** CPU percentage of 10000%).
*/
procprt_SORTITEM.width =
snprintf(linebuf, sizeof linebuf, "%lld", numcpu*100) + 1;
}
/*
** make_detail_prints: make array of detail_printpairs
** input: string, detail_printpair array, maxentries
*/
static void
make_detail_prints(detail_printpair *ar, int maxn, const char *pairs,
const char *linename)
{
name_prio items[MAXITEMS];
int n=strlen(pairs);
char str[n+1];
strcpy(str, pairs);
makeargv(str, linename, items);
int i;
for(i=0; items[i].name && i<maxn-1; ++i)
{
const char *name=items[i].name;
int j;
for (j=0; alldetaildefs[j] != 0; ++j)
{
if (strcmp(alldetaildefs[j]->configname, name)==0)
{
ar[i].pf = alldetaildefs[j];
ar[i].prio = items[i].prio;
break;
}
}
if (alldetaildefs[j]==0)
{
mcleanstop(1,
"atoprc - ownprocline: item %s invalid!\n",
name);
}
}
ar[i].pf=0;
ar[i].prio=0;
}
/*
** calculate the total consumption on system-level for the
** four main resources
*/
void
totalcap(struct syscap *psc, struct sstat *sstat,
struct tstat **proclist, int nactproc)
{
register int i;
psc->nrcpu = sstat->cpu.nrcpu;
psc->availcpu = sstat->cpu.all.stime +
sstat->cpu.all.utime +
sstat->cpu.all.ntime +
sstat->cpu.all.itime +
sstat->cpu.all.wtime +
sstat->cpu.all.Itime +
sstat->cpu.all.Stime +
sstat->cpu.all.steal;
psc->availmem = sstat->mem.physmem * pagesize/1024;
/*
** calculate total transfer issued by the active processes
** for disk and for network
*/
for (psc->availnet=psc->availdsk=0, i=0; i < nactproc; i++)
{
struct tstat *curstat = *(proclist+i);
count_t nett_wsz;
psc->availnet += curstat->net.tcpssz;
psc->availnet += curstat->net.tcprsz;
psc->availnet += curstat->net.udpssz;
psc->availnet += curstat->net.udprsz;
if (curstat->dsk.wsz > curstat->dsk.cwsz)
nett_wsz = curstat->dsk.wsz -
curstat->dsk.cwsz;
else
nett_wsz = 0;
psc->availdsk += curstat->dsk.rsz;
psc->availdsk += nett_wsz;
}
for (psc->availgpumem=i=0; i < sstat->gpu.nrgpus; i++)
psc->availgpumem += sstat->gpu.gpu[i].memtotnow;
psc->nrgpu = sstat->gpu.nrgpus;
psc->nrmemnuma = sstat->memnuma.nrnuma;
psc->nrcpunuma = sstat->cpunuma.nrnuma;
}
/*
** calculate cumulative system- and user-time for all active processes
** besides, initialize all counter lines on system level
*/
void
pricumproc(struct sstat *sstat, struct devtstat *devtstat,
int nexit, unsigned int noverflow, int avgval, int nsecs)
{
static int firsttime=1;
int i;
extraparam extra;
for (i=0, extra.totut=extra.totst=0; i < devtstat->nprocactive; i++)
{
struct tstat *curstat = *(devtstat->procactive+i);
extra.totut += curstat->cpu.utime;
extra.totst += curstat->cpu.stime;
}
extra.nproc = devtstat->nprocall;
extra.ntrun = devtstat->totrun;
extra.ntslpi = devtstat->totslpi;
extra.ntslpu = devtstat->totslpu;
extra.ntidle = devtstat->totidle;
extra.nzomb = devtstat->totzombie;
extra.nexit = nexit;
extra.noverflow = noverflow;
extra.avgval = avgval;
extra.nsecs = nsecs;
extra.index = 0;
if (firsttime)
{
firsttime=0;
if (sysprcline[0].f == 0)
{
make_sys_prints(sysprcline, MAXITEMS,
"PRCSYS:8 "
"PRCUSER:8 "
"BLANKBOX:0 "
"PRCNPROC:7 "
"PRCNRUNNING:5 "
"PRCNSLEEPING:5 "
"PRCNDSLEEPING:5 "
"PRCNIDLE:5 "
"PRCNZOMBIE:4 "
"PRCCLONES:3 "
"BLANKBOX:0 "
"PRCNNEXIT:6",
prcsyspdefs, "builtin sysprcline",
sstat, &extra);
}
if (allcpuline[0].f == 0)
{
make_sys_prints(allcpuline, MAXITEMS,
"CPUSYS:9 "
"CPUUSER:8 "
"CPUIRQ:6 "
"BLANKBOX:0 "
"CPUIDLE:7 "
"CPUWAIT:7 "
"CPUSTEAL:2 "
"CPUGUEST:3 "
"BLANKBOX:0 "
"CPUIPC:5 "
"CPUCYCLE:4 "
"CPUFREQ:4 "
"CPUSCALE:4 ",
cpusyspdefs, "builtin allcpuline",
sstat, &extra);
}
if (indivcpuline[0].f == 0)
{
make_sys_prints(indivcpuline, MAXITEMS,
"CPUISYS:9 "
"CPUIUSER:8 "
"CPUIIRQ:6 "
"BLANKBOX:0 "
"CPUIIDLE:7 "
"CPUIWAIT:7 "
"CPUISTEAL:2 "
"CPUIGUEST:3 "
"BLANKBOX:0 "
"CPUIIPC:5 "
"CPUICYCLE:4 "
"CPUIFREQ:4 "
"CPUISCALE:4 ",
cpisyspdefs, "builtin indivcpuline",
sstat, &extra);
}
if (cplline[0].f == 0)
{
make_sys_prints(cplline, MAXITEMS,
"CPLNUMCPU:7"
"BLANKBOX:0 "
"CPLAVG1:4 "
"CPLAVG5:3 "
"CPLAVG15:2 "
"BLANKBOX:0 "
"CPLCSW:6 "
"CPLINTR:5 ",
cplsyspdefs, "builtin cplline",
sstat, &extra);
}
if (gpuline[0].f == 0)
{
make_sys_prints(gpuline, MAXITEMS,
"GPUBUS:8 "
"GPUGPUPERC:7 "
"GPUMEMPERC:6 "
"GPUMEMOCC:5 "
"GPUMEMTOT:3 "
"GPUMEMUSE:4 "
"GPUMEMAVG:2 "
"GPUNRPROC:2 "
"BLANKBOX:0 "
"GPUTYPE:1 ",
gpusyspdefs, "builtin gpuline",
NULL, NULL);
}
if (memline1[0].f == 0)
{
make_sys_prints(memline1, MAXITEMS,
"MEMTOT:8 "
"MEMFREE:9 "
"MEMAVAIL:7 "
"BLANKBOX:0 "
"MEMCACHE:7 "
"MEMDIRTY:5 "
"MEMBUFFER:6 "
"BLANKBOX:0 "
"MEMSLAB:6 "
"RECSLAB:2 "
"BLANKBOX:0 "
"HUPTOT:4 "
"HUPUSE:1 ",
memsyspdefs1, "builtin memline1",
sstat, &extra);
}
if (memline2[0].f == 0)
{
make_sys_prints(memline2, MAXITEMS,
"NUMNUMA:8 "
"BLANKBOX:1 "
"SHMEM:6 "
"SHMRSS:4 "
"SHMSWP:4 "
"BLANKBOX:0 "
"TCPSOCK:3 "
"UDPSOCK:2 "
"BLANKBOX:0 "
"PAGETABS:5 "
"BLANKBOX:0 "
"ANONTHP:4 "
"VMWBAL:4 "
"BLANKBOX:0 "
"ZFSARC:5 ",
memsyspdefs2, "builtin memline2",
sstat, &extra);
}
if (swpline[0].f == 0)
{
make_sys_prints(swpline, MAXITEMS,
"SWPTOT:5 "
"SWPFREE:6 "
"SWPCACHE:4 "
"BLANKBOX:0 "
"ZSWPOOL:3 "
"ZSWSTORED:3 "
"BLANKBOX:0 "
"KSMSHARED:2 "
"KSMSHARING:2 "
"BLANKBOX:0 "
"SWPCOMMITTED:7 "
"SWPCOMMITLIM:8",
swpsyspdefs, "builtin swpline",
sstat, &extra);
}
if (memnumaline[0].f == 0)
{
make_sys_prints(memnumaline, MAXITEMS,
"NUMATOT:8 "
"NUMAFREE:9 "
"NUMAFILEPAGE:9 "
"NUMANR:7 "
"NUMADIRTY:5 "
"NUMAACTIVE:5 "
"NUMAINACTIVE:5 "
"NUMASLAB:7 "
"NUMASLABRECLAIM:4 "
"NUMASHMEM:4 "
"NUMAFRAG:6 "
"NUMAHUPTOT:4 "
"NUMAHUPUSE:3 ",
memnumasyspdefs, "builtin memnumaline",
sstat, &extra);
}
if (cpunumaline[0].f == 0)
{
make_sys_prints(cpunumaline, MAXITEMS,
"NUMACPUSYS:9 "
"NUMACPUUSER:8 "
"NUMACPUNICE:8 "
"NUMACPUIRQ:6 "
"NUMACPUSOFTIRQ:6 "
"NUMACPUIDLE:7 "
"NUMACPUWAIT:7 "
"NUMACPUSTEAL:2 "
"NUMACPUGUEST:3 "
"NUMANUMCPU:5",
cpunumasyspdefs, "builtin cpunumaline",
NULL, NULL);
}
if (llcline[0].f == 0)
{
make_sys_prints(llcline, MAXITEMS,
"LLCMBMTOTAL:9 "
"LLCMBMLOCAL:8 "
"NUMLLC:7 "
"BLANKBOX:0 ",
llcsyspdefs, "builtin llcline",
sstat, &extra);
}
if (pagline[0].f == 0)
{
make_sys_prints(pagline, MAXITEMS,
"PAGSCAN:3 "
"PAGSTEAL:2 "
"PAGSTALL:1 "
"PAGCOMPACT:5 "
"NUMAMIGRATE:5"
"PGMIGRATE:6"
"PAGPGIN:6 "
"PAGPGOUT:6 "
"PAGZSWIN:4 "
"PAGZSWOUT:7 "
"PAGSWIN:5 "
"PAGSWOUT:8 "
"OOMKILLS:9 ",
pagsyspdefs, "builtin pagline",
sstat, &extra);
}
if (psiline[0].f == 0)
{
make_sys_prints(psiline, MAXITEMS,
"PSICPUSTOT:7 "
"PSIMEMSTOT:7 "
"PSIMEMFTOT:8 "
"PSIIOSTOT:7 "
"PSIIOFTOT:8 "
"PSICPUS:6 "
"PSIMEMS:5 "
"PSIMEMF:3 "
"PSIIOS:4 "
"PSIIOF:2 "
"BLANKBOX:0 ",
psisyspdefs, "builtin psiline",
sstat, &extra);
}
if (contline[0].f == 0)
{
make_sys_prints(contline, MAXITEMS,
"CONTNAME:8 "
"CONTNPROC:7 "
"CONTCPU:6 "
"CONTMEM:6 "
"BLANKBOX:0 "
"BLANKBOX:0 ",
contsyspdefs, "builtin contline",
NULL, NULL);
}
if (dskline[0].f == 0)
{
make_sys_prints(dskline, MAXITEMS,
"DSKNAME:9 "
"DSKBUSY:8 "
"DSKNREAD:7 "
"DSKNWRITE:7 "
"DSKNDISC:6 "
"DSKKBPERRD:5 "
"DSKKBPERWR:5 "
"DSKKBPERDS:4 "
"DSKMBPERSECRD:6 "
"DSKMBPERSECWR:6 "
"DSKINFLIGHT:2 "
"DSKAVQUEUE:1 "
"DSKAVIO:6",
dsksyspdefs, "builtin dskline",
sstat, &extra);
}
if (nfsmountline[0].f == 0)
{
make_sys_prints(nfsmountline, MAXITEMS,
"NFMPATH:8 "
"NFMSERVER:8 "
"NFMTOTREAD:8 "
"NFMTOTWRITE:8 "
"BLANKBOX:0 "
"NFMNREAD:7 "
"NFMNWRITE:6 "
"BLANKBOX:0 "
"NFMDREAD:5 "
"NFMDWRITE:4 "
"BLANKBOX:0 "
"NFMMREAD:3 "
"NFMMWRITE:2 "
"BLANKBOX:0 "
"BLANKBOX:0",
nfsmntsyspdefs, "builtin nfsmountline",
NULL, NULL);
}
if (nfcline[0].f == 0)
{
make_sys_prints(nfcline, MAXITEMS,
"NFCRPCCNT:8 "
"NFCRPCREAD:7 "
"NFCRPCWRITE:7 "
"NFCRPCRET:5 "
"NFCRPCARF:5 "
"BLANKBOX:0 "
"BLANKBOX:0 "
"BLANKBOX:0 "
"BLANKBOX:0 "
"BLANKBOX:0 ",
nfcsyspdefs, "builtin nfcline",
sstat, &extra);
}
if (nfsline[0].f == 0)
{
make_sys_prints(nfsline, MAXITEMS,
"NFSRPCCNT:8 "
"NFSRPCREAD:6 "
"NFSRPCWRITE:6 "
"BLANKBOX:0 "
"NFSNRBYTES:7 "
"NFSNWBYTES:7 "
"BLANKBOX:0 "
"NFSNETTCP:5 "
"NFSNETUDP:5 "
"BLANKBOX:0 "
"NFSRCHITS:3 "
"NFSRCMISS:2 "
"NFSRCNOCA:1 "
"BLANKBOX:0 "
"NFSBADFMT:4 "
"NFSBADAUT:4 "
"NFSBADCLN:4 ",
nfssyspdefs, "builtin nfsline",
sstat, &extra);
}
if (nettransportline[0].f == 0)
{
make_sys_prints(nettransportline, MAXITEMS,
"NETTRANSPORT:9 "
"NETTCPI:8 "
"NETTCPO:8 "
"NETUDPI:8 "
"NETUDPO:8 "
"NETTCPACTOPEN:6 "
"NETTCPPASVOPEN:5 "
"NETTCPRETRANS:4 "
"NETTCPINERR:3 "
"NETTCPORESET:2 "
"NETTCPCSUMERR:2 "
"NETUDPNOPORT:1 "
"NETUDPINERR:3",
nettranssyspdefs, "builtin nettransportline",
sstat, &extra);
}
if (netnetline[0].f == 0)
{
make_sys_prints(netnetline, MAXITEMS,
"NETNETWORK:5 "
"NETIPI:4 "
"NETIPO:4 "
"NETIPFRW:4 "
"NETIPDELIV:4 "
"BLANKBOX:0 "
"BLANKBOX:0 "
"BLANKBOX:0 "
"NETICMPIN:1 "
"NETICMPOUT:1 ",
netnetsyspdefs, "builtin netnetline",
sstat, &extra);
}
if (netinterfaceline[0].f == 0)
{
make_sys_prints(netinterfaceline, MAXITEMS,
"NETNAME:8 "
"BLANKBOX:0 "
"NETPCKI:7 "
"NETPCKO:7 "
"BLANKBOX:0 "
"NETSPEEDMAX:5 "
"NETSPEEDIN:6 "
"NETSPEEDOUT:6 "
"BLANKBOX:0 "
"NETCOLLIS:2 "
"NETMULTICASTIN:2 "
"NETRCVERR:4 "
"NETSNDERR:4 "
"NETRCVDROP:3 "
"NETSNDDROP:3",
netintfsyspdefs, "builtin netinterfaceline",
NULL, NULL);
}
if (infinibandline[0].f == 0)
{
make_sys_prints(infinibandline, MAXITEMS,
"IFBNAME:8 "
"BLANKBOX:0 "
"IFBPCKI:7 "
"IFBPCKO:7 "
"BLANKBOX:0 "
"IFBSPEEDMAX:5 "
"IFBSPEEDIN:6 "
"IFBSPEEDOUT:6 "
"IFBLANES:4 "
"BLANKBOX:0 "
"BLANKBOX:0 "
"BLANKBOX:0 "
"BLANKBOX:0 "
"BLANKBOX:0 "
"BLANKBOX:0 ",
infinisyspdefs, "builtin infinibandline",
NULL, NULL);
}
} // firsttime
move(1, 0);
showsysline(sysprcline, sstat, &extra, "PRC", 0);
}
/*
** print the header for the process/cgroups list
*/
void
prihead(int curlist, int totlist, char *showtype, char *showorder,
char autosort, count_t numcpu)
{
static int firsttime=1;
static int prev_supportflags = -1, prev_threadview = -1;
/*
** determine once the layout of all per-process reports
** except for the generic report (might change dynamically)
*/
if (firsttime)
{
init_proc_prints(numcpu);
make_detail_prints(memprocs, MAXITEMS,
"PID:10 TID:3 MINFLT:2 MAJFLT:2 VSTEXT:4 VSLIBS:4 "
"VDATA:4 VSTACK:4 LOCKSZ:3 VSIZE:6 RSIZE:7 PSIZE:5 "
"VGROW:7 RGROW:8 SWAPSZ:5 RUID:1 EUID:0 "
"SORTITEM:9 CMD:10",
"built-in memprocs");
make_detail_prints(schedprocs, MAXITEMS,
"PID:10 TID:6 CID:4 VPID:3 CTID:3 TRUN:7 TSLPI:7 "
"TSLPU:7 TIDLE:7 POLI:8 NICE:9 PRI:5 RTPR:9 CPUNR:8 "
"ST:8 EXC:8 S:8 RDELAY:8 BDELAY:7 WCHAN:5 "
"NVCSW:7 NIVCSW:7 SORTITEM:10 CMD:10",
"built-in schedprocs");
make_detail_prints(dskprocs, MAXITEMS,
"PID:10 TID:4 RDDSK:9 "
"WRDSK:9 WCANCL:8 "
"SORTITEM:10 CMD:10",
"built-in dskprocs");
make_detail_prints(netprocs, MAXITEMS,
"PID:10 TID:6 "
"TCPRCV:9 TCPRASZ:4 TCPSND:9 TCPSASZ:4 "
"UDPRCV:8 UDPRASZ:3 UDPSND:8 UDPSASZ:3 "
"BANDWI:10 BANDWO:10 "
"SORTITEM:10 CMD:10",
"built-in netprocs");
make_detail_prints(gpuprocs, MAXITEMS,
"PID:10 TID:5 CID:4 GPULIST:8 GPUGPUBUSY:8 GPUMEMBUSY:8 "
"GPUMEM:7 GPUMEMAVG:6 S:8 SORTITEM:10 CMD:10",
"built-in gpuprocs");
make_detail_prints(varprocs, MAXITEMS,
"PID:10 TID:4 PPID:9 CID:2 VPID:1 CTID:1 "
"RUID:8 RGID:8 EUID:5 EGID:4 "
"SUID:3 SGID:2 FSUID:3 FSGID:2 "
"STDATE:7 STTIME:7 ENDATE:5 ENTIME:5 "
"ST:6 EXC:6 S:6 SORTITEM:10 CMD:10",
"built-in varprocs");
make_detail_prints(cmdprocs, MAXITEMS,
"PID:10 TID:4 S:8 SORTITEM:10 COMMAND-LINE:10",
"built-in cmdprocs");
make_detail_prints(totusers, MAXITEMS,
"NPROCS:10 SYSCPU:9 USRCPU:9 VSIZE:6 "
"RSIZE:8 PSIZE:8 LOCKSZ:3 SWAPSZ:5 RDDSK:7 CWRDSK:7 "
"RNET:6 SNET:6 SORTITEM:10 RUID:10",
"built-in totusers");
make_detail_prints(totprocs, MAXITEMS,
"NPROCS:10 SYSCPU:9 USRCPU:9 VSIZE:6 "
"RSIZE:8 PSIZE:8 LOCKSZ:3 SWAPSZ:5 RDDSK:7 CWRDSK:7 "
"RNET:6 SNET:6 SORTITEM:10 CMD:10",
"built-in totprocs");
make_detail_prints(totconts, MAXITEMS,
"NPROCS:10 SYSCPU:9 USRCPU:9 RDELAY:8 BDELAY:7 VSIZE:6 "
"RSIZE:8 PSIZE:8 LOCKSZ:3 SWAPSZ:5 RDDSK:7 CWRDSK:7 "
"RNET:6 SNET:6 SORTITEM:10 CID:10",
"built-in totconts");
// meant to show cgroups
//
make_detail_prints(gencgroups, MAXITEMS,
"CGRPATH:10 CGRNPROCS:9 CGRNPROCSB:8 "
"CGRCPUBUSY:7 CGRCPUPSI:4 CGRCPUMAX:3 CGRCPUWGT:2 "
"CGRMEMORY:7 CGRMEMPSI:4 CGRMEMMAX:3 CGRSWPMAX:1 "
"CGRDISKIO:6 CGRDSKPSI:4 CGRDSKWGT:2 CGRPID:6 CGRCMD:5",
"built-in gencgroups");
}
/*
** update the generic report if needed
*/
if (prev_supportflags != supportflags || prev_threadview != threadview)
{
make_proc_dynamicgen();
prev_supportflags = supportflags;
prev_threadview = threadview;
if (*showtype == MPROCNET && !(supportflags&NETATOP||supportflags&NETATOPBPF) )
{
*showtype = MPROCGEN;
*showorder = MSORTCPU;
}
}
/*
** print the header line
*/
switch (*showtype)
{
case MPROCGEN:
showprochead(genprocs, curlist, totlist, *showorder, autosort);
break;
case MPROCMEM:
showprochead(memprocs, curlist, totlist, *showorder, autosort);
break;
case MPROCDSK:
showprochead(dskprocs, curlist, totlist, *showorder, autosort);
break;
case MPROCNET:
showprochead(netprocs, curlist, totlist, *showorder, autosort);
break;
case MPROCGPU:
showprochead(gpuprocs, curlist, totlist, *showorder, autosort);
break;
case MPROCVAR:
showprochead(varprocs, curlist, totlist, *showorder, autosort);
break;
case MPROCARG:
showprochead(cmdprocs, curlist, totlist, *showorder, autosort);
break;
case MPROCOWN:
showprochead(ownprocs, curlist, totlist, *showorder, autosort);
break;
case MPROCSCH:
showprochead(schedprocs, curlist, totlist, *showorder, autosort);
break;
case MCUMUSER:
showprochead(totusers, curlist, totlist, *showorder, autosort);
break;
case MCUMPROC:
showprochead(totprocs, curlist, totlist, *showorder, autosort);
break;
case MCUMCONT:
showprochead(totconts, curlist, totlist, *showorder, autosort);
break;
case MCGROUPS:
showcgrouphead(gencgroups, curlist, totlist, *showorder);
break;
}
}
/*
** assemble the layout of the generic line,
** depending on the supported features (like
** I/O stats, network stats) and current view
*/
#define FORMPID "PID:10 "
#define FORMTID "TID:6 "
#define FORMCID "CID:5 "
#define FORMCPU "SYSCPU:9 USRCPU:9 "
#define FORMDEL "RDELAY:4 "
#define FORMBDL "BDELAY:4 "
#define FORMMEM "VGROW:8 RGROW:8 "
#define FORMDSK "RDDSK:7 CWRDSK:7 "
#define FORMNET "RNET:6 SNET:6 "
#define FORMMSC "RUID:2 EUID:1 ST:3 EXC:3 THR:3 S:3 CPUNR:3 "
#define FORMEND "SORTITEM:10 CMD:10"
static void
make_proc_dynamicgen()
{
char format[300], *p = format;
memcpy(p, FORMPID, sizeof FORMPID -1);
p += sizeof FORMPID -1;
if (threadview)
{
memcpy(p, FORMTID, sizeof FORMTID -1);
p += sizeof FORMTID -1;
}
if (supportflags & CONTAINERSTAT)
{
memcpy(p, FORMCID, sizeof FORMCID -1);
p += sizeof FORMCID -1;
}
memcpy(p, FORMCPU, sizeof FORMCPU -1);
p += sizeof FORMCPU -1;
memcpy(p, FORMDEL, sizeof FORMDEL -1);
p += sizeof FORMDEL -1;
memcpy(p, FORMBDL, sizeof FORMBDL -1);
p += sizeof FORMBDL -1;
memcpy(p, FORMMEM, sizeof FORMMEM -1);
p += sizeof FORMMEM -1;
if (supportflags & IOSTAT)
{
memcpy(p, FORMDSK, sizeof FORMDSK -1);
p += sizeof FORMDSK -1;
}
if (supportflags & NETATOP || supportflags & NETATOPBPF)
{
memcpy(p, FORMNET, sizeof FORMNET -1);
p += sizeof FORMNET -1;
}
memcpy(p, FORMMSC, sizeof FORMMSC -1);
p += sizeof FORMMSC -1;
memcpy(p, FORMEND, sizeof FORMEND);
p += sizeof FORMEND;
make_detail_prints(genprocs, MAXITEMS, format, "built-in genprocs");
}
/*
** print the list of cgroups (and processes) from the deviation list
*/
int
pricgroup(struct cglinesel *itemlist, int firstitem, int lastitem,
int curline, int curlist, int totlist, struct syscap *sb,
int nsecs, int avgval)
{
int i;
/*
** print info per cgroup
*/
for (i=firstitem; i < lastitem; i++)
{
/*
** screen filled entirely ?
*/
if (screen && curline >= LINES)
break;
if (screen)
move(curline,0);
/*
** print information for next line
*/
showcgroupline(gencgroups,
(itemlist+i)->cgp, (itemlist+i)->tsp,
nsecs, avgval, sb->availcpu, sb->nrcpu);
curline++;
}
return curline;
}
/*
** print the list of processes from the deviation list
*/
int
priproc(struct tstat **proclist, int firstproc, int lastproc, int curline,
int curlist, int totlist, char showtype, char showorder,
struct syscap *sb, int nsecs, int avgval)
{
register int i;
register struct tstat *curstat;
double perc;
/*
** print info per actual process and maintain totals
*/
for (i=firstproc; i < lastproc; i++)
{
curstat = *(proclist+i);
if (screen && curline >= LINES) /* screen filled entirely ? */
break;
/*
** calculate occupation-percentage of this process
** depending on selected resource
*/
switch (showorder)
{
case MSORTCPU:
perc = 0.0;
if (sb->availcpu)
{
perc = (double)(curstat->cpu.stime +
curstat->cpu.utime ) * 100 /
(sb->availcpu / sb->nrcpu);
if (perc > 100.0 * sb->nrcpu)
perc = 100.0 * sb->nrcpu;
if (perc > 100.0 * curstat->gen.nthr)
perc = 100.0 * curstat->gen.nthr;
}
break;
case MSORTMEM:
perc = 0.0;
if (sb->availmem)
{
perc = (double)curstat->mem.rmem *
100.0 / sb->availmem;
if (perc > 100.0)
perc = 100.0;
}
break;
case MSORTDSK:
perc = 0.0;
if (sb->availdsk)
{
count_t nett_wsz;
if (curstat->dsk.wsz > curstat->dsk.cwsz)
nett_wsz = curstat->dsk.wsz -
curstat->dsk.cwsz;
else
nett_wsz = 0;
perc = (double)(curstat->dsk.rsz + nett_wsz) *
100.0 / sb->availdsk;
if (perc > 100.0)
perc = 100.0;
}
break;
case MSORTNET:
perc = 0.0;
if (sb->availnet)
{
perc = (double)(curstat->net.tcpssz +
curstat->net.tcprsz +
curstat->net.udpssz +
curstat->net.udprsz ) *
100.0 / sb->availnet;
if (perc > 100.0)
perc = 100.0;
}
break;
case MSORTGPU:
perc = 0.0;
if (!curstat->gpu.state)
break;
if (curstat->gpu.gpubusy != -1)
{
perc = curstat->gpu.gpubusy;
}
else
{
perc = curstat->gpu.memnow*100 *
sb->nrgpu / sb->availgpumem;
}
break;
default:
perc = 0.0;
}
/*
** now do the formatting of output
*/
if (screen) {
move(curline,0);
}
switch (showtype)
{
case MPROCGEN:
showprocline(genprocs, curstat, perc, nsecs, avgval);
break;
case MPROCMEM:
showprocline(memprocs, curstat, perc, nsecs, avgval);
break;
case MPROCDSK:
showprocline(dskprocs, curstat, perc, nsecs, avgval);
break;
case MPROCNET:
showprocline(netprocs, curstat, perc, nsecs, avgval);
break;
case MPROCGPU:
showprocline(gpuprocs, curstat, perc, nsecs, avgval);
break;
case MPROCVAR:
showprocline(varprocs, curstat, perc, nsecs, avgval);
break;
case MPROCARG:
showprocline(cmdprocs, curstat, perc, nsecs, avgval);
break;
case MPROCOWN:
showprocline(ownprocs, curstat, perc, nsecs, avgval);
break;
case MPROCSCH:
showprocline(schedprocs, curstat, perc, nsecs, avgval);
break;
case MCUMUSER:
showprocline(totusers, curstat, perc, nsecs, avgval);
break;
case MCUMPROC:
showprocline(totprocs, curstat, perc, nsecs, avgval);
break;
case MCUMCONT:
showprocline(totconts, curstat, perc, nsecs, avgval);
break;
}
curline++;
}
return curline;
}
/*
** print the system-wide statistics
*/
static void pridisklike(extraparam *, struct perdsk *, char *,
char *, int, unsigned int *, int *, int, regex_t *);
int
prisyst(struct sstat *sstat, int curline, int nsecs, int avgval,
int fixedhead, struct sselection *selp, char *highorderp,
int maxcpulines, int maxgpulines, int maxdsklines, int maxmddlines,
int maxlvmlines, int maxintlines, int maxifblines,
int maxnfslines, int maxcontlines, int maxnumalines, int maxllclines)
{
extraparam extra;
int lin;
count_t busy;
unsigned int badness, highbadness=0;
extra.nsecs = nsecs;
extra.avgval = avgval;
/*
** CPU statistics
*/
extra.cputot = sstat->cpu.all.stime + sstat->cpu.all.utime +
sstat->cpu.all.ntime + sstat->cpu.all.itime +
sstat->cpu.all.wtime + sstat->cpu.all.Itime +
sstat->cpu.all.Stime + sstat->cpu.all.steal;
busy = (extra.cputot - sstat->cpu.all.itime - sstat->cpu.all.wtime)
* 100.0 / extra.cputot;
if (cpubadness)
badness = busy * 100 / cpubadness;
else
badness = 0;
if (highbadness < badness)
{
highbadness = badness;
*highorderp = MSORTCPU;
}
if (extra.cputot == 0)
extra.cputot = 1; /* avoid divide-by-zero */
extra.percputot = extra.cputot / sstat->cpu.nrcpu;
if (extra.percputot == 0)
extra.percputot = 1; /* avoid divide-by-zero */
if (screen)
move(curline, 0);
showsysline(allcpuline, sstat, &extra, "CPU", badness);
curline++;
if (sstat->cpu.nrcpu > 1)
{
for (extra.index=lin=0;
extra.index < sstat->cpu.nrcpu && lin < maxcpulines;
extra.index++)
{
extra.percputot = sstat->cpu.cpu[extra.index].stime +
sstat->cpu.cpu[extra.index].utime +
sstat->cpu.cpu[extra.index].ntime +
sstat->cpu.cpu[extra.index].itime +
sstat->cpu.cpu[extra.index].wtime +
sstat->cpu.cpu[extra.index].Itime +
sstat->cpu.cpu[extra.index].Stime +
sstat->cpu.cpu[extra.index].steal;
if (extra.percputot ==
(sstat->cpu.cpu[extra.index].itime +
sstat->cpu.cpu[extra.index].wtime ) &&
!fixedhead )
continue; /* inactive cpu */
busy = (extra.percputot -
sstat->cpu.cpu[extra.index].itime -
sstat->cpu.cpu[extra.index].wtime)
* 100.0 / extra.percputot;
if (cpubadness)
badness = busy * 100 / cpubadness;
else
badness = 0;
if (highbadness < badness)
{
highbadness = badness;
*highorderp = MSORTCPU;
}
if (extra.percputot == 0)
extra.percputot = 1; /* avoid divide-by-zero */
if (screen)
move(curline, 0);
showsysline(indivcpuline, sstat, &extra, "cpu",
badness);
curline++;
lin++;
}
}
/*
** other CPU-related statistics
*/
if (screen)
move(curline, 0);
showsysline(cplline, sstat, &extra, "CPL", 0);
curline++;
/*
** GPU statistics
*/
if (sstat->gpu.nrgpus)
{
for (extra.index=0, lin=0;
extra.index < sstat->gpu.nrgpus && lin < maxgpulines;
extra.index++)
{
int totbusy;
count_t avgmemuse;
// notice that GPU percentage and memory percentage
// are not always available; in that case both
// values have the value -1
//
totbusy = sstat->gpu.gpu[extra.index].gpuperccum +
sstat->gpu.gpu[extra.index].memperccum;
if (totbusy == -2) // metrics available?
totbusy= 0;
if (sstat->gpu.gpu[extra.index].samples == 0)
{
totbusy =
sstat->gpu.gpu[extra.index].gpupercnow +
sstat->gpu.gpu[extra.index].mempercnow;
avgmemuse =
sstat->gpu.gpu[extra.index].memusenow;
}
else
{
totbusy = totbusy /
sstat->gpu.gpu[extra.index].samples;
avgmemuse =
sstat->gpu.gpu[extra.index].memusecum/
sstat->gpu.gpu[extra.index].samples;
}
if (gpubadness)
badness = totbusy * 100 / gpubadness;
else
badness = 0;
if ( totbusy > 0 ||
// memusage > 512 MiB (rather arbitrary)?
avgmemuse > 512*1024 ||
fixedhead )
{
showsysline(gpuline, sstat,
&extra, "GPU", badness);
curline++;
lin++;
}
}
}
/*
** MEMORY statistics
*/
busy = (sstat->mem.physmem - sstat->mem.freemem
- sstat->mem.cachemem
- sstat->mem.buffermem
- sstat->mem.slabreclaim
+ sstat->mem.shmem)
* 100.0 / sstat->mem.physmem;
if (membadness)
badness = busy * 100 / membadness;
else
badness = 0;
if (highbadness < badness)
{
highbadness = badness;
*highorderp = MSORTMEM;
}
if (screen)
move(curline, 0);
showsysline(memline1, sstat, &extra, "MEM", badness);
curline++;
showsysline(memline2, sstat, &extra, "MEM", badness);
curline++;
/*
** SWAP statistics
*/
busy = (sstat->mem.totswap - sstat->mem.freeswap)
* 100.0 / sstat->mem.totswap;
if (swpbadness)
{
badness = busy * 100 / swpbadness;
}
else
{
badness = 0;
}
if (highbadness < badness)
{
highbadness = badness;
*highorderp = MSORTMEM;
}
if (screen)
move(curline, 0);
showsysline(swpline, sstat, &extra, "SWP", badness);
curline++;
/*
** memory info related for per NUMA
*/
if (sstat->memnuma.nrnuma > 1)
{
for (extra.index=lin=0;
extra.index < sstat->memnuma.nrnuma && lin < maxnumalines;
extra.index++)
{
busy = (sstat->memnuma.numa[extra.index].totmem
- sstat->memnuma.numa[extra.index].freemem
- sstat->memnuma.numa[extra.index].filepage
- sstat->memnuma.numa[extra.index].slabreclaim
+ sstat->memnuma.numa[extra.index].shmem)
* 100.0 / sstat->memnuma.numa[extra.index].totmem;
if (membadness)
badness = busy * 100 / membadness;
else
badness = 0;
if (highbadness < badness)
{
highbadness = badness;
*highorderp = MSORTMEM;
}
if (screen)
move(curline, 0);
showsysline(memnumaline, sstat, &extra, "NUM", badness);
curline++;
lin++;
}
}
/*
** Accumulate each cpu statistic for per NUMA
*/
if (sstat->cpunuma.nrnuma > 1)
{
for (extra.index=lin=0;
extra.index < sstat->cpunuma.nrnuma && lin < maxnumalines;
extra.index++)
{
extra.pernumacputot = sstat->cpunuma.numa[extra.index].stime +
sstat->cpunuma.numa[extra.index].utime +
sstat->cpunuma.numa[extra.index].ntime +
sstat->cpunuma.numa[extra.index].itime +
sstat->cpunuma.numa[extra.index].wtime +
sstat->cpunuma.numa[extra.index].Itime +
sstat->cpunuma.numa[extra.index].Stime +
sstat->cpunuma.numa[extra.index].steal;
if (extra.pernumacputot ==
(sstat->cpunuma.numa[extra.index].itime +
sstat->cpunuma.numa[extra.index].wtime ) &&
!fixedhead )
continue; /* inactive cpu */
if (extra.pernumacputot == 0)
extra.pernumacputot = 1; /* avoid divide-by-zero */
busy = (extra.pernumacputot -
sstat->cpunuma.numa[extra.index].itime -
sstat->cpunuma.numa[extra.index].wtime)
* 100.0 / extra.pernumacputot;
if (cpubadness)
badness = busy * 100 / cpubadness;
else
badness = 0;
if (highbadness < badness)
{
highbadness = badness;
*highorderp = MSORTCPU;
}
extra.percputot = extra.pernumacputot /
(sstat->cpu.nrcpu/sstat->cpunuma.nrnuma);
if (extra.percputot == 0)
extra.percputot = 1; /* avoid divide-by-zero */
if (screen)
move(curline, 0);
showsysline(cpunumaline, sstat, &extra, "NUC", badness);
curline++;
lin++;
}
}
/*
** LLC statistics (if supported by kernel and
** pseudo filesystem mounted)
*/
for (extra.index=0, lin=0;
extra.index < sstat->llc.nrllcs && lin < maxllclines;
extra.index++)
{
if (fixedhead ||
sstat->llc.perllc[extra.index].mbm_local ||
sstat->llc.perllc[extra.index].mbm_total )
{
if (screen)
move(curline, 0);
showsysline(llcline, sstat, &extra, "LLC", 0);
curline++;
lin++;
}
}
/*
** PAGING statistics
*/
if (fixedhead ||
sstat->mem.pgscans ||
sstat->mem.pgsteal ||
sstat->mem.allocstall ||
sstat->mem.compactstall ||
sstat->mem.pgins ||
sstat->mem.pgouts ||
sstat->mem.tcpsock ||
sstat->mem.udpsock ||
sstat->mem.swins ||
sstat->mem.swouts ||
sstat->mem.oomkills > 0 ||
sstat->mem.pgmigrate ||
sstat->mem.numamigrate )
{
busy = sstat->mem.swouts / nsecs * pagbadness;
if (busy > 100)
busy = 100;
if (membadness)
badness = busy * 100 / membadness;
else
badness = 0;
if (highbadness < badness)
{
highbadness = badness;
*highorderp = MSORTMEM;
}
/*
** take care that this line is anyhow colored for
** 'almost critical' in case of swapouts > 1 per second
*/
if (sstat->mem.swouts / nsecs > 0 &&
pagbadness && almostcrit && badness < almostcrit)
badness = almostcrit;
if (screen)
move(curline, 0);
showsysline(pagline, sstat, &extra, "PAG", badness);
curline++;
}
/*
** Pressure statistics
*/
if (sstat->psi.present)
{
if (fixedhead ||
sstat->psi.cpusome.avg10 || sstat->psi.memsome.avg10 ||
sstat->psi.iosome.avg10 ||
sstat->psi.cpusome.avg60 || sstat->psi.memsome.avg60 ||
sstat->psi.iosome.avg60 ||
sstat->psi.cpusome.avg300 || sstat->psi.memsome.avg300 ||
sstat->psi.iosome.avg300 )
{
badness = sstat->psi.cpusome.avg10 >
sstat->psi.cpusome.avg60 ?
sstat->psi.cpusome.avg10 :
sstat->psi.cpusome.avg60;
if (badness < sstat->psi.cpusome.avg300)
badness = sstat->psi.cpusome.avg300;
if (screen)
move(curline, 0);
showsysline(psiline, sstat, &extra,"PSI", badness);
curline++;
}
}
/*
** Container statistics (if any)
*/
for (extra.index=0, lin=0;
extra.index < sstat->cfs.nrcontainer && lin < maxcontlines;
extra.index++)
{
if (fixedhead ||
sstat->cfs.cont[extra.index].system ||
sstat->cfs.cont[extra.index].user ||
sstat->cfs.cont[extra.index].nice )
{
if (screen)
move(curline, 0);
showsysline(contline, sstat, &extra, "CON", 0);
curline++;
lin++;
}
}
/*
** DISK statistics
*/
extra.mstot = extra.cputot * 1000 / hertz / sstat->cpu.nrcpu;
pridisklike(&extra, sstat->dsk.lvm, "LVM", highorderp, maxlvmlines,
&highbadness, &curline, fixedhead,
selp->lvmnamesz ? &(selp->lvmregex) : (void *) 0);
pridisklike(&extra, sstat->dsk.mdd, "MDD", highorderp, maxmddlines,
&highbadness, &curline, fixedhead, (void *) 0);
pridisklike(&extra, sstat->dsk.dsk, "DSK", highorderp, maxdsklines,
&highbadness, &curline, fixedhead,
selp->dsknamesz ? &(selp->dskregex) : (void *) 0);
/*
** NFS server and client statistics
*/
for (extra.index=0, lin=0;
extra.index < sstat->nfs.nfsmounts.nrmounts && lin < maxnfslines;
extra.index++)
{
int i = extra.index;
if ( (sstat->nfs.nfsmounts.nfsmnt[i].bytesread +
sstat->nfs.nfsmounts.nfsmnt[i].byteswrite +
sstat->nfs.nfsmounts.nfsmnt[i].bytesdread +
sstat->nfs.nfsmounts.nfsmnt[i].bytesdwrite +
sstat->nfs.nfsmounts.nfsmnt[i].bytestotread +
sstat->nfs.nfsmounts.nfsmnt[i].bytestotwrite +
sstat->nfs.nfsmounts.nfsmnt[i].pagesmread +
sstat->nfs.nfsmounts.nfsmnt[i].pagesmwrite ) ||
sstat->nfs.nfsmounts.nfsmnt[i].age < nsecs ||
fixedhead )
{
if (screen)
move(curline, 0);
showsysline(nfsmountline, sstat, &extra, "NFM", 0);
curline++;
lin++;
}
}
if (sstat->nfs.client.rpccnt || fixedhead )
{
if (screen)
move(curline, 0);
showsysline(nfcline, sstat, &extra, "NFC", 0);
curline++;
}
if (sstat->nfs.server.rpccnt || fixedhead )
{
if (screen)
move(curline, 0);
showsysline(nfsline, sstat, &extra, "NFS", 0);
curline++;
}
/*
** NET statistics: transport
*/
if (sstat->net.tcp.InSegs ||
sstat->net.tcp.OutSegs ||
sstat->net.udpv4.InDatagrams ||
sstat->net.udpv6.Udp6InDatagrams ||
sstat->net.udpv4.OutDatagrams ||
sstat->net.udpv6.Udp6OutDatagrams ||
fixedhead )
{
if (screen)
move(curline, 0);
showsysline(nettransportline, sstat, &extra, "NET", 0);
curline++;
}
/*
** NET statistics: network
*/
if (sstat->net.ipv4.InReceives ||
sstat->net.ipv6.Ip6InReceives ||
sstat->net.ipv4.OutRequests ||
sstat->net.ipv6.Ip6OutRequests ||
fixedhead )
{
if (screen)
move(curline, 0);
showsysline(netnetline, sstat, &extra, "NET", 0);
curline++;
}
/*
** NET statistics: interfaces
*/
for (extra.index=0, lin=0;
sstat->intf.intf[extra.index].name[0] && lin < maxintlines;
extra.index++)
{
if (sstat->intf.intf[extra.index].rpack ||
sstat->intf.intf[extra.index].spack || fixedhead)
{
if (selp->itfnamesz && regexec(&(selp->itfregex),
sstat->intf.intf[extra.index].name, 0, NULL, 0))
continue; // suppress (not selected)
/*
** calculate busy-percentage for interface
*/
count_t ival, oval;
/*
** convert byte-transfers to bit-transfers (* 8)
** convert bit-transfers to kilobit-transfers (/ 1000)
** per second
*/
ival = sstat->intf.intf[extra.index].rbyte/125/nsecs;
oval = sstat->intf.intf[extra.index].sbyte/125/nsecs;
/* speed known? */
if (sstat->intf.intf[extra.index].speed)
{
if (sstat->intf.intf[extra.index].duplex)
busy = (ival > oval ? ival : oval) /
(sstat->intf.intf[extra.index].speed
*10);
else
busy = (ival + oval) /
(sstat->intf.intf[extra.index].speed
*10);
}
else
{
busy = 0;
}
if (netbadness)
badness = busy * 100 / netbadness;
else
badness = 0;
if (highbadness < badness && (supportflags & NETATOP || supportflags & NETATOPBPF) )
{
highbadness = badness;
*highorderp = MSORTNET;
}
if (screen)
move(curline, 0);
showsysline(netinterfaceline, sstat, &extra,
"NET", badness);
curline++;
lin++;
}
}
/*
** NET statistics: InfiniBand
*/
for (extra.index=0, lin=0;
extra.index < sstat->ifb.nrports && lin < maxifblines;
extra.index++)
{
if (sstat->ifb.ifb[extra.index].rcvb ||
sstat->ifb.ifb[extra.index].sndb || fixedhead)
{
/*
** calculate busy-percentage for IB port
*/
count_t ival, oval;
/*
** convert byte-transfers to bit-transfers (* 8)
** convert bit-transfers to kilobit-transfers (/ 1000)
** per second
*/
ival = sstat->ifb.ifb[extra.index].rcvb/125/nsecs;
oval = sstat->ifb.ifb[extra.index].sndb/125/nsecs;
if (sstat->ifb.ifb[extra.index].rate)
busy = (ival > oval ? ival : oval) *
sstat->ifb.ifb[extra.index].lanes /
(sstat->ifb.ifb[extra.index].rate * 10);
else
busy = 0;
if (netbadness)
badness = busy * 100 / netbadness;
else
badness = 0;
if (highbadness < badness)
{
highbadness = badness;
*highorderp = MSORTNET;
}
if (screen)
move(curline, 0);
showsysline(infinibandline, sstat, &extra,
"IFB", badness);
curline++;
lin++;
}
}
/*
** application statistics
**
** WWW: notice that we cause one access ourselves by fetching
** the statistical counters
*/
#if HTTPSTATS
if (sstat->www.accesses > 1 || fixedhead )
{
char format1[8], format2[8], format3[8], format4[8], format5[8];
if (screen)
move(curline, 0);
printg("WWW | reqs %s | totKB %s | byt/rq %s | iwork %s |"
" bwork %s |",
val2valstr(sstat->www.accesses, format1, 6,
avgval, nsecs),
val2valstr(sstat->www.totkbytes, format2, 6,
avgval, nsecs),
val2valstr(sstat->www.accesses ?
sstat->www.totkbytes*1024/sstat->www.accesses : 0,
format3, 5, 0, 0),
val2valstr(sstat->www.iworkers, format4, 6, 0, 0),
val2valstr(sstat->www.bworkers, format5, 6, 0, 0) );
if (!screen)
{
printg("\n");
}
curline++;
}
#endif
/*
** if the system is hardly loaded, still CPU-ordering of
** processes is most interesting (instead of memory)
*/
if (highbadness < 70 && *highorderp == MSORTMEM)
*highorderp = MSORTCPU;
return curline;
}
/*
** handle all instances of a specific disk-like device
*/
static void
pridisklike(extraparam *ep, struct perdsk *dp, char *lp, char *highorderp,
int maxlines, unsigned int *highbadp, int *curlinp, int fixedhead,
regex_t *rep)
{
int lin;
count_t busy;
unsigned int badness;
for (ep->perdsk = dp, ep->index=0, lin=0;
ep->perdsk[ep->index].name[0] && lin < maxlines; ep->index++)
{
if (rep && regexec(rep, ep->perdsk[ep->index].name, 0, NULL, 0))
continue; // suppress (not selected)
ep->iotot = ep->perdsk[ep->index].nread +
ep->perdsk[ep->index].nwrite;
busy = (double)(ep->perdsk[ep->index].io_ms *
100.0 / ep->mstot);
if (dskbadness)
badness = busy * 100 / dskbadness;
else
badness = 0;
if (*highbadp < badness && (supportflags & IOSTAT) )
{
*highbadp = badness;
*highorderp = MSORTDSK;
}
if (ep->iotot || fixedhead)
{
move(*curlinp, 0);
showsysline(dskline, 0, ep, lp, badness);
(*curlinp)++;
lin++;
}
}
}
/*
** process-level sort functions
*/
int
compcpu(const void *a, const void *b)
{
register count_t acpu = (*(struct tstat **)a)->cpu.stime +
(*(struct tstat **)a)->cpu.utime;
register count_t bcpu = (*(struct tstat **)b)->cpu.stime +
(*(struct tstat **)b)->cpu.utime;
if (acpu < bcpu)
return 1;
if (acpu > bcpu)
return -1;
return compmem(a, b);
}
int
compdsk(const void *a, const void *b)
{
struct tstat *ta = *(struct tstat **)a;
struct tstat *tb = *(struct tstat **)b;
count_t adsk;
count_t bdsk;
if (ta->dsk.wsz > ta->dsk.cwsz)
adsk = ta->dsk.rio + ta->dsk.wsz - ta->dsk.cwsz;
else
adsk = ta->dsk.rio;
if (tb->dsk.wsz > tb->dsk.cwsz)
bdsk = tb->dsk.rio + tb->dsk.wsz - tb->dsk.cwsz;
else
bdsk = tb->dsk.rio;
if (adsk < bdsk)
return 1;
if (adsk > bdsk)
return -1;
return compcpu(a, b);
}
int
compmem(const void *a, const void *b)
{
register count_t amem = (*(struct tstat **)a)->mem.rmem;
register count_t bmem = (*(struct tstat **)b)->mem.rmem;
if (amem < bmem)
return 1;
if (amem > bmem)
return -1;
return 0;
}
int
compgpu(const void *a, const void *b)
{
register char astate = (*(struct tstat **)a)->gpu.state;
register char bstate = (*(struct tstat **)b)->gpu.state;
register count_t abusy = (*(struct tstat **)a)->gpu.gpubusy;
register count_t bbusy = (*(struct tstat **)b)->gpu.gpubusy;
register count_t amem = (*(struct tstat **)a)->gpu.memnow;
register count_t bmem = (*(struct tstat **)b)->gpu.memnow;
if (!astate) // no GPU usage?
abusy = amem = -2;
if (!bstate) // no GPU usage?
bbusy = bmem = -2;
if (abusy == -1 || bbusy == -1)
{
if (amem < bmem)
return 1;
if (amem > bmem)
return -1;
return 0;
}
else
{
if (abusy < bbusy)
return 1;
if (abusy > bbusy)
return -1;
return 0;
}
}
int
compnet(const void *a, const void *b)
{
register count_t anet = (*(struct tstat **)a)->net.tcpssz +
(*(struct tstat **)a)->net.tcprsz +
(*(struct tstat **)a)->net.udpssz +
(*(struct tstat **)a)->net.udprsz ;
register count_t bnet = (*(struct tstat **)b)->net.tcpssz +
(*(struct tstat **)b)->net.tcprsz +
(*(struct tstat **)b)->net.udpssz +
(*(struct tstat **)b)->net.udprsz ;
if (anet < bnet)
return 1;
if (anet > bnet)
return -1;
return compcpu(a, b);
}
int
compusr(const void *a, const void *b)
{
register int uida = (*(struct tstat **)a)->gen.ruid;
register int uidb = (*(struct tstat **)b)->gen.ruid;
if (uida > uidb)
return 1;
if (uida < uidb)
return -1;
return 0;
}
int
compnam(const void *a, const void *b)
{
register char *nama = (*(struct tstat **)a)->gen.name;
register char *namb = (*(struct tstat **)b)->gen.name;
return strcmp(nama, namb);
}
int
compcon(const void *a, const void *b)
{
register char *utsa = (*(struct tstat **)a)->gen.utsname;
register char *utsb = (*(struct tstat **)b)->gen.utsname;
return strcmp(utsa, utsb);
}
/*
** system-level sort functions
*/
int
cpucompar(const void *a, const void *b)
{
register count_t aidle = ((struct percpu *)a)->itime +
((struct percpu *)a)->wtime;
register count_t bidle = ((struct percpu *)b)->itime +
((struct percpu *)b)->wtime;
if (aidle < bidle)
return -1;
if (aidle > bidle)
return 1;
return 0;
}
int
gpucompar(const void *a, const void *b)
{
register count_t agpuperc = ((struct pergpu *)a)->gpuperccum;
register count_t bgpuperc = ((struct pergpu *)b)->gpuperccum;
register count_t amemuse = ((struct pergpu *)a)->memusenow;
register count_t bmemuse = ((struct pergpu *)b)->memusenow;
if (agpuperc == -1 || bgpuperc == -1)
{
if (amemuse < bmemuse)
return 1;
if (amemuse > bmemuse)
return -1;
return 0;
}
else
{
if (agpuperc < bgpuperc)
return 1;
if (agpuperc > bgpuperc)
return -1;
return 0;
}
}
int
diskcompar(const void *a, const void *b)
{
register count_t amsio = ((struct perdsk *)a)->io_ms;
register count_t bmsio = ((struct perdsk *)b)->io_ms;
if (amsio < bmsio)
return 1;
if (amsio > bmsio)
return -1;
return 0;
}
int
intfcompar(const void *a, const void *b)
{
register count_t afactor=0, bfactor=0;
count_t aspeed = ((struct perintf *)a)->speed;
count_t bspeed = ((struct perintf *)b)->speed;
char aduplex = ((struct perintf *)a)->duplex;
char bduplex = ((struct perintf *)b)->duplex;
count_t arbyte = ((struct perintf *)a)->rbyte;
count_t brbyte = ((struct perintf *)b)->rbyte;
count_t asbyte = ((struct perintf *)a)->sbyte;
count_t bsbyte = ((struct perintf *)b)->sbyte;
/*
** if speed of first interface known, calculate busy factor
*/
if (aspeed)
{
if (aduplex)
afactor = (arbyte > asbyte ? arbyte : asbyte)
* 10 / aspeed;
else
afactor = (arbyte + asbyte) * 10 / aspeed;
}
/*
** if speed of second interface known, calculate busy factor
*/
if (bspeed)
{
if (bduplex)
bfactor = (brbyte > bsbyte ? brbyte : bsbyte)
* 10 / bspeed;
else
bfactor = (brbyte + bsbyte) * 10 / bspeed;
}
/*
** compare interfaces
*/
if (aspeed && bspeed)
{
if (afactor < bfactor)
return 1;
if (afactor > bfactor)
return -1;
return 0;
}
if (!aspeed && !bspeed)
{
if ((arbyte + asbyte) < (brbyte + bsbyte))
return 1;
if ((arbyte + asbyte) > (brbyte + bsbyte))
return -1;
return 0;
}
if (aspeed)
return -1;
else
return 1;
}
int
ifbcompar(const void *a, const void *b)
{
count_t atransfer = ((struct perifb *)a)->rcvb +
((struct perifb *)a)->sndb;
count_t btransfer = ((struct perifb *)b)->rcvb +
((struct perifb *)b)->sndb;
if (atransfer < btransfer)
return 1;
if (atransfer > btransfer)
return -1;
return 0;
}
int
nfsmcompar(const void *a, const void *b)
{
const struct pernfsmount *na = a;
const struct pernfsmount *nb = b;
register count_t aused = na->bytesread + na->byteswrite +
na->bytesdread + na->bytesdwrite +
na->bytestotread + na->bytestotwrite +
na->pagesmread + na->pagesmwrite;
register count_t bused = nb->bytesread + nb->byteswrite +
nb->bytesdread + nb->bytesdwrite +
nb->bytestotread + nb->bytestotwrite +
nb->pagesmread + nb->pagesmwrite;
if (aused < bused)
return 1;
if (aused > bused)
return -1;
return 0;
}
int
contcompar(const void *a, const void *b)
{
const struct percontainer *ca = a;
const struct percontainer *cb = b;
register count_t aused = ca->system + ca->user + ca->nice;
register count_t bused = cb->system + cb->user + cb->nice;
if (aused < bused)
return 1;
if (aused > bused)
return -1;
return 0;
}
int
memnumacompar(const void *a, const void *b)
{
register count_t aused = ((struct mempernuma *)a)->totmem -
((struct mempernuma *)a)->freemem;
register count_t bused = ((struct mempernuma *)b)->totmem -
((struct mempernuma *)b)->freemem;
if (aused < bused)
return 1;
if (aused > bused)
return -1;
return 0;
}
int
cpunumacompar(const void *a, const void *b)
{
register count_t aidle = ((struct cpupernuma *)a)->itime +
((struct cpupernuma *)a)->wtime;
register count_t bidle = ((struct cpupernuma *)b)->itime +
((struct cpupernuma *)b)->wtime;
if (aidle < bidle)
return -1;
if (aidle > bidle)
return 1;
return 0;
}
int
llccompar(const void *a, const void *b)
{
const struct perllc *ca = a;
const struct perllc *cb = b;
register count_t aused = ca->mbm_local + ca->mbm_total;
register count_t bused = cb->mbm_local + cb->mbm_total;
if (aused < bused)
return 1;
if (aused > bused)
return -1;
return 0;
}
/*
** handle modifications from the /etc/atoprc and ~/.atoprc file
*/
int
get_posval(char *name, char *val)
{
int value = atoi(val);
if ( !numeric(val))
{
fprintf(stderr, "atoprc: %s value %s not a (positive) numeric\n",
name, val);
exit(1);
}
if (value < 0)
{
fprintf(stderr,
"atoprc: %s value %d not positive\n",
name, value);
exit(1);
}
return value;
}
static int
get_perc(char *name, char *val)
{
int value = get_posval(name, val);
if (value < 0 || value > 100)
{
fprintf(stderr, "atoprc: %s value %d not in range 0-100\n",
name, value);
exit(1);
}
return value;
}
void
do_cpucritperc(char *name, char *val)
{
cpubadness = get_perc(name, val);
}
void
do_gpucritperc(char *name, char *val)
{
gpubadness = get_perc(name, val);
}
void
do_memcritperc(char *name, char *val)
{
membadness = get_perc(name, val);
}
void
do_swpcritperc(char *name, char *val)
{
swpbadness = get_perc(name, val);
}
void
do_dskcritperc(char *name, char *val)
{
dskbadness = get_perc(name, val);
}
void
do_netcritperc(char *name, char *val)
{
netbadness = get_perc(name, val);
}
void
do_swoutcritsec(char *name, char *val)
{
pagbadness = get_posval(name, val);
}
void
do_almostcrit(char *name, char *val)
{
almostcrit = get_perc(name, val);
}
void
do_ownsysprcline(char *name, char *val)
{
make_sys_prints(sysprcline, MAXITEMS, val, prcsyspdefs, name,
NULL, NULL);
}
void
do_ownallcpuline(char *name, char *val)
{
make_sys_prints(allcpuline, MAXITEMS, val, cpusyspdefs, name,
NULL, NULL);
}
void
do_ownindivcpuline(char *name, char *val)
{
make_sys_prints(indivcpuline, MAXITEMS, val, cpisyspdefs, name,
NULL, NULL);
}
void
do_owncplline(char *name, char *val)
{
make_sys_prints(cplline, MAXITEMS, val, cplsyspdefs, name,
NULL, NULL);
}
void
do_owngpuline(char *name, char *val)
{
make_sys_prints(gpuline, MAXITEMS, val, gpusyspdefs, name,
NULL, NULL);
}
void
do_ownmemline(char *name, char *val)
{
make_sys_prints(memline1, MAXITEMS, val, memsyspdefs1, name,
NULL, NULL);
}
void
do_ownswpline(char *name, char *val)
{
make_sys_prints(swpline, MAXITEMS, val, swpsyspdefs, name,
NULL, NULL);
}
void
do_ownpagline(char *name, char *val)
{
make_sys_prints(pagline, MAXITEMS, val, pagsyspdefs, name,
NULL, NULL);
}
void
do_ownmemnumaline(char *name, char *val)
{
make_sys_prints(memnumaline, MAXITEMS, val, memnumasyspdefs, name,
NULL, NULL);
}
void
do_owncpunumaline(char *name, char *val)
{
make_sys_prints(cpunumaline, MAXITEMS, val, cpunumasyspdefs, name,
NULL, NULL);
}
void
do_ownllcline(char *name, char *val)
{
make_sys_prints(llcline, MAXITEMS, val, llcsyspdefs, name,
NULL, NULL);
}
void
do_owndskline(char *name, char *val)
{
make_sys_prints(dskline, MAXITEMS, val, dsksyspdefs, name,
NULL, NULL);
}
void
do_ownnettransportline(char *name, char *val)
{
make_sys_prints(nettransportline, MAXITEMS, val, nettranssyspdefs, name,
NULL, NULL);
}
void
do_ownnetnetline(char *name, char *val)
{
make_sys_prints(netnetline, MAXITEMS, val, netnetsyspdefs, name,
NULL, NULL);
}
void
do_ownnetinterfaceline(char *name, char *val)
{
make_sys_prints(netinterfaceline, MAXITEMS, val, netintfsyspdefs, name,
NULL, NULL);
}
void
do_owninfinibandline(char *name, char *val)
{
make_sys_prints(infinibandline, MAXITEMS, val, infinisyspdefs, name,
NULL, NULL);
}
void
do_ownprocline(char *name, char *val)
{
make_detail_prints(ownprocs, MAXITEMS, val, name);
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。