124139Sjoerg/*
224139Sjoerg * top - a top users display for Unix
324139Sjoerg *
424139Sjoerg * THIS IS A TEMPLATE FILE FOR A MACHINE DEPENDENT (m_...c) FILE
524139Sjoerg *
624139Sjoerg * SYNOPSIS:  one line description of machine this module works with
724139Sjoerg *
824139Sjoerg * DESCRIPTION:
924139Sjoerg * Detailed description of this machine dependent module.
1024139Sjoerg * It can be multiple lines, but a blank comment line (one with only an
1124139Sjoerg * asterisk) is considered to end it.  Place here a complete list of 
1224139Sjoerg * the machines and OS versions that this module works on.
1324139Sjoerg *
1424139Sjoerg * LIBS:  list of special libraries to include at link step (REMOVE THIS LINE IF NOT NEEDED)
1524139Sjoerg *
1624139Sjoerg * AUTHOR:  your name and <your@internet.address>
1724139Sjoerg */
1824139Sjoerg
1924139Sjoerg#include "top.h"
2024139Sjoerg#include "machine.h"
2124139Sjoerg
2224139Sjoerg
2324139Sjoerg/*
2424139Sjoerg *  These definitions control the format of the per-process area
2524139Sjoerg */
2624139Sjoerg
2724139Sjoergstatic char header[] =
2824139Sjoerg  "  PID X        PRI NICE   SIZE   RES STATE   TIME   WCPU    CPU COMMAND";
2924139Sjoerg/* 0123456   -- field to fill in starts at header+6 */
3024139Sjoerg#define UNAME_START 6
3124139Sjoerg
3224139Sjoerg#define Proc_format \
3324139Sjoerg	"%5d %-8.8s %3d %4d%6dK %4dK %-5s%4d:%02d %5.2f%% %5.2f%% %.14s"
3424139Sjoerg
3524139Sjoerg/* these are for detailing the process states */
3624139Sjoerg
3724139Sjoergint process_states[?];
3824139Sjoergchar *procstatenames[] = {
3924139Sjoerg    "", " sleeping, ", " ABANDONED, ", " running, ", " starting, ",
4024139Sjoerg    " zombie, ", " stopped, ",
4124139Sjoerg    NULL
4224139Sjoerg};
4324139Sjoerg
4424139Sjoerg/* these are for detailing the cpu states */
4524139Sjoerg
4624139Sjoergint cpu_states[?];
4724139Sjoergchar *cpustatenames[] = {
4824139Sjoerg    "user", "nice", "system", "idle",
4924139Sjoerg    NULL
5024139Sjoerg};
5124139Sjoerg
5224139Sjoerg/* these are for detailing the memory statistics */
5324139Sjoerg
5424139Sjoergint memory_stats[?];
5524139Sjoergchar *memorynames[] = {
5624139Sjoerg    "K available, ", "K in use, ", "K free, ", "K locked", NULL
5724139Sjoerg};
5824139Sjoerg
5924139Sjoerg/* useful externals */
6024139Sjoergextern int errno;
6124139Sjoergextern char *sys_errlist[];
6224139Sjoerg
6324139Sjoerglong lseek();
6424139Sjoerglong time();
6524139Sjoerglong percentages();
6624139Sjoerg
6724139Sjoergmachine_init(statics)
6824139Sjoerg
6924139Sjoergstruct statics *statics;
7024139Sjoerg
7124139Sjoerg{
7224139Sjoerg    return(0);
7324139Sjoerg}
7424139Sjoerg
7524139Sjoergchar *format_header(uname_field)
7624139Sjoerg
7724139Sjoergregister char *uname_field;
7824139Sjoerg
7924139Sjoerg{
8024139Sjoerg    register char *ptr;
8124139Sjoerg
8224139Sjoerg    ptr = header + UNAME_START;
8324139Sjoerg    while (*uname_field != '\0')
8424139Sjoerg    {
8524139Sjoerg	*ptr++ = *uname_field++;
8624139Sjoerg    }
8724139Sjoerg
8824139Sjoerg    return(header);
8924139Sjoerg}
9024139Sjoerg
9124139Sjoergget_system_info(si)
9224139Sjoerg
9324139Sjoergstruct system_info *si;
9424139Sjoerg
9524139Sjoerg{
9624139Sjoerg}
9724139Sjoerg
9824139Sjoergstatic struct handle handle;
9924139Sjoerg
10024139Sjoergcaddr_t get_process_info(si, sel, compare)
10124139Sjoerg
10224139Sjoergstruct system_info *si;
10324139Sjoergstruct process_select *sel;
10424139Sjoergint (*compare)();
10524139Sjoerg
10624139Sjoerg{
10724139Sjoerg    return((caddr_t)&handle);
10824139Sjoerg}
10924139Sjoerg
11024139Sjoergchar fmt[128];		/* static area where result is built */
11124139Sjoerg
11224139Sjoerg/* define what weighted cpu is.  */
11324139Sjoerg#define weighted_cpu(pct, pp) ((pp)->p_time == 0 ? 0.0 : \
11424139Sjoerg			 ((pct) / (1.0 - exp((pp)->p_time * logcpu))))
11524139Sjoerg
11624139Sjoergchar *format_next_process(handle, get_userid)
11724139Sjoerg
11824139Sjoergcaddr_t handle;
11924139Sjoergchar *(*get_userid)();
12024139Sjoerg
12124139Sjoerg{
12224139Sjoerg    return(fmt);
12324139Sjoerg}
12424139Sjoerg
12524139Sjoerg/*
12624139Sjoerg *  getkval(offset, ptr, size, refstr) - get a value out of the kernel.
12724139Sjoerg *	"offset" is the byte offset into the kernel for the desired value,
12824139Sjoerg *  	"ptr" points to a buffer into which the value is retrieved,
12924139Sjoerg *  	"size" is the size of the buffer (and the object to retrieve),
13024139Sjoerg *  	"refstr" is a reference string used when printing error meessages,
13124139Sjoerg *	    if "refstr" starts with a '!', then a failure on read will not
13224139Sjoerg *  	    be fatal (this may seem like a silly way to do things, but I
13324139Sjoerg *  	    really didn't want the overhead of another argument).
13424139Sjoerg *  	
13524139Sjoerg */
13624139Sjoerg
13724139Sjoerggetkval(offset, ptr, size, refstr)
13824139Sjoerg
13924139Sjoergunsigned long offset;
14024139Sjoergint *ptr;
14124139Sjoergint size;
14224139Sjoergchar *refstr;
14324139Sjoerg
14424139Sjoerg{
14524139Sjoerg    if (kvm_read(kd, offset, ptr, size) != size)
14624139Sjoerg    {
14724139Sjoerg	if (*refstr == '!')
14824139Sjoerg	{
14924139Sjoerg	    return(0);
15024139Sjoerg	}
15124139Sjoerg	else
15224139Sjoerg	{
15324139Sjoerg	    fprintf(stderr, "top: kvm_read for %s: %s\n",
15424139Sjoerg		refstr, sys_errlist[errno]);
15524139Sjoerg	    quit(23);
15624139Sjoerg	}
15724139Sjoerg    }
15824139Sjoerg    return(1);
15924139Sjoerg}
16024139Sjoerg    
16124139Sjoerg/* comparison routine for qsort */
16224139Sjoerg/* NOTE: this is specific to the BSD proc structure, but it should
16324139Sjoerg   give you a good place to start. */
16424139Sjoerg
16524139Sjoerg/*
16624139Sjoerg *  proc_compare - comparison function for "qsort"
16724139Sjoerg *	Compares the resource consumption of two processes using five
16824139Sjoerg *  	distinct keys.  The keys (in descending order of importance) are:
16924139Sjoerg *  	percent cpu, cpu ticks, state, resident set size, total virtual
17024139Sjoerg *  	memory usage.  The process states are ordered as follows (from least
17124139Sjoerg *  	to most important):  WAIT, zombie, sleep, stop, start, run.  The
17224139Sjoerg *  	array declaration below maps a process state index into a number
17324139Sjoerg *  	that reflects this ordering.
17424139Sjoerg */
17524139Sjoerg
17624139Sjoergstatic unsigned char sorted_state[] =
17724139Sjoerg{
17824139Sjoerg    0,	/* not used		*/
17924139Sjoerg    3,	/* sleep		*/
18024139Sjoerg    1,	/* ABANDONED (WAIT)	*/
18124139Sjoerg    6,	/* run			*/
18224139Sjoerg    5,	/* start		*/
18324139Sjoerg    2,	/* zombie		*/
18424139Sjoerg    4	/* stop			*/
18524139Sjoerg};
18624139Sjoerg 
18724139Sjoergproc_compare(pp1, pp2)
18824139Sjoerg
18924139Sjoergstruct proc **pp1;
19024139Sjoergstruct proc **pp2;
19124139Sjoerg
19224139Sjoerg{
19324139Sjoerg    register struct proc *p1;
19424139Sjoerg    register struct proc *p2;
19524139Sjoerg    register int result;
19624139Sjoerg    register pctcpu lresult;
19724139Sjoerg
19824139Sjoerg    /* remove one level of indirection */
19924139Sjoerg    p1 = *pp1;
20024139Sjoerg    p2 = *pp2;
20124139Sjoerg
20224139Sjoerg    /* compare percent cpu (pctcpu) */
20324139Sjoerg    if ((lresult = p2->p_pctcpu - p1->p_pctcpu) == 0)
20424139Sjoerg    {
20524139Sjoerg	/* use cpticks to break the tie */
20624139Sjoerg	if ((result = p2->p_cpticks - p1->p_cpticks) == 0)
20724139Sjoerg	{
20824139Sjoerg	    /* use process state to break the tie */
20924139Sjoerg	    if ((result = sorted_state[p2->p_stat] -
21024139Sjoerg			  sorted_state[p1->p_stat])  == 0)
21124139Sjoerg	    {
21224139Sjoerg		/* use priority to break the tie */
21324139Sjoerg		if ((result = p2->p_pri - p1->p_pri) == 0)
21424139Sjoerg		{
21524139Sjoerg		    /* use resident set size (rssize) to break the tie */
21624139Sjoerg		    if ((result = p2->p_rssize - p1->p_rssize) == 0)
21724139Sjoerg		    {
21824139Sjoerg			/* use total memory to break the tie */
21924139Sjoerg			result = PROCSIZE(p2) - PROCSIZE(p1);
22024139Sjoerg		    }
22124139Sjoerg		}
22224139Sjoerg	    }
22324139Sjoerg	}
22424139Sjoerg    }
22524139Sjoerg    else
22624139Sjoerg    {
22724139Sjoerg	result = lresult < 0 ? -1 : 1;
22824139Sjoerg    }
22924139Sjoerg
23024139Sjoerg    return(result);
23124139Sjoerg}
23224139Sjoerg
23324139Sjoergproc_owner(pid)
23424139Sjoerg
23524139Sjoergint pid;
23624139Sjoerg
23724139Sjoerg{
23824139Sjoerg   /* returns uid of owner of process pid */
23924139Sjoerg   return(uid);
24024139Sjoerg}
24124139Sjoerg
242