xref: /minix3/external/bsd/top/dist/machine/m_sunos4.c (revision b89261ba018da33f0bd8cd05f5a1fe9e7a9c837b)
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 Sun running SunOS version 4.x
37*b89261baSDavid van Moolenbroek  *
38*b89261baSDavid van Moolenbroek  * DESCRIPTION:
39*b89261baSDavid van Moolenbroek  * This is the machine-dependent module for SunOS 4.x.
40*b89261baSDavid van Moolenbroek  * This makes top work on the following systems:
41*b89261baSDavid van Moolenbroek  *	SunOS 4.0
42*b89261baSDavid van Moolenbroek  *	SunOS 4.0.1
43*b89261baSDavid van Moolenbroek  *	SunOS 4.0.2 (including 386i architecture)
44*b89261baSDavid van Moolenbroek  *	SunOS 4.0.3
45*b89261baSDavid van Moolenbroek  *	SunOS 4.1
46*b89261baSDavid van Moolenbroek  *	SunOS 4.1.1
47*b89261baSDavid van Moolenbroek  *	SunOS 4.1.2 (including MP architectures)
48*b89261baSDavid van Moolenbroek  *	SunOS 4.1.3 (including MP architectures)
49*b89261baSDavid van Moolenbroek  *      SunOS 4.1.3_U1 (including MP architectures)
50*b89261baSDavid van Moolenbroek  *      SunOS 4.1.4 (including MP architectures)
51*b89261baSDavid van Moolenbroek  *	Solbourne OS/MP PRIOR to 4.1A
52*b89261baSDavid van Moolenbroek  *
53*b89261baSDavid van Moolenbroek  * LIBS:  -lkvm
54*b89261baSDavid van Moolenbroek  *
55*b89261baSDavid van Moolenbroek  * CFLAGS: -DHAVE_GETOPT -DORDER
56*b89261baSDavid van Moolenbroek  *
57*b89261baSDavid van Moolenbroek  * AUTHOR:  William LeFebvre <wnl@groupsys.com>
58*b89261baSDavid van Moolenbroek  * Solbourne support by David MacKenzie <djm@eng.umd.edu>
59*b89261baSDavid van Moolenbroek  */
60*b89261baSDavid van Moolenbroek 
61*b89261baSDavid van Moolenbroek /*
62*b89261baSDavid van Moolenbroek  * #ifdef MULTIPROCESSOR means Sun MP.
63*b89261baSDavid van Moolenbroek  * #ifdef solbourne is for Solbourne.
64*b89261baSDavid van Moolenbroek  */
65*b89261baSDavid van Moolenbroek 
66*b89261baSDavid van Moolenbroek #include "config.h"
67*b89261baSDavid van Moolenbroek #include <sys/types.h>
68*b89261baSDavid van Moolenbroek #include <sys/signal.h>
69*b89261baSDavid van Moolenbroek 
70*b89261baSDavid van Moolenbroek /* make sure param.h gets loaded with KERNEL defined to get PZERO & NZERO */
71*b89261baSDavid van Moolenbroek #define KERNEL
72*b89261baSDavid van Moolenbroek #include <sys/param.h>
73*b89261baSDavid van Moolenbroek #undef KERNEL
74*b89261baSDavid van Moolenbroek 
75*b89261baSDavid van Moolenbroek #include <stdio.h>
76*b89261baSDavid van Moolenbroek #include <kvm.h>
77*b89261baSDavid van Moolenbroek #include <nlist.h>
78*b89261baSDavid van Moolenbroek #include <math.h>
79*b89261baSDavid van Moolenbroek #include <sys/dir.h>
80*b89261baSDavid van Moolenbroek #include <sys/user.h>
81*b89261baSDavid van Moolenbroek #include <sys/proc.h>
82*b89261baSDavid van Moolenbroek #include <sys/dk.h>
83*b89261baSDavid van Moolenbroek #include <sys/vm.h>
84*b89261baSDavid van Moolenbroek #include <sys/file.h>
85*b89261baSDavid van Moolenbroek #include <sys/time.h>
86*b89261baSDavid van Moolenbroek #include <vm/page.h>
87*b89261baSDavid van Moolenbroek 
88*b89261baSDavid van Moolenbroek #ifdef solbourne
89*b89261baSDavid van Moolenbroek #include <sys/syscall.h>
90*b89261baSDavid van Moolenbroek #endif
91*b89261baSDavid van Moolenbroek 
92*b89261baSDavid van Moolenbroek /* Older versions of SunOS don't have a typedef for pid_t.
93*b89261baSDavid van Moolenbroek    Hopefully this will catch all those cases without causing other problems.
94*b89261baSDavid van Moolenbroek  */
95*b89261baSDavid van Moolenbroek #ifndef __sys_stdtypes_h
96*b89261baSDavid van Moolenbroek typedef int pid_t;
97*b89261baSDavid van Moolenbroek #endif
98*b89261baSDavid van Moolenbroek 
99*b89261baSDavid van Moolenbroek #include "top.h"
100*b89261baSDavid van Moolenbroek #include "machine.h"
101*b89261baSDavid van Moolenbroek #include "utils.h"
102*b89261baSDavid van Moolenbroek 
103*b89261baSDavid van Moolenbroek /* declarations for load_avg */
104*b89261baSDavid van Moolenbroek #include "loadavg.h"
105*b89261baSDavid van Moolenbroek 
106*b89261baSDavid van Moolenbroek /* get_process_info passes back a handle.  This is what it looks like: */
107*b89261baSDavid van Moolenbroek 
108*b89261baSDavid van Moolenbroek struct handle
109*b89261baSDavid van Moolenbroek {
110*b89261baSDavid van Moolenbroek     struct proc **next_proc;	/* points to next valid proc pointer */
111*b89261baSDavid van Moolenbroek     int remaining;		/* number of pointers remaining */
112*b89261baSDavid van Moolenbroek };
113*b89261baSDavid van Moolenbroek 
114*b89261baSDavid van Moolenbroek /* define what weighted cpu is.  */
115*b89261baSDavid van Moolenbroek #define weighted_cpu(pct, pp) ((pp)->p_time == 0 ? 0.0 : \
116*b89261baSDavid van Moolenbroek 			 ((pct) / (1.0 - exp((pp)->p_time * logcpu))))
117*b89261baSDavid van Moolenbroek 
118*b89261baSDavid van Moolenbroek /* what we consider to be process size: */
119*b89261baSDavid van Moolenbroek #define PROCSIZE(pp) ((pp)->p_tsize + (pp)->p_dsize + (pp)->p_ssize)
120*b89261baSDavid van Moolenbroek 
121*b89261baSDavid van Moolenbroek /* definitions for indices in the nlist array */
122*b89261baSDavid van Moolenbroek #define X_AVENRUN	0
123*b89261baSDavid van Moolenbroek #define X_CCPU		1
124*b89261baSDavid van Moolenbroek #define X_MPID		2
125*b89261baSDavid van Moolenbroek #define X_NPROC		3
126*b89261baSDavid van Moolenbroek #define X_PROC		4
127*b89261baSDavid van Moolenbroek #define X_TOTAL		5
128*b89261baSDavid van Moolenbroek #define X_CP_TIME	6
129*b89261baSDavid van Moolenbroek #define X_PAGES		7
130*b89261baSDavid van Moolenbroek #define X_EPAGES	8
131*b89261baSDavid van Moolenbroek 
132*b89261baSDavid van Moolenbroek static struct nlist nlst[] = {
133*b89261baSDavid van Moolenbroek #ifdef i386
134*b89261baSDavid van Moolenbroek     { "avenrun" },		/* 0 */
135*b89261baSDavid van Moolenbroek     { "ccpu" },			/* 1 */
136*b89261baSDavid van Moolenbroek     { "mpid" },			/* 2 */
137*b89261baSDavid van Moolenbroek     { "nproc" },		/* 3 */
138*b89261baSDavid van Moolenbroek     { "proc" },			/* 4 */
139*b89261baSDavid van Moolenbroek     { "total" },		/* 5 */
140*b89261baSDavid van Moolenbroek     { "cp_time" },		/* 6 */
141*b89261baSDavid van Moolenbroek     { "pages" },		/* 7 */
142*b89261baSDavid van Moolenbroek     { "epages" },		/* 8 */
143*b89261baSDavid van Moolenbroek #else
144*b89261baSDavid van Moolenbroek     { "_avenrun" },		/* 0 */
145*b89261baSDavid van Moolenbroek     { "_ccpu" },		/* 1 */
146*b89261baSDavid van Moolenbroek     { "_mpid" },		/* 2 */
147*b89261baSDavid van Moolenbroek     { "_nproc" },		/* 3 */
148*b89261baSDavid van Moolenbroek     { "_proc" },		/* 4 */
149*b89261baSDavid van Moolenbroek     { "_total" },		/* 5 */
150*b89261baSDavid van Moolenbroek     { "_cp_time" },		/* 6 */
151*b89261baSDavid van Moolenbroek     { "_pages" },		/* 7 */
152*b89261baSDavid van Moolenbroek     { "_epages" },		/* 8 */
153*b89261baSDavid van Moolenbroek #ifdef MULTIPROCESSOR
154*b89261baSDavid van Moolenbroek     { "_ncpu" },
155*b89261baSDavid van Moolenbroek #define X_NCPU		9
156*b89261baSDavid van Moolenbroek     { "_xp_time" },
157*b89261baSDavid van Moolenbroek #define X_XP_TIME	10
158*b89261baSDavid van Moolenbroek #endif
159*b89261baSDavid van Moolenbroek #endif
160*b89261baSDavid van Moolenbroek     { 0 }
161*b89261baSDavid van Moolenbroek };
162*b89261baSDavid van Moolenbroek 
163*b89261baSDavid van Moolenbroek /*
164*b89261baSDavid van Moolenbroek  *  These definitions control the format of the per-process area
165*b89261baSDavid van Moolenbroek  */
166*b89261baSDavid van Moolenbroek 
167*b89261baSDavid van Moolenbroek static char header[] =
168*b89261baSDavid van Moolenbroek   "  PID X        PRI NICE  SIZE   RES STATE   TIME   WCPU    CPU COMMAND";
169*b89261baSDavid van Moolenbroek /* 0123456   -- field to fill in starts at header+6 */
170*b89261baSDavid van Moolenbroek #define UNAME_START 6
171*b89261baSDavid van Moolenbroek 
172*b89261baSDavid van Moolenbroek #define Proc_format \
173*b89261baSDavid van Moolenbroek 	"%5d %-8.8s %3d %4d %5s %5s %-5s %-6s %5.2f%% %5.2f%% %s"
174*b89261baSDavid van Moolenbroek 
175*b89261baSDavid van Moolenbroek 
176*b89261baSDavid van Moolenbroek /* process state names for the "STATE" column of the display */
177*b89261baSDavid van Moolenbroek /* the extra nulls in the string "run" are for adding a slash and
178*b89261baSDavid van Moolenbroek    the processor number when needed */
179*b89261baSDavid van Moolenbroek 
180*b89261baSDavid van Moolenbroek char *state_abbrev[] =
181*b89261baSDavid van Moolenbroek {
182*b89261baSDavid van Moolenbroek     "", "sleep", "WAIT", "run\0\0\0", "start", "zomb", "stop"
183*b89261baSDavid van Moolenbroek };
184*b89261baSDavid van Moolenbroek 
185*b89261baSDavid van Moolenbroek /* values that we stash away in _init and use in later routines */
186*b89261baSDavid van Moolenbroek 
187*b89261baSDavid van Moolenbroek static double logcpu;
188*b89261baSDavid van Moolenbroek kvm_t *kd;
189*b89261baSDavid van Moolenbroek 
190*b89261baSDavid van Moolenbroek /* these are retrieved from the kernel in _init */
191*b89261baSDavid van Moolenbroek 
192*b89261baSDavid van Moolenbroek static unsigned long proc;
193*b89261baSDavid van Moolenbroek static          int  nproc;
194*b89261baSDavid van Moolenbroek static load_avg ccpu;
195*b89261baSDavid van Moolenbroek static unsigned long pages;
196*b89261baSDavid van Moolenbroek static unsigned long epages;
197*b89261baSDavid van Moolenbroek static          int  ncpu = 0;
198*b89261baSDavid van Moolenbroek 
199*b89261baSDavid van Moolenbroek /* these are offsets obtained via nlist and used in the get_ functions */
200*b89261baSDavid van Moolenbroek 
201*b89261baSDavid van Moolenbroek static unsigned long mpid_offset;
202*b89261baSDavid van Moolenbroek static unsigned long avenrun_offset;
203*b89261baSDavid van Moolenbroek static unsigned long total_offset;
204*b89261baSDavid van Moolenbroek static unsigned long cp_time_offset;
205*b89261baSDavid van Moolenbroek #ifdef MULTIPROCESSOR
206*b89261baSDavid van Moolenbroek static unsigned long xp_time_offset;
207*b89261baSDavid van Moolenbroek #endif
208*b89261baSDavid van Moolenbroek 
209*b89261baSDavid van Moolenbroek /* these are for calculating cpu state percentages */
210*b89261baSDavid van Moolenbroek 
211*b89261baSDavid van Moolenbroek static long cp_time[CPUSTATES];
212*b89261baSDavid van Moolenbroek static long cp_old[CPUSTATES];
213*b89261baSDavid van Moolenbroek static long cp_diff[CPUSTATES];
214*b89261baSDavid van Moolenbroek #ifdef MULTIPROCESSOR
215*b89261baSDavid van Moolenbroek static long xp_time[NCPU][XPSTATES];
216*b89261baSDavid van Moolenbroek /* for now we only accumulate spin time, but extending this to pick up
217*b89261baSDavid van Moolenbroek    other stuff in xp_time is trivial.  */
218*b89261baSDavid van Moolenbroek static long xp_old[NCPU];
219*b89261baSDavid van Moolenbroek #endif
220*b89261baSDavid van Moolenbroek 
221*b89261baSDavid van Moolenbroek /* these are for detailing the process states */
222*b89261baSDavid van Moolenbroek 
223*b89261baSDavid van Moolenbroek int process_states[7];
224*b89261baSDavid van Moolenbroek char *procstatenames[] = {
225*b89261baSDavid van Moolenbroek     "", " sleeping, ", " ABANDONED, ", " running, ", " starting, ",
226*b89261baSDavid van Moolenbroek     " zombie, ", " stopped, ",
227*b89261baSDavid van Moolenbroek     NULL
228*b89261baSDavid van Moolenbroek };
229*b89261baSDavid van Moolenbroek 
230*b89261baSDavid van Moolenbroek /* these are for detailing the cpu states */
231*b89261baSDavid van Moolenbroek 
232*b89261baSDavid van Moolenbroek int cpu_states[5];
233*b89261baSDavid van Moolenbroek char *cpustatenames[] = {
234*b89261baSDavid van Moolenbroek     "user", "nice", "system", "idle",
235*b89261baSDavid van Moolenbroek #ifdef MULTIPROCESSOR
236*b89261baSDavid van Moolenbroek     "spin",
237*b89261baSDavid van Moolenbroek #define XCP_SPIN 4
238*b89261baSDavid van Moolenbroek #endif
239*b89261baSDavid van Moolenbroek     NULL
240*b89261baSDavid van Moolenbroek };
241*b89261baSDavid van Moolenbroek 
242*b89261baSDavid van Moolenbroek /* these are for detailing the memory statistics */
243*b89261baSDavid van Moolenbroek 
244*b89261baSDavid van Moolenbroek long memory_stats[4];
245*b89261baSDavid van Moolenbroek char *memorynames[] = {
246*b89261baSDavid van Moolenbroek     "K available, ", "K in use, ", "K free, ", "K locked", NULL
247*b89261baSDavid van Moolenbroek };
248*b89261baSDavid van Moolenbroek 
249*b89261baSDavid van Moolenbroek /* these are names given to allowed sorting orders -- first is default */
250*b89261baSDavid van Moolenbroek char *ordernames[] =
251*b89261baSDavid van Moolenbroek {"cpu", "size", "res", NULL};
252*b89261baSDavid van Moolenbroek 
253*b89261baSDavid van Moolenbroek /* forward definitions for comparison functions */
254*b89261baSDavid van Moolenbroek int compare_cpu();
255*b89261baSDavid van Moolenbroek int compare_size();
256*b89261baSDavid van Moolenbroek int compare_res();
257*b89261baSDavid van Moolenbroek 
258*b89261baSDavid van Moolenbroek int (*proc_compares[])() = {
259*b89261baSDavid van Moolenbroek     compare_cpu,
260*b89261baSDavid van Moolenbroek     compare_size,
261*b89261baSDavid van Moolenbroek     compare_res,
262*b89261baSDavid van Moolenbroek     NULL };
263*b89261baSDavid van Moolenbroek 
264*b89261baSDavid van Moolenbroek 
265*b89261baSDavid van Moolenbroek /* these are for keeping track of the proc array */
266*b89261baSDavid van Moolenbroek 
267*b89261baSDavid van Moolenbroek static int bytes;
268*b89261baSDavid van Moolenbroek static int pref_len;
269*b89261baSDavid van Moolenbroek static struct proc *pbase;
270*b89261baSDavid van Moolenbroek static struct proc **pref;
271*b89261baSDavid van Moolenbroek 
272*b89261baSDavid van Moolenbroek /* these are for getting the memory statistics */
273*b89261baSDavid van Moolenbroek 
274*b89261baSDavid van Moolenbroek static struct page *physpage;
275*b89261baSDavid van Moolenbroek static int bytesize;
276*b89261baSDavid van Moolenbroek static int count;
277*b89261baSDavid van Moolenbroek static int pageshift;		/* log base 2 of the pagesize */
278*b89261baSDavid van Moolenbroek 
279*b89261baSDavid van Moolenbroek /* define pagetok in terms of pageshift */
280*b89261baSDavid van Moolenbroek 
281*b89261baSDavid van Moolenbroek #define pagetok(size) ((size) << pageshift)
282*b89261baSDavid van Moolenbroek 
283*b89261baSDavid van Moolenbroek /* useful externals */
284*b89261baSDavid van Moolenbroek extern int errno;
285*b89261baSDavid van Moolenbroek extern char *sys_errlist[];
286*b89261baSDavid van Moolenbroek 
287*b89261baSDavid van Moolenbroek long lseek();
288*b89261baSDavid van Moolenbroek long time();
289*b89261baSDavid van Moolenbroek 
290*b89261baSDavid van Moolenbroek machine_init(statics)
291*b89261baSDavid van Moolenbroek 
292*b89261baSDavid van Moolenbroek struct statics *statics;
293*b89261baSDavid van Moolenbroek 
294*b89261baSDavid van Moolenbroek {
295*b89261baSDavid van Moolenbroek     register int i;
296*b89261baSDavid van Moolenbroek     register int pagesize;
297*b89261baSDavid van Moolenbroek 
298*b89261baSDavid van Moolenbroek     /* initialize the kernel interface */
299*b89261baSDavid van Moolenbroek     if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "top")) == NULL)
300*b89261baSDavid van Moolenbroek     {
301*b89261baSDavid van Moolenbroek 	perror("kvm_open");
302*b89261baSDavid van Moolenbroek 	return(-1);
303*b89261baSDavid van Moolenbroek     }
304*b89261baSDavid van Moolenbroek 
305*b89261baSDavid van Moolenbroek     /* get the list of symbols we want to access in the kernel */
306*b89261baSDavid van Moolenbroek     if ((i = kvm_nlist(kd, nlst)) < 0)
307*b89261baSDavid van Moolenbroek     {
308*b89261baSDavid van Moolenbroek 	fprintf(stderr, "top: nlist failed\n");
309*b89261baSDavid van Moolenbroek 	return(-1);
310*b89261baSDavid van Moolenbroek     }
311*b89261baSDavid van Moolenbroek 
312*b89261baSDavid van Moolenbroek #ifdef MULTIPROCESSOR
313*b89261baSDavid van Moolenbroek     /* were ncpu and xp_time not found in the nlist? */
314*b89261baSDavid van Moolenbroek     if (i > 0 && nlst[X_NCPU].n_type == 0 && nlst[X_XP_TIME].n_type == 0)
315*b89261baSDavid van Moolenbroek     {
316*b89261baSDavid van Moolenbroek 	/* we were compiled on an MP system but we are not running on one */
317*b89261baSDavid van Moolenbroek 	/* so we will pretend this didn't happen and set ncpu = 1 */
318*b89261baSDavid van Moolenbroek 	i -= 2;
319*b89261baSDavid van Moolenbroek 	ncpu = 1;
320*b89261baSDavid van Moolenbroek     }
321*b89261baSDavid van Moolenbroek #endif
322*b89261baSDavid van Moolenbroek 
323*b89261baSDavid van Moolenbroek #ifdef solbourne
324*b89261baSDavid van Moolenbroek     {
325*b89261baSDavid van Moolenbroek 	unsigned int status, type;
326*b89261baSDavid van Moolenbroek 
327*b89261baSDavid van Moolenbroek 	/* Get the number of CPUs on this system.  */
328*b89261baSDavid van Moolenbroek 	syscall(SYS_getcpustatus, &status, &ncpu, &type);
329*b89261baSDavid van Moolenbroek     }
330*b89261baSDavid van Moolenbroek #endif
331*b89261baSDavid van Moolenbroek 
332*b89261baSDavid van Moolenbroek     /* make sure they were all found */
333*b89261baSDavid van Moolenbroek     if (i > 0 && check_nlist(nlst) > 0)
334*b89261baSDavid van Moolenbroek     {
335*b89261baSDavid van Moolenbroek 	return(-1);
336*b89261baSDavid van Moolenbroek     }
337*b89261baSDavid van Moolenbroek 
338*b89261baSDavid van Moolenbroek     /* get the symbol values out of kmem */
339*b89261baSDavid van Moolenbroek     (void) getkval(nlst[X_PROC].n_value,   (int *)(&proc),	sizeof(proc),
340*b89261baSDavid van Moolenbroek 	    nlst[X_PROC].n_name);
341*b89261baSDavid van Moolenbroek     (void) getkval(nlst[X_NPROC].n_value,  &nproc,		sizeof(nproc),
342*b89261baSDavid van Moolenbroek 	    nlst[X_NPROC].n_name);
343*b89261baSDavid van Moolenbroek     (void) getkval(nlst[X_CCPU].n_value,   (int *)(&ccpu),	sizeof(ccpu),
344*b89261baSDavid van Moolenbroek 	    nlst[X_CCPU].n_name);
345*b89261baSDavid van Moolenbroek     (void) getkval(nlst[X_PAGES].n_value,  (int *)(&pages),	sizeof(pages),
346*b89261baSDavid van Moolenbroek 	    nlst[X_PAGES].n_name);
347*b89261baSDavid van Moolenbroek     (void) getkval(nlst[X_EPAGES].n_value, (int *)(&epages),	sizeof(epages),
348*b89261baSDavid van Moolenbroek 	    nlst[X_EPAGES].n_name);
349*b89261baSDavid van Moolenbroek #ifdef MULTIPROCESSOR
350*b89261baSDavid van Moolenbroek     if (ncpu == 0)
351*b89261baSDavid van Moolenbroek     {
352*b89261baSDavid van Moolenbroek 	/* if ncpu > 0 then we are not really on an MP system */
353*b89261baSDavid van Moolenbroek 	(void) getkval(nlst[X_NCPU].n_value,   (int *)(&ncpu),	sizeof(ncpu),
354*b89261baSDavid van Moolenbroek 		       nlst[X_NCPU].n_name);
355*b89261baSDavid van Moolenbroek     }
356*b89261baSDavid van Moolenbroek #endif
357*b89261baSDavid van Moolenbroek 
358*b89261baSDavid van Moolenbroek     /* stash away certain offsets for later use */
359*b89261baSDavid van Moolenbroek     mpid_offset = nlst[X_MPID].n_value;
360*b89261baSDavid van Moolenbroek     avenrun_offset = nlst[X_AVENRUN].n_value;
361*b89261baSDavid van Moolenbroek     total_offset = nlst[X_TOTAL].n_value;
362*b89261baSDavid van Moolenbroek     cp_time_offset = nlst[X_CP_TIME].n_value;
363*b89261baSDavid van Moolenbroek #ifdef MULTIPROCESSOR
364*b89261baSDavid van Moolenbroek     xp_time_offset = nlst[X_XP_TIME].n_value;
365*b89261baSDavid van Moolenbroek #endif
366*b89261baSDavid van Moolenbroek 
367*b89261baSDavid van Moolenbroek     /* this is used in calculating WCPU -- calculate it ahead of time */
368*b89261baSDavid van Moolenbroek     logcpu = log(loaddouble(ccpu));
369*b89261baSDavid van Moolenbroek 
370*b89261baSDavid van Moolenbroek     /* allocate space for proc structure array and array of pointers */
371*b89261baSDavid van Moolenbroek     bytes = nproc * sizeof(struct proc);
372*b89261baSDavid van Moolenbroek     pbase = (struct proc *)malloc(bytes);
373*b89261baSDavid van Moolenbroek     pref  = (struct proc **)malloc(nproc * sizeof(struct proc *));
374*b89261baSDavid van Moolenbroek 
375*b89261baSDavid van Moolenbroek     /* Just in case ... */
376*b89261baSDavid van Moolenbroek     if (pbase == (struct proc *)NULL || pref == (struct proc **)NULL)
377*b89261baSDavid van Moolenbroek     {
378*b89261baSDavid van Moolenbroek 	fprintf(stderr, "top: can't allocate sufficient memory\n");
379*b89261baSDavid van Moolenbroek 	return(-1);
380*b89261baSDavid van Moolenbroek     }
381*b89261baSDavid van Moolenbroek 
382*b89261baSDavid van Moolenbroek     /* allocate a table to hold all the page structs */
383*b89261baSDavid van Moolenbroek     bytesize = epages - pages;
384*b89261baSDavid van Moolenbroek     count = bytesize / sizeof(struct page);
385*b89261baSDavid van Moolenbroek     physpage = (struct page *)malloc(epages - pages);
386*b89261baSDavid van Moolenbroek     if (physpage == NULL)
387*b89261baSDavid van Moolenbroek     {
388*b89261baSDavid van Moolenbroek 	fprintf(stderr, "top: can't allocate sufficient memory\n");
389*b89261baSDavid van Moolenbroek 	return(-1);
390*b89261baSDavid van Moolenbroek     }
391*b89261baSDavid van Moolenbroek 
392*b89261baSDavid van Moolenbroek     /* get the page size with "getpagesize" and calculate pageshift from it */
393*b89261baSDavid van Moolenbroek     pagesize = getpagesize();
394*b89261baSDavid van Moolenbroek     pageshift = 0;
395*b89261baSDavid van Moolenbroek     while (pagesize > 1)
396*b89261baSDavid van Moolenbroek     {
397*b89261baSDavid van Moolenbroek 	pageshift++;
398*b89261baSDavid van Moolenbroek 	pagesize >>= 1;
399*b89261baSDavid van Moolenbroek     }
400*b89261baSDavid van Moolenbroek 
401*b89261baSDavid van Moolenbroek     /* we only need the amount of log(2)1024 for our conversion */
402*b89261baSDavid van Moolenbroek     pageshift -= LOG1024;
403*b89261baSDavid van Moolenbroek 
404*b89261baSDavid van Moolenbroek #if defined(MULTIPROCESSOR) || defined(solbourne)
405*b89261baSDavid van Moolenbroek     /* add a slash to the "run" state abbreviation */
406*b89261baSDavid van Moolenbroek     if (ncpu > 1)
407*b89261baSDavid van Moolenbroek     {
408*b89261baSDavid van Moolenbroek 	state_abbrev[SRUN][3] = '/';
409*b89261baSDavid van Moolenbroek     }
410*b89261baSDavid van Moolenbroek #endif
411*b89261baSDavid van Moolenbroek 
412*b89261baSDavid van Moolenbroek     /* fill in the statics information */
413*b89261baSDavid van Moolenbroek     statics->procstate_names = procstatenames;
414*b89261baSDavid van Moolenbroek     statics->cpustate_names = cpustatenames;
415*b89261baSDavid van Moolenbroek     statics->memory_names = memorynames;
416*b89261baSDavid van Moolenbroek     statics->order_names = ordernames;
417*b89261baSDavid van Moolenbroek 
418*b89261baSDavid van Moolenbroek     /* all done! */
419*b89261baSDavid van Moolenbroek     return(0);
420*b89261baSDavid van Moolenbroek }
421*b89261baSDavid van Moolenbroek 
format_header(uname_field)422*b89261baSDavid van Moolenbroek char *format_header(uname_field)
423*b89261baSDavid van Moolenbroek 
424*b89261baSDavid van Moolenbroek register char *uname_field;
425*b89261baSDavid van Moolenbroek 
426*b89261baSDavid van Moolenbroek {
427*b89261baSDavid van Moolenbroek     register char *ptr;
428*b89261baSDavid van Moolenbroek 
429*b89261baSDavid van Moolenbroek     ptr = header + UNAME_START;
430*b89261baSDavid van Moolenbroek     while (*uname_field != '\0')
431*b89261baSDavid van Moolenbroek     {
432*b89261baSDavid van Moolenbroek 	*ptr++ = *uname_field++;
433*b89261baSDavid van Moolenbroek     }
434*b89261baSDavid van Moolenbroek 
435*b89261baSDavid van Moolenbroek     return(header);
436*b89261baSDavid van Moolenbroek }
437*b89261baSDavid van Moolenbroek 
438*b89261baSDavid van Moolenbroek void
get_system_info(si)439*b89261baSDavid van Moolenbroek get_system_info(si)
440*b89261baSDavid van Moolenbroek 
441*b89261baSDavid van Moolenbroek struct system_info *si;
442*b89261baSDavid van Moolenbroek 
443*b89261baSDavid van Moolenbroek {
444*b89261baSDavid van Moolenbroek     load_avg avenrun[3];
445*b89261baSDavid van Moolenbroek     long total;
446*b89261baSDavid van Moolenbroek #ifdef MULTIPROCESSOR
447*b89261baSDavid van Moolenbroek     long half_total;
448*b89261baSDavid van Moolenbroek #endif
449*b89261baSDavid van Moolenbroek 
450*b89261baSDavid van Moolenbroek     /* get the cp_time array */
451*b89261baSDavid van Moolenbroek     (void) getkval(cp_time_offset, (int *)cp_time, sizeof(cp_time),
452*b89261baSDavid van Moolenbroek 		   "_cp_time");
453*b89261baSDavid van Moolenbroek 
454*b89261baSDavid van Moolenbroek #ifdef MULTIPROCESSOR
455*b89261baSDavid van Moolenbroek     /* get the xp_time array as well */
456*b89261baSDavid van Moolenbroek     if (ncpu > 1)
457*b89261baSDavid van Moolenbroek     {
458*b89261baSDavid van Moolenbroek 	(void) getkval(xp_time_offset, (int *)xp_time, sizeof(xp_time),
459*b89261baSDavid van Moolenbroek 		       "_xp_time");
460*b89261baSDavid van Moolenbroek     }
461*b89261baSDavid van Moolenbroek #endif
462*b89261baSDavid van Moolenbroek 
463*b89261baSDavid van Moolenbroek     /* get load average array */
464*b89261baSDavid van Moolenbroek     (void) getkval(avenrun_offset, (int *)avenrun, sizeof(avenrun),
465*b89261baSDavid van Moolenbroek 		   "_avenrun");
466*b89261baSDavid van Moolenbroek 
467*b89261baSDavid van Moolenbroek     /* get mpid -- process id of last process */
468*b89261baSDavid van Moolenbroek     (void) getkval(mpid_offset, &(si->last_pid), sizeof(si->last_pid),
469*b89261baSDavid van Moolenbroek 		   "_mpid");
470*b89261baSDavid van Moolenbroek 
471*b89261baSDavid van Moolenbroek     /* get the array of physpage descriptors */
472*b89261baSDavid van Moolenbroek     (void) getkval(pages, (int *)physpage, bytesize, "array _page");
473*b89261baSDavid van Moolenbroek 
474*b89261baSDavid van Moolenbroek     /* convert load averages to doubles */
475*b89261baSDavid van Moolenbroek     {
476*b89261baSDavid van Moolenbroek 	register int i;
477*b89261baSDavid van Moolenbroek 	register double *infoloadp;
478*b89261baSDavid van Moolenbroek 	register load_avg *sysloadp;
479*b89261baSDavid van Moolenbroek 
480*b89261baSDavid van Moolenbroek 	infoloadp = si->load_avg;
481*b89261baSDavid van Moolenbroek 	sysloadp = avenrun;
482*b89261baSDavid van Moolenbroek 	for (i = 0; i < 3; i++)
483*b89261baSDavid van Moolenbroek 	{
484*b89261baSDavid van Moolenbroek 	    *infoloadp++ = loaddouble(*sysloadp++);
485*b89261baSDavid van Moolenbroek 	}
486*b89261baSDavid van Moolenbroek     }
487*b89261baSDavid van Moolenbroek 
488*b89261baSDavid van Moolenbroek     /* convert cp_time counts to percentages */
489*b89261baSDavid van Moolenbroek     total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
490*b89261baSDavid van Moolenbroek 
491*b89261baSDavid van Moolenbroek #ifdef MULTIPROCESSOR
492*b89261baSDavid van Moolenbroek     /* calculate spin time from all processors */
493*b89261baSDavid van Moolenbroek     if (ncpu > 1)
494*b89261baSDavid van Moolenbroek     {
495*b89261baSDavid van Moolenbroek 	register int c;
496*b89261baSDavid van Moolenbroek 	register int i;
497*b89261baSDavid van Moolenbroek 	register long sum;
498*b89261baSDavid van Moolenbroek 	register long change;
499*b89261baSDavid van Moolenbroek 
500*b89261baSDavid van Moolenbroek 	/* collect differences for each processor and add them */
501*b89261baSDavid van Moolenbroek 	sum = 0;
502*b89261baSDavid van Moolenbroek 	for (i = 0; i < ncpu; i++)
503*b89261baSDavid van Moolenbroek 	{
504*b89261baSDavid van Moolenbroek 	    c = xp_time[i][XP_SPIN];
505*b89261baSDavid van Moolenbroek 	    change = c - xp_old[i];
506*b89261baSDavid van Moolenbroek 	    if (change < 0)
507*b89261baSDavid van Moolenbroek 	    {
508*b89261baSDavid van Moolenbroek 		/* counter wrapped */
509*b89261baSDavid van Moolenbroek 		change = (long)((unsigned long)c -
510*b89261baSDavid van Moolenbroek 				(unsigned long)xp_old[i]);
511*b89261baSDavid van Moolenbroek 	    }
512*b89261baSDavid van Moolenbroek 	    sum += change;
513*b89261baSDavid van Moolenbroek 	    xp_old[i] = c;
514*b89261baSDavid van Moolenbroek 	}
515*b89261baSDavid van Moolenbroek 
516*b89261baSDavid van Moolenbroek 	/*
517*b89261baSDavid van Moolenbroek 	 *  NOTE:  I am assuming that the ticks found in xp_time are
518*b89261baSDavid van Moolenbroek 	 *  already included in the ticks accumulated in cp_time.  To
519*b89261baSDavid van Moolenbroek 	 *  get an accurate reflection, therefore, we have to subtract
520*b89261baSDavid van Moolenbroek 	 *  the spin time from the system time and recompute those two
521*b89261baSDavid van Moolenbroek 	 *  percentages.
522*b89261baSDavid van Moolenbroek 	 */
523*b89261baSDavid van Moolenbroek 	half_total = total / 2l;
524*b89261baSDavid van Moolenbroek 	cp_diff[CP_SYS] -= sum;
525*b89261baSDavid van Moolenbroek 	cpu_states[CP_SYS] = (int)((cp_diff[CP_SYS] * 1000 + half_total) /
526*b89261baSDavid van Moolenbroek 				   total);
527*b89261baSDavid van Moolenbroek 	cpu_states[XCP_SPIN] = (int)((sum * 1000 + half_total) / total);
528*b89261baSDavid van Moolenbroek     }
529*b89261baSDavid van Moolenbroek #endif
530*b89261baSDavid van Moolenbroek 
531*b89261baSDavid van Moolenbroek     /* sum memory statistics */
532*b89261baSDavid van Moolenbroek     {
533*b89261baSDavid van Moolenbroek 	register struct page *pp;
534*b89261baSDavid van Moolenbroek 	register int cnt;
535*b89261baSDavid van Moolenbroek 	register int inuse;
536*b89261baSDavid van Moolenbroek 	register int free;
537*b89261baSDavid van Moolenbroek 	register int locked;
538*b89261baSDavid van Moolenbroek 
539*b89261baSDavid van Moolenbroek 	/* bop thru the array counting page types */
540*b89261baSDavid van Moolenbroek 	pp = physpage;
541*b89261baSDavid van Moolenbroek 	inuse = free = locked = 0;
542*b89261baSDavid van Moolenbroek 	for (cnt = count; --cnt >= 0; pp++)
543*b89261baSDavid van Moolenbroek 	{
544*b89261baSDavid van Moolenbroek 	    if (pp->p_free)
545*b89261baSDavid van Moolenbroek 	    	free++;
546*b89261baSDavid van Moolenbroek 	    else if (pp->p_lock || pp->p_keepcnt > 0)
547*b89261baSDavid van Moolenbroek 	    	locked++;
548*b89261baSDavid van Moolenbroek 	    else
549*b89261baSDavid van Moolenbroek 	    	inuse++;
550*b89261baSDavid van Moolenbroek 	}
551*b89261baSDavid van Moolenbroek 
552*b89261baSDavid van Moolenbroek 	/* convert memory stats to Kbytes */
553*b89261baSDavid van Moolenbroek 	memory_stats[0] = pagetok(inuse + free);
554*b89261baSDavid van Moolenbroek 	memory_stats[1] = pagetok(inuse);
555*b89261baSDavid van Moolenbroek 	memory_stats[2] = pagetok(free);
556*b89261baSDavid van Moolenbroek 	memory_stats[3] = pagetok(locked);
557*b89261baSDavid van Moolenbroek     }
558*b89261baSDavid van Moolenbroek 
559*b89261baSDavid van Moolenbroek     /* set arrays and strings */
560*b89261baSDavid van Moolenbroek     si->cpustates = cpu_states;
561*b89261baSDavid van Moolenbroek     si->memory = memory_stats;
562*b89261baSDavid van Moolenbroek }
563*b89261baSDavid van Moolenbroek 
564*b89261baSDavid van Moolenbroek static struct handle handle;
565*b89261baSDavid van Moolenbroek 
get_process_info(si,sel,compare_index)566*b89261baSDavid van Moolenbroek caddr_t get_process_info(si, sel, compare_index)
567*b89261baSDavid van Moolenbroek 
568*b89261baSDavid van Moolenbroek struct system_info *si;
569*b89261baSDavid van Moolenbroek struct process_select *sel;
570*b89261baSDavid van Moolenbroek int compare_index;
571*b89261baSDavid van Moolenbroek 
572*b89261baSDavid van Moolenbroek {
573*b89261baSDavid van Moolenbroek     register int i;
574*b89261baSDavid van Moolenbroek     register int total_procs;
575*b89261baSDavid van Moolenbroek     register int active_procs;
576*b89261baSDavid van Moolenbroek     register struct proc **prefp;
577*b89261baSDavid van Moolenbroek     register struct proc *pp;
578*b89261baSDavid van Moolenbroek 
579*b89261baSDavid van Moolenbroek     /* these are copied out of sel for speed */
580*b89261baSDavid van Moolenbroek     int show_idle;
581*b89261baSDavid van Moolenbroek     int show_system;
582*b89261baSDavid van Moolenbroek     int show_uid;
583*b89261baSDavid van Moolenbroek     int show_command;
584*b89261baSDavid van Moolenbroek 
585*b89261baSDavid van Moolenbroek     /* read all the proc structures in one fell swoop */
586*b89261baSDavid van Moolenbroek     (void) getkval(proc, (int *)pbase, bytes, "proc array");
587*b89261baSDavid van Moolenbroek 
588*b89261baSDavid van Moolenbroek     /* get a pointer to the states summary array */
589*b89261baSDavid van Moolenbroek     si->procstates = process_states;
590*b89261baSDavid van Moolenbroek 
591*b89261baSDavid van Moolenbroek     /* set up flags which define what we are going to select */
592*b89261baSDavid van Moolenbroek     show_idle = sel->idle;
593*b89261baSDavid van Moolenbroek     show_system = sel->system;
594*b89261baSDavid van Moolenbroek     show_uid = sel->uid != -1;
595*b89261baSDavid van Moolenbroek     show_command = sel->command != NULL;
596*b89261baSDavid van Moolenbroek 
597*b89261baSDavid van Moolenbroek     /* count up process states and get pointers to interesting procs */
598*b89261baSDavid van Moolenbroek     total_procs = 0;
599*b89261baSDavid van Moolenbroek     active_procs = 0;
600*b89261baSDavid van Moolenbroek     bzero((char *)process_states, sizeof(process_states));
601*b89261baSDavid van Moolenbroek     prefp = pref;
602*b89261baSDavid van Moolenbroek     for (pp = pbase, i = 0; i < nproc; pp++, i++)
603*b89261baSDavid van Moolenbroek     {
604*b89261baSDavid van Moolenbroek 	/*
605*b89261baSDavid van Moolenbroek 	 *  Place pointers to each valid proc structure in pref[].
606*b89261baSDavid van Moolenbroek 	 *  Process slots that are actually in use have a non-zero
607*b89261baSDavid van Moolenbroek 	 *  status field.  Processes with SSYS set are system
608*b89261baSDavid van Moolenbroek 	 *  processes---these get ignored unless show_sysprocs is set.
609*b89261baSDavid van Moolenbroek 	 */
610*b89261baSDavid van Moolenbroek 	if (pp->p_stat != 0 &&
611*b89261baSDavid van Moolenbroek 	    (show_system || ((pp->p_flag & SSYS) == 0)))
612*b89261baSDavid van Moolenbroek 	{
613*b89261baSDavid van Moolenbroek 	    total_procs++;
614*b89261baSDavid van Moolenbroek 	    process_states[pp->p_stat]++;
615*b89261baSDavid van Moolenbroek 	    if ((pp->p_stat != SZOMB) &&
616*b89261baSDavid van Moolenbroek 		(show_idle || (pp->p_pctcpu != 0) || (pp->p_stat == SRUN)) &&
617*b89261baSDavid van Moolenbroek 		(!show_uid || pp->p_uid == (uid_t)sel->uid))
618*b89261baSDavid van Moolenbroek 	    {
619*b89261baSDavid van Moolenbroek 		*prefp++ = pp;
620*b89261baSDavid van Moolenbroek 		active_procs++;
621*b89261baSDavid van Moolenbroek 	    }
622*b89261baSDavid van Moolenbroek 	}
623*b89261baSDavid van Moolenbroek     }
624*b89261baSDavid van Moolenbroek 
625*b89261baSDavid van Moolenbroek     /* if requested, sort the "interesting" processes */
626*b89261baSDavid van Moolenbroek     qsort((char *)pref, active_procs, sizeof(struct proc *),
627*b89261baSDavid van Moolenbroek 	  proc_compares[compare_index]);
628*b89261baSDavid van Moolenbroek 
629*b89261baSDavid van Moolenbroek     /* remember active and total counts */
630*b89261baSDavid van Moolenbroek     si->p_total = total_procs;
631*b89261baSDavid van Moolenbroek     si->p_active = pref_len = active_procs;
632*b89261baSDavid van Moolenbroek 
633*b89261baSDavid van Moolenbroek     /* pass back a handle */
634*b89261baSDavid van Moolenbroek     handle.next_proc = pref;
635*b89261baSDavid van Moolenbroek     handle.remaining = active_procs;
636*b89261baSDavid van Moolenbroek     return((caddr_t)&handle);
637*b89261baSDavid van Moolenbroek }
638*b89261baSDavid van Moolenbroek 
639*b89261baSDavid van Moolenbroek char fmt[MAX_COLS];		/* static area where result is built */
640*b89261baSDavid van Moolenbroek 
format_next_process(handle,get_userid)641*b89261baSDavid van Moolenbroek char *format_next_process(handle, get_userid)
642*b89261baSDavid van Moolenbroek 
643*b89261baSDavid van Moolenbroek caddr_t handle;
644*b89261baSDavid van Moolenbroek char *(*get_userid)();
645*b89261baSDavid van Moolenbroek 
646*b89261baSDavid van Moolenbroek {
647*b89261baSDavid van Moolenbroek     register struct proc *pp;
648*b89261baSDavid van Moolenbroek     register long cputime;
649*b89261baSDavid van Moolenbroek     register double pct;
650*b89261baSDavid van Moolenbroek     struct user u;
651*b89261baSDavid van Moolenbroek     struct handle *hp;
652*b89261baSDavid van Moolenbroek 
653*b89261baSDavid van Moolenbroek     /* find and remember the next proc structure */
654*b89261baSDavid van Moolenbroek     hp = (struct handle *)handle;
655*b89261baSDavid van Moolenbroek     pp = *(hp->next_proc++);
656*b89261baSDavid van Moolenbroek     hp->remaining--;
657*b89261baSDavid van Moolenbroek 
658*b89261baSDavid van Moolenbroek     /* get the process's user struct and set cputime */
659*b89261baSDavid van Moolenbroek     if (getu(pp, &u) == -1)
660*b89261baSDavid van Moolenbroek     {
661*b89261baSDavid van Moolenbroek 	(void) strcpy(u.u_comm, "<swapped>");
662*b89261baSDavid van Moolenbroek 	cputime = 0;
663*b89261baSDavid van Moolenbroek     }
664*b89261baSDavid van Moolenbroek     else
665*b89261baSDavid van Moolenbroek     {
666*b89261baSDavid van Moolenbroek 	/* set u_comm for system processes */
667*b89261baSDavid van Moolenbroek 	if (u.u_comm[0] == '\0')
668*b89261baSDavid van Moolenbroek 	{
669*b89261baSDavid van Moolenbroek 	    if (pp->p_pid == 0)
670*b89261baSDavid van Moolenbroek 	    {
671*b89261baSDavid van Moolenbroek 		(void) strcpy(u.u_comm, "Swapper");
672*b89261baSDavid van Moolenbroek 	    }
673*b89261baSDavid van Moolenbroek 	    else if (pp->p_pid == 2)
674*b89261baSDavid van Moolenbroek 	    {
675*b89261baSDavid van Moolenbroek 		(void) strcpy(u.u_comm, "Pager");
676*b89261baSDavid van Moolenbroek 	    }
677*b89261baSDavid van Moolenbroek 	}
678*b89261baSDavid van Moolenbroek 
679*b89261baSDavid van Moolenbroek 	cputime = u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec;
680*b89261baSDavid van Moolenbroek     }
681*b89261baSDavid van Moolenbroek 
682*b89261baSDavid van Moolenbroek     /* calculate the base for cpu percentages */
683*b89261baSDavid van Moolenbroek     pct = pctdouble(pp->p_pctcpu);
684*b89261baSDavid van Moolenbroek 
685*b89261baSDavid van Moolenbroek #ifdef MULTIPROCESSOR
686*b89261baSDavid van Moolenbroek     /*
687*b89261baSDavid van Moolenbroek      *  If there is more than one cpu then add the processor number to
688*b89261baSDavid van Moolenbroek      *  the "run/" string.  Note that this will only show up if the
689*b89261baSDavid van Moolenbroek      *  process is in the run state.  Also note:  when they
690*b89261baSDavid van Moolenbroek      *  start making Suns with more than 9 processors this will break
691*b89261baSDavid van Moolenbroek      *  since the string will then be more than 5 characters.
692*b89261baSDavid van Moolenbroek      */
693*b89261baSDavid van Moolenbroek     if (ncpu > 1)
694*b89261baSDavid van Moolenbroek     {
695*b89261baSDavid van Moolenbroek 	state_abbrev[SRUN][4] = (pp->p_cpuid & 0xf) + '0';
696*b89261baSDavid van Moolenbroek     }
697*b89261baSDavid van Moolenbroek #endif
698*b89261baSDavid van Moolenbroek #ifdef solbourne
699*b89261baSDavid van Moolenbroek     if (ncpu > 1)
700*b89261baSDavid van Moolenbroek       {
701*b89261baSDavid van Moolenbroek 	state_abbrev[SRUN][4] = (pp->p_lastcpu) + '0';
702*b89261baSDavid van Moolenbroek       }
703*b89261baSDavid van Moolenbroek #endif
704*b89261baSDavid van Moolenbroek 
705*b89261baSDavid van Moolenbroek     /* format this entry */
706*b89261baSDavid van Moolenbroek     sprintf(fmt,
707*b89261baSDavid van Moolenbroek 	    Proc_format,
708*b89261baSDavid van Moolenbroek 	    pp->p_pid,
709*b89261baSDavid van Moolenbroek 	    (*get_userid)(pp->p_uid),
710*b89261baSDavid van Moolenbroek 	    pp->p_pri - PZERO,
711*b89261baSDavid van Moolenbroek 	    pp->p_nice - NZERO,
712*b89261baSDavid van Moolenbroek 	    format_k(pagetok(PROCSIZE(pp))),
713*b89261baSDavid van Moolenbroek 	    format_k(pagetok(pp->p_rssize)),
714*b89261baSDavid van Moolenbroek 	    state_abbrev[pp->p_stat],
715*b89261baSDavid van Moolenbroek 	    format_time(cputime),
716*b89261baSDavid van Moolenbroek 	    100.0 * weighted_cpu(pct, pp),
717*b89261baSDavid van Moolenbroek 	    100.0 * pct,
718*b89261baSDavid van Moolenbroek 	    printable(u.u_comm));
719*b89261baSDavid van Moolenbroek 
720*b89261baSDavid van Moolenbroek     /* return the result */
721*b89261baSDavid van Moolenbroek     return(fmt);
722*b89261baSDavid van Moolenbroek }
723*b89261baSDavid van Moolenbroek 
724*b89261baSDavid van Moolenbroek /*
725*b89261baSDavid van Moolenbroek  *  getu(p, u) - get the user structure for the process whose proc structure
726*b89261baSDavid van Moolenbroek  *	is pointed to by p.  The user structure is put in the buffer pointed
727*b89261baSDavid van Moolenbroek  *	to by u.  Return 0 if successful, -1 on failure (such as the process
728*b89261baSDavid van Moolenbroek  *	being swapped out).
729*b89261baSDavid van Moolenbroek  */
730*b89261baSDavid van Moolenbroek 
getu(p,u)731*b89261baSDavid van Moolenbroek getu(p, u)
732*b89261baSDavid van Moolenbroek 
733*b89261baSDavid van Moolenbroek register struct proc *p;
734*b89261baSDavid van Moolenbroek struct user *u;
735*b89261baSDavid van Moolenbroek 
736*b89261baSDavid van Moolenbroek {
737*b89261baSDavid van Moolenbroek     register struct user *lu;
738*b89261baSDavid van Moolenbroek 
739*b89261baSDavid van Moolenbroek     lu = kvm_getu(kd, p);
740*b89261baSDavid van Moolenbroek     if (lu == NULL)
741*b89261baSDavid van Moolenbroek     {
742*b89261baSDavid van Moolenbroek 	return(-1);
743*b89261baSDavid van Moolenbroek     }
744*b89261baSDavid van Moolenbroek     else
745*b89261baSDavid van Moolenbroek     {
746*b89261baSDavid van Moolenbroek 	*u = *lu;
747*b89261baSDavid van Moolenbroek 	return(0);
748*b89261baSDavid van Moolenbroek     }
749*b89261baSDavid van Moolenbroek }
750*b89261baSDavid van Moolenbroek 
751*b89261baSDavid van Moolenbroek /*
752*b89261baSDavid van Moolenbroek  * check_nlist(nlst) - checks the nlist to see if any symbols were not
753*b89261baSDavid van Moolenbroek  *		found.  For every symbol that was not found, a one-line
754*b89261baSDavid van Moolenbroek  *		message is printed to stderr.  The routine returns the
755*b89261baSDavid van Moolenbroek  *		number of symbols NOT found.
756*b89261baSDavid van Moolenbroek  */
757*b89261baSDavid van Moolenbroek 
check_nlist(nlst)758*b89261baSDavid van Moolenbroek int check_nlist(nlst)
759*b89261baSDavid van Moolenbroek 
760*b89261baSDavid van Moolenbroek register struct nlist *nlst;
761*b89261baSDavid van Moolenbroek 
762*b89261baSDavid van Moolenbroek {
763*b89261baSDavid van Moolenbroek     register int i;
764*b89261baSDavid van Moolenbroek 
765*b89261baSDavid van Moolenbroek     /* check to see if we got ALL the symbols we requested */
766*b89261baSDavid van Moolenbroek     /* this will write one line to stderr for every symbol not found */
767*b89261baSDavid van Moolenbroek 
768*b89261baSDavid van Moolenbroek     i = 0;
769*b89261baSDavid van Moolenbroek     while (nlst->n_name != NULL)
770*b89261baSDavid van Moolenbroek     {
771*b89261baSDavid van Moolenbroek #ifdef i386
772*b89261baSDavid van Moolenbroek 	if (nlst->n_value == 0)
773*b89261baSDavid van Moolenbroek #else
774*b89261baSDavid van Moolenbroek 	if (nlst->n_type == 0)
775*b89261baSDavid van Moolenbroek #endif
776*b89261baSDavid van Moolenbroek 	{
777*b89261baSDavid van Moolenbroek 	    /* this one wasn't found */
778*b89261baSDavid van Moolenbroek 	    fprintf(stderr, "kernel: no symbol named `%s'\n", nlst->n_name);
779*b89261baSDavid van Moolenbroek 	    i = 1;
780*b89261baSDavid van Moolenbroek 	}
781*b89261baSDavid van Moolenbroek 	nlst++;
782*b89261baSDavid van Moolenbroek     }
783*b89261baSDavid van Moolenbroek 
784*b89261baSDavid van Moolenbroek     return(i);
785*b89261baSDavid van Moolenbroek }
786*b89261baSDavid van Moolenbroek 
787*b89261baSDavid van Moolenbroek 
788*b89261baSDavid van Moolenbroek /*
789*b89261baSDavid van Moolenbroek  *  getkval(offset, ptr, size, refstr) - get a value out of the kernel.
790*b89261baSDavid van Moolenbroek  *	"offset" is the byte offset into the kernel for the desired value,
791*b89261baSDavid van Moolenbroek  *  	"ptr" points to a buffer into which the value is retrieved,
792*b89261baSDavid van Moolenbroek  *  	"size" is the size of the buffer (and the object to retrieve),
793*b89261baSDavid van Moolenbroek  *  	"refstr" is a reference string used when printing error meessages,
794*b89261baSDavid van Moolenbroek  *	    if "refstr" starts with a '!', then a failure on read will not
795*b89261baSDavid van Moolenbroek  *  	    be fatal (this may seem like a silly way to do things, but I
796*b89261baSDavid van Moolenbroek  *  	    really didn't want the overhead of another argument).
797*b89261baSDavid van Moolenbroek  *
798*b89261baSDavid van Moolenbroek  */
799*b89261baSDavid van Moolenbroek 
getkval(offset,ptr,size,refstr)800*b89261baSDavid van Moolenbroek getkval(offset, ptr, size, refstr)
801*b89261baSDavid van Moolenbroek 
802*b89261baSDavid van Moolenbroek unsigned long offset;
803*b89261baSDavid van Moolenbroek int *ptr;
804*b89261baSDavid van Moolenbroek int size;
805*b89261baSDavid van Moolenbroek char *refstr;
806*b89261baSDavid van Moolenbroek 
807*b89261baSDavid van Moolenbroek {
808*b89261baSDavid van Moolenbroek     if (kvm_read(kd, offset, ptr, size) != size)
809*b89261baSDavid van Moolenbroek     {
810*b89261baSDavid van Moolenbroek 	if (*refstr == '!')
811*b89261baSDavid van Moolenbroek 	{
812*b89261baSDavid van Moolenbroek 	    return(0);
813*b89261baSDavid van Moolenbroek 	}
814*b89261baSDavid van Moolenbroek 	else
815*b89261baSDavid van Moolenbroek 	{
816*b89261baSDavid van Moolenbroek 	    fprintf(stderr, "top: kvm_read for %s: %s\n",
817*b89261baSDavid van Moolenbroek 		refstr, sys_errlist[errno]);
818*b89261baSDavid van Moolenbroek 	    quit(23);
819*b89261baSDavid van Moolenbroek 	    /*NOTREACHED*/
820*b89261baSDavid van Moolenbroek 	}
821*b89261baSDavid van Moolenbroek     }
822*b89261baSDavid van Moolenbroek     return(1);
823*b89261baSDavid van Moolenbroek }
824*b89261baSDavid van Moolenbroek 
825*b89261baSDavid van Moolenbroek /* comparison routines for qsort */
826*b89261baSDavid van Moolenbroek 
827*b89261baSDavid van Moolenbroek /*
828*b89261baSDavid van Moolenbroek  * There are currently four possible comparison routines.  main selects
829*b89261baSDavid van Moolenbroek  * one of these by indexing in to the array proc_compares.
830*b89261baSDavid van Moolenbroek  *
831*b89261baSDavid van Moolenbroek  * Possible keys are defined as macros below.  Currently these keys are
832*b89261baSDavid van Moolenbroek  * defined:  percent cpu, cpu ticks, process state, resident set size,
833*b89261baSDavid van Moolenbroek  * total virtual memory usage.  The process states are ordered as follows
834*b89261baSDavid van Moolenbroek  * (from least to most important):  WAIT, zombie, sleep, stop, start, run.
835*b89261baSDavid van Moolenbroek  * The array declaration below maps a process state index into a number
836*b89261baSDavid van Moolenbroek  * that reflects this ordering.
837*b89261baSDavid van Moolenbroek  */
838*b89261baSDavid van Moolenbroek 
839*b89261baSDavid van Moolenbroek /* First, the possible comparison keys.  These are defined in such a way
840*b89261baSDavid van Moolenbroek    that they can be merely listed in the source code to define the actual
841*b89261baSDavid van Moolenbroek    desired ordering.
842*b89261baSDavid van Moolenbroek  */
843*b89261baSDavid van Moolenbroek 
844*b89261baSDavid van Moolenbroek #define ORDERKEY_PCTCPU  if (lresult = p2->p_pctcpu - p1->p_pctcpu,\
845*b89261baSDavid van Moolenbroek 			     (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
846*b89261baSDavid van Moolenbroek #define ORDERKEY_CPTICKS if ((result = p2->p_cpticks - p1->p_cpticks) == 0)
847*b89261baSDavid van Moolenbroek #define ORDERKEY_STATE   if ((result = sorted_state[p2->p_stat] - \
848*b89261baSDavid van Moolenbroek 			      sorted_state[p1->p_stat])  == 0)
849*b89261baSDavid van Moolenbroek #define ORDERKEY_PRIO    if ((result = p2->p_pri - p1->p_pri) == 0)
850*b89261baSDavid van Moolenbroek #define ORDERKEY_RSSIZE  if ((result = p2->p_rssize - p1->p_rssize) == 0)
851*b89261baSDavid van Moolenbroek #define ORDERKEY_MEM     if ((result = PROCSIZE(p2) - PROCSIZE(p1)) == 0)
852*b89261baSDavid van Moolenbroek 
853*b89261baSDavid van Moolenbroek /* Now the array that maps process state to a weight */
854*b89261baSDavid van Moolenbroek 
855*b89261baSDavid van Moolenbroek static unsigned char sorted_state[] =
856*b89261baSDavid van Moolenbroek {
857*b89261baSDavid van Moolenbroek     0,	/* not used		*/
858*b89261baSDavid van Moolenbroek     3,	/* sleep		*/
859*b89261baSDavid van Moolenbroek     1,	/* ABANDONED (WAIT)	*/
860*b89261baSDavid van Moolenbroek     6,	/* run			*/
861*b89261baSDavid van Moolenbroek     5,	/* start		*/
862*b89261baSDavid van Moolenbroek     2,	/* zombie		*/
863*b89261baSDavid van Moolenbroek     4	/* stop			*/
864*b89261baSDavid van Moolenbroek };
865*b89261baSDavid van Moolenbroek 
866*b89261baSDavid van Moolenbroek /* compare_cpu - the comparison function for sorting by cpu percentage */
867*b89261baSDavid van Moolenbroek 
868*b89261baSDavid van Moolenbroek compare_cpu(pp1, pp2)
869*b89261baSDavid van Moolenbroek 
870*b89261baSDavid van Moolenbroek struct proc **pp1;
871*b89261baSDavid van Moolenbroek struct proc **pp2;
872*b89261baSDavid van Moolenbroek 
873*b89261baSDavid van Moolenbroek {
874*b89261baSDavid van Moolenbroek     register struct proc *p1;
875*b89261baSDavid van Moolenbroek     register struct proc *p2;
876*b89261baSDavid van Moolenbroek     register int result;
877*b89261baSDavid van Moolenbroek     register pctcpu lresult;
878*b89261baSDavid van Moolenbroek 
879*b89261baSDavid van Moolenbroek     /* remove one level of indirection */
880*b89261baSDavid van Moolenbroek     p1 = *pp1;
881*b89261baSDavid van Moolenbroek     p2 = *pp2;
882*b89261baSDavid van Moolenbroek 
883*b89261baSDavid van Moolenbroek     ORDERKEY_PCTCPU
884*b89261baSDavid van Moolenbroek     ORDERKEY_CPTICKS
885*b89261baSDavid van Moolenbroek     ORDERKEY_STATE
886*b89261baSDavid van Moolenbroek     ORDERKEY_PRIO
887*b89261baSDavid van Moolenbroek     ORDERKEY_RSSIZE
888*b89261baSDavid van Moolenbroek     ORDERKEY_MEM
889*b89261baSDavid van Moolenbroek     ;
890*b89261baSDavid van Moolenbroek 
891*b89261baSDavid van Moolenbroek     return(result);
892*b89261baSDavid van Moolenbroek }
893*b89261baSDavid van Moolenbroek 
894*b89261baSDavid van Moolenbroek /* compare_size - the comparison function for sorting by total memory usage */
895*b89261baSDavid van Moolenbroek 
896*b89261baSDavid van Moolenbroek compare_size(pp1, pp2)
897*b89261baSDavid van Moolenbroek 
898*b89261baSDavid van Moolenbroek struct proc **pp1;
899*b89261baSDavid van Moolenbroek struct proc **pp2;
900*b89261baSDavid van Moolenbroek 
901*b89261baSDavid van Moolenbroek {
902*b89261baSDavid van Moolenbroek     register struct proc *p1;
903*b89261baSDavid van Moolenbroek     register struct proc *p2;
904*b89261baSDavid van Moolenbroek     register int result;
905*b89261baSDavid van Moolenbroek     register pctcpu lresult;
906*b89261baSDavid van Moolenbroek 
907*b89261baSDavid van Moolenbroek     /* remove one level of indirection */
908*b89261baSDavid van Moolenbroek     p1 = *pp1;
909*b89261baSDavid van Moolenbroek     p2 = *pp2;
910*b89261baSDavid van Moolenbroek 
911*b89261baSDavid van Moolenbroek     ORDERKEY_MEM
912*b89261baSDavid van Moolenbroek     ORDERKEY_RSSIZE
913*b89261baSDavid van Moolenbroek     ORDERKEY_PCTCPU
914*b89261baSDavid van Moolenbroek     ORDERKEY_CPTICKS
915*b89261baSDavid van Moolenbroek     ORDERKEY_STATE
916*b89261baSDavid van Moolenbroek     ORDERKEY_PRIO
917*b89261baSDavid van Moolenbroek     ;
918*b89261baSDavid van Moolenbroek 
919*b89261baSDavid van Moolenbroek     return(result);
920*b89261baSDavid van Moolenbroek }
921*b89261baSDavid van Moolenbroek 
922*b89261baSDavid van Moolenbroek /* compare_res - the comparison function for sorting by resident set size */
923*b89261baSDavid van Moolenbroek 
924*b89261baSDavid van Moolenbroek compare_res(pp1, pp2)
925*b89261baSDavid van Moolenbroek 
926*b89261baSDavid van Moolenbroek struct proc **pp1;
927*b89261baSDavid van Moolenbroek struct proc **pp2;
928*b89261baSDavid van Moolenbroek 
929*b89261baSDavid van Moolenbroek {
930*b89261baSDavid van Moolenbroek     register struct proc *p1;
931*b89261baSDavid van Moolenbroek     register struct proc *p2;
932*b89261baSDavid van Moolenbroek     register int result;
933*b89261baSDavid van Moolenbroek     register pctcpu lresult;
934*b89261baSDavid van Moolenbroek 
935*b89261baSDavid van Moolenbroek     /* remove one level of indirection */
936*b89261baSDavid van Moolenbroek     p1 = *pp1;
937*b89261baSDavid van Moolenbroek     p2 = *pp2;
938*b89261baSDavid van Moolenbroek 
939*b89261baSDavid van Moolenbroek     ORDERKEY_RSSIZE
940*b89261baSDavid van Moolenbroek     ORDERKEY_MEM
941*b89261baSDavid van Moolenbroek     ORDERKEY_PCTCPU
942*b89261baSDavid van Moolenbroek     ORDERKEY_CPTICKS
943*b89261baSDavid van Moolenbroek     ORDERKEY_STATE
944*b89261baSDavid van Moolenbroek     ORDERKEY_PRIO
945*b89261baSDavid van Moolenbroek     ;
946*b89261baSDavid van Moolenbroek 
947*b89261baSDavid van Moolenbroek     return(result);
948*b89261baSDavid van Moolenbroek }
949*b89261baSDavid van Moolenbroek 
950*b89261baSDavid van Moolenbroek /*
951*b89261baSDavid van Moolenbroek  * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
952*b89261baSDavid van Moolenbroek  *		the process does not exist.
953*b89261baSDavid van Moolenbroek  *		It is EXTREMLY IMPORTANT that this function work correctly.
954*b89261baSDavid van Moolenbroek  *		If top runs setuid root (as in SVR4), then this function
955*b89261baSDavid van Moolenbroek  *		is the only thing that stands in the way of a serious
956*b89261baSDavid van Moolenbroek  *		security problem.  It validates requests for the "kill"
957*b89261baSDavid van Moolenbroek  *		and "renice" commands.
958*b89261baSDavid van Moolenbroek  */
959*b89261baSDavid van Moolenbroek 
proc_owner(pid)960*b89261baSDavid van Moolenbroek int proc_owner(pid)
961*b89261baSDavid van Moolenbroek 
962*b89261baSDavid van Moolenbroek int pid;
963*b89261baSDavid van Moolenbroek 
964*b89261baSDavid van Moolenbroek {
965*b89261baSDavid van Moolenbroek     register int cnt;
966*b89261baSDavid van Moolenbroek     register struct proc **prefp;
967*b89261baSDavid van Moolenbroek     register struct proc *pp;
968*b89261baSDavid van Moolenbroek 
969*b89261baSDavid van Moolenbroek     prefp = pref;
970*b89261baSDavid van Moolenbroek     cnt = pref_len;
971*b89261baSDavid van Moolenbroek     while (--cnt >= 0)
972*b89261baSDavid van Moolenbroek     {
973*b89261baSDavid van Moolenbroek 	if ((pp = *prefp++)->p_pid == (pid_t)pid)
974*b89261baSDavid van Moolenbroek 	{
975*b89261baSDavid van Moolenbroek 	    return((int)pp->p_uid);
976*b89261baSDavid van Moolenbroek 	}
977*b89261baSDavid van Moolenbroek     }
978*b89261baSDavid van Moolenbroek     return(-1);
979*b89261baSDavid van Moolenbroek }
980