1 | /* |
---|
2 | * top - a top users display for Unix |
---|
3 | * |
---|
4 | * THIS IS A TEMPLATE FILE FOR A MACHINE DEPENDENT (m_...c) FILE |
---|
5 | * |
---|
6 | * SYNOPSIS: one line description of machine this module works with |
---|
7 | * |
---|
8 | * DESCRIPTION: |
---|
9 | * Detailed description of this machine dependent module. |
---|
10 | * It can be multiple lines, but a blank comment line (one with only an |
---|
11 | * asterisk) is considered to end it. Place here a complete list of |
---|
12 | * the machines and OS versions that this module works on. |
---|
13 | * |
---|
14 | * LIBS: list of special libraries to include at link step (REMOVE THIS LINE IF NOT NEEDED) |
---|
15 | * |
---|
16 | * AUTHOR: your name and <your@internet.address> |
---|
17 | */ |
---|
18 | |
---|
19 | #include "top.h" |
---|
20 | #include "machine.h" |
---|
21 | |
---|
22 | |
---|
23 | /* |
---|
24 | * These definitions control the format of the per-process area |
---|
25 | */ |
---|
26 | |
---|
27 | static char header[] = |
---|
28 | " PID X PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND"; |
---|
29 | /* 0123456 -- field to fill in starts at header+6 */ |
---|
30 | #define UNAME_START 6 |
---|
31 | |
---|
32 | #define Proc_format \ |
---|
33 | "%5d %-8.8s %3d %4d%6dK %4dK %-5s%4d:%02d %5.2f%% %5.2f%% %.14s" |
---|
34 | |
---|
35 | /* these are for detailing the process states */ |
---|
36 | |
---|
37 | int process_states[?]; |
---|
38 | char *procstatenames[] = { |
---|
39 | "", " sleeping, ", " ABANDONED, ", " running, ", " starting, ", |
---|
40 | " zombie, ", " stopped, ", |
---|
41 | NULL |
---|
42 | }; |
---|
43 | |
---|
44 | /* these are for detailing the cpu states */ |
---|
45 | |
---|
46 | int cpu_states[?]; |
---|
47 | char *cpustatenames[] = { |
---|
48 | "user", "nice", "system", "idle", |
---|
49 | NULL |
---|
50 | }; |
---|
51 | |
---|
52 | /* these are for detailing the memory statistics */ |
---|
53 | |
---|
54 | int memory_stats[?]; |
---|
55 | char *memorynames[] = { |
---|
56 | "K available, ", "K in use, ", "K free, ", "K locked", NULL |
---|
57 | }; |
---|
58 | |
---|
59 | /* useful externals */ |
---|
60 | extern int errno; |
---|
61 | extern char *sys_errlist[]; |
---|
62 | |
---|
63 | long lseek(); |
---|
64 | long time(); |
---|
65 | long percentages(); |
---|
66 | |
---|
67 | machine_init(statics) |
---|
68 | |
---|
69 | struct statics *statics; |
---|
70 | |
---|
71 | { |
---|
72 | return(0); |
---|
73 | } |
---|
74 | |
---|
75 | char *format_header(uname_field) |
---|
76 | |
---|
77 | register char *uname_field; |
---|
78 | |
---|
79 | { |
---|
80 | register char *ptr; |
---|
81 | |
---|
82 | ptr = header + UNAME_START; |
---|
83 | while (*uname_field != '\0') |
---|
84 | { |
---|
85 | *ptr++ = *uname_field++; |
---|
86 | } |
---|
87 | |
---|
88 | return(header); |
---|
89 | } |
---|
90 | |
---|
91 | get_system_info(si) |
---|
92 | |
---|
93 | struct system_info *si; |
---|
94 | |
---|
95 | { |
---|
96 | } |
---|
97 | |
---|
98 | static struct handle handle; |
---|
99 | |
---|
100 | caddr_t get_process_info(si, sel, compare) |
---|
101 | |
---|
102 | struct system_info *si; |
---|
103 | struct process_select *sel; |
---|
104 | int (*compare)(); |
---|
105 | |
---|
106 | { |
---|
107 | return((caddr_t)&handle); |
---|
108 | } |
---|
109 | |
---|
110 | char fmt[128]; /* static area where result is built */ |
---|
111 | |
---|
112 | /* define what weighted cpu is. */ |
---|
113 | #define weighted_cpu(pct, pp) ((pp)->p_time == 0 ? 0.0 : \ |
---|
114 | ((pct) / (1.0 - exp((pp)->p_time * logcpu)))) |
---|
115 | |
---|
116 | char *format_next_process(handle, get_userid) |
---|
117 | |
---|
118 | caddr_t handle; |
---|
119 | char *(*get_userid)(); |
---|
120 | |
---|
121 | { |
---|
122 | return(fmt); |
---|
123 | } |
---|
124 | |
---|
125 | /* |
---|
126 | * getkval(offset, ptr, size, refstr) - get a value out of the kernel. |
---|
127 | * "offset" is the byte offset into the kernel for the desired value, |
---|
128 | * "ptr" points to a buffer into which the value is retrieved, |
---|
129 | * "size" is the size of the buffer (and the object to retrieve), |
---|
130 | * "refstr" is a reference string used when printing error meessages, |
---|
131 | * if "refstr" starts with a '!', then a failure on read will not |
---|
132 | * be fatal (this may seem like a silly way to do things, but I |
---|
133 | * really didn't want the overhead of another argument). |
---|
134 | * |
---|
135 | */ |
---|
136 | |
---|
137 | getkval(offset, ptr, size, refstr) |
---|
138 | |
---|
139 | unsigned long offset; |
---|
140 | int *ptr; |
---|
141 | int size; |
---|
142 | char *refstr; |
---|
143 | |
---|
144 | { |
---|
145 | if (kvm_read(kd, offset, ptr, size) != size) |
---|
146 | { |
---|
147 | if (*refstr == '!') |
---|
148 | { |
---|
149 | return(0); |
---|
150 | } |
---|
151 | else |
---|
152 | { |
---|
153 | fprintf(stderr, "top: kvm_read for %s: %s\n", |
---|
154 | refstr, sys_errlist[errno]); |
---|
155 | quit(23); |
---|
156 | } |
---|
157 | } |
---|
158 | return(1); |
---|
159 | } |
---|
160 | |
---|
161 | /* comparison routine for qsort */ |
---|
162 | /* NOTE: this is specific to the BSD proc structure, but it should |
---|
163 | give you a good place to start. */ |
---|
164 | |
---|
165 | /* |
---|
166 | * proc_compare - comparison function for "qsort" |
---|
167 | * Compares the resource consumption of two processes using five |
---|
168 | * distinct keys. The keys (in descending order of importance) are: |
---|
169 | * percent cpu, cpu ticks, state, resident set size, total virtual |
---|
170 | * memory usage. The process states are ordered as follows (from least |
---|
171 | * to most important): WAIT, zombie, sleep, stop, start, run. The |
---|
172 | * array declaration below maps a process state index into a number |
---|
173 | * that reflects this ordering. |
---|
174 | */ |
---|
175 | |
---|
176 | static unsigned char sorted_state[] = |
---|
177 | { |
---|
178 | 0, /* not used */ |
---|
179 | 3, /* sleep */ |
---|
180 | 1, /* ABANDONED (WAIT) */ |
---|
181 | 6, /* run */ |
---|
182 | 5, /* start */ |
---|
183 | 2, /* zombie */ |
---|
184 | 4 /* stop */ |
---|
185 | }; |
---|
186 | |
---|
187 | proc_compare(pp1, pp2) |
---|
188 | |
---|
189 | struct proc **pp1; |
---|
190 | struct proc **pp2; |
---|
191 | |
---|
192 | { |
---|
193 | register struct proc *p1; |
---|
194 | register struct proc *p2; |
---|
195 | register int result; |
---|
196 | register pctcpu lresult; |
---|
197 | |
---|
198 | /* remove one level of indirection */ |
---|
199 | p1 = *pp1; |
---|
200 | p2 = *pp2; |
---|
201 | |
---|
202 | /* compare percent cpu (pctcpu) */ |
---|
203 | if ((lresult = p2->p_pctcpu - p1->p_pctcpu) == 0) |
---|
204 | { |
---|
205 | /* use cpticks to break the tie */ |
---|
206 | if ((result = p2->p_cpticks - p1->p_cpticks) == 0) |
---|
207 | { |
---|
208 | /* use process state to break the tie */ |
---|
209 | if ((result = sorted_state[p2->p_stat] - |
---|
210 | sorted_state[p1->p_stat]) == 0) |
---|
211 | { |
---|
212 | /* use priority to break the tie */ |
---|
213 | if ((result = p2->p_pri - p1->p_pri) == 0) |
---|
214 | { |
---|
215 | /* use resident set size (rssize) to break the tie */ |
---|
216 | if ((result = p2->p_rssize - p1->p_rssize) == 0) |
---|
217 | { |
---|
218 | /* use total memory to break the tie */ |
---|
219 | result = PROCSIZE(p2) - PROCSIZE(p1); |
---|
220 | } |
---|
221 | } |
---|
222 | } |
---|
223 | } |
---|
224 | } |
---|
225 | else |
---|
226 | { |
---|
227 | result = lresult < 0 ? -1 : 1; |
---|
228 | } |
---|
229 | |
---|
230 | return(result); |
---|
231 | } |
---|
232 | |
---|
233 | proc_owner(pid) |
---|
234 | |
---|
235 | int pid; |
---|
236 | |
---|
237 | { |
---|
238 | /* returns uid of owner of process pid */ |
---|
239 | return(uid); |
---|
240 | } |
---|
241 | |
---|