source: trunk/third/top/machine/m_sunos4mp.c @ 16185

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