1 | /* |
---|
2 | * top - a top users display for Unix |
---|
3 | * |
---|
4 | * SYNOPSIS: PowerPC running AIX 4.2 or higher |
---|
5 | * |
---|
6 | * DESCRIPTION: |
---|
7 | * This is the machine-dependent module for AIX 4.2 and higher |
---|
8 | * It is currenlty only tested on PowerPC architectures. |
---|
9 | * |
---|
10 | * TERMCAP: -lcurses |
---|
11 | * |
---|
12 | * CFLAGS: -DORDER -DHAVE_GETOPT |
---|
13 | * |
---|
14 | * LIBS: -bD:0x18000000 |
---|
15 | * |
---|
16 | * AUTHOR: Joep Vesseur <joep@fwi.uva.nl> |
---|
17 | * |
---|
18 | * PATCHES: Antoine Tabary <tabary@bruyeres.cea.fr> |
---|
19 | */ |
---|
20 | |
---|
21 | #include <stdlib.h> |
---|
22 | #include <stdio.h> |
---|
23 | #include <fcntl.h> |
---|
24 | #include <nlist.h> |
---|
25 | #include <sys/sysinfo.h> |
---|
26 | #include <procinfo.h> |
---|
27 | #include <sys/proc.h> |
---|
28 | #include <pwd.h> |
---|
29 | #include "top.h" |
---|
30 | #include "machine.h" |
---|
31 | |
---|
32 | |
---|
33 | #define PROCRESS(p) (((p)->pi_trss + (p)->pi_drss)*4) |
---|
34 | #define PROCSIZE(p) (((p)->pi_tsize/1024+(p)->pi_dvm)*4) |
---|
35 | #define PROCTIME(pi) (pi->pi_ru.ru_utime.tv_sec + pi->pi_ru.ru_stime.tv_sec) |
---|
36 | |
---|
37 | |
---|
38 | /* |
---|
39 | * structure definition taken from 'monitor' by Jussi Maki (jmaki@hut.fi) |
---|
40 | */ |
---|
41 | struct vmker { |
---|
42 | uint n0,n1,n2,n3,n4,n5,n6,n7,n8; |
---|
43 | uint totalmem; |
---|
44 | uint badmem; /* this is used in RS/6000 model 220 */ |
---|
45 | uint freemem; |
---|
46 | uint n12; |
---|
47 | uint numperm; /* this seems to keep other than text and data segment |
---|
48 | usage; name taken from /usr/lpp/bos/samples/vmtune.c */ |
---|
49 | uint totalvmem,freevmem; |
---|
50 | uint n15, n16, n17, n18, n19; |
---|
51 | }; |
---|
52 | |
---|
53 | |
---|
54 | #define KMEM "/dev/kmem" |
---|
55 | |
---|
56 | /* Indices in the nlist array */ |
---|
57 | #define X_AVENRUN 0 |
---|
58 | #define X_SYSINFO 1 |
---|
59 | #define X_VMKER 2 |
---|
60 | #define X_PROC 3 |
---|
61 | #define X_V 4 |
---|
62 | |
---|
63 | static struct nlist nlst[] = { |
---|
64 | { "avenrun", 0, 0, 0, 0, 0 }, /* 0 */ |
---|
65 | { "sysinfo", 0, 0, 0, 0, 0 }, /* 1 */ |
---|
66 | { "vmker", 0, 0, 0, 0, 0 }, /* 2 */ |
---|
67 | { "proc", 0, 0, 0, 0, 0 }, /* 3 */ |
---|
68 | { "v", 0, 0, 0, 0, 0 }, /* 4 */ |
---|
69 | { NULL, 0, 0, 0, 0, 0 } |
---|
70 | }; |
---|
71 | |
---|
72 | |
---|
73 | /* get_process_info returns handle. definition is here */ |
---|
74 | struct handle |
---|
75 | { |
---|
76 | struct procsinfo **next_proc; |
---|
77 | int remaining; |
---|
78 | }; |
---|
79 | |
---|
80 | /* |
---|
81 | * These definitions control the format of the per-process area |
---|
82 | */ |
---|
83 | static char header[] = |
---|
84 | " PID X PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND"; |
---|
85 | /* 0123456 -- field to fill in starts at header+6 */ |
---|
86 | #define UNAME_START 7 |
---|
87 | |
---|
88 | #define Proc_format \ |
---|
89 | "%6d %-8.8s %3d %4d %5d%c %4d%c %-5s %6s %5.2f%% %5.2f%% %.14s%s" |
---|
90 | |
---|
91 | |
---|
92 | /* these are for detailing the process states */ |
---|
93 | int process_states[9]; |
---|
94 | char *procstatenames[] = { |
---|
95 | " none, ", " sleeping, ", " state2, ", " runnable, ", |
---|
96 | " idle, ", " zombie, ", " stopped, ", " running, ", " swapped, ", |
---|
97 | NULL |
---|
98 | }; |
---|
99 | |
---|
100 | |
---|
101 | /* these are for detailing the cpu states */ |
---|
102 | int cpu_states[4]; |
---|
103 | char *cpustatenames[] = { |
---|
104 | "idle", "user", "kernel", "wait", |
---|
105 | NULL |
---|
106 | }; |
---|
107 | |
---|
108 | /* these are for detailing the memory statistics */ |
---|
109 | int memory_stats[7]; |
---|
110 | char *memorynames[] = { |
---|
111 | "M Total. Real: ", "M, ", "M Free, ", "M Buffers. Virtual: ", "M, ", "M Free, ", NULL |
---|
112 | }; |
---|
113 | #define M_TOTAL 0 |
---|
114 | #define M_REAL 1 |
---|
115 | #define M_REALFREE 2 |
---|
116 | #define M_BUFFERS 3 |
---|
117 | #define M_VIRTUAL 4 |
---|
118 | #define M_VIRTFREE 5 |
---|
119 | |
---|
120 | char *state_abbrev[] = { |
---|
121 | "", "sleep", "", "", "sleep", "zomb", "stop", "run", "swap" |
---|
122 | }; |
---|
123 | |
---|
124 | /* sorting orders. first is default */ |
---|
125 | char *ordernames[] = { |
---|
126 | "cpu", "size", "res", "time", "pri", NULL |
---|
127 | }; |
---|
128 | |
---|
129 | /* compare routines */ |
---|
130 | int compare_cpu(), compare_size(), compare_res(), compare_time(), |
---|
131 | compare_prio(); |
---|
132 | |
---|
133 | int (*proc_compares[])() = { |
---|
134 | compare_cpu, |
---|
135 | compare_size, |
---|
136 | compare_res, |
---|
137 | compare_time, |
---|
138 | compare_prio, |
---|
139 | NULL |
---|
140 | }; |
---|
141 | |
---|
142 | /* useful externals */ |
---|
143 | extern int errno; |
---|
144 | extern char *sys_errlist[]; |
---|
145 | long lseek(); |
---|
146 | long time(); |
---|
147 | long percentages(); |
---|
148 | |
---|
149 | |
---|
150 | /* useful globals */ |
---|
151 | int kmem; /* file descriptor */ |
---|
152 | |
---|
153 | /* offsets in kernel */ |
---|
154 | static unsigned long avenrun_offset; |
---|
155 | static unsigned long sysinfo_offset; |
---|
156 | static unsigned long vmker_offset; |
---|
157 | static unsigned long proc_offset; |
---|
158 | static unsigned long v_offset; |
---|
159 | |
---|
160 | /* used for calculating cpu state percentages */ |
---|
161 | static long cp_time[CPU_NTIMES]; |
---|
162 | static long cp_old[CPU_NTIMES]; |
---|
163 | static long cp_diff[CPU_NTIMES]; |
---|
164 | |
---|
165 | /* the runqueue length is a cumulative value. keep old value */ |
---|
166 | long old_runque; |
---|
167 | |
---|
168 | /* process info */ |
---|
169 | struct var v_info; /* to determine nprocs */ |
---|
170 | int nprocs; /* maximum nr of procs in proctab */ |
---|
171 | int ncpus; /* nr of cpus installed */ |
---|
172 | |
---|
173 | int ptsize; /* size of process table in bytes */ |
---|
174 | struct proc *p_proc; /* a copy of the process table */ |
---|
175 | struct procsinfo *p_info; /* needed for vm and ru info */ |
---|
176 | struct procsinfo **pref; /* processes selected for display */ |
---|
177 | int pref_len; /* number of processes selected */ |
---|
178 | |
---|
179 | /* needed to calculate WCPU */ |
---|
180 | unsigned long curtime; |
---|
181 | |
---|
182 | |
---|
183 | /* |
---|
184 | * Initialize globals, get kernel offsets and stuff... |
---|
185 | */ |
---|
186 | machine_init(statics) |
---|
187 | struct statics *statics; |
---|
188 | { |
---|
189 | if ((kmem = open(KMEM, O_RDONLY)) == -1) { |
---|
190 | perror(KMEM); |
---|
191 | return -1; |
---|
192 | } |
---|
193 | |
---|
194 | /* get kernel symbol offsets */ |
---|
195 | if (knlist(nlst, 5, sizeof(struct nlist)) != 0) { |
---|
196 | perror("knlist"); |
---|
197 | return -1; |
---|
198 | } |
---|
199 | avenrun_offset = nlst[X_AVENRUN].n_value; |
---|
200 | sysinfo_offset = nlst[X_SYSINFO].n_value; |
---|
201 | vmker_offset = nlst[X_VMKER].n_value; |
---|
202 | proc_offset = nlst[X_PROC].n_value; |
---|
203 | v_offset = nlst[X_V].n_value; |
---|
204 | |
---|
205 | getkval(v_offset, (caddr_t)&v_info, sizeof v_info, "v"); |
---|
206 | |
---|
207 | ncpus = v_info.v_ncpus; /* number of cpus */ |
---|
208 | nprocs = PROCMASK(PIDMAX); |
---|
209 | |
---|
210 | ptsize = nprocs * sizeof (struct proc); |
---|
211 | p_proc = (struct proc *)malloc(ptsize); |
---|
212 | p_info = (struct procsinfo *)malloc(nprocs * sizeof (struct procsinfo)); |
---|
213 | pref = (struct procsinfo **)malloc(nprocs * sizeof (struct procsinfo *)); |
---|
214 | |
---|
215 | if (!p_proc || !p_info || !pref) { |
---|
216 | fprintf(stderr, "top: not enough memory\n"); |
---|
217 | return -1; |
---|
218 | } |
---|
219 | |
---|
220 | statics->procstate_names = procstatenames; |
---|
221 | statics->cpustate_names = cpustatenames; |
---|
222 | statics->memory_names = memorynames; |
---|
223 | statics->order_names = ordernames; |
---|
224 | |
---|
225 | return(0); |
---|
226 | } |
---|
227 | |
---|
228 | |
---|
229 | |
---|
230 | char *format_header(uname_field) |
---|
231 | register char *uname_field; |
---|
232 | { |
---|
233 | register char *ptr; |
---|
234 | |
---|
235 | ptr = header + UNAME_START; |
---|
236 | while (*uname_field != '\0') |
---|
237 | { |
---|
238 | *ptr++ = *uname_field++; |
---|
239 | } |
---|
240 | |
---|
241 | return(header); |
---|
242 | } |
---|
243 | |
---|
244 | |
---|
245 | |
---|
246 | |
---|
247 | get_system_info(si) |
---|
248 | struct system_info *si; |
---|
249 | { |
---|
250 | int load_avg[3]; |
---|
251 | struct sysinfo s_info; |
---|
252 | struct vmker m_info; |
---|
253 | int i; |
---|
254 | double total = 0; |
---|
255 | |
---|
256 | /* get the load avarage array */ |
---|
257 | getkval(avenrun_offset, (caddr_t)load_avg, sizeof load_avg, "avenrun"); |
---|
258 | |
---|
259 | /* get the sysinfo structure */ |
---|
260 | getkval(sysinfo_offset, (caddr_t)&s_info, sizeof s_info, "sysinfo"); |
---|
261 | |
---|
262 | /* get vmker structure */ |
---|
263 | getkval(vmker_offset, (caddr_t)&m_info, sizeof m_info, "vmker"); |
---|
264 | |
---|
265 | /* convert load avarages to doubles */ |
---|
266 | for (i = 0; i < 3; i++) |
---|
267 | si->load_avg[i] = (double)load_avg[i]/65536.0; |
---|
268 | |
---|
269 | /* calculate cpu state in percentages */ |
---|
270 | for (i = 0; i < CPU_NTIMES; i++) { |
---|
271 | cp_old[i] = cp_time[i]; |
---|
272 | cp_time[i] = s_info.cpu[i]; |
---|
273 | cp_diff[i] = cp_time[i] - cp_old[i]; |
---|
274 | total += cp_diff[i]; |
---|
275 | } |
---|
276 | |
---|
277 | total = total/1000.0; /* top itself will correct this */ |
---|
278 | for (i = 0; i < CPU_NTIMES; i++) { |
---|
279 | cpu_states[i] = cp_diff[i] / total; |
---|
280 | } |
---|
281 | |
---|
282 | /* calculate memory statistics, scale 4K pages to megabytes */ |
---|
283 | #define PAGE_TO_MB(a) ((a)*4/1024) |
---|
284 | memory_stats[M_TOTAL] = PAGE_TO_MB(m_info.totalmem+m_info.totalvmem); |
---|
285 | memory_stats[M_REAL] = PAGE_TO_MB(m_info.totalmem); |
---|
286 | memory_stats[M_REALFREE] = PAGE_TO_MB(m_info.freemem); |
---|
287 | memory_stats[M_BUFFERS] = PAGE_TO_MB(m_info.numperm); |
---|
288 | memory_stats[M_VIRTUAL] = PAGE_TO_MB(m_info.totalvmem); |
---|
289 | memory_stats[M_VIRTFREE] = PAGE_TO_MB(m_info.freevmem); |
---|
290 | |
---|
291 | /* runnable processes */ |
---|
292 | process_states[0] = s_info.runque - old_runque; |
---|
293 | old_runque = s_info.runque; |
---|
294 | |
---|
295 | si->cpustates = cpu_states; |
---|
296 | si->memory = memory_stats; |
---|
297 | } |
---|
298 | |
---|
299 | static struct handle handle; |
---|
300 | |
---|
301 | caddr_t get_process_info(si, sel, compare) |
---|
302 | struct system_info *si; |
---|
303 | struct process_select *sel; |
---|
304 | int (*compare)(); |
---|
305 | { |
---|
306 | int i, nproc; |
---|
307 | int ptsize_util; |
---|
308 | int active_procs = 0, total_procs = 0; |
---|
309 | struct procsinfo *pp, **p_pref = pref; |
---|
310 | unsigned long pctcpu; |
---|
311 | pid_t procsindex = 0; |
---|
312 | struct proc *p; |
---|
313 | |
---|
314 | si->procstates = process_states; |
---|
315 | |
---|
316 | curtime = time(0); |
---|
317 | |
---|
318 | /* get the procsinfo structures of all running processes */ |
---|
319 | nproc = getprocs(p_info, sizeof (struct procsinfo), NULL, 0, |
---|
320 | &procsindex, nprocs); |
---|
321 | if (nproc < 0) { |
---|
322 | perror("getprocs"); |
---|
323 | quit(1); |
---|
324 | } |
---|
325 | |
---|
326 | /* the swapper has no cmd-line attached */ |
---|
327 | strcpy(p_info[0].pi_comm, "swapper"); |
---|
328 | |
---|
329 | /* get proc table */ |
---|
330 | ptsize_util = (PROCMASK(p_info[nproc-1].pi_pid)+1) * sizeof(struct proc); |
---|
331 | getkval(proc_offset, (caddr_t)p_proc, ptsize_util, "proc"); |
---|
332 | |
---|
333 | memset(process_states, 0, sizeof process_states); |
---|
334 | |
---|
335 | /* build a list of pointers to processes to show. walk through the |
---|
336 | * list of procsinfo structures instead of the proc table since the |
---|
337 | * mapping of procsinfo -> proctable is easy, the other way around |
---|
338 | * is cumbersome |
---|
339 | */ |
---|
340 | for (pp = p_info, i = 0; i < nproc; pp++, i++) { |
---|
341 | |
---|
342 | p = &p_proc[PROCMASK(pp->pi_pid)]; |
---|
343 | |
---|
344 | /* AIX marks all runnable processes as ACTIVE. We want to know |
---|
345 | which processes are sleeping, so check used cpu ticks and adjust |
---|
346 | status field accordingly |
---|
347 | */ |
---|
348 | if (p->p_stat == SACTIVE && p->p_cpticks == 0) |
---|
349 | p->p_stat = SIDL; |
---|
350 | |
---|
351 | if (pp->pi_state && (sel->system || ((pp->pi_flags & SKPROC) == 0))) { |
---|
352 | total_procs++; |
---|
353 | process_states[p->p_stat]++; |
---|
354 | if ( (pp->pi_state != SZOMB) && |
---|
355 | (sel->idle || p->p_cpticks != 0 || (p->p_stat == SACTIVE)) |
---|
356 | && (sel->uid == -1 || pp->pi_uid == (uid_t)sel->uid)) { |
---|
357 | *p_pref++ = pp; |
---|
358 | active_procs++; |
---|
359 | } |
---|
360 | } |
---|
361 | } |
---|
362 | |
---|
363 | /* the pref array now holds pointers to the procsinfo structures in |
---|
364 | * the p_info array that were selected for display |
---|
365 | */ |
---|
366 | |
---|
367 | /* sort if requested */ |
---|
368 | if (compare != NULL) |
---|
369 | qsort((char *)pref, active_procs, sizeof (struct procsinfo *), |
---|
370 | compare); |
---|
371 | |
---|
372 | si->last_pid = -1; /* no way to figure out last used pid */ |
---|
373 | si->p_total = total_procs; |
---|
374 | si->p_active = pref_len = active_procs; |
---|
375 | |
---|
376 | handle.next_proc = pref; |
---|
377 | handle.remaining = active_procs; |
---|
378 | |
---|
379 | return((caddr_t)&handle); |
---|
380 | } |
---|
381 | |
---|
382 | char fmt[128]; /* static area where result is built */ |
---|
383 | |
---|
384 | /* define what weighted cpu is. use definition of %CPU from 'man ps(1)' */ |
---|
385 | #define weighted_cpu(pp) (PROCTIME(pp) == 0 ? 0.0 : \ |
---|
386 | (((PROCTIME(pp)*100.0)/(curtime-pi->pi_start)/ncpus))) |
---|
387 | #define double_pctcpu(p) ((double)p->p_pctcpu/(double)FLT_MODULO) |
---|
388 | |
---|
389 | char *format_next_process(handle, get_userid) |
---|
390 | caddr_t handle; |
---|
391 | char *(*get_userid)(); |
---|
392 | { |
---|
393 | register struct handle *hp; |
---|
394 | register struct procsinfo *pi; |
---|
395 | register struct proc *p; |
---|
396 | char *uname; |
---|
397 | long cpu_time; |
---|
398 | int proc_size, proc_ress; |
---|
399 | char size_unit = 'K'; |
---|
400 | char ress_unit = 'K'; |
---|
401 | |
---|
402 | hp = (struct handle *)handle; |
---|
403 | if (hp->remaining == 0) { /* safe guard */ |
---|
404 | fmt[0] = '\0'; |
---|
405 | return fmt; |
---|
406 | } |
---|
407 | pi = *(hp->next_proc++); |
---|
408 | hp->remaining--; |
---|
409 | p = &p_proc[PROCMASK(pi->pi_pid)]; |
---|
410 | |
---|
411 | cpu_time = PROCTIME(pi); |
---|
412 | |
---|
413 | /* we disply sizes up to 10M in KiloBytes, beyond 10M in MegaBytes */ |
---|
414 | if ((proc_size = (pi->pi_tsize/1024+pi->pi_dvm)*4) > 10240) { |
---|
415 | proc_size /= 1024; |
---|
416 | size_unit = 'M'; |
---|
417 | } |
---|
418 | if ((proc_ress = (pi->pi_trss + pi->pi_drss)*4) > 10240) { |
---|
419 | proc_ress /= 1024; |
---|
420 | ress_unit = 'M'; |
---|
421 | } |
---|
422 | |
---|
423 | sprintf(fmt, Proc_format , |
---|
424 | pi->pi_pid, /* PID */ |
---|
425 | (*get_userid)(pi->pi_uid), /* login name */ |
---|
426 | getpriority(PRIO_PROCESS, pi->pi_pid), |
---|
427 | EXTRACT_NICE(p), /* fixed or vari */ |
---|
428 | proc_size, /* size */ |
---|
429 | size_unit, /* K or M */ |
---|
430 | proc_ress, /* resident */ |
---|
431 | ress_unit, /* K or M */ |
---|
432 | state_abbrev[p->p_stat], /* process state */ |
---|
433 | format_time(cpu_time), /* time used */ |
---|
434 | weighted_cpu(pi), /* WCPU */ |
---|
435 | 100.0 * double_pctcpu(p), /* CPU */ |
---|
436 | printable(pi->pi_comm), /* COMM */ |
---|
437 | (pi->pi_flags & SKPROC) == 0 ? "" : " (sys)" /* kernel process? */ |
---|
438 | ); |
---|
439 | return(fmt); |
---|
440 | } |
---|
441 | |
---|
442 | |
---|
443 | /* |
---|
444 | * getkval(offset, ptr, size, refstr) - get a value out of the kernel. |
---|
445 | * "offset" is the byte offset into the kernel for the desired value, |
---|
446 | * "ptr" points to a buffer into which the value is retrieved, |
---|
447 | * "size" is the size of the buffer (and the object to retrieve), |
---|
448 | * "refstr" is a reference string used when printing error meessages, |
---|
449 | * if "refstr" starts with a '!', then a failure on read will not |
---|
450 | * be fatal (this may seem like a silly way to do things, but I |
---|
451 | * really didn't want the overhead of another argument). |
---|
452 | * |
---|
453 | */ |
---|
454 | getkval(offset, ptr, size, refstr) |
---|
455 | unsigned long offset; |
---|
456 | caddr_t ptr; |
---|
457 | int size; |
---|
458 | char *refstr; |
---|
459 | { |
---|
460 | int upper_2gb = 0; |
---|
461 | |
---|
462 | /* reads above 2Gb are done by seeking to offset%2Gb, and supplying |
---|
463 | * 1 (opposed to 0) as fourth parameter to readx (see 'man kmem') |
---|
464 | */ |
---|
465 | if (offset > 1<<31) { |
---|
466 | upper_2gb = 1; |
---|
467 | offset &= 0x7fffffff; |
---|
468 | } |
---|
469 | |
---|
470 | if (lseek(kmem, offset, SEEK_SET) != offset) { |
---|
471 | fprintf(stderr, "top: lseek failed\n"); |
---|
472 | quit(2); |
---|
473 | } |
---|
474 | |
---|
475 | if (readx(kmem, ptr, size, upper_2gb) != size) { |
---|
476 | if (*refstr == '!') |
---|
477 | return 0; |
---|
478 | else { |
---|
479 | fprintf(stderr, "top: kvm_read for %s: %s\n", refstr, |
---|
480 | sys_errlist[errno]); |
---|
481 | quit(2); |
---|
482 | } |
---|
483 | } |
---|
484 | |
---|
485 | return 1 ; |
---|
486 | } |
---|
487 | |
---|
488 | /* comparison routine for qsort */ |
---|
489 | /* |
---|
490 | * The following code is taken from the solaris module and adjusted |
---|
491 | * for AIX -- JV . |
---|
492 | */ |
---|
493 | |
---|
494 | #define ORDERKEY_PCTCPU \ |
---|
495 | if (lresult = p2->p_pctcpu - p1->p_pctcpu, \ |
---|
496 | (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0) |
---|
497 | |
---|
498 | #define ORDERKEY_CPTICKS \ |
---|
499 | if ((result = PROCTIME(pi2) - PROCTIME(pi1)) == 0) |
---|
500 | |
---|
501 | |
---|
502 | #define ORDERKEY_STATE \ |
---|
503 | if ((result = sorted_state[p2->p_stat] \ |
---|
504 | - sorted_state[p1->p_stat]) == 0) |
---|
505 | |
---|
506 | /* Nice values directly reflect the process' priority, and are always >0 ;-) */ |
---|
507 | #define ORDERKEY_PRIO \ |
---|
508 | if ((result = EXTRACT_NICE(p1) - EXTRACT_NICE(p2)) == 0) |
---|
509 | |
---|
510 | #define ORDERKEY_RSSIZE \ |
---|
511 | if ((result = PROCRESS(pi2) - PROCRESS(pi1)) == 0) |
---|
512 | #define ORDERKEY_MEM \ |
---|
513 | if ((result = PROCSIZE(pi2) - PROCSIZE(pi1)) == 0) |
---|
514 | |
---|
515 | static unsigned char sorted_state[] = |
---|
516 | { |
---|
517 | 0, /* not used */ |
---|
518 | 0, |
---|
519 | 0, |
---|
520 | 0, |
---|
521 | 3, /* sleep */ |
---|
522 | 1, /* zombie */ |
---|
523 | 4, /* stop */ |
---|
524 | 6, /* run */ |
---|
525 | 2, /* swap */ |
---|
526 | }; |
---|
527 | |
---|
528 | /* compare_cpu - the comparison function for sorting by cpu percentage */ |
---|
529 | |
---|
530 | int |
---|
531 | compare_cpu(ppi1, ppi2) |
---|
532 | struct procsinfo **ppi1; |
---|
533 | struct procsinfo **ppi2; |
---|
534 | { |
---|
535 | register struct procsinfo *pi1 = *ppi1, *pi2 = *ppi2; |
---|
536 | register struct proc *p1; |
---|
537 | register struct proc *p2; |
---|
538 | register int result; |
---|
539 | register long lresult; |
---|
540 | |
---|
541 | p1 = &p_proc[PROCMASK(pi1->pi_pid)]; |
---|
542 | p2 = &p_proc[PROCMASK(pi2->pi_pid)]; |
---|
543 | |
---|
544 | ORDERKEY_PCTCPU |
---|
545 | ORDERKEY_CPTICKS |
---|
546 | ORDERKEY_STATE |
---|
547 | ORDERKEY_PRIO |
---|
548 | ORDERKEY_RSSIZE |
---|
549 | ORDERKEY_MEM |
---|
550 | ; |
---|
551 | |
---|
552 | return result; |
---|
553 | } |
---|
554 | |
---|
555 | |
---|
556 | /* compare_size - the comparison function for sorting by total memory usage */ |
---|
557 | |
---|
558 | int |
---|
559 | compare_size(ppi1, ppi2) |
---|
560 | struct procsinfo **ppi1; |
---|
561 | struct procsinfo **ppi2; |
---|
562 | { |
---|
563 | register struct procsinfo *pi1 = *ppi1, *pi2 = *ppi2; |
---|
564 | register struct proc *p1; |
---|
565 | register struct proc *p2; |
---|
566 | register int result; |
---|
567 | register long lresult; |
---|
568 | |
---|
569 | p1 = &p_proc[PROCMASK(pi1->pi_pid)]; |
---|
570 | p2 = &p_proc[PROCMASK(pi2->pi_pid)]; |
---|
571 | |
---|
572 | ORDERKEY_MEM |
---|
573 | ORDERKEY_RSSIZE |
---|
574 | ORDERKEY_PCTCPU |
---|
575 | ORDERKEY_CPTICKS |
---|
576 | ORDERKEY_STATE |
---|
577 | ORDERKEY_PRIO |
---|
578 | ; |
---|
579 | |
---|
580 | return result; |
---|
581 | } |
---|
582 | |
---|
583 | |
---|
584 | /* compare_res - the comparison function for sorting by resident set size */ |
---|
585 | |
---|
586 | int |
---|
587 | compare_res(ppi1, ppi2) |
---|
588 | struct procsinfo **ppi1; |
---|
589 | struct procsinfo **ppi2; |
---|
590 | { |
---|
591 | register struct procsinfo *pi1 = *ppi1, *pi2 = *ppi2; |
---|
592 | register struct proc *p1; |
---|
593 | register struct proc *p2; |
---|
594 | register int result; |
---|
595 | register long lresult; |
---|
596 | |
---|
597 | p1 = &p_proc[PROCMASK(pi1->pi_pid)]; |
---|
598 | p2 = &p_proc[PROCMASK(pi2->pi_pid)]; |
---|
599 | |
---|
600 | ORDERKEY_RSSIZE |
---|
601 | ORDERKEY_MEM |
---|
602 | ORDERKEY_PCTCPU |
---|
603 | ORDERKEY_CPTICKS |
---|
604 | ORDERKEY_STATE |
---|
605 | ORDERKEY_PRIO |
---|
606 | ; |
---|
607 | |
---|
608 | return result; |
---|
609 | } |
---|
610 | |
---|
611 | |
---|
612 | /* compare_time - the comparison function for sorting by total cpu time */ |
---|
613 | |
---|
614 | int |
---|
615 | compare_time(ppi1, ppi2) |
---|
616 | struct procsinfo **ppi1; |
---|
617 | struct procsinfo **ppi2; |
---|
618 | { |
---|
619 | register struct procsinfo *pi1 = *ppi1, *pi2 = *ppi2; |
---|
620 | register struct proc *p1; |
---|
621 | register struct proc *p2; |
---|
622 | register int result; |
---|
623 | register long lresult; |
---|
624 | |
---|
625 | p1 = &p_proc[PROCMASK(pi1->pi_pid)]; |
---|
626 | p2 = &p_proc[PROCMASK(pi2->pi_pid)]; |
---|
627 | |
---|
628 | ORDERKEY_CPTICKS |
---|
629 | ORDERKEY_PCTCPU |
---|
630 | ORDERKEY_STATE |
---|
631 | ORDERKEY_PRIO |
---|
632 | ORDERKEY_MEM |
---|
633 | ORDERKEY_RSSIZE |
---|
634 | ; |
---|
635 | |
---|
636 | return result; |
---|
637 | } |
---|
638 | |
---|
639 | |
---|
640 | /* compare_prio - the comparison function for sorting by cpu percentage */ |
---|
641 | |
---|
642 | int |
---|
643 | compare_prio(ppi1, ppi2) |
---|
644 | struct procsinfo **ppi1; |
---|
645 | struct procsinfo **ppi2; |
---|
646 | { |
---|
647 | register struct procsinfo *pi1 = *ppi1, *pi2 = *ppi2; |
---|
648 | register struct proc *p1; |
---|
649 | register struct proc *p2; |
---|
650 | register int result; |
---|
651 | register long lresult; |
---|
652 | |
---|
653 | p1 = &p_proc[PROCMASK(pi1->pi_pid)]; |
---|
654 | p2 = &p_proc[PROCMASK(pi2->pi_pid)]; |
---|
655 | |
---|
656 | ORDERKEY_PRIO |
---|
657 | ORDERKEY_PCTCPU |
---|
658 | ORDERKEY_CPTICKS |
---|
659 | ORDERKEY_STATE |
---|
660 | ORDERKEY_RSSIZE |
---|
661 | ORDERKEY_MEM |
---|
662 | ; |
---|
663 | |
---|
664 | return result; |
---|
665 | } |
---|
666 | |
---|
667 | |
---|
668 | proc_owner(pid) |
---|
669 | int pid; |
---|
670 | { |
---|
671 | int uid; |
---|
672 | register struct procsinfo **prefp = pref; |
---|
673 | register int cnt = pref_len; |
---|
674 | |
---|
675 | while (--cnt >= 0) { |
---|
676 | if ((*prefp)->pi_pid == pid) |
---|
677 | return (*prefp)->pi_uid; |
---|
678 | prefp++; |
---|
679 | } |
---|
680 | |
---|
681 | return(-1); |
---|
682 | } |
---|
683 | |
---|
684 | |
---|