| 1 |
1 |
/*
|
| 2 |
2 |
* top - a top users display for Unix
|
| 3 |
|
*
|
|
3 |
*
|
| 4 |
4 |
* SYNOPSIS: For DragonFly 2.x and later
|
| 5 |
|
*
|
| 6 |
|
* DESCRIPTION:
|
| 7 |
|
* Originally written for BSD4.4 system by Christos Zoulas.
|
| 8 |
|
* Ported to FreeBSD 2.x by Steven Wallace && Wolfram Schneider
|
| 9 |
|
* Order support hacked in from top-3.5beta6/machine/m_aix41.c
|
| 10 |
|
* by Monte Mitzelfelt (for latest top see http://www.groupsys.com/topinfo/)
|
| 11 |
|
*
|
| 12 |
|
* This is the machine-dependent module for DragonFly 2.5.1
|
| 13 |
|
* Should work for:
|
| 14 |
|
* DragonFly 2.x and above
|
| 15 |
|
*
|
|
5 |
*
|
|
6 |
* DESCRIPTION: Originally written for BSD4.4 system by Christos Zoulas. Ported
|
|
7 |
* to FreeBSD 2.x by Steven Wallace && Wolfram Schneider Order support hacked
|
|
8 |
* in from top-3.5beta6/machine/m_aix41.c by Monte Mitzelfelt (for latest top
|
|
9 |
* see http://www.groupsys.com/topinfo/)
|
|
10 |
*
|
|
11 |
* This is the machine-dependent module for DragonFly 2.5.1 Should work for:
|
|
12 |
* DragonFly 2.x and above
|
|
13 |
*
|
| 16 |
14 |
* LIBS: -lkvm
|
| 17 |
|
*
|
|
15 |
*
|
| 18 |
16 |
* AUTHOR: Jan Lentfer <Jan.Lentfer@web.de>
|
| 19 |
|
* This module has been put together from different sources and is based on the
|
| 20 |
|
* work of many other people, e.g. Matthew Dillon, Simon Schubert, Jordan Gordeev.
|
| 21 |
|
*
|
|
17 |
* This module has been put together from different sources and is based on
|
|
18 |
* the work of many other people, e.g. Matthew Dillon, Simon Schubert,
|
|
19 |
* Jordan Gordeev.
|
|
20 |
*
|
| 22 |
21 |
* $FreeBSD: src/usr.bin/top/machine.c,v 1.29.2.2 2001/07/31 20:27:05 tmm Exp $
|
| 23 |
|
* $DragonFly: src/usr.bin/top/machine.c,v 1.26 2008/10/16 01:52:33 swildner Exp $
|
|
22 |
* $DragonFly: src/usr.bin/top/machine.c,v 1.26 2008/10/16 01:52:33 swildner
|
|
23 |
* Exp $
|
| 24 |
24 |
*/
|
| 25 |
25 |
|
| 26 |
26 |
|
| ... | ... | |
| 50 |
50 |
#include <stdio.h>
|
| 51 |
51 |
#include <sys/conf.h>
|
| 52 |
52 |
|
| 53 |
|
#include <osreldate.h> /* for changes in kernel structures */
|
|
53 |
#include <osreldate.h> /* for changes in kernel structures */
|
| 54 |
54 |
|
| 55 |
55 |
#include <sys/kinfo.h>
|
| 56 |
56 |
#include <kinfo.h>
|
| ... | ... | |
| 60 |
60 |
#include "screen.h"
|
| 61 |
61 |
#include "utils.h"
|
| 62 |
62 |
|
| 63 |
|
#if 0
|
| 64 |
|
static int check_nlist(struct nlist *);
|
| 65 |
|
static int getkval(unsigned long, int *, int, char *);
|
| 66 |
|
#endif
|
| 67 |
63 |
int swapmode(int *retavail, int *retfree);
|
| 68 |
64 |
static int smpmode;
|
| 69 |
65 |
static int namelength;
|
| ... | ... | |
| 71 |
67 |
|
| 72 |
68 |
int n_cpus = 0;
|
| 73 |
69 |
|
| 74 |
|
/*
|
| 75 |
|
* needs to be a global symbol, so wrapper can be
|
| 76 |
|
* modified accordingly.
|
|
70 |
/*
|
|
71 |
* needs to be a global symbol, so wrapper can be modified accordingly.
|
| 77 |
72 |
*/
|
| 78 |
73 |
static int show_threads = 0;
|
| 79 |
74 |
|
| 80 |
75 |
/* get_process_info passes back a handle. This is what it looks like: */
|
| 81 |
76 |
|
| 82 |
|
struct handle
|
| 83 |
|
{
|
| 84 |
|
struct kinfo_proc **next_proc; /* points to next valid proc pointer */
|
| 85 |
|
int remaining; /* number of pointers remaining */
|
|
77 |
struct handle {
|
|
78 |
struct kinfo_proc **next_proc; /* points to next valid proc pointer */
|
|
79 |
int remaining; /* number of pointers remaining */
|
| 86 |
80 |
};
|
| 87 |
81 |
|
| 88 |
82 |
/* declarations for load_avg */
|
| ... | ... | |
| 100 |
94 |
#define PROCSIZE(pp) (VP((pp), map_size) / 1024)
|
| 101 |
95 |
|
| 102 |
96 |
/*
|
| 103 |
|
* These definitions control the format of the per-process area
|
|
97 |
* These definitions control the format of the per-process area
|
| 104 |
98 |
*/
|
| 105 |
99 |
|
| 106 |
100 |
static char smp_header[] =
|
| 107 |
|
" PID %-*.*s PRI NICE SIZE RES STATE C TIME WCPU CPU COMMAND";
|
|
101 |
" PID %-*.*s PRI NICE SIZE RES STATE C TIME WCPU CPU COMMAND";
|
| 108 |
102 |
|
| 109 |
103 |
#define smp_Proc_format \
|
| 110 |
104 |
"%5d %-*.*s %3d %3d%7s %6s %-6.6s %1x%7s %5.2f%% %5.2f%% %.*s"
|
| 111 |
105 |
|
| 112 |
106 |
static char up_header[] =
|
| 113 |
|
" PID %-*.*s PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND";
|
|
107 |
" PID %-*.*s PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND";
|
| 114 |
108 |
|
| 115 |
109 |
#define up_Proc_format \
|
| 116 |
110 |
"%5d %-*.*s %3d %3d%7s %6s %-6.6s%.0d%7s %5.2f%% %5.2f%% %.*s"
|
| ... | ... | |
| 118 |
112 |
|
| 119 |
113 |
|
| 120 |
114 |
/* process state names for the "STATE" column of the display */
|
| 121 |
|
/* the extra nulls in the string "run" are for adding a slash and
|
| 122 |
|
the processor number when needed */
|
|
115 |
/*
|
|
116 |
* the extra nulls in the string "run" are for adding a slash and the
|
|
117 |
* processor number when needed
|
|
118 |
*/
|
| 123 |
119 |
|
| 124 |
|
const char *state_abbrev[] =
|
| 125 |
|
{
|
| 126 |
|
"", "RUN\0\0\0", "STOP", "SLEEP",
|
|
120 |
const char *state_abbrev[] = {
|
|
121 |
"", "RUN\0\0\0", "STOP", "SLEEP",
|
| 127 |
122 |
};
|
| 128 |
123 |
|
| 129 |
124 |
|
| ... | ... | |
| 144 |
139 |
|
| 145 |
140 |
int process_states[6];
|
| 146 |
141 |
char *procstatenames[] = {
|
| 147 |
|
"", " starting, ", " running, ", " sleeping, ", " stopped, ",
|
| 148 |
|
" zombie, ",
|
| 149 |
|
NULL
|
|
142 |
"", " starting, ", " running, ", " sleeping, ", " stopped, ",
|
|
143 |
" zombie, ",
|
|
144 |
NULL
|
| 150 |
145 |
};
|
| 151 |
146 |
|
| 152 |
147 |
/* these are for detailing the cpu states */
|
| 153 |
148 |
#define CPU_STATES 5
|
| 154 |
149 |
int *cpu_states;
|
| 155 |
150 |
char *cpustatenames[CPU_STATES + 1] = {
|
| 156 |
|
"user", "nice", "system", "interrupt", "idle", NULL
|
|
151 |
"user", "nice", "system", "interrupt", "idle", NULL
|
| 157 |
152 |
};
|
| 158 |
153 |
|
| 159 |
154 |
/* these are for detailing the memory statistics */
|
| 160 |
155 |
|
| 161 |
156 |
long memory_stats[7];
|
| 162 |
157 |
char *memorynames[] = {
|
| 163 |
|
"K Active, ", "K Inact, ", "K Wired, ", "K Cache, ", "K Buf, ", "K Free",
|
| 164 |
|
NULL
|
|
158 |
"K Active, ", "K Inact, ", "K Wired, ", "K Cache, ", "K Buf, ", "K Free",
|
|
159 |
NULL
|
| 165 |
160 |
};
|
| 166 |
161 |
|
| 167 |
162 |
long swap_stats[7];
|
| 168 |
163 |
char *swapnames[] = {
|
| 169 |
|
/* 0 1 2 3 4 5 */
|
| 170 |
|
"K Total, ", "K Used, ", "K Free, ", "% Inuse, ", "K In, ", "K Out",
|
| 171 |
|
NULL
|
|
164 |
/* 0 1 2 3 4 5 */
|
|
165 |
"K Total, ", "K Used, ", "K Free, ", "% Inuse, ", "K In, ", "K Out",
|
|
166 |
NULL
|
| 172 |
167 |
};
|
| 173 |
168 |
|
| 174 |
169 |
|
| ... | ... | |
| 190 |
185 |
|
| 191 |
186 |
/* sorting orders. first is default */
|
| 192 |
187 |
char *ordernames[] = {
|
| 193 |
|
"cpu", "size", "res", "time", "pri", "thr", NULL
|
|
188 |
"cpu", "size", "res", "time", "pri", "thr", NULL
|
| 194 |
189 |
};
|
| 195 |
190 |
|
| 196 |
191 |
/* compare routines */
|
| 197 |
192 |
int proc_compare(), compare_size(), compare_res(), compare_time(), compare_prio(), compare_thr();
|
| 198 |
193 |
|
| 199 |
|
int (*proc_compares[])() = {
|
|
194 |
int (*proc_compares[]) () = {
|
| 200 |
195 |
proc_compare,
|
| 201 |
196 |
compare_size,
|
| 202 |
197 |
compare_res,
|
| ... | ... | |
| 207 |
202 |
|
| 208 |
203 |
static void
|
| 209 |
204 |
cputime_percentages(int out[CPU_STATES], struct kinfo_cputime *new,
|
| 210 |
|
struct kinfo_cputime *old)
|
|
205 |
struct kinfo_cputime *old)
|
| 211 |
206 |
{
|
| 212 |
|
struct kinfo_cputime diffs;
|
|
207 |
struct kinfo_cputime diffs;
|
| 213 |
208 |
uint64_t total_change, half_total;
|
| 214 |
209 |
|
| 215 |
|
/* initialization */
|
|
210 |
/* initialization */
|
| 216 |
211 |
total_change = 0;
|
| 217 |
212 |
|
| 218 |
|
diffs.cp_user = new->cp_user - old->cp_user;
|
|
213 |
diffs.cp_user = new->cp_user - old->cp_user;
|
| 219 |
214 |
diffs.cp_nice = new->cp_nice - old->cp_nice;
|
| 220 |
215 |
diffs.cp_sys = new->cp_sys - old->cp_sys;
|
| 221 |
|
diffs.cp_intr = new->cp_intr - old->cp_intr;
|
| 222 |
|
diffs.cp_idle = new->cp_idle - old->cp_idle;
|
|
216 |
diffs.cp_intr = new->cp_intr - old->cp_intr;
|
|
217 |
diffs.cp_idle = new->cp_idle - old->cp_idle;
|
| 223 |
218 |
total_change = diffs.cp_user + diffs.cp_nice + diffs.cp_sys +
|
| 224 |
|
diffs.cp_intr + diffs.cp_idle;
|
| 225 |
|
old->cp_user = new->cp_user;
|
| 226 |
|
old->cp_nice = new->cp_nice;
|
| 227 |
|
old->cp_sys = new->cp_sys;
|
| 228 |
|
old->cp_intr = new->cp_intr;
|
|
219 |
diffs.cp_intr + diffs.cp_idle;
|
|
220 |
old->cp_user = new->cp_user;
|
|
221 |
old->cp_nice = new->cp_nice;
|
|
222 |
old->cp_sys = new->cp_sys;
|
|
223 |
old->cp_intr = new->cp_intr;
|
| 229 |
224 |
old->cp_idle = new->cp_idle;
|
| 230 |
225 |
|
| 231 |
|
/* avoid divide by zero potential */
|
|
226 |
/* avoid divide by zero potential */
|
| 232 |
227 |
if (total_change == 0)
|
| 233 |
228 |
total_change = 1;
|
| 234 |
229 |
|
| 235 |
230 |
/* calculate percentages based on overall change, rounding up */
|
| 236 |
|
half_total = total_change >> 1;
|
|
231 |
half_total = total_change >> 1;
|
| 237 |
232 |
|
| 238 |
233 |
out[0] = ((diffs.cp_user * 1000LL + half_total) / total_change);
|
| 239 |
|
out[1] = ((diffs.cp_nice * 1000LL + half_total) / total_change);
|
|
234 |
out[1] = ((diffs.cp_nice * 1000LL + half_total) / total_change);
|
| 240 |
235 |
out[2] = ((diffs.cp_sys * 1000LL + half_total) / total_change);
|
| 241 |
|
out[3] = ((diffs.cp_intr * 1000LL + half_total) / total_change);
|
|
236 |
out[3] = ((diffs.cp_intr * 1000LL + half_total) / total_change);
|
| 242 |
237 |
out[4] = ((diffs.cp_idle * 1000LL + half_total) / total_change);
|
| 243 |
238 |
}
|
| 244 |
239 |
|
| 245 |
240 |
int
|
| 246 |
241 |
machine_init(struct statics *statics)
|
| 247 |
242 |
{
|
| 248 |
|
int pagesize;
|
| 249 |
|
size_t modelen;
|
| 250 |
|
struct passwd *pw;
|
|
243 |
int pagesize;
|
|
244 |
size_t modelen;
|
|
245 |
struct passwd *pw;
|
| 251 |
246 |
struct timeval boottime;
|
| 252 |
247 |
|
| 253 |
|
if (n_cpus < 1) {
|
| 254 |
|
if (kinfo_get_cpus(&n_cpus))
|
| 255 |
|
err(1, "kinfo_get_cpus failed");
|
| 256 |
|
}
|
| 257 |
|
|
|
248 |
if (n_cpus < 1) {
|
|
249 |
if (kinfo_get_cpus(&n_cpus))
|
|
250 |
err(1, "kinfo_get_cpus failed");
|
|
251 |
}
|
| 258 |
252 |
/* get boot time */
|
| 259 |
253 |
modelen = sizeof(boottime);
|
| 260 |
254 |
if (sysctlbyname("kern.boottime", &boottime, &modelen, NULL, 0) == -1) {
|
| 261 |
|
|
| 262 |
255 |
/* we have no boottime to report */
|
| 263 |
256 |
boottime.tv_sec = -1;
|
| 264 |
257 |
}
|
|
258 |
modelen = sizeof(smpmode);
|
|
259 |
if ((sysctlbyname("machdep.smp_active", &smpmode, &modelen, NULL, 0) < 0 &&
|
|
260 |
sysctlbyname("smp.smp_active", &smpmode, &modelen, NULL, 0) < 0) ||
|
|
261 |
modelen != sizeof(smpmode))
|
|
262 |
smpmode = 0;
|
|
263 |
|
|
264 |
while ((pw = getpwent()) != NULL) {
|
|
265 |
if ((int)strlen(pw->pw_name) > namelength)
|
|
266 |
namelength = strlen(pw->pw_name);
|
|
267 |
}
|
|
268 |
if (namelength < 8)
|
|
269 |
namelength = 8;
|
|
270 |
if (smpmode && namelength > 13)
|
|
271 |
namelength = 13;
|
|
272 |
else if (namelength > 15)
|
|
273 |
namelength = 15;
|
|
274 |
|
|
275 |
if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")) == NULL)
|
|
276 |
return -1;
|
|
277 |
|
|
278 |
if (kinfo_get_sched_ccpu(&ccpu)) {
|
|
279 |
fprintf(stderr, "top: kinfo_get_sched_ccpu failed\n");
|
|
280 |
return (-1);
|
|
281 |
}
|
|
282 |
/* this is used in calculating WCPU -- calculate it ahead of time */
|
|
283 |
logcpu = log(loaddouble(ccpu));
|
|
284 |
|
|
285 |
pbase = NULL;
|
|
286 |
pref = NULL;
|
|
287 |
nproc = 0;
|
|
288 |
onproc = -1;
|
|
289 |
/*
|
|
290 |
* get the page size with "getpagesize" and calculate pageshift from
|
|
291 |
* it
|
|
292 |
*/
|
|
293 |
pagesize = getpagesize();
|
|
294 |
pageshift = 0;
|
|
295 |
while (pagesize > 1) {
|
|
296 |
pageshift++;
|
|
297 |
pagesize >>= 1;
|
|
298 |
}
|
|
299 |
|
|
300 |
/* we only need the amount of log(2)1024 for our conversion */
|
|
301 |
pageshift -= LOG1024;
|
|
302 |
|
|
303 |
/* fill in the statics information */
|
|
304 |
statics->procstate_names = procstatenames;
|
|
305 |
statics->cpustate_names = cpustatenames;
|
|
306 |
statics->memory_names = memorynames;
|
|
307 |
statics->boottime = boottime.tv_sec;
|
|
308 |
statics->swap_names = swapnames;
|
|
309 |
statics->order_names = ordernames;
|
| 265 |
310 |
|
| 266 |
|
modelen = sizeof(smpmode);
|
| 267 |
|
if ((sysctlbyname("machdep.smp_active", &smpmode, &modelen, NULL, 0) < 0 &&
|
| 268 |
|
sysctlbyname("smp.smp_active", &smpmode, &modelen, NULL, 0) < 0) ||
|
| 269 |
|
modelen != sizeof(smpmode))
|
| 270 |
|
smpmode = 0;
|
| 271 |
|
|
| 272 |
|
while ((pw = getpwent()) != NULL) {
|
| 273 |
|
if ((int)strlen(pw->pw_name) > namelength)
|
| 274 |
|
namelength = strlen(pw->pw_name);
|
| 275 |
|
}
|
| 276 |
|
if (namelength < 8)
|
| 277 |
|
namelength = 8;
|
| 278 |
|
if (smpmode && namelength > 13)
|
| 279 |
|
namelength = 13;
|
| 280 |
|
else if (namelength > 15)
|
| 281 |
|
namelength = 15;
|
| 282 |
|
|
| 283 |
|
if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")) == NULL)
|
| 284 |
|
return -1;
|
| 285 |
|
|
| 286 |
|
if (kinfo_get_sched_ccpu(&ccpu)) {
|
| 287 |
|
fprintf(stderr, "top: kinfo_get_sched_ccpu failed\n");
|
| 288 |
|
return(-1);
|
| 289 |
|
}
|
| 290 |
|
|
| 291 |
|
/* this is used in calculating WCPU -- calculate it ahead of time */
|
| 292 |
|
logcpu = log(loaddouble(ccpu));
|
| 293 |
|
|
| 294 |
|
pbase = NULL;
|
| 295 |
|
pref = NULL;
|
| 296 |
|
nproc = 0;
|
| 297 |
|
onproc = -1;
|
| 298 |
|
/* get the page size with "getpagesize" and calculate pageshift from it */
|
| 299 |
|
pagesize = getpagesize();
|
| 300 |
|
pageshift = 0;
|
| 301 |
|
while (pagesize > 1)
|
| 302 |
|
{
|
| 303 |
|
pageshift++;
|
| 304 |
|
pagesize >>= 1;
|
| 305 |
|
}
|
| 306 |
|
|
| 307 |
|
/* we only need the amount of log(2)1024 for our conversion */
|
| 308 |
|
pageshift -= LOG1024;
|
| 309 |
|
|
| 310 |
|
/* fill in the statics information */
|
| 311 |
|
statics->procstate_names = procstatenames;
|
| 312 |
|
statics->cpustate_names = cpustatenames;
|
| 313 |
|
statics->memory_names = memorynames;
|
| 314 |
|
statics->boottime = boottime.tv_sec;
|
| 315 |
|
statics->swap_names = swapnames;
|
| 316 |
|
statics->order_names = ordernames;
|
| 317 |
|
|
| 318 |
|
/* all done! */
|
| 319 |
|
return(0);
|
|
311 |
/* all done! */
|
|
312 |
return (0);
|
| 320 |
313 |
}
|
| 321 |
314 |
|
| 322 |
315 |
char *
|
| 323 |
316 |
format_header(char *uname_field)
|
| 324 |
317 |
{
|
| 325 |
|
static char Header[128];
|
|
318 |
static char Header[128];
|
| 326 |
319 |
|
| 327 |
|
snprintf(Header, sizeof(Header), smpmode ? smp_header : up_header,
|
| 328 |
|
namelength, namelength, uname_field);
|
|
320 |
snprintf(Header, sizeof(Header), smpmode ? smp_header : up_header,
|
|
321 |
namelength, namelength, uname_field);
|
| 329 |
322 |
|
| 330 |
|
if (screen_width <= 79)
|
| 331 |
|
cmdlength = 80;
|
| 332 |
|
else
|
| 333 |
|
cmdlength = 89;
|
|
323 |
if (screen_width <= 79)
|
|
324 |
cmdlength = 80;
|
|
325 |
else
|
|
326 |
cmdlength = 89;
|
| 334 |
327 |
|
| 335 |
|
cmdlength = cmdlength - strlen(Header) + 6;
|
|
328 |
cmdlength = cmdlength - strlen(Header) + 6;
|
| 336 |
329 |
|
| 337 |
|
return Header;
|
|
330 |
return Header;
|
| 338 |
331 |
}
|
| 339 |
332 |
|
| 340 |
333 |
static int swappgsin = -1;
|
| ... | ... | |
| 344 |
337 |
void
|
| 345 |
338 |
get_system_info(struct system_info *si)
|
| 346 |
339 |
{
|
| 347 |
|
size_t len;
|
| 348 |
|
int cpu;
|
| 349 |
|
|
| 350 |
|
if (cpu_states == NULL) {
|
| 351 |
|
cpu_states = malloc(sizeof(*cpu_states) * CPU_STATES * n_cpus);
|
| 352 |
|
if (cpu_states == NULL)
|
| 353 |
|
err(1, "malloc");
|
| 354 |
|
bzero(cpu_states, sizeof(*cpu_states) * CPU_STATES * n_cpus);
|
| 355 |
|
}
|
| 356 |
|
if (cp_time == NULL) {
|
| 357 |
|
cp_time = malloc(2 * n_cpus * sizeof(cp_time[0]));
|
| 358 |
|
if (cp_time == NULL)
|
| 359 |
|
err(1, "cp_time");
|
| 360 |
|
cp_old = cp_time + n_cpus;
|
| 361 |
|
|
| 362 |
|
len = n_cpus * sizeof(cp_old[0]);
|
| 363 |
|
bzero(cp_time, len);
|
| 364 |
|
if (sysctlbyname("kern.cputime", cp_old, &len, NULL, 0))
|
| 365 |
|
err(1, "kern.cputime");
|
| 366 |
|
}
|
| 367 |
|
|
| 368 |
|
len = n_cpus * sizeof(cp_time[0]);
|
| 369 |
|
bzero(cp_time, len);
|
| 370 |
|
if (sysctlbyname("kern.cputime", cp_time, &len, NULL, 0))
|
| 371 |
|
err(1, "kern.cputime");
|
| 372 |
|
|
| 373 |
|
getloadavg(si->load_avg, 3);
|
| 374 |
|
|
| 375 |
|
lastpid = 0;
|
| 376 |
|
|
| 377 |
|
/* convert cp_time counts to percentages */
|
| 378 |
|
for (cpu = 0; cpu < n_cpus; ++cpu) {
|
| 379 |
|
cputime_percentages(cpu_states + cpu * CPU_STATES,
|
| 380 |
|
&cp_time[cpu], &cp_old[cpu]);
|
| 381 |
|
}
|
| 382 |
|
|
| 383 |
|
/* sum memory & swap statistics */
|
| 384 |
|
{
|
| 385 |
|
struct vmmeter vmm;
|
| 386 |
|
struct vmstats vms;
|
| 387 |
|
size_t vms_size = sizeof(vms);
|
| 388 |
|
size_t vmm_size = sizeof(vmm);
|
| 389 |
|
static unsigned int swap_delay = 0;
|
| 390 |
|
static int swapavail = 0;
|
| 391 |
|
static int swapfree = 0;
|
| 392 |
|
static int bufspace = 0;
|
| 393 |
|
|
| 394 |
|
if (sysctlbyname("vm.vmstats", &vms, &vms_size, NULL, 0))
|
| 395 |
|
err(1, "sysctlbyname: vm.vmstats");
|
| 396 |
|
|
| 397 |
|
if (sysctlbyname("vm.vmmeter", &vmm, &vmm_size, NULL, 0))
|
| 398 |
|
err(1, "sysctlbyname: vm.vmmeter");
|
| 399 |
|
|
| 400 |
|
if (kinfo_get_vfs_bufspace(&bufspace))
|
| 401 |
|
err(1, "kinfo_get_vfs_bufspace");
|
| 402 |
|
|
| 403 |
|
/* convert memory stats to Kbytes */
|
| 404 |
|
memory_stats[0] = pagetok(vms.v_active_count);
|
| 405 |
|
memory_stats[1] = pagetok(vms.v_inactive_count);
|
| 406 |
|
memory_stats[2] = pagetok(vms.v_wire_count);
|
| 407 |
|
memory_stats[3] = pagetok(vms.v_cache_count);
|
| 408 |
|
memory_stats[4] = bufspace / 1024;
|
| 409 |
|
memory_stats[5] = pagetok(vms.v_free_count);
|
| 410 |
|
memory_stats[6] = -1;
|
| 411 |
|
|
| 412 |
|
/* first interval */
|
| 413 |
|
if (swappgsin < 0) {
|
| 414 |
|
swap_stats[4] = 0;
|
| 415 |
|
swap_stats[5] = 0;
|
| 416 |
|
}
|
| 417 |
|
|
| 418 |
|
/* compute differences between old and new swap statistic */
|
| 419 |
|
else {
|
| 420 |
|
swap_stats[4] = pagetok(((vmm.v_swappgsin - swappgsin)));
|
| 421 |
|
swap_stats[5] = pagetok(((vmm.v_swappgsout - swappgsout)));
|
|
340 |
size_t len;
|
|
341 |
int cpu;
|
|
342 |
|
|
343 |
if (cpu_states == NULL) {
|
|
344 |
cpu_states = malloc(sizeof(*cpu_states) * CPU_STATES * n_cpus);
|
|
345 |
if (cpu_states == NULL)
|
|
346 |
err(1, "malloc");
|
|
347 |
bzero(cpu_states, sizeof(*cpu_states) * CPU_STATES * n_cpus);
|
|
348 |
}
|
|
349 |
if (cp_time == NULL) {
|
|
350 |
cp_time = malloc(2 * n_cpus * sizeof(cp_time[0]));
|
|
351 |
if (cp_time == NULL)
|
|
352 |
err(1, "cp_time");
|
|
353 |
cp_old = cp_time + n_cpus;
|
|
354 |
|
|
355 |
len = n_cpus * sizeof(cp_old[0]);
|
|
356 |
bzero(cp_time, len);
|
|
357 |
if (sysctlbyname("kern.cputime", cp_old, &len, NULL, 0))
|
|
358 |
err(1, "kern.cputime");
|
| 422 |
359 |
}
|
|
360 |
len = n_cpus * sizeof(cp_time[0]);
|
|
361 |
bzero(cp_time, len);
|
|
362 |
if (sysctlbyname("kern.cputime", cp_time, &len, NULL, 0))
|
|
363 |
err(1, "kern.cputime");
|
| 423 |
364 |
|
| 424 |
|
swappgsin = vmm.v_swappgsin;
|
| 425 |
|
swappgsout = vmm.v_swappgsout;
|
|
365 |
getloadavg(si->load_avg, 3);
|
| 426 |
366 |
|
| 427 |
|
/* call CPU heavy swapmode() only for changes */
|
| 428 |
|
if (swap_stats[4] > 0 || swap_stats[5] > 0 || swap_delay == 0) {
|
| 429 |
|
swap_stats[3] = swapmode(&swapavail, &swapfree);
|
| 430 |
|
swap_stats[0] = swapavail;
|
| 431 |
|
swap_stats[1] = swapavail - swapfree;
|
| 432 |
|
swap_stats[2] = swapfree;
|
|
367 |
lastpid = 0;
|
|
368 |
|
|
369 |
/* convert cp_time counts to percentages */
|
|
370 |
for (cpu = 0; cpu < n_cpus; ++cpu) {
|
|
371 |
cputime_percentages(cpu_states + cpu * CPU_STATES,
|
|
372 |
&cp_time[cpu], &cp_old[cpu]);
|
| 433 |
373 |
}
|
| 434 |
|
swap_delay = 1;
|
| 435 |
|
swap_stats[6] = -1;
|
| 436 |
|
}
|
| 437 |
374 |
|
| 438 |
|
/* set arrays and strings */
|
| 439 |
|
si->cpustates = cpu_states;
|
| 440 |
|
si->memory = memory_stats;
|
| 441 |
|
si->swap = swap_stats;
|
|
375 |
/* sum memory & swap statistics */
|
|
376 |
{
|
|
377 |
struct vmmeter vmm;
|
|
378 |
struct vmstats vms;
|
|
379 |
size_t vms_size = sizeof(vms);
|
|
380 |
size_t vmm_size = sizeof(vmm);
|
|
381 |
static unsigned int swap_delay = 0;
|
|
382 |
static int swapavail = 0;
|
|
383 |
static int swapfree = 0;
|
|
384 |
static int bufspace = 0;
|
|
385 |
|
|
386 |
if (sysctlbyname("vm.vmstats", &vms, &vms_size, NULL, 0))
|
|
387 |
err(1, "sysctlbyname: vm.vmstats");
|
|
388 |
|
|
389 |
if (sysctlbyname("vm.vmmeter", &vmm, &vmm_size, NULL, 0))
|
|
390 |
err(1, "sysctlbyname: vm.vmmeter");
|
|
391 |
|
|
392 |
if (kinfo_get_vfs_bufspace(&bufspace))
|
|
393 |
err(1, "kinfo_get_vfs_bufspace");
|
|
394 |
|
|
395 |
/* convert memory stats to Kbytes */
|
|
396 |
memory_stats[0] = pagetok(vms.v_active_count);
|
|
397 |
memory_stats[1] = pagetok(vms.v_inactive_count);
|
|
398 |
memory_stats[2] = pagetok(vms.v_wire_count);
|
|
399 |
memory_stats[3] = pagetok(vms.v_cache_count);
|
|
400 |
memory_stats[4] = bufspace / 1024;
|
|
401 |
memory_stats[5] = pagetok(vms.v_free_count);
|
|
402 |
memory_stats[6] = -1;
|
|
403 |
|
|
404 |
/* first interval */
|
|
405 |
if (swappgsin < 0) {
|
|
406 |
swap_stats[4] = 0;
|
|
407 |
swap_stats[5] = 0;
|
|
408 |
}
|
|
409 |
/* compute differences between old and new swap statistic */
|
|
410 |
else {
|
|
411 |
swap_stats[4] = pagetok(((vmm.v_swappgsin - swappgsin)));
|
|
412 |
swap_stats[5] = pagetok(((vmm.v_swappgsout - swappgsout)));
|
|
413 |
}
|
|
414 |
|
|
415 |
swappgsin = vmm.v_swappgsin;
|
|
416 |
swappgsout = vmm.v_swappgsout;
|
|
417 |
|
|
418 |
/* call CPU heavy swapmode() only for changes */
|
|
419 |
if (swap_stats[4] > 0 || swap_stats[5] > 0 || swap_delay == 0) {
|
|
420 |
swap_stats[3] = swapmode(&swapavail, &swapfree);
|
|
421 |
swap_stats[0] = swapavail;
|
|
422 |
swap_stats[1] = swapavail - swapfree;
|
|
423 |
swap_stats[2] = swapfree;
|
|
424 |
}
|
|
425 |
swap_delay = 1;
|
|
426 |
swap_stats[6] = -1;
|
|
427 |
}
|
|
428 |
|
|
429 |
/* set arrays and strings */
|
|
430 |
si->cpustates = cpu_states;
|
|
431 |
si->memory = memory_stats;
|
|
432 |
si->swap = swap_stats;
|
| 442 |
433 |
|
| 443 |
434 |
|
| 444 |
|
if(lastpid > 0) {
|
| 445 |
|
si->last_pid = lastpid;
|
| 446 |
|
} else {
|
| 447 |
|
si->last_pid = -1;
|
| 448 |
|
}
|
|
435 |
if (lastpid > 0) {
|
|
436 |
si->last_pid = lastpid;
|
|
437 |
} else {
|
|
438 |
si->last_pid = -1;
|
|
439 |
}
|
| 449 |
440 |
}
|
| 450 |
441 |
|
| 451 |
442 |
|
| 452 |
443 |
static struct handle handle;
|
| 453 |
444 |
|
| 454 |
|
caddr_t get_process_info(struct system_info *si, struct process_select *sel,
|
|
445 |
caddr_t
|
|
446 |
get_process_info(struct system_info *si, struct process_select *sel,
|
| 455 |
447 |
int compare_index)
|
| 456 |
448 |
{
|
| 457 |
|
int i;
|
| 458 |
|
int total_procs;
|
| 459 |
|
int active_procs;
|
| 460 |
|
struct kinfo_proc **prefp;
|
| 461 |
|
struct kinfo_proc *pp;
|
| 462 |
|
|
| 463 |
|
/* these are copied out of sel for speed */
|
| 464 |
|
int show_idle;
|
| 465 |
|
int show_system;
|
| 466 |
|
int show_uid;
|
| 467 |
|
|
| 468 |
|
|
| 469 |
|
pbase = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc);
|
| 470 |
|
if (nproc > onproc)
|
| 471 |
|
pref = (struct kinfo_proc **) realloc(pref, sizeof(struct kinfo_proc *)
|
| 472 |
|
* (onproc = nproc));
|
| 473 |
|
if (pref == NULL || pbase == NULL) {
|
| 474 |
|
(void) fprintf(stderr, "top: Out of memory.\n");
|
| 475 |
|
quit(23);
|
| 476 |
|
}
|
| 477 |
|
/* get a pointer to the states summary array */
|
| 478 |
|
si->procstates = process_states;
|
| 479 |
|
|
| 480 |
|
/* set up flags which define what we are going to select */
|
| 481 |
|
show_idle = sel->idle;
|
| 482 |
|
show_system = sel->system;
|
| 483 |
|
show_uid = sel->uid != -1;
|
| 484 |
|
|
| 485 |
|
/* count up process states and get pointers to interesting procs */
|
| 486 |
|
total_procs = 0;
|
| 487 |
|
active_procs = 0;
|
| 488 |
|
memset((char *)process_states, 0, sizeof(process_states));
|
| 489 |
|
prefp = pref;
|
| 490 |
|
for (pp = pbase, i = 0; i < nproc; pp++, i++)
|
| 491 |
|
{
|
| 492 |
|
/*
|
| 493 |
|
* Place pointers to each valid proc structure in pref[].
|
| 494 |
|
* Process slots that are actually in use have a non-zero
|
| 495 |
|
* status field. Processes with P_SYSTEM set are system
|
| 496 |
|
* processes---these get ignored unless show_sysprocs is set.
|
| 497 |
|
*/
|
| 498 |
|
if ((show_threads && (LP(pp, pid) == -1)) ||
|
| 499 |
|
(show_system || ((PP(pp, flags) & P_SYSTEM) == 0)))
|
| 500 |
|
{
|
| 501 |
|
total_procs++;
|
| 502 |
|
process_states[(unsigned char) PP(pp, stat)]++;
|
| 503 |
|
if ((show_threads && (LP(pp, pid) == -1)) ||
|
| 504 |
|
(show_idle || (LP(pp, pctcpu) != 0) ||
|
| 505 |
|
(LP(pp, stat) == LSRUN)) &&
|
| 506 |
|
(!show_uid || PP(pp, ruid) == (uid_t)sel->uid))
|
| 507 |
|
{
|
| 508 |
|
*prefp++ = pp;
|
| 509 |
|
active_procs++;
|
| 510 |
|
}
|
|
449 |
int i;
|
|
450 |
int total_procs;
|
|
451 |
int active_procs;
|
|
452 |
struct kinfo_proc **prefp;
|
|
453 |
struct kinfo_proc *pp;
|
|
454 |
|
|
455 |
/* these are copied out of sel for speed */
|
|
456 |
int show_idle;
|
|
457 |
int show_system;
|
|
458 |
int show_uid;
|
|
459 |
|
|
460 |
|
|
461 |
pbase = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc);
|
|
462 |
if (nproc > onproc)
|
|
463 |
pref = (struct kinfo_proc **)realloc(pref, sizeof(struct kinfo_proc *)
|
|
464 |
* (onproc = nproc));
|
|
465 |
if (pref == NULL || pbase == NULL) {
|
|
466 |
(void)fprintf(stderr, "top: Out of memory.\n");
|
|
467 |
quit(23);
|
|
468 |
}
|
|
469 |
/* get a pointer to the states summary array */
|
|
470 |
si->procstates = process_states;
|
|
471 |
|
|
472 |
/* set up flags which define what we are going to select */
|
|
473 |
show_idle = sel->idle;
|
|
474 |
show_system = sel->system;
|
|
475 |
show_uid = sel->uid != -1;
|
|
476 |
|
|
477 |
/* count up process states and get pointers to interesting procs */
|
|
478 |
total_procs = 0;
|
|
479 |
active_procs = 0;
|
|
480 |
memset((char *)process_states, 0, sizeof(process_states));
|
|
481 |
prefp = pref;
|
|
482 |
for (pp = pbase, i = 0; i < nproc; pp++, i++) {
|
|
483 |
/*
|
|
484 |
* Place pointers to each valid proc structure in pref[].
|
|
485 |
* Process slots that are actually in use have a non-zero
|
|
486 |
* status field. Processes with P_SYSTEM set are system
|
|
487 |
* processes---these get ignored unless show_sysprocs is set.
|
|
488 |
*/
|
|
489 |
if ((show_threads && (LP(pp, pid) == -1)) ||
|
|
490 |
(show_system || ((PP(pp, flags) & P_SYSTEM) == 0))) {
|
|
491 |
total_procs++;
|
|
492 |
process_states[(unsigned char)PP(pp, stat)]++;
|
|
493 |
if ((show_threads && (LP(pp, pid) == -1)) ||
|
|
494 |
(show_idle || (LP(pp, pctcpu) != 0) ||
|
|
495 |
(LP(pp, stat) == LSRUN)) &&
|
|
496 |
(!show_uid || PP(pp, ruid) == (uid_t) sel->uid)) {
|
|
497 |
*prefp++ = pp;
|
|
498 |
active_procs++;
|
|
499 |
}
|
|
500 |
}
|
| 511 |
501 |
}
|
| 512 |
|
}
|
| 513 |
502 |
|
| 514 |
503 |
qsort((char *)pref, active_procs, sizeof(struct kinfo_proc *),
|
| 515 |
|
proc_compares[compare_index]);
|
|
504 |
proc_compares[compare_index]);
|
| 516 |
505 |
|
| 517 |
|
/* remember active and total counts */
|
| 518 |
|
si->p_total = total_procs;
|
| 519 |
|
si->p_active = pref_len = active_procs;
|
|
506 |
/* remember active and total counts */
|
|
507 |
si->p_total = total_procs;
|
|
508 |
si->p_active = pref_len = active_procs;
|
| 520 |
509 |
|
| 521 |
|
/* pass back a handle */
|
| 522 |
|
handle.next_proc = pref;
|
| 523 |
|
handle.remaining = active_procs;
|
| 524 |
|
return((caddr_t)&handle);
|
|
510 |
/* pass back a handle */
|
|
511 |
handle.next_proc = pref;
|
|
512 |
handle.remaining = active_procs;
|
|
513 |
return ((caddr_t) & handle);
|
| 525 |
514 |
}
|
| 526 |
515 |
|
| 527 |
|
char fmt[128]; /* static area where result is built */
|
|
516 |
char fmt[128]; /* static area where result is built */
|
| 528 |
517 |
|
| 529 |
518 |
char *
|
| 530 |
|
format_next_process(caddr_t xhandle, char *(*get_userid)(int))
|
|
519 |
format_next_process(caddr_t xhandle, char *(*get_userid) (int))
|
| 531 |
520 |
{
|
| 532 |
|
struct kinfo_proc *pp;
|
| 533 |
|
long cputime;
|
| 534 |
|
double pct;
|
| 535 |
|
struct handle *hp;
|
| 536 |
|
char status[16];
|
| 537 |
|
char const *wrapper;
|
| 538 |
|
int state;
|
| 539 |
|
int xnice;
|
| 540 |
|
|
| 541 |
|
/* find and remember the next proc structure */
|
| 542 |
|
hp = (struct handle *)xhandle;
|
| 543 |
|
pp = *(hp->next_proc++);
|
| 544 |
|
hp->remaining--;
|
| 545 |
|
|
| 546 |
|
/* set the wrapper for the process/thread name */
|
| 547 |
|
if ((PP(pp, flags) & P_SWAPPEDOUT))
|
| 548 |
|
wrapper = "[]"; /* swapped process [pname] */
|
| 549 |
|
else if (((PP(pp, flags) & P_SYSTEM) != 0) && (LP(pp, pid) > 0))
|
| 550 |
|
wrapper = "()"; /* system process (pname) */
|
| 551 |
|
else if (show_threads && (LP(pp, pid) == -1))
|
| 552 |
|
wrapper = "<>"; /* pure kernel threads <thread> */
|
| 553 |
|
else
|
| 554 |
|
wrapper = NULL;
|
| 555 |
|
|
| 556 |
|
/* get the process's command name */
|
| 557 |
|
if (wrapper != NULL) {
|
| 558 |
|
char *comm = PP(pp, comm);
|
|
521 |
struct kinfo_proc *pp;
|
|
522 |
long cputime;
|
|
523 |
double pct;
|
|
524 |
struct handle *hp;
|
|
525 |
char status[16];
|
|
526 |
char const *wrapper;
|
|
527 |
int state;
|
|
528 |
int xnice;
|
|
529 |
|
|
530 |
/* find and remember the next proc structure */
|
|
531 |
hp = (struct handle *)xhandle;
|
|
532 |
pp = *(hp->next_proc++);
|
|
533 |
hp->remaining--;
|
|
534 |
|
|
535 |
/* set the wrapper for the process/thread name */
|
|
536 |
if ((PP(pp, flags) & P_SWAPPEDOUT))
|
|
537 |
wrapper = "[]"; /* swapped process [pname] */
|
|
538 |
else if (((PP(pp, flags) & P_SYSTEM) != 0) && (LP(pp, pid) > 0))
|
|
539 |
wrapper = "()"; /* system process (pname) */
|
|
540 |
else if (show_threads && (LP(pp, pid) == -1))
|
|
541 |
wrapper = "<>"; /* pure kernel threads <thread> */
|
|
542 |
else
|
|
543 |
wrapper = NULL;
|
|
544 |
|
|
545 |
/* get the process's command name */
|
|
546 |
if (wrapper != NULL) {
|
|
547 |
char *comm = PP(pp, comm);
|
| 559 |
548 |
#define COMSIZ sizeof(PP(pp, comm))
|
| 560 |
|
char buf[COMSIZ];
|
| 561 |
|
(void) strncpy(buf, comm, COMSIZ);
|
| 562 |
|
comm[0] = wrapper[0];
|
| 563 |
|
(void) strncpy(&comm[1], buf, COMSIZ - 2);
|
| 564 |
|
comm[COMSIZ - 2] = '\0';
|
| 565 |
|
(void) strncat(comm, &wrapper[1], COMSIZ - 1);
|
| 566 |
|
comm[COMSIZ - 1] = '\0';
|
| 567 |
|
}
|
| 568 |
|
|
| 569 |
|
/*
|
| 570 |
|
* Convert the process's runtime from microseconds to seconds. This
|
| 571 |
|
* time includes the interrupt time although that is not wanted here.
|
| 572 |
|
* ps(1) is similarly sloppy.
|
| 573 |
|
*/
|
| 574 |
|
cputime = (LP(pp, uticks) + LP(pp, sticks)) / 1000000;
|
| 575 |
|
|
| 576 |
|
/* calculate the base for cpu percentages */
|
| 577 |
|
pct = pctdouble(LP(pp, pctcpu));
|
| 578 |
|
|
| 579 |
|
/* generate "STATE" field */
|
| 580 |
|
switch (state = LP(pp, stat)) {
|
|
549 |
char buf[COMSIZ];
|
|
550 |
(void)strncpy(buf, comm, COMSIZ);
|
|
551 |
comm[0] = wrapper[0];
|
|
552 |
(void)strncpy(&comm[1], buf, COMSIZ - 2);
|
|
553 |
comm[COMSIZ - 2] = '\0';
|
|
554 |
(void)strncat(comm, &wrapper[1], COMSIZ - 1);
|
|
555 |
comm[COMSIZ - 1] = '\0';
|
|
556 |
}
|
|
557 |
/*
|
|
558 |
* Convert the process's runtime from microseconds to seconds. This
|
|
559 |
* time includes the interrupt time although that is not wanted here.
|
|
560 |
* ps(1) is similarly sloppy.
|
|
561 |
*/
|
|
562 |
cputime = (LP(pp, uticks) + LP(pp, sticks)) / 1000000;
|
|
563 |
|
|
564 |
/* calculate the base for cpu percentages */
|
|
565 |
pct = pctdouble(LP(pp, pctcpu));
|
|
566 |
|
|
567 |
/* generate "STATE" field */
|
|
568 |
switch (state = LP(pp, stat)) {
|
| 581 |
569 |
case LSRUN:
|
| 582 |
|
if (smpmode && LP(pp, tdflags) & TDF_RUNNING)
|
| 583 |
|
sprintf(status, "CPU%d", LP(pp, cpuid));
|
| 584 |
|
else
|
| 585 |
|
strcpy(status, "RUN");
|
| 586 |
|
break;
|
|
570 |
if (smpmode && LP(pp, tdflags) & TDF_RUNNING)
|
|
571 |
sprintf(status, "CPU%d", LP(pp, cpuid));
|
|
572 |
else
|
|
573 |
strcpy(status, "RUN");
|
|
574 |
break;
|
| 587 |
575 |
case LSSLEEP:
|
| 588 |
|
if (LP(pp, wmesg) != NULL) {
|
| 589 |
|
sprintf(status, "%.6s", LP(pp, wmesg));
|
|
576 |
if (LP(pp, wmesg) != NULL) {
|
|
577 |
sprintf(status, "%.6s", LP(pp, wmesg));
|
|
578 |
break;
|
|
579 |
}
|
|
580 |
/* fall through */
|
|
581 |
default:
|
|
582 |
|
|
583 |
if (state >= 0 &&
|
|
584 |
(unsigned)state < sizeof(state_abbrev) / sizeof(*state_abbrev))
|
|
585 |
sprintf(status, "%.6s", state_abbrev[(unsigned char)state]);
|
|
586 |
else
|
|
587 |
sprintf(status, "?%5d", state);
|
|
588 |
break;
|
|
589 |
}
|
|
590 |
|
|
591 |
if (PP(pp, stat) == SZOMB)
|
|
592 |
strcpy(status, "ZOMB");
|
|
593 |
|
|
594 |
/*
|
|
595 |
* idle time 0 - 31 -> nice value +21 - +52 normal time -> nice
|
|
596 |
* value -20 - +20 real time 0 - 31 -> nice value -52 - -21 thread
|
|
597 |
* 0 - 31 -> nice value -53 -
|
|
598 |
*/
|
|
599 |
switch (LP(pp, rtprio.type)) {
|
|
600 |
case RTP_PRIO_REALTIME:
|
|
601 |
xnice = PRIO_MIN - 1 - RTP_PRIO_MAX + LP(pp, rtprio.prio);
|
|
602 |
break;
|
|
603 |
case RTP_PRIO_IDLE:
|
|
604 |
xnice = PRIO_MAX + 1 + LP(pp, rtprio.prio);
|
|
605 |
break;
|
|
606 |
case RTP_PRIO_THREAD:
|
|
607 |
xnice = PRIO_MIN - 1 - RTP_PRIO_MAX - LP(pp, rtprio.prio);
|
| 590 |
608 |
break;
|
| 591 |
|
}
|
| 592 |
|
/* fall through */
|
| 593 |
609 |
default:
|
|
610 |
xnice = PP(pp, nice);
|
|
611 |
break;
|
|
612 |
}
|
| 594 |
613 |
|
| 595 |
|
if (state >= 0 &&
|
| 596 |
|
(unsigned)state < sizeof(state_abbrev) / sizeof(*state_abbrev))
|
| 597 |
|
sprintf(status, "%.6s", state_abbrev[(unsigned char) state]);
|
| 598 |
|
else
|
| 599 |
|
sprintf(status, "?%5d", state);
|
| 600 |
|
break;
|
| 601 |
|
}
|
| 602 |
|
|
| 603 |
|
if (PP(pp, stat) == SZOMB)
|
| 604 |
|
strcpy(status, "ZOMB");
|
| 605 |
|
|
| 606 |
|
/*
|
| 607 |
|
* idle time 0 - 31 -> nice value +21 - +52
|
| 608 |
|
* normal time -> nice value -20 - +20
|
| 609 |
|
* real time 0 - 31 -> nice value -52 - -21
|
| 610 |
|
* thread 0 - 31 -> nice value -53 -
|
| 611 |
|
*/
|
| 612 |
|
switch(LP(pp, rtprio.type)) {
|
| 613 |
|
case RTP_PRIO_REALTIME:
|
| 614 |
|
xnice = PRIO_MIN - 1 - RTP_PRIO_MAX + LP(pp, rtprio.prio);
|
| 615 |
|
break;
|
| 616 |
|
case RTP_PRIO_IDLE:
|
| 617 |
|
xnice = PRIO_MAX + 1 + LP(pp, rtprio.prio);
|
| 618 |
|
break;
|
| 619 |
|
case RTP_PRIO_THREAD:
|
| 620 |
|
xnice = PRIO_MIN - 1 - RTP_PRIO_MAX - LP(pp, rtprio.prio);
|
| 621 |
|
break;
|
| 622 |
|
default:
|
| 623 |
|
xnice = PP(pp, nice);
|
| 624 |
|
break;
|
| 625 |
|
}
|
| 626 |
|
|
| 627 |
|
/* format this entry */
|
| 628 |
|
snprintf(fmt, sizeof(fmt),
|
|
614 |
/* format this entry */
|
|
615 |
snprintf(fmt, sizeof(fmt),
|
| 629 |
616 |
smpmode ? smp_Proc_format : up_Proc_format,
|
| 630 |
617 |
(int)PP(pp, pid),
|
| 631 |
618 |
namelength, namelength,
|
| 632 |
619 |
get_userid(PP(pp, ruid)),
|
| 633 |
620 |
(int)((show_threads && (LP(pp, pid) == -1)) ?
|
| 634 |
|
LP(pp, tdprio) : LP(pp, prio)),
|
|
621 |
LP(pp, tdprio) : LP(pp, prio)),
|
| 635 |
622 |
(int)xnice,
|
| 636 |
623 |
format_k(PROCSIZE(pp)),
|
| 637 |
624 |
format_k(pagetok(VP(pp, rssize))),
|
| ... | ... | |
| 643 |
630 |
cmdlength,
|
| 644 |
631 |
printable(PP(pp, comm)));
|
| 645 |
632 |
|
| 646 |
|
/* return the result */
|
| 647 |
|
return(fmt);
|
|
633 |
/* return the result */
|
|
634 |
return (fmt);
|
| 648 |
635 |
}
|
| 649 |
636 |
|
| 650 |
|
#if 0
|
| 651 |
|
/*
|
| 652 |
|
* check_nlist(nlst) - checks the nlist to see if any symbols were not
|
| 653 |
|
* found. For every symbol that was not found, a one-line
|
| 654 |
|
* message is printed to stderr. The routine returns the
|
| 655 |
|
* number of symbols NOT found.
|
| 656 |
|
*/
|
| 657 |
|
static int
|
| 658 |
|
check_nlist(struct nlist *nlst)
|
| 659 |
|
{
|
| 660 |
|
int i;
|
| 661 |
|
|
| 662 |
|
/* check to see if we got ALL the symbols we requested */
|
| 663 |
|
/* this will write one line to stderr for every symbol not found */
|
| 664 |
|
|
| 665 |
|
i = 0;
|
| 666 |
|
while (nlst->n_name != NULL)
|
| 667 |
|
{
|
| 668 |
|
if (nlst->n_type == 0)
|
| 669 |
|
{
|
| 670 |
|
/* this one wasn't found */
|
| 671 |
|
(void) fprintf(stderr, "kernel: no symbol named `%s'\n",
|
| 672 |
|
nlst->n_name);
|
| 673 |
|
i = 1;
|
| 674 |
|
}
|
| 675 |
|
nlst++;
|
| 676 |
|
}
|
| 677 |
|
|
| 678 |
|
return(i);
|
| 679 |
|
}
|
| 680 |
|
#endif
|
| 681 |
|
|
| 682 |
637 |
/* comparison routines for qsort */
|
| 683 |
638 |
|
| 684 |
639 |
/*
|
| 685 |
|
* proc_compare - comparison function for "qsort"
|
| 686 |
|
* Compares the resource consumption of two processes using five
|
| 687 |
|
* distinct keys. The keys (in descending order of importance) are:
|
| 688 |
|
* percent cpu, cpu ticks, state, resident set size, total virtual
|
| 689 |
|
* memory usage. The process states are ordered as follows (from least
|
| 690 |
|
* to most important): WAIT, zombie, sleep, stop, start, run. The
|
| 691 |
|
* array declaration below maps a process state index into a number
|
| 692 |
|
* that reflects this ordering.
|
|
640 |
* proc_compare - comparison function for "qsort" Compares the resource
|
|
641 |
* consumption of two processes using five distinct keys. The keys (in
|
|
642 |
* descending order of importance) are: percent cpu, cpu ticks, state,
|
|
643 |
* resident set size, total virtual memory usage. The process states are
|
|
644 |
* ordered as follows (from least to most important): WAIT, zombie, sleep,
|
|
645 |
* stop, start, run. The array declaration below maps a process state index
|
|
646 |
* into a number that reflects this ordering.
|
| 693 |
647 |
*/
|
| 694 |
648 |
|
| 695 |
649 |
static unsigned char sorted_state[] =
|
| 696 |
650 |
{
|
| 697 |
|
0, /* not used */
|
| 698 |
|
3, /* sleep */
|
| 699 |
|
1, /* ABANDONED (WAIT) */
|
| 700 |
|
6, /* run */
|
| 701 |
|
5, /* start */
|
| 702 |
|
2, /* zombie */
|
| 703 |
|
4 /* stop */
|
|
651 |
0, /* not used */
|
|
652 |
3, /* sleep */
|
|
653 |
1, /* ABANDONED (WAIT) */
|
|
654 |
6, /* run */
|
|
655 |
5, /* start */
|
|
656 |
2, /* zombie */
|
|
657 |
4 /* stop */
|
| 704 |
658 |
};
|
| 705 |
|
|
|
659 |
|
| 706 |
660 |
|
| 707 |
661 |
#define ORDERKEY_PCTCPU \
|
| 708 |
662 |
if (lresult = (long) LP(p2, pctcpu) - (long) LP(p1, pctcpu), \
|
| ... | ... | |
| 728 |
682 |
if ((result = LP(p2, tdprio) - LP(p1, tdprio)) == 0)
|
| 729 |
683 |
|
| 730 |
684 |
#define ORDERKEY_RSSIZE \
|
| 731 |
|
if ((result = VP(p2, rssize) - VP(p1, rssize)) == 0)
|
|
685 |
if ((result = VP(p2, rssize) - VP(p1, rssize)) == 0)
|
| 732 |
686 |
|
| 733 |
687 |
#define ORDERKEY_MEM \
|
| 734 |
688 |
if ( (result = PROCSIZE(p2) - PROCSIZE(p1)) == 0 )
|
| ... | ... | |
| 738 |
692 |
int
|
| 739 |
693 |
proc_compare(const void *arg1, const void *arg2)
|
| 740 |
694 |
{
|
| 741 |
|
const struct proc *const*pp1 = arg1;
|
| 742 |
|
const struct proc *const*pp2 = arg2;
|
| 743 |
|
const struct kinfo_proc *p1;
|
| 744 |
|
const struct kinfo_proc *p2;
|
| 745 |
|
int result;
|
| 746 |
|
pctcpu lresult;
|
| 747 |
|
|
| 748 |
|
/* remove one level of indirection */
|
| 749 |
|
p1 = *(const struct kinfo_proc *const *) pp1;
|
| 750 |
|
p2 = *(const struct kinfo_proc *const *) pp2;
|
| 751 |
|
|
| 752 |
|
ORDERKEY_PCTCPU
|
| 753 |
|
ORDERKEY_CPTICKS
|
| 754 |
|
ORDERKEY_STATE
|
| 755 |
|
ORDERKEY_PRIO
|
| 756 |
|
ORDERKEY_RSSIZE
|
| 757 |
|
ORDERKEY_MEM
|
| 758 |
|
{}
|
| 759 |
|
|
| 760 |
|
return(result);
|
|
695 |
const struct proc *const *pp1 = arg1;
|
|
696 |
const struct proc *const *pp2 = arg2;
|
|
697 |
const struct kinfo_proc *p1;
|
|
698 |
const struct kinfo_proc *p2;
|
|
699 |
int result;
|
|
700 |
pctcpu lresult;
|
|
701 |
|
|
702 |
/* remove one level of indirection */
|
|
703 |
p1 = *(const struct kinfo_proc *const *)pp1;
|
|
704 |
p2 = *(const struct kinfo_proc *const *)pp2;
|
|
705 |
|
|
706 |
ORDERKEY_PCTCPU
|
|
707 |
ORDERKEY_CPTICKS
|
|
708 |
ORDERKEY_STATE
|
|
709 |
ORDERKEY_PRIO
|
|
710 |
ORDERKEY_RSSIZE
|
|
711 |
ORDERKEY_MEM
|
|
712 |
{
|
|
713 |
}
|
|
714 |
|
|
715 |
return (result);
|
| 761 |
716 |
}
|
| 762 |
717 |
|
| 763 |
718 |
/* compare_size - the comparison function for sorting by total memory usage */
|
| ... | ... | |
| 765 |
720 |
int
|
| 766 |
721 |
compare_size(const void *arg1, const void *arg2)
|
| 767 |
722 |
{
|
| 768 |
|
struct proc *const *pp1 = arg1;
|
| 769 |
|
struct proc *const *pp2 = arg2;
|
| 770 |
|
struct kinfo_proc *p1;
|
| 771 |
|
struct kinfo_proc *p2;
|
| 772 |
|
int result;
|
| 773 |
|
pctcpu lresult;
|
| 774 |
|
|
| 775 |
|
/* remove one level of indirection */
|
| 776 |
|
p1 = *(struct kinfo_proc *const*) pp1;
|
| 777 |
|
p2 = *(struct kinfo_proc *const*) pp2;
|
| 778 |
|
|
| 779 |
|
ORDERKEY_MEM
|
| 780 |
|
ORDERKEY_RSSIZE
|
| 781 |
|
ORDERKEY_PCTCPU
|
| 782 |
|
ORDERKEY_CPTICKS
|
| 783 |
|
ORDERKEY_STATE
|
| 784 |
|
ORDERKEY_PRIO
|
| 785 |
|
{}
|
| 786 |
|
|
| 787 |
|
return(result);
|
|
723 |
struct proc *const *pp1 = arg1;
|
|
724 |
struct proc *const *pp2 = arg2;
|
|
725 |
struct kinfo_proc *p1;
|
|
726 |
struct kinfo_proc *p2;
|
|
727 |
int result;
|
|
728 |
pctcpu lresult;
|
|
729 |
|
|
730 |
/* remove one level of indirection */
|
|
731 |
p1 = *(struct kinfo_proc *const *)pp1;
|
|
732 |
p2 = *(struct kinfo_proc *const *)pp2;
|
|
733 |
|
|
734 |
ORDERKEY_MEM
|
|
735 |
ORDERKEY_RSSIZE
|
|
736 |
ORDERKEY_PCTCPU
|
|
737 |
ORDERKEY_CPTICKS
|
|
738 |
ORDERKEY_STATE
|
|
739 |
ORDERKEY_PRIO
|
|
740 |
{
|
|
741 |
}
|
|
742 |
|
|
743 |
return (result);
|
| 788 |
744 |
}
|
| 789 |
745 |
|
| 790 |
746 |
/* compare_res - the comparison function for sorting by resident set size */
|
| ... | ... | |
| 792 |
748 |
int
|
| 793 |
749 |
compare_res(const void *arg1, const void *arg2)
|
| 794 |
750 |
{
|
| 795 |
|
struct proc *const *pp1 = arg1;
|
| 796 |
|
struct proc *const *pp2 = arg2;
|
| 797 |
|
struct kinfo_proc *p1;
|
| 798 |
|
struct kinfo_proc *p2;
|
| 799 |
|
int result;
|
| 800 |
|
pctcpu lresult;
|
| 801 |
|
|
| 802 |
|
/* remove one level of indirection */
|
| 803 |
|
p1 = *(struct kinfo_proc *const*) pp1;
|
| 804 |
|
p2 = *(struct kinfo_proc *const*) pp2;
|
| 805 |
|
|
| 806 |
|
ORDERKEY_RSSIZE
|
| 807 |
|
ORDERKEY_MEM
|
| 808 |
|
ORDERKEY_PCTCPU
|
| 809 |
|
ORDERKEY_CPTICKS
|
| 810 |
|
ORDERKEY_STATE
|
| 811 |
|
ORDERKEY_PRIO
|
| 812 |
|
{}
|
| 813 |
|
|
| 814 |
|
return(result);
|
|
751 |
struct proc *const *pp1 = arg1;
|
|
752 |
struct proc *const *pp2 = arg2;
|
|
753 |
struct kinfo_proc *p1;
|
|
754 |
struct kinfo_proc *p2;
|
|
755 |
int result;
|
|
756 |
pctcpu lresult;
|
|
757 |
|
|
758 |
/* remove one level of indirection */
|
|
759 |
p1 = *(struct kinfo_proc *const *)pp1;
|
|
760 |
p2 = *(struct kinfo_proc *const *)pp2;
|
|
761 |
|
|
762 |
ORDERKEY_RSSIZE
|
|
763 |
ORDERKEY_MEM
|
|
764 |
ORDERKEY_PCTCPU
|
|
765 |
ORDERKEY_CPTICKS
|
|
766 |
ORDERKEY_STATE
|
|
767 |
ORDERKEY_PRIO
|
|
768 |
{
|
|
769 |
}
|
|
770 |
|
|
771 |
return (result);
|
| 815 |
772 |
}
|
| 816 |
773 |
|
| 817 |
774 |
/* compare_time - the comparison function for sorting by total cpu time */
|
| ... | ... | |
| 819 |
776 |
int
|
| 820 |
777 |
compare_time(const void *arg1, const void *arg2)
|
| 821 |
778 |
{
|
| 822 |
|
struct proc *const *pp1 = arg1;
|
| 823 |
|
struct proc *const *pp2 = arg2;
|
| 824 |
|
const struct kinfo_proc *p1;
|
| 825 |
|
const struct kinfo_proc *p2;
|
| 826 |
|
int result;
|
| 827 |
|
pctcpu lresult;
|
| 828 |
|
|
| 829 |
|
/* remove one level of indirection */
|
| 830 |
|
p1 = *(struct kinfo_proc *const*) pp1;
|
| 831 |
|
p2 = *(struct kinfo_proc *const*) pp2;
|
| 832 |
|
|
| 833 |
|
ORDERKEY_CPTICKS
|
| 834 |
|
ORDERKEY_PCTCPU
|
| 835 |
|
ORDERKEY_KTHREADS
|
| 836 |
|
ORDERKEY_KTHREADS_PRIO
|
| 837 |
|
ORDERKEY_STATE
|
| 838 |
|
ORDERKEY_PRIO
|
| 839 |
|
ORDERKEY_RSSIZE
|
| 840 |
|
ORDERKEY_MEM
|
| 841 |
|
{}
|
| 842 |
|
|
| 843 |
|
return(result);
|
| 844 |
|
}
|
| 845 |
|
|
|
779 |
struct proc *const *pp1 = arg1;
|
|
780 |
struct proc *const *pp2 = arg2;
|
|
781 |
const struct kinfo_proc *p1;
|
|
782 |
const struct kinfo_proc *p2;
|
|
783 |
int result;
|
|
784 |
pctcpu lresult;
|
|
785 |
|
|
786 |
/* remove one level of indirection */
|
|
787 |
p1 = *(struct kinfo_proc *const *)pp1;
|
|
788 |
p2 = *(struct kinfo_proc *const *)pp2;
|
|
789 |
|
|
790 |
ORDERKEY_CPTICKS
|
|
791 |
ORDERKEY_PCTCPU
|
|
792 |
ORDERKEY_KTHREADS
|
|
793 |
ORDERKEY_KTHREADS_PRIO
|
|
794 |
ORDERKEY_STATE
|
|
795 |
ORDERKEY_PRIO
|
|
796 |
ORDERKEY_RSSIZE
|
|
797 |
ORDERKEY_MEM
|
|
798 |
{}
|
|
799 |
|
|
800 |
return (result);
|
|
801 |
}
|
|
802 |
|
| 846 |
803 |
/* compare_prio - the comparison function for sorting by cpu percentage */
|
| 847 |
804 |
|
| 848 |
805 |
int
|
| 849 |
806 |
compare_prio(const void *arg1, const void *arg2)
|
| 850 |
807 |
{
|
| 851 |
|
struct proc *const *pp1 = arg1;
|
| 852 |
|
struct proc *const *pp2 = arg2;
|
| 853 |
|
const struct kinfo_proc *p1;
|
| 854 |
|
const struct kinfo_proc *p2;
|
| 855 |
|
int result;
|
| 856 |
|
pctcpu lresult;
|
| 857 |
|
|
| 858 |
|
/* remove one level of indirection */
|
| 859 |
|
p1 = *(struct kinfo_proc *const*) pp1;
|
| 860 |
|
p2 = *(struct kinfo_proc *const*) pp2;
|
| 861 |
|
|
| 862 |
|
ORDERKEY_KTHREADS
|
| 863 |
|
ORDERKEY_KTHREADS_PRIO
|
| 864 |
|
ORDERKEY_PRIO
|
| 865 |
|
ORDERKEY_CPTICKS
|
| 866 |
|
ORDERKEY_PCTCPU
|
| 867 |
|
ORDERKEY_STATE
|
| 868 |
|
ORDERKEY_RSSIZE
|
| 869 |
|
ORDERKEY_MEM
|
| 870 |
|
{}
|
| 871 |
|
|
| 872 |
|
return(result);
|
|
808 |
struct proc *const *pp1 = arg1;
|
|
809 |
struct proc *const *pp2 = arg2;
|
|
810 |
const struct kinfo_proc *p1;
|
|
811 |
const struct kinfo_proc *p2;
|
|
812 |
int result;
|
|
813 |
pctcpu lresult;
|
|
814 |
|
|
815 |
/* remove one level of indirection */
|
|
816 |
p1 = *(struct kinfo_proc *const *)pp1;
|
|
817 |
p2 = *(struct kinfo_proc *const *)pp2;
|
|
818 |
|
|
819 |
ORDERKEY_KTHREADS
|
|
820 |
ORDERKEY_KTHREADS_PRIO
|
|
821 |
ORDERKEY_PRIO
|
|
822 |
ORDERKEY_CPTICKS
|
|
823 |
ORDERKEY_PCTCPU
|
|
824 |
ORDERKEY_STATE
|
|
825 |
ORDERKEY_RSSIZE
|
|
826 |
ORDERKEY_MEM
|
|
827 |
{}
|
|
828 |
|
|
829 |
return (result);
|
| 873 |
830 |
}
|
| 874 |
831 |
|
| 875 |
832 |
int
|
| 876 |
833 |
compare_thr(const void *arg1, const void *arg2)
|
| 877 |
834 |
{
|
| 878 |
|
struct proc *const *pp1 = arg1;
|
| 879 |
|
struct proc *const *pp2 = arg2;
|
| 880 |
|
const struct kinfo_proc *p1;
|
| 881 |
|
const struct kinfo_proc *p2;
|
| 882 |
|
int result;
|
| 883 |
|
pctcpu lresult;
|
| 884 |
|
|
| 885 |
|
/* remove one level of indirection */
|
| 886 |
|
p1 = *(struct kinfo_proc *const*) pp1;
|
| 887 |
|
p2 = *(struct kinfo_proc *const*) pp2;
|
| 888 |
|
|
| 889 |
|
ORDERKEY_KTHREADS
|
| 890 |
|
ORDERKEY_KTHREADS_PRIO
|
| 891 |
|
ORDERKEY_CPTICKS
|
| 892 |
|
ORDERKEY_PCTCPU
|
| 893 |
|
ORDERKEY_STATE
|
| 894 |
|
ORDERKEY_RSSIZE
|
| 895 |
|
ORDERKEY_MEM
|
| 896 |
|
{}
|
| 897 |
|
|
| 898 |
|
return(result);
|
|
835 |
struct proc *const *pp1 = arg1;
|
|
836 |
struct proc *const *pp2 = arg2;
|
|
837 |
const struct kinfo_proc *p1;
|
|
838 |
const struct kinfo_proc *p2;
|
|
839 |
int result;
|
|
840 |
pctcpu lresult;
|
|
841 |
|
|
842 |
/* remove one level of indirection */
|
|
843 |
p1 = *(struct kinfo_proc *const *)pp1;
|
|
844 |
p2 = *(struct kinfo_proc *const *)pp2;
|
|
845 |
|
|
846 |
ORDERKEY_KTHREADS
|
|
847 |
ORDERKEY_KTHREADS_PRIO
|
|
848 |
ORDERKEY_CPTICKS
|
|
849 |
ORDERKEY_PCTCPU
|
|
850 |
ORDERKEY_STATE
|
|
851 |
ORDERKEY_RSSIZE
|
|
852 |
ORDERKEY_MEM
|
|
853 |
{}
|
|
854 |
|
|
855 |
return (result);
|
| 899 |
856 |
}
|
| 900 |
857 |
|
| 901 |
858 |
/*
|
| 902 |
|
* proc_owner(pid) - returns the uid that owns process "pid", or -1 if
|
| 903 |
|
* the process does not exist.
|
| 904 |
|
* It is EXTREMLY IMPORTANT that this function work correctly.
|
| 905 |
|
* If top runs setuid root (as in SVR4), then this function
|
| 906 |
|
* is the only thing that stands in the way of a serious
|
| 907 |
|
* security problem. It validates requests for the "kill"
|
| 908 |
|
* and "renice" commands.
|
|
859 |
* proc_owner(pid) - returns the uid that owns process "pid", or -1 if the
|
|
860 |
* process does not exist. It is EXTREMLY IMPORTANT that this function work
|
|
861 |
* correctly. If top runs setuid root (as in SVR4), then this function is the
|
|
862 |
* only thing that stands in the way of a serious security problem. It
|
|
863 |
* validates requests for the "kill" and "renice" commands.
|
| 909 |
864 |
*/
|
| 910 |
865 |
|
| 911 |
866 |
int
|
| 912 |
867 |
proc_owner(int pid)
|
| 913 |
868 |
{
|
| 914 |
|
int xcnt;
|
| 915 |
|
struct kinfo_proc **prefp;
|
| 916 |
|
struct kinfo_proc *pp;
|
| 917 |
|
|
| 918 |
|
prefp = pref;
|
| 919 |
|
xcnt = pref_len;
|
| 920 |
|
while (--xcnt >= 0)
|
| 921 |
|
{
|
| 922 |
|
pp = *prefp++;
|
| 923 |
|
if (PP(pp, pid) == (pid_t)pid)
|
| 924 |
|
{
|
| 925 |
|
return((int)PP(pp, ruid));
|
|
869 |
int xcnt;
|
|
870 |
struct kinfo_proc **prefp;
|
|
871 |
struct kinfo_proc *pp;
|
|
872 |
|
|
873 |
prefp = pref;
|
|
874 |
xcnt = pref_len;
|
|
875 |
while (--xcnt >= 0) {
|
|
876 |
pp = *prefp++;
|
|
877 |
if (PP(pp, pid) == (pid_t) pid) {
|
|
878 |
return ((int)PP(pp, ruid));
|
|
879 |
}
|
| 926 |
880 |
}
|
| 927 |
|
}
|
| 928 |
|
return(-1);
|
|
881 |
return (-1);
|
| 929 |
882 |
}
|
| 930 |
883 |
|
| 931 |
884 |
|
| 932 |
885 |
/*
|
| 933 |
|
* swapmode is based on a program called swapinfo written
|
| 934 |
|
* by Kevin Lahey <kml@rokkaku.atl.ga.us>.
|
|
886 |
* swapmode is based on a program called swapinfo written by Kevin Lahey
|
|
887 |
* <kml@rokkaku.atl.ga.us>.
|
| 935 |
888 |
*/
|
| 936 |
889 |
int
|
| 937 |
890 |
swapmode(int *retavail, int *retfree)
|
| ... | ... | |
| 947 |
900 |
|
| 948 |
901 |
n = kvm_getswapinfo(kd, swapary, 1, 0);
|
| 949 |
902 |
if (n < 0 || swapary[0].ksw_total == 0)
|
| 950 |
|
return(0);
|
|
903 |
return (0);
|
| 951 |
904 |
|
| 952 |
905 |
*retavail = CONVERT(swapary[0].ksw_total);
|
| 953 |
906 |
*retfree = CONVERT(swapary[0].ksw_total - swapary[0].ksw_used);
|
| 954 |
907 |
|
| 955 |
908 |
n = (int)((double)swapary[0].ksw_used * 100.0 /
|
| 956 |
909 |
(double)swapary[0].ksw_total);
|
| 957 |
|
return(n);
|
|
910 |
return (n);
|
| 958 |
911 |
}
|