1*b89261baSDavid van Moolenbroek /*
2*b89261baSDavid van Moolenbroek * Copyright (c) 1984 through 2008, William LeFebvre
3*b89261baSDavid van Moolenbroek * All rights reserved.
4*b89261baSDavid van Moolenbroek *
5*b89261baSDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
6*b89261baSDavid van Moolenbroek * modification, are permitted provided that the following conditions are met:
7*b89261baSDavid van Moolenbroek *
8*b89261baSDavid van Moolenbroek * * Redistributions of source code must retain the above copyright
9*b89261baSDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
10*b89261baSDavid van Moolenbroek *
11*b89261baSDavid van Moolenbroek * * Redistributions in binary form must reproduce the above
12*b89261baSDavid van Moolenbroek * copyright notice, this list of conditions and the following disclaimer
13*b89261baSDavid van Moolenbroek * in the documentation and/or other materials provided with the
14*b89261baSDavid van Moolenbroek * distribution.
15*b89261baSDavid van Moolenbroek *
16*b89261baSDavid van Moolenbroek * * Neither the name of William LeFebvre nor the names of other
17*b89261baSDavid van Moolenbroek * contributors may be used to endorse or promote products derived from
18*b89261baSDavid van Moolenbroek * this software without specific prior written permission.
19*b89261baSDavid van Moolenbroek *
20*b89261baSDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21*b89261baSDavid van Moolenbroek * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*b89261baSDavid van Moolenbroek * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23*b89261baSDavid van Moolenbroek * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24*b89261baSDavid van Moolenbroek * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25*b89261baSDavid van Moolenbroek * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26*b89261baSDavid van Moolenbroek * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27*b89261baSDavid van Moolenbroek * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28*b89261baSDavid van Moolenbroek * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29*b89261baSDavid van Moolenbroek * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30*b89261baSDavid van Moolenbroek * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*b89261baSDavid van Moolenbroek */
32*b89261baSDavid van Moolenbroek
33*b89261baSDavid van Moolenbroek /*
34*b89261baSDavid van Moolenbroek * top - a top users display for Unix
35*b89261baSDavid van Moolenbroek *
36*b89261baSDavid van Moolenbroek * SYNOPSIS: any uniprocessor, 32 bit SGI machine running IRIX 5.3
37*b89261baSDavid van Moolenbroek *
38*b89261baSDavid van Moolenbroek * DESCRIPTION:
39*b89261baSDavid van Moolenbroek * This is the machine-dependent module for IRIX 5.3.
40*b89261baSDavid van Moolenbroek * It has been tested on Indys running 5.3 and Indigos running 5.3XFS
41*b89261baSDavid van Moolenbroek *
42*b89261baSDavid van Moolenbroek * LIBS: -lmld
43*b89261baSDavid van Moolenbroek * CFLAGS: -DHAVE_GETOPT
44*b89261baSDavid van Moolenbroek *
45*b89261baSDavid van Moolenbroek * AUTHOR: Sandeep Cariapa <cariapa@sgi.com>
46*b89261baSDavid van Moolenbroek * This is not a supported product of Silicon Graphics, Inc.
47*b89261baSDavid van Moolenbroek * Please do not call SGI for support.
48*b89261baSDavid van Moolenbroek *
49*b89261baSDavid van Moolenbroek */
50*b89261baSDavid van Moolenbroek
51*b89261baSDavid van Moolenbroek #define _KMEMUSER
52*b89261baSDavid van Moolenbroek
53*b89261baSDavid van Moolenbroek #include "config.h"
54*b89261baSDavid van Moolenbroek
55*b89261baSDavid van Moolenbroek #include <sys/types.h>
56*b89261baSDavid van Moolenbroek #include <sys/time.h>
57*b89261baSDavid van Moolenbroek #include <sys/stat.h>
58*b89261baSDavid van Moolenbroek #include <sys/swap.h>
59*b89261baSDavid van Moolenbroek #include <sys/proc.h>
60*b89261baSDavid van Moolenbroek #include <sys/procfs.h>
61*b89261baSDavid van Moolenbroek #include <sys/sysinfo.h>
62*b89261baSDavid van Moolenbroek #include <sys/sysmp.h>
63*b89261baSDavid van Moolenbroek #include <paths.h>
64*b89261baSDavid van Moolenbroek #include <dirent.h>
65*b89261baSDavid van Moolenbroek #include <stdio.h>
66*b89261baSDavid van Moolenbroek #include <nlist.h>
67*b89261baSDavid van Moolenbroek #include <unistd.h>
68*b89261baSDavid van Moolenbroek #include <errno.h>
69*b89261baSDavid van Moolenbroek #include <fcntl.h>
70*b89261baSDavid van Moolenbroek #include "top.h"
71*b89261baSDavid van Moolenbroek #include "machine.h"
72*b89261baSDavid van Moolenbroek
73*b89261baSDavid van Moolenbroek #ifdef IRIX64
74*b89261baSDavid van Moolenbroek #define nlist nlist64
75*b89261baSDavid van Moolenbroek #define lseek lseek64
76*b89261baSDavid van Moolenbroek #define off_t off64_t
77*b89261baSDavid van Moolenbroek #endif
78*b89261baSDavid van Moolenbroek
79*b89261baSDavid van Moolenbroek #define UNIX "/unix"
80*b89261baSDavid van Moolenbroek #define KMEM "/dev/kmem"
81*b89261baSDavid van Moolenbroek #define CPUSTATES 6
82*b89261baSDavid van Moolenbroek
83*b89261baSDavid van Moolenbroek #ifndef FSCALE
84*b89261baSDavid van Moolenbroek #define FSHIFT 8 /* bits to right of fixed binary point */
85*b89261baSDavid van Moolenbroek #define FSCALE (1<<FSHIFT)
86*b89261baSDavid van Moolenbroek #endif /* FSCALE */
87*b89261baSDavid van Moolenbroek
88*b89261baSDavid van Moolenbroek #ifdef FIXED_LOADAVG
89*b89261baSDavid van Moolenbroek typedef long load_avg;
90*b89261baSDavid van Moolenbroek # define loaddouble(la) ((double)(la) / FIXED_LOADAVG)
91*b89261baSDavid van Moolenbroek # define intload(i) ((int)((i) * FIXED_LOADAVG))
92*b89261baSDavid van Moolenbroek #else
93*b89261baSDavid van Moolenbroek typedef double load_avg;
94*b89261baSDavid van Moolenbroek # define loaddouble(la) (la)
95*b89261baSDavid van Moolenbroek # define intload(i) ((double)(i))
96*b89261baSDavid van Moolenbroek #endif
97*b89261baSDavid van Moolenbroek
98*b89261baSDavid van Moolenbroek #define percent_cpu(pp) (*(double *)pp->pr_fill)
99*b89261baSDavid van Moolenbroek #define weighted_cpu(pp) (*(double *)&pp->pr_fill[2])
100*b89261baSDavid van Moolenbroek
101*b89261baSDavid van Moolenbroek static int pagesize;
102*b89261baSDavid van Moolenbroek #define pagetok(size) ((size)*pagesize)
103*b89261baSDavid van Moolenbroek
104*b89261baSDavid van Moolenbroek static int numcpus;
105*b89261baSDavid van Moolenbroek
106*b89261baSDavid van Moolenbroek /*
107*b89261baSDavid van Moolenbroek * These definitions control the format of the per-process area
108*b89261baSDavid van Moolenbroek */
109*b89261baSDavid van Moolenbroek
110*b89261baSDavid van Moolenbroek static char header[] =
111*b89261baSDavid van Moolenbroek " PID X PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND";
112*b89261baSDavid van Moolenbroek /* 0123456 -- field to fill in starts at header+6 */
113*b89261baSDavid van Moolenbroek #define UNAME_START 6
114*b89261baSDavid van Moolenbroek
115*b89261baSDavid van Moolenbroek #define Proc_format \
116*b89261baSDavid van Moolenbroek "%5d %-8.8s %3d %4d %5s %5s %-5s %6s %5.2f%% %5.2f%% %.16s"
117*b89261baSDavid van Moolenbroek
118*b89261baSDavid van Moolenbroek /* these are for detailing the process states */
119*b89261baSDavid van Moolenbroek char *state_abbrev[] =
120*b89261baSDavid van Moolenbroek {"", "sleep", "run\0\0\0", "zombie", "stop", "idle", "", "swap"};
121*b89261baSDavid van Moolenbroek
122*b89261baSDavid van Moolenbroek int process_states[8];
123*b89261baSDavid van Moolenbroek char *procstatenames[] = {
124*b89261baSDavid van Moolenbroek "", " sleeping, ", " running, ", " zombie, ", " stopped, ",
125*b89261baSDavid van Moolenbroek " idle, ", "", " swapped, ",
126*b89261baSDavid van Moolenbroek NULL
127*b89261baSDavid van Moolenbroek };
128*b89261baSDavid van Moolenbroek
129*b89261baSDavid van Moolenbroek /* these are for detailing the cpu states */
130*b89261baSDavid van Moolenbroek int cpu_states[CPUSTATES];
131*b89261baSDavid van Moolenbroek char *cpustatenames[] = {
132*b89261baSDavid van Moolenbroek "idle", "usr", "ker", "wait", "swp", "intr",
133*b89261baSDavid van Moolenbroek NULL
134*b89261baSDavid van Moolenbroek };
135*b89261baSDavid van Moolenbroek
136*b89261baSDavid van Moolenbroek /* these are for detailing the memory statistics */
137*b89261baSDavid van Moolenbroek
138*b89261baSDavid van Moolenbroek long memory_stats[5];
139*b89261baSDavid van Moolenbroek char *memorynames[] = {
140*b89261baSDavid van Moolenbroek "K max, ", "K avail, ", "K free, ", "K swap, ", "K free swap", NULL
141*b89261baSDavid van Moolenbroek };
142*b89261baSDavid van Moolenbroek
143*b89261baSDavid van Moolenbroek /* useful externals */
144*b89261baSDavid van Moolenbroek extern int errno;
145*b89261baSDavid van Moolenbroek extern char *myname;
146*b89261baSDavid van Moolenbroek extern char *sys_errlist[];
147*b89261baSDavid van Moolenbroek extern char *format_k();
148*b89261baSDavid van Moolenbroek extern char *format_time();
149*b89261baSDavid van Moolenbroek extern long percentages();
150*b89261baSDavid van Moolenbroek
151*b89261baSDavid van Moolenbroek /* forward references */
152*b89261baSDavid van Moolenbroek int proc_compare (void *pp1, void *pp2);
153*b89261baSDavid van Moolenbroek
154*b89261baSDavid van Moolenbroek #define X_AVENRUN 0
155*b89261baSDavid van Moolenbroek #define X_NPROC 1
156*b89261baSDavid van Moolenbroek #define X_FREEMEM 2
157*b89261baSDavid van Moolenbroek #define X_MAXMEM 3
158*b89261baSDavid van Moolenbroek #define X_AVAILRMEM 4
159*b89261baSDavid van Moolenbroek #define X_MPID 5
160*b89261baSDavid van Moolenbroek
161*b89261baSDavid van Moolenbroek static struct nlist nlst[] = {
162*b89261baSDavid van Moolenbroek { "avenrun" }, /* 0. Array containing the 3 load averages. */
163*b89261baSDavid van Moolenbroek { "nproc" }, /* 1. Kernel parameter: Max number of processes. */
164*b89261baSDavid van Moolenbroek { "freemem" }, /* 2. Amount of free memory in system. */
165*b89261baSDavid van Moolenbroek { "maxmem" }, /* 3. Maximum amount of memory usable by system. */
166*b89261baSDavid van Moolenbroek { "availrmem" }, /* 4. Available real memory. */
167*b89261baSDavid van Moolenbroek #ifndef IRIX64
168*b89261baSDavid van Moolenbroek { "mpid" }, /* 5. PID of last process. */
169*b89261baSDavid van Moolenbroek #endif
170*b89261baSDavid van Moolenbroek { 0 }
171*b89261baSDavid van Moolenbroek };
172*b89261baSDavid van Moolenbroek static unsigned long avenrun_offset;
173*b89261baSDavid van Moolenbroek static unsigned long nproc_offset;
174*b89261baSDavid van Moolenbroek static unsigned long freemem_offset;
175*b89261baSDavid van Moolenbroek static unsigned long maxmem_offset;
176*b89261baSDavid van Moolenbroek static unsigned long availrmem_offset;
177*b89261baSDavid van Moolenbroek static unsigned long mpid_offset;
178*b89261baSDavid van Moolenbroek double load[3];
179*b89261baSDavid van Moolenbroek char fmt[MAX_COLS];
180*b89261baSDavid van Moolenbroek static int kmem;
181*b89261baSDavid van Moolenbroek static int nproc;
182*b89261baSDavid van Moolenbroek static int bytes;
183*b89261baSDavid van Moolenbroek static struct prpsinfo *pbase;
184*b89261baSDavid van Moolenbroek static struct prpsinfo **pref;
185*b89261baSDavid van Moolenbroek static DIR *procdir;
186*b89261baSDavid van Moolenbroek
187*b89261baSDavid van Moolenbroek /* get_process_info passes back a handle. This is what it looks like: */
188*b89261baSDavid van Moolenbroek struct handle {
189*b89261baSDavid van Moolenbroek struct prpsinfo **next_proc;/* points to next valid proc pointer */
190*b89261baSDavid van Moolenbroek int remaining; /* number of pointers remaining */
191*b89261baSDavid van Moolenbroek };
192*b89261baSDavid van Moolenbroek
193*b89261baSDavid van Moolenbroek static struct handle handle;
194*b89261baSDavid van Moolenbroek void getptable();
195*b89261baSDavid van Moolenbroek
196*b89261baSDavid van Moolenbroek /*
197*b89261baSDavid van Moolenbroek * Structure for keeping track of CPU times from last time around
198*b89261baSDavid van Moolenbroek * the program. We keep these things in a hash table, which is
199*b89261baSDavid van Moolenbroek * recreated at every cycle.
200*b89261baSDavid van Moolenbroek */
201*b89261baSDavid van Moolenbroek struct oldproc
202*b89261baSDavid van Moolenbroek {
203*b89261baSDavid van Moolenbroek pid_t oldpid;
204*b89261baSDavid van Moolenbroek double oldtime;
205*b89261baSDavid van Moolenbroek double oldpct;
206*b89261baSDavid van Moolenbroek };
207*b89261baSDavid van Moolenbroek static int oldprocs; /* size of table */
208*b89261baSDavid van Moolenbroek static struct oldproc *oldbase;
209*b89261baSDavid van Moolenbroek #define HASH(x) ((x << 1) % oldprocs)
210*b89261baSDavid van Moolenbroek #define PRPSINFOSIZE (sizeof(struct prpsinfo))
211*b89261baSDavid van Moolenbroek
machine_init(statics)212*b89261baSDavid van Moolenbroek int machine_init(statics)
213*b89261baSDavid van Moolenbroek struct statics *statics;
214*b89261baSDavid van Moolenbroek {
215*b89261baSDavid van Moolenbroek struct oldproc *op, *endbase;
216*b89261baSDavid van Moolenbroek
217*b89261baSDavid van Moolenbroek if ((kmem = open(KMEM, O_RDONLY)) == -1) {
218*b89261baSDavid van Moolenbroek perror(KMEM);
219*b89261baSDavid van Moolenbroek return(-1);
220*b89261baSDavid van Moolenbroek }
221*b89261baSDavid van Moolenbroek
222*b89261baSDavid van Moolenbroek /* get the list of symbols we want to access in the kernel */
223*b89261baSDavid van Moolenbroek (void) nlist(UNIX, nlst);
224*b89261baSDavid van Moolenbroek if (nlst[0].n_type == 0) {
225*b89261baSDavid van Moolenbroek fprintf(stderr, "%s: nlist failed\n", myname);
226*b89261baSDavid van Moolenbroek return(-1);
227*b89261baSDavid van Moolenbroek }
228*b89261baSDavid van Moolenbroek
229*b89261baSDavid van Moolenbroek /* Check if we got all of 'em. */
230*b89261baSDavid van Moolenbroek if (check_nlist(nlst) > 0) {
231*b89261baSDavid van Moolenbroek return(-1);
232*b89261baSDavid van Moolenbroek }
233*b89261baSDavid van Moolenbroek avenrun_offset = nlst[X_AVENRUN].n_value;
234*b89261baSDavid van Moolenbroek nproc_offset = nlst[X_NPROC].n_value;
235*b89261baSDavid van Moolenbroek freemem_offset = nlst[X_FREEMEM].n_value;
236*b89261baSDavid van Moolenbroek maxmem_offset = nlst[X_MAXMEM].n_value;
237*b89261baSDavid van Moolenbroek availrmem_offset = nlst[X_AVAILRMEM].n_value;
238*b89261baSDavid van Moolenbroek #ifndef IRIX64
239*b89261baSDavid van Moolenbroek mpid_offset = nlst[X_MPID].n_value;
240*b89261baSDavid van Moolenbroek #endif
241*b89261baSDavid van Moolenbroek
242*b89261baSDavid van Moolenbroek /* Got to do this first so that we can map real estate for the
243*b89261baSDavid van Moolenbroek process array. */
244*b89261baSDavid van Moolenbroek (void) getkval(nproc_offset, (int *) (&nproc), sizeof(nproc), "nproc");
245*b89261baSDavid van Moolenbroek
246*b89261baSDavid van Moolenbroek /* allocate space for proc structure array and array of pointers */
247*b89261baSDavid van Moolenbroek bytes = nproc * sizeof (struct prpsinfo);
248*b89261baSDavid van Moolenbroek pbase = (struct prpsinfo *) malloc (bytes);
249*b89261baSDavid van Moolenbroek pref = (struct prpsinfo **) malloc (nproc * sizeof (struct prpsinfo *));
250*b89261baSDavid van Moolenbroek oldbase = (struct oldproc *) malloc (2 * nproc * sizeof (struct oldproc));
251*b89261baSDavid van Moolenbroek
252*b89261baSDavid van Moolenbroek /* Just in case ... */
253*b89261baSDavid van Moolenbroek if (pbase == (struct prpsinfo *) NULL || pref == (struct prpsinfo **) NULL ||
254*b89261baSDavid van Moolenbroek oldbase == (struct oldproc *)NULL) {
255*b89261baSDavid van Moolenbroek (void) fprintf (stderr, "%s: can't allocate sufficient memory\n", myname);
256*b89261baSDavid van Moolenbroek return (-1);
257*b89261baSDavid van Moolenbroek }
258*b89261baSDavid van Moolenbroek
259*b89261baSDavid van Moolenbroek oldprocs = 2 * nproc;
260*b89261baSDavid van Moolenbroek endbase = oldbase + oldprocs;
261*b89261baSDavid van Moolenbroek for (op = oldbase; op < endbase; op++) {
262*b89261baSDavid van Moolenbroek op->oldpid = -1;
263*b89261baSDavid van Moolenbroek }
264*b89261baSDavid van Moolenbroek
265*b89261baSDavid van Moolenbroek if (!(procdir = opendir (_PATH_PROCFSPI))) {
266*b89261baSDavid van Moolenbroek (void) fprintf (stderr, "Unable to open %s\n", _PATH_PROCFSPI);
267*b89261baSDavid van Moolenbroek return (-1);
268*b89261baSDavid van Moolenbroek }
269*b89261baSDavid van Moolenbroek
270*b89261baSDavid van Moolenbroek if (chdir (_PATH_PROCFSPI)) {
271*b89261baSDavid van Moolenbroek /* handy for later on when we're reading it */
272*b89261baSDavid van Moolenbroek (void) fprintf (stderr, "Unable to chdir to %s\n", _PATH_PROCFSPI);
273*b89261baSDavid van Moolenbroek return (-1);
274*b89261baSDavid van Moolenbroek }
275*b89261baSDavid van Moolenbroek
276*b89261baSDavid van Moolenbroek statics->procstate_names = procstatenames;
277*b89261baSDavid van Moolenbroek statics->cpustate_names = cpustatenames;
278*b89261baSDavid van Moolenbroek statics->memory_names = memorynames;
279*b89261baSDavid van Moolenbroek
280*b89261baSDavid van Moolenbroek pagesize = getpagesize()/1024;
281*b89261baSDavid van Moolenbroek
282*b89261baSDavid van Moolenbroek /* all done! */
283*b89261baSDavid van Moolenbroek return(0);
284*b89261baSDavid van Moolenbroek }
285*b89261baSDavid van Moolenbroek
format_header(uname_field)286*b89261baSDavid van Moolenbroek char *format_header(uname_field)
287*b89261baSDavid van Moolenbroek register char *uname_field;
288*b89261baSDavid van Moolenbroek
289*b89261baSDavid van Moolenbroek {
290*b89261baSDavid van Moolenbroek register char *ptr;
291*b89261baSDavid van Moolenbroek
292*b89261baSDavid van Moolenbroek ptr = header + UNAME_START;
293*b89261baSDavid van Moolenbroek while (*uname_field != '\0') {
294*b89261baSDavid van Moolenbroek *ptr++ = *uname_field++;
295*b89261baSDavid van Moolenbroek }
296*b89261baSDavid van Moolenbroek
297*b89261baSDavid van Moolenbroek return(header);
298*b89261baSDavid van Moolenbroek }
299*b89261baSDavid van Moolenbroek
get_system_info(si)300*b89261baSDavid van Moolenbroek void get_system_info(si)
301*b89261baSDavid van Moolenbroek struct system_info *si;
302*b89261baSDavid van Moolenbroek
303*b89261baSDavid van Moolenbroek {
304*b89261baSDavid van Moolenbroek register int i;
305*b89261baSDavid van Moolenbroek int avenrun[3];
306*b89261baSDavid van Moolenbroek static int freemem;
307*b89261baSDavid van Moolenbroek static int maxmem;
308*b89261baSDavid van Moolenbroek static int availrmem;
309*b89261baSDavid van Moolenbroek struct sysinfo sysinfo;
310*b89261baSDavid van Moolenbroek static long cp_new[CPUSTATES];
311*b89261baSDavid van Moolenbroek static long cp_old[CPUSTATES];
312*b89261baSDavid van Moolenbroek static long cp_diff[CPUSTATES]; /* for cpu state percentages */
313*b89261baSDavid van Moolenbroek off_t fswap; /* current free swap in blocks */
314*b89261baSDavid van Moolenbroek off_t tswap; /* total swap in blocks */
315*b89261baSDavid van Moolenbroek
316*b89261baSDavid van Moolenbroek (void) getkval(avenrun_offset, (int *)avenrun, sizeof(avenrun), "avenrun");
317*b89261baSDavid van Moolenbroek for (i = 0; i < 3; i++) {
318*b89261baSDavid van Moolenbroek si->load_avg[i] = loaddouble (avenrun[i]);
319*b89261baSDavid van Moolenbroek si->load_avg[i] = si->load_avg[i]/1024.0;
320*b89261baSDavid van Moolenbroek }
321*b89261baSDavid van Moolenbroek
322*b89261baSDavid van Moolenbroek (void) getkval(freemem_offset, (int *) (&freemem), sizeof(freemem),
323*b89261baSDavid van Moolenbroek "freemem");
324*b89261baSDavid van Moolenbroek (void) getkval(maxmem_offset, (int *) (&maxmem), sizeof(maxmem), "maxmem");
325*b89261baSDavid van Moolenbroek (void) getkval(availrmem_offset, (int *) (&availrmem), sizeof(availrmem),
326*b89261baSDavid van Moolenbroek "availrmem");
327*b89261baSDavid van Moolenbroek #ifdef IRIX64
328*b89261baSDavid van Moolenbroek si->last_pid = 0;
329*b89261baSDavid van Moolenbroek #else
330*b89261baSDavid van Moolenbroek (void) getkval(mpid_offset, &(si->last_pid), sizeof (si->last_pid), "mpid");
331*b89261baSDavid van Moolenbroek #endif
332*b89261baSDavid van Moolenbroek swapctl(SC_GETFREESWAP, &fswap);
333*b89261baSDavid van Moolenbroek swapctl(SC_GETSWAPTOT, &tswap);
334*b89261baSDavid van Moolenbroek memory_stats[0] = pagetok(maxmem);
335*b89261baSDavid van Moolenbroek memory_stats[1] = pagetok(availrmem);
336*b89261baSDavid van Moolenbroek memory_stats[2] = pagetok(freemem);
337*b89261baSDavid van Moolenbroek memory_stats[3] = tswap / 2;
338*b89261baSDavid van Moolenbroek memory_stats[4] = fswap / 2;
339*b89261baSDavid van Moolenbroek
340*b89261baSDavid van Moolenbroek /* use sysmp() to get current sysinfo usage. Can run into all kinds of
341*b89261baSDavid van Moolenbroek problems if you try to nlist this kernel variable. */
342*b89261baSDavid van Moolenbroek if (sysmp(MP_SAGET, MPSA_SINFO, &sysinfo, sizeof(struct sysinfo)) == -1) {
343*b89261baSDavid van Moolenbroek perror("sysmp");
344*b89261baSDavid van Moolenbroek return;
345*b89261baSDavid van Moolenbroek }
346*b89261baSDavid van Moolenbroek /* copy sysinfo.cpu to an array of longs, as expected by percentages() */
347*b89261baSDavid van Moolenbroek for (i = 0; i < CPUSTATES; i++) {
348*b89261baSDavid van Moolenbroek cp_new[i] = sysinfo.cpu[i];
349*b89261baSDavid van Moolenbroek }
350*b89261baSDavid van Moolenbroek (void) percentages (CPUSTATES, cpu_states, cp_new, cp_old, cp_diff);
351*b89261baSDavid van Moolenbroek
352*b89261baSDavid van Moolenbroek si->cpustates = cpu_states;
353*b89261baSDavid van Moolenbroek si->memory = memory_stats;
354*b89261baSDavid van Moolenbroek
355*b89261baSDavid van Moolenbroek numcpus = sysmp(MP_NPROCS);
356*b89261baSDavid van Moolenbroek
357*b89261baSDavid van Moolenbroek /* add a slash to the "run" state abbreviation */
358*b89261baSDavid van Moolenbroek if (numcpus > 1) {
359*b89261baSDavid van Moolenbroek state_abbrev[SRUN][3] = '/';
360*b89261baSDavid van Moolenbroek }
361*b89261baSDavid van Moolenbroek
362*b89261baSDavid van Moolenbroek return;
363*b89261baSDavid van Moolenbroek }
364*b89261baSDavid van Moolenbroek
get_process_info(si,sel,x)365*b89261baSDavid van Moolenbroek caddr_t get_process_info(si, sel, x)
366*b89261baSDavid van Moolenbroek struct system_info *si;
367*b89261baSDavid van Moolenbroek struct process_select *sel;
368*b89261baSDavid van Moolenbroek int x;
369*b89261baSDavid van Moolenbroek {
370*b89261baSDavid van Moolenbroek register int i;
371*b89261baSDavid van Moolenbroek register int total_procs;
372*b89261baSDavid van Moolenbroek register int active_procs;
373*b89261baSDavid van Moolenbroek register struct prpsinfo **prefp;
374*b89261baSDavid van Moolenbroek register struct prpsinfo *pp;
375*b89261baSDavid van Moolenbroek
376*b89261baSDavid van Moolenbroek /* these are copied out of sel for speed */
377*b89261baSDavid van Moolenbroek int show_idle;
378*b89261baSDavid van Moolenbroek int show_system;
379*b89261baSDavid van Moolenbroek int show_uid;
380*b89261baSDavid van Moolenbroek
381*b89261baSDavid van Moolenbroek /* read all the proc structures */
382*b89261baSDavid van Moolenbroek getptable (pbase);
383*b89261baSDavid van Moolenbroek
384*b89261baSDavid van Moolenbroek /* get a pointer to the states summary array */
385*b89261baSDavid van Moolenbroek si->procstates = process_states;
386*b89261baSDavid van Moolenbroek
387*b89261baSDavid van Moolenbroek /* set up flags which define what we are going to select */
388*b89261baSDavid van Moolenbroek show_idle = sel->idle;
389*b89261baSDavid van Moolenbroek show_system = sel->system;
390*b89261baSDavid van Moolenbroek show_uid = sel->uid != -1;
391*b89261baSDavid van Moolenbroek
392*b89261baSDavid van Moolenbroek /* count up process states and get pointers to interesting procs */
393*b89261baSDavid van Moolenbroek total_procs = 0;
394*b89261baSDavid van Moolenbroek active_procs = 0;
395*b89261baSDavid van Moolenbroek (void) memset (process_states, 0, sizeof (process_states));
396*b89261baSDavid van Moolenbroek prefp = pref;
397*b89261baSDavid van Moolenbroek
398*b89261baSDavid van Moolenbroek for (pp = pbase, i = 0; i < nproc; pp++, i++) {
399*b89261baSDavid van Moolenbroek /*
400*b89261baSDavid van Moolenbroek * Place pointers to each valid proc structure in pref[].
401*b89261baSDavid van Moolenbroek * Process slots that are actually in use have a non-zero
402*b89261baSDavid van Moolenbroek * status field. Processes with SSYS set are system
403*b89261baSDavid van Moolenbroek * processes---these get ignored unless show_system is set.
404*b89261baSDavid van Moolenbroek */
405*b89261baSDavid van Moolenbroek if (pp->pr_state != 0 &&
406*b89261baSDavid van Moolenbroek (show_system || ((pp->pr_flag & SSYS) == 0))) {
407*b89261baSDavid van Moolenbroek total_procs++;
408*b89261baSDavid van Moolenbroek process_states[pp->pr_state]++;
409*b89261baSDavid van Moolenbroek if ((!pp->pr_zomb) &&
410*b89261baSDavid van Moolenbroek (show_idle || (pp->pr_state == SRUN)) &&
411*b89261baSDavid van Moolenbroek (!show_uid || pp->pr_uid == (uid_t) sel->uid)) {
412*b89261baSDavid van Moolenbroek *prefp++ = pp;
413*b89261baSDavid van Moolenbroek active_procs++;
414*b89261baSDavid van Moolenbroek }
415*b89261baSDavid van Moolenbroek }
416*b89261baSDavid van Moolenbroek }
417*b89261baSDavid van Moolenbroek
418*b89261baSDavid van Moolenbroek /* if requested, sort the "interesting" processes */
419*b89261baSDavid van Moolenbroek if (compare != NULL)
420*b89261baSDavid van Moolenbroek qsort ((char *) pref, active_procs, sizeof (struct prpsinfo *), proc_compare);
421*b89261baSDavid van Moolenbroek
422*b89261baSDavid van Moolenbroek /* remember active and total counts */
423*b89261baSDavid van Moolenbroek si->p_total = total_procs;
424*b89261baSDavid van Moolenbroek si->p_active = active_procs;
425*b89261baSDavid van Moolenbroek
426*b89261baSDavid van Moolenbroek /* pass back a handle */
427*b89261baSDavid van Moolenbroek handle.next_proc = pref;
428*b89261baSDavid van Moolenbroek handle.remaining = active_procs;
429*b89261baSDavid van Moolenbroek return((caddr_t)&handle);
430*b89261baSDavid van Moolenbroek }
431*b89261baSDavid van Moolenbroek
format_next_process(handle,get_userid)432*b89261baSDavid van Moolenbroek char *format_next_process(handle, get_userid)
433*b89261baSDavid van Moolenbroek caddr_t handle;
434*b89261baSDavid van Moolenbroek char *(*get_userid)();
435*b89261baSDavid van Moolenbroek
436*b89261baSDavid van Moolenbroek {
437*b89261baSDavid van Moolenbroek register struct prpsinfo *pp;
438*b89261baSDavid van Moolenbroek struct handle *hp;
439*b89261baSDavid van Moolenbroek register long cputime;
440*b89261baSDavid van Moolenbroek register double pctcpu;
441*b89261baSDavid van Moolenbroek
442*b89261baSDavid van Moolenbroek /* find and remember the next proc structure */
443*b89261baSDavid van Moolenbroek hp = (struct handle *) handle;
444*b89261baSDavid van Moolenbroek pp = *(hp->next_proc++);
445*b89261baSDavid van Moolenbroek hp->remaining--;
446*b89261baSDavid van Moolenbroek
447*b89261baSDavid van Moolenbroek /* get the cpu usage and calculate the cpu percentages */
448*b89261baSDavid van Moolenbroek cputime = pp->pr_time.tv_sec;
449*b89261baSDavid van Moolenbroek pctcpu = percent_cpu (pp);
450*b89261baSDavid van Moolenbroek
451*b89261baSDavid van Moolenbroek if (numcpus > 1) {
452*b89261baSDavid van Moolenbroek if (pp->pr_sonproc < 0)
453*b89261baSDavid van Moolenbroek state_abbrev[SRUN][4] = '*';
454*b89261baSDavid van Moolenbroek else
455*b89261baSDavid van Moolenbroek state_abbrev[SRUN][4] = pp->pr_sonproc + '0';
456*b89261baSDavid van Moolenbroek }
457*b89261baSDavid van Moolenbroek
458*b89261baSDavid van Moolenbroek /* format this entry */
459*b89261baSDavid van Moolenbroek sprintf (fmt,
460*b89261baSDavid van Moolenbroek Proc_format,
461*b89261baSDavid van Moolenbroek pp->pr_pid,
462*b89261baSDavid van Moolenbroek (*get_userid) (pp->pr_uid),
463*b89261baSDavid van Moolenbroek pp->pr_pri - PZERO,
464*b89261baSDavid van Moolenbroek pp->pr_nice - NZERO,
465*b89261baSDavid van Moolenbroek format_k(pagetok(pp->pr_size)),
466*b89261baSDavid van Moolenbroek format_k(pagetok(pp->pr_rssize)),
467*b89261baSDavid van Moolenbroek state_abbrev[pp->pr_state],
468*b89261baSDavid van Moolenbroek format_time(cputime),
469*b89261baSDavid van Moolenbroek weighted_cpu (pp),
470*b89261baSDavid van Moolenbroek pctcpu,
471*b89261baSDavid van Moolenbroek pp->pr_fname);
472*b89261baSDavid van Moolenbroek
473*b89261baSDavid van Moolenbroek /* return the result */
474*b89261baSDavid van Moolenbroek return(fmt);
475*b89261baSDavid van Moolenbroek }
476*b89261baSDavid van Moolenbroek
477*b89261baSDavid van Moolenbroek /*
478*b89261baSDavid van Moolenbroek * getkval(offset, ptr, size, refstr) - get a value out of the kernel.
479*b89261baSDavid van Moolenbroek * "offset" is the byte offset into the kernel for the desired value,
480*b89261baSDavid van Moolenbroek * "ptr" points to a buffer into which the value is retrieved,
481*b89261baSDavid van Moolenbroek * "size" is the size of the buffer (and the object to retrieve),
482*b89261baSDavid van Moolenbroek * "refstr" is a reference string used when printing error meessages,
483*b89261baSDavid van Moolenbroek * if "refstr" starts with a '!', then a failure on read will not
484*b89261baSDavid van Moolenbroek * be fatal (this may seem like a silly way to do things, but I
485*b89261baSDavid van Moolenbroek * really didn't want the overhead of another argument).
486*b89261baSDavid van Moolenbroek *
487*b89261baSDavid van Moolenbroek */
488*b89261baSDavid van Moolenbroek
getkval(offset,ptr,size,refstr)489*b89261baSDavid van Moolenbroek int getkval(offset, ptr, size, refstr)
490*b89261baSDavid van Moolenbroek off_t offset;
491*b89261baSDavid van Moolenbroek int *ptr;
492*b89261baSDavid van Moolenbroek int size;
493*b89261baSDavid van Moolenbroek char *refstr;
494*b89261baSDavid van Moolenbroek
495*b89261baSDavid van Moolenbroek {
496*b89261baSDavid van Moolenbroek if (lseek(kmem, offset, SEEK_SET) == -1) {
497*b89261baSDavid van Moolenbroek if (*refstr == '!')
498*b89261baSDavid van Moolenbroek refstr++;
499*b89261baSDavid van Moolenbroek (void) fprintf(stderr, "%s: lseek to %s: %s\n", KMEM,
500*b89261baSDavid van Moolenbroek refstr, strerror(errno));
501*b89261baSDavid van Moolenbroek quit(0);
502*b89261baSDavid van Moolenbroek }
503*b89261baSDavid van Moolenbroek if (read(kmem, (char *) ptr, size) == -1) {
504*b89261baSDavid van Moolenbroek if (*refstr == '!')
505*b89261baSDavid van Moolenbroek return(0);
506*b89261baSDavid van Moolenbroek else {
507*b89261baSDavid van Moolenbroek (void) fprintf(stderr, "%s: reading %s: %s\n", KMEM,
508*b89261baSDavid van Moolenbroek refstr, strerror(errno));
509*b89261baSDavid van Moolenbroek quit(0);
510*b89261baSDavid van Moolenbroek }
511*b89261baSDavid van Moolenbroek }
512*b89261baSDavid van Moolenbroek return(1);
513*b89261baSDavid van Moolenbroek }
514*b89261baSDavid van Moolenbroek
515*b89261baSDavid van Moolenbroek /*
516*b89261baSDavid van Moolenbroek * proc_compare - comparison function for "qsort"
517*b89261baSDavid van Moolenbroek * Compares the resource consumption of two processes using five
518*b89261baSDavid van Moolenbroek * distinct keys. The keys (in descending order of importance) are:
519*b89261baSDavid van Moolenbroek * percent cpu, cpu ticks, state, resident set size, total virtual
520*b89261baSDavid van Moolenbroek * memory usage. The process states are ordered as follows (from least
521*b89261baSDavid van Moolenbroek * to most important): WAIT, zombie, sleep, stop, idle, run. The
522*b89261baSDavid van Moolenbroek * array declaration below maps a process state index into a number
523*b89261baSDavid van Moolenbroek * that reflects this ordering.
524*b89261baSDavid van Moolenbroek */
525*b89261baSDavid van Moolenbroek
526*b89261baSDavid van Moolenbroek
527*b89261baSDavid van Moolenbroek unsigned char sorted_state[] =
528*b89261baSDavid van Moolenbroek {
529*b89261baSDavid van Moolenbroek 0, /* not used */
530*b89261baSDavid van Moolenbroek 3, /* sleep */
531*b89261baSDavid van Moolenbroek 6, /* run */
532*b89261baSDavid van Moolenbroek 2, /* zombie */
533*b89261baSDavid van Moolenbroek 4, /* stop */
534*b89261baSDavid van Moolenbroek 5, /* idle */
535*b89261baSDavid van Moolenbroek 0, /* not used */
536*b89261baSDavid van Moolenbroek 1 /* being swapped (WAIT) */
537*b89261baSDavid van Moolenbroek };
538*b89261baSDavid van Moolenbroek
proc_compare(pp1,pp2)539*b89261baSDavid van Moolenbroek int proc_compare (pp1, pp2)
540*b89261baSDavid van Moolenbroek void *pp1;
541*b89261baSDavid van Moolenbroek void *pp2;
542*b89261baSDavid van Moolenbroek {
543*b89261baSDavid van Moolenbroek register struct prpsinfo *p1;
544*b89261baSDavid van Moolenbroek register struct prpsinfo *p2;
545*b89261baSDavid van Moolenbroek register long result;
546*b89261baSDavid van Moolenbroek
547*b89261baSDavid van Moolenbroek /* remove one level of indirection */
548*b89261baSDavid van Moolenbroek p1 = *(struct prpsinfo **)pp1;
549*b89261baSDavid van Moolenbroek p2 = *(struct prpsinfo **)pp2;
550*b89261baSDavid van Moolenbroek
551*b89261baSDavid van Moolenbroek /* compare percent cpu (pctcpu) */
552*b89261baSDavid van Moolenbroek if ((result = (long) (p2->pr_cpu - p1->pr_cpu)) == 0) {
553*b89261baSDavid van Moolenbroek /* use cpticks to break the tie */
554*b89261baSDavid van Moolenbroek if ((result = p2->pr_time.tv_sec - p1->pr_time.tv_sec) == 0) {
555*b89261baSDavid van Moolenbroek /* use process state to break the tie */
556*b89261baSDavid van Moolenbroek if ((result = (long) (sorted_state[p2->pr_state] -
557*b89261baSDavid van Moolenbroek sorted_state[p1->pr_state])) == 0) {
558*b89261baSDavid van Moolenbroek /* use priority to break the tie */
559*b89261baSDavid van Moolenbroek if ((result = p2->pr_oldpri - p1->pr_oldpri) == 0) {
560*b89261baSDavid van Moolenbroek /* use resident set size (rssize) to break the tie */
561*b89261baSDavid van Moolenbroek if ((result = p2->pr_rssize - p1->pr_rssize) == 0) {
562*b89261baSDavid van Moolenbroek /* use total memory to break the tie */
563*b89261baSDavid van Moolenbroek result = (p2->pr_size - p1->pr_size);
564*b89261baSDavid van Moolenbroek }
565*b89261baSDavid van Moolenbroek }
566*b89261baSDavid van Moolenbroek }
567*b89261baSDavid van Moolenbroek }
568*b89261baSDavid van Moolenbroek }
569*b89261baSDavid van Moolenbroek return (result);
570*b89261baSDavid van Moolenbroek }
571*b89261baSDavid van Moolenbroek
572*b89261baSDavid van Moolenbroek /* return the owner of the specified process. */
proc_owner(pid)573*b89261baSDavid van Moolenbroek int proc_owner (pid)
574*b89261baSDavid van Moolenbroek int pid;
575*b89261baSDavid van Moolenbroek {
576*b89261baSDavid van Moolenbroek register struct prpsinfo *p;
577*b89261baSDavid van Moolenbroek int i;
578*b89261baSDavid van Moolenbroek
579*b89261baSDavid van Moolenbroek for (i = 0, p = pbase; i < nproc; i++, p++)
580*b89261baSDavid van Moolenbroek if (p->pr_pid == (oid_t)pid)
581*b89261baSDavid van Moolenbroek return ((int)p->pr_uid);
582*b89261baSDavid van Moolenbroek
583*b89261baSDavid van Moolenbroek return (-1);
584*b89261baSDavid van Moolenbroek }
585*b89261baSDavid van Moolenbroek
586*b89261baSDavid van Moolenbroek /*
587*b89261baSDavid van Moolenbroek * check_nlist(nlst) - checks the nlist to see if any symbols were not
588*b89261baSDavid van Moolenbroek * found. For every symbol that was not found, a one-line
589*b89261baSDavid van Moolenbroek * message is printed to stderr. The routine returns the
590*b89261baSDavid van Moolenbroek * number of symbols NOT found.
591*b89261baSDavid van Moolenbroek */
592*b89261baSDavid van Moolenbroek
check_nlist(nlst)593*b89261baSDavid van Moolenbroek int check_nlist(nlst)
594*b89261baSDavid van Moolenbroek register struct nlist *nlst;
595*b89261baSDavid van Moolenbroek
596*b89261baSDavid van Moolenbroek {
597*b89261baSDavid van Moolenbroek register int i;
598*b89261baSDavid van Moolenbroek
599*b89261baSDavid van Moolenbroek /* check to see if we got ALL the symbols we requested */
600*b89261baSDavid van Moolenbroek /* this will write one line to stderr for every symbol not found */
601*b89261baSDavid van Moolenbroek
602*b89261baSDavid van Moolenbroek i = 0;
603*b89261baSDavid van Moolenbroek while (nlst->n_name != NULL) {
604*b89261baSDavid van Moolenbroek if (nlst->n_type == 0) {
605*b89261baSDavid van Moolenbroek /* this one wasn't found */
606*b89261baSDavid van Moolenbroek fprintf(stderr, "kernel: no symbol named `%s'\n", nlst->n_name);
607*b89261baSDavid van Moolenbroek i = 1;
608*b89261baSDavid van Moolenbroek }
609*b89261baSDavid van Moolenbroek nlst++;
610*b89261baSDavid van Moolenbroek }
611*b89261baSDavid van Moolenbroek
612*b89261baSDavid van Moolenbroek return(i);
613*b89261baSDavid van Moolenbroek }
614*b89261baSDavid van Moolenbroek
615*b89261baSDavid van Moolenbroek /* get process table */
getptable(baseptr)616*b89261baSDavid van Moolenbroek void getptable (baseptr)
617*b89261baSDavid van Moolenbroek struct prpsinfo *baseptr;
618*b89261baSDavid van Moolenbroek {
619*b89261baSDavid van Moolenbroek struct prpsinfo *currproc; /* pointer to current proc structure */
620*b89261baSDavid van Moolenbroek int numprocs = 0;
621*b89261baSDavid van Moolenbroek int i;
622*b89261baSDavid van Moolenbroek struct dirent *directp;
623*b89261baSDavid van Moolenbroek struct oldproc *op;
624*b89261baSDavid van Moolenbroek static struct timeval lasttime =
625*b89261baSDavid van Moolenbroek {0L, 0L};
626*b89261baSDavid van Moolenbroek struct timeval thistime;
627*b89261baSDavid van Moolenbroek struct timezone thiszone;
628*b89261baSDavid van Moolenbroek double timediff;
629*b89261baSDavid van Moolenbroek double alpha, beta;
630*b89261baSDavid van Moolenbroek struct oldproc *endbase;
631*b89261baSDavid van Moolenbroek
632*b89261baSDavid van Moolenbroek gettimeofday (&thistime, &thiszone);
633*b89261baSDavid van Moolenbroek
634*b89261baSDavid van Moolenbroek /*
635*b89261baSDavid van Moolenbroek * To avoid divides, we keep times in nanoseconds. This is
636*b89261baSDavid van Moolenbroek * scaled by 1e7 rather than 1e9 so that when we divide we
637*b89261baSDavid van Moolenbroek * get percent.
638*b89261baSDavid van Moolenbroek */
639*b89261baSDavid van Moolenbroek if (lasttime.tv_sec)
640*b89261baSDavid van Moolenbroek timediff = ((double) thistime.tv_sec * 1.0e7 +
641*b89261baSDavid van Moolenbroek ((double) thistime.tv_usec * 10.0)) -
642*b89261baSDavid van Moolenbroek ((double) lasttime.tv_sec * 1.0e7 +
643*b89261baSDavid van Moolenbroek ((double) lasttime.tv_usec * 10.0));
644*b89261baSDavid van Moolenbroek else
645*b89261baSDavid van Moolenbroek timediff = 1.0e7;
646*b89261baSDavid van Moolenbroek
647*b89261baSDavid van Moolenbroek /*
648*b89261baSDavid van Moolenbroek * constants for exponential average. avg = alpha * new + beta * avg
649*b89261baSDavid van Moolenbroek * The goal is 50% decay in 30 sec. However if the sample period
650*b89261baSDavid van Moolenbroek * is greater than 30 sec, there's not a lot we can do.
651*b89261baSDavid van Moolenbroek */
652*b89261baSDavid van Moolenbroek if (timediff < 30.0e7)
653*b89261baSDavid van Moolenbroek {
654*b89261baSDavid van Moolenbroek alpha = 0.5 * (timediff / 30.0e7);
655*b89261baSDavid van Moolenbroek beta = 1.0 - alpha;
656*b89261baSDavid van Moolenbroek }
657*b89261baSDavid van Moolenbroek else
658*b89261baSDavid van Moolenbroek {
659*b89261baSDavid van Moolenbroek alpha = 0.5;
660*b89261baSDavid van Moolenbroek beta = 0.5;
661*b89261baSDavid van Moolenbroek }
662*b89261baSDavid van Moolenbroek
663*b89261baSDavid van Moolenbroek endbase = oldbase + oldprocs;
664*b89261baSDavid van Moolenbroek currproc = baseptr;
665*b89261baSDavid van Moolenbroek
666*b89261baSDavid van Moolenbroek
667*b89261baSDavid van Moolenbroek for (rewinddir (procdir); directp = readdir (procdir);)
668*b89261baSDavid van Moolenbroek {
669*b89261baSDavid van Moolenbroek int fd;
670*b89261baSDavid van Moolenbroek
671*b89261baSDavid van Moolenbroek if ((fd = open (directp->d_name, O_RDONLY)) < 0)
672*b89261baSDavid van Moolenbroek continue;
673*b89261baSDavid van Moolenbroek
674*b89261baSDavid van Moolenbroek currproc = &baseptr[numprocs];
675*b89261baSDavid van Moolenbroek if (ioctl (fd, PIOCPSINFO, currproc) < 0)
676*b89261baSDavid van Moolenbroek {
677*b89261baSDavid van Moolenbroek (void) close (fd);
678*b89261baSDavid van Moolenbroek continue;
679*b89261baSDavid van Moolenbroek }
680*b89261baSDavid van Moolenbroek
681*b89261baSDavid van Moolenbroek /*
682*b89261baSDavid van Moolenbroek * SVr4 doesn't keep track of CPU% in the kernel, so we have
683*b89261baSDavid van Moolenbroek * to do our own. See if we've heard of this process before.
684*b89261baSDavid van Moolenbroek * If so, compute % based on CPU since last time.
685*b89261baSDavid van Moolenbroek */
686*b89261baSDavid van Moolenbroek op = oldbase + HASH (currproc->pr_pid);
687*b89261baSDavid van Moolenbroek while (1)
688*b89261baSDavid van Moolenbroek {
689*b89261baSDavid van Moolenbroek if (op->oldpid == -1) /* not there */
690*b89261baSDavid van Moolenbroek break;
691*b89261baSDavid van Moolenbroek if (op->oldpid == currproc->pr_pid)
692*b89261baSDavid van Moolenbroek { /* found old data */
693*b89261baSDavid van Moolenbroek percent_cpu (currproc) =
694*b89261baSDavid van Moolenbroek ((currproc->pr_time.tv_sec * 1.0e9 +
695*b89261baSDavid van Moolenbroek currproc->pr_time.tv_nsec)
696*b89261baSDavid van Moolenbroek - op->oldtime) / timediff;
697*b89261baSDavid van Moolenbroek weighted_cpu (currproc) =
698*b89261baSDavid van Moolenbroek op->oldpct * beta + percent_cpu (currproc) * alpha;
699*b89261baSDavid van Moolenbroek
700*b89261baSDavid van Moolenbroek break;
701*b89261baSDavid van Moolenbroek }
702*b89261baSDavid van Moolenbroek op++; /* try next entry in hash table */
703*b89261baSDavid van Moolenbroek if (op == endbase) /* table wrapped around */
704*b89261baSDavid van Moolenbroek op = oldbase;
705*b89261baSDavid van Moolenbroek }
706*b89261baSDavid van Moolenbroek
707*b89261baSDavid van Moolenbroek /* Otherwise, it's new, so use all of its CPU time */
708*b89261baSDavid van Moolenbroek if (op->oldpid == -1)
709*b89261baSDavid van Moolenbroek {
710*b89261baSDavid van Moolenbroek if (lasttime.tv_sec)
711*b89261baSDavid van Moolenbroek {
712*b89261baSDavid van Moolenbroek percent_cpu (currproc) =
713*b89261baSDavid van Moolenbroek (currproc->pr_time.tv_sec * 1.0e9 +
714*b89261baSDavid van Moolenbroek currproc->pr_time.tv_nsec) / timediff;
715*b89261baSDavid van Moolenbroek weighted_cpu (currproc) =
716*b89261baSDavid van Moolenbroek percent_cpu (currproc);
717*b89261baSDavid van Moolenbroek }
718*b89261baSDavid van Moolenbroek else
719*b89261baSDavid van Moolenbroek { /* first screen -- no difference is possible */
720*b89261baSDavid van Moolenbroek percent_cpu (currproc) = 0.0;
721*b89261baSDavid van Moolenbroek weighted_cpu (currproc) = 0.0;
722*b89261baSDavid van Moolenbroek }
723*b89261baSDavid van Moolenbroek }
724*b89261baSDavid van Moolenbroek
725*b89261baSDavid van Moolenbroek numprocs++;
726*b89261baSDavid van Moolenbroek (void) close (fd);
727*b89261baSDavid van Moolenbroek }
728*b89261baSDavid van Moolenbroek
729*b89261baSDavid van Moolenbroek if (nproc != numprocs)
730*b89261baSDavid van Moolenbroek nproc = numprocs;
731*b89261baSDavid van Moolenbroek
732*b89261baSDavid van Moolenbroek /*
733*b89261baSDavid van Moolenbroek * Save current CPU time for next time around
734*b89261baSDavid van Moolenbroek * For the moment recreate the hash table each time, as the code
735*b89261baSDavid van Moolenbroek * is easier that way.
736*b89261baSDavid van Moolenbroek */
737*b89261baSDavid van Moolenbroek oldprocs = 2 * nproc;
738*b89261baSDavid van Moolenbroek endbase = oldbase + oldprocs;
739*b89261baSDavid van Moolenbroek for (op = oldbase; op < endbase; op++)
740*b89261baSDavid van Moolenbroek op->oldpid = -1;
741*b89261baSDavid van Moolenbroek for (i = 0, currproc = baseptr;
742*b89261baSDavid van Moolenbroek i < nproc;
743*b89261baSDavid van Moolenbroek i++, currproc = (struct prpsinfo *) ((char *) currproc + PRPSINFOSIZE))
744*b89261baSDavid van Moolenbroek {
745*b89261baSDavid van Moolenbroek /* find an empty spot */
746*b89261baSDavid van Moolenbroek op = oldbase + HASH (currproc->pr_pid);
747*b89261baSDavid van Moolenbroek while (1)
748*b89261baSDavid van Moolenbroek {
749*b89261baSDavid van Moolenbroek if (op->oldpid == -1)
750*b89261baSDavid van Moolenbroek break;
751*b89261baSDavid van Moolenbroek op++;
752*b89261baSDavid van Moolenbroek if (op == endbase)
753*b89261baSDavid van Moolenbroek op = oldbase;
754*b89261baSDavid van Moolenbroek }
755*b89261baSDavid van Moolenbroek op->oldpid = currproc->pr_pid;
756*b89261baSDavid van Moolenbroek op->oldtime = (currproc->pr_time.tv_sec * 1.0e9 +
757*b89261baSDavid van Moolenbroek currproc->pr_time.tv_nsec);
758*b89261baSDavid van Moolenbroek op->oldpct = weighted_cpu (currproc);
759*b89261baSDavid van Moolenbroek }
760*b89261baSDavid van Moolenbroek lasttime = thistime;
761*b89261baSDavid van Moolenbroek
762*b89261baSDavid van Moolenbroek }
763*b89261baSDavid van Moolenbroek
764