Print this page
8158 Want named threads API
9857 proc manpages should have LIBRARY section
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/prstat/prstat.c
+++ new/usr/src/cmd/prstat/prstat.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2013 Gary Mills
24 24 *
25 25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
26 26 * Use is subject to license terms.
27 27 *
28 28 * Portions Copyright 2009 Chad Mynhier
29 + * Copyright 2018 Joyent, Inc. All rights reserved.
29 30 */
30 31
31 32 #include <sys/types.h>
32 33 #include <sys/resource.h>
33 34 #include <sys/loadavg.h>
34 35 #include <sys/time.h>
35 36 #include <sys/pset.h>
36 37 #include <sys/vm_usage.h>
37 38 #include <zone.h>
38 39 #include <libzonecfg.h>
39 40
40 41 #include <stdio.h>
41 42 #include <stdlib.h>
42 43 #include <unistd.h>
43 44 #include <dirent.h>
44 45 #include <string.h>
45 46 #include <errno.h>
46 47 #include <poll.h>
47 48 #include <ctype.h>
48 49 #include <fcntl.h>
49 50 #include <limits.h>
50 51 #include <signal.h>
51 52 #include <time.h>
52 53 #include <project.h>
53 54
54 55 #include <langinfo.h>
55 56 #include <libintl.h>
56 57 #include <locale.h>
57 58
58 59 #include "prstat.h"
59 60 #include "prutil.h"
60 61 #include "prtable.h"
61 62 #include "prsort.h"
62 63 #include "prfile.h"
63 64
64 65 /*
65 66 * x86 <sys/regs.h> ERR conflicts with <curses.h> ERR. For the purposes
66 67 * of this file, we care about the curses.h ERR so include that last.
67 68 */
68 69
69 70 #if defined(ERR)
70 71 #undef ERR
71 72 #endif
72 73
73 74 #ifndef TEXT_DOMAIN /* should be defined by cc -D */
74 75 #define TEXT_DOMAIN "SYS_TEST" /* use this only if it wasn't */
75 76 #endif
76 77
77 78 #include <curses.h>
78 79 #include <term.h>
↓ open down ↓ |
40 lines elided |
↑ open up ↑ |
79 80
80 81 #define LOGIN_WIDTH 8
81 82 #define ZONE_WIDTH 28
82 83 #define PROJECT_WIDTH 28
83 84
84 85 #define PSINFO_HEADER_PROC \
85 86 " PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/NLWP "
86 87 #define PSINFO_HEADER_PROC_LGRP \
87 88 " PID USERNAME SIZE RSS STATE PRI NICE TIME CPU LGRP PROCESS/NLWP "
88 89 #define PSINFO_HEADER_LWP \
89 -" PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/LWPID "
90 +" PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/LWP "
90 91 #define PSINFO_HEADER_LWP_LGRP \
91 -" PID USERNAME SIZE RSS STATE PRI NICE TIME CPU LGRP PROCESS/LWPID "
92 +" PID USERNAME SIZE RSS STATE PRI NICE TIME CPU LGRP PROCESS/LWP "
92 93 #define USAGE_HEADER_PROC \
93 94 " PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/NLWP "
94 95 #define USAGE_HEADER_LWP \
95 -" PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/LWPID "
96 +" PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/LWP "
96 97 #define USER_HEADER_PROC \
97 98 " NPROC USERNAME SWAP RSS MEMORY TIME CPU "
98 99 #define USER_HEADER_LWP \
99 100 " NLWP USERNAME SWAP RSS MEMORY TIME CPU "
100 101 #define TASK_HEADER_PROC \
101 102 "TASKID NPROC SWAP RSS MEMORY TIME CPU PROJECT "
102 103 #define TASK_HEADER_LWP \
103 104 "TASKID NLWP SWAP RSS MEMORY TIME CPU PROJECT "
104 105 #define PROJECT_HEADER_PROC \
105 106 "PROJID NPROC SWAP RSS MEMORY TIME CPU PROJECT "
106 107 #define PROJECT_HEADER_LWP \
107 108 "PROJID NLWP SWAP RSS MEMORY TIME CPU PROJECT "
108 109 #define ZONE_HEADER_PROC \
109 110 "ZONEID NPROC SWAP RSS MEMORY TIME CPU ZONE "
110 111 #define ZONE_HEADER_LWP \
111 112 "ZONEID NLWP SWAP RSS MEMORY TIME CPU ZONE "
112 113 #define PSINFO_LINE \
113 -"%6d %-8s %5s %5s %-6s %3s %3s %9s %3.3s%% %-.16s/%d"
114 +"%6d %-8s %5s %5s %-6s %3s %3s %9s %3.3s%% %s"
114 115 #define PSINFO_LINE_LGRP \
115 -"%6d %-8s %5s %5s %-6s %3s %3s %9s %3.3s%% %4d %-.16s/%d"
116 +"%6d %-8s %5s %5s %-6s %3s %3s %9s %3.3s%% %4d %s"
116 117 #define USAGE_LINE \
117 118 "%6d %-8s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s "\
118 -"%3.3s %3.3s %-.12s/%d"
119 +"%3.3s %3.3s %s"
119 120 #define USER_LINE \
120 121 "%6d %-8s %5.5s %5.5s %3.3s%% %9s %3.3s%%"
121 122 #define TASK_LINE \
122 123 "%6d %8d %5s %5s %3.3s%% %9s %3.3s%% %28s"
123 124 #define PROJECT_LINE \
124 125 "%6d %8d %5s %5s %3.3s%% %9s %3.3s%% %28s"
125 126 #define ZONE_LINE \
126 127 "%6d %8d %5s %5s %3.3s%% %9s %3.3s%% %28s"
127 128
128 129 #define TOTAL_LINE \
129 130 "Total: %d processes, %d lwps, load averages: %3.2f, %3.2f, %3.2f"
130 131
131 132 /* global variables */
132 133
133 134 static char *t_ulon; /* termcap: start underline */
134 135 static char *t_uloff; /* termcap: end underline */
135 136 static char *t_up; /* termcap: cursor 1 line up */
136 137 static char *t_eol; /* termcap: clear end of line */
137 138 static char *t_smcup; /* termcap: cursor mvcap on */
138 139 static char *t_rmcup; /* termcap: cursor mvcap off */
139 140 static char *t_home; /* termcap: move cursor home */
140 141 static char *movecur = NULL; /* termcap: move up string */
141 142 static char *empty_string = "\0"; /* termcap: empty string */
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
142 143 static uint_t print_movecur = FALSE; /* print movecur or not */
143 144 static int is_curses_on = FALSE; /* current curses state */
144 145
145 146 static table_t pid_tbl = {0, 0, NULL}; /* selected processes */
146 147 static table_t cpu_tbl = {0, 0, NULL}; /* selected processors */
147 148 static table_t set_tbl = {0, 0, NULL}; /* selected processor sets */
148 149 static table_t prj_tbl = {0, 0, NULL}; /* selected projects */
149 150 static table_t tsk_tbl = {0, 0, NULL}; /* selected tasks */
150 151 static table_t lgr_tbl = {0, 0, NULL}; /* selected lgroups */
151 152 static zonetbl_t zone_tbl = {0, 0, NULL}; /* selected zones */
152 -static uidtbl_t euid_tbl = {0, 0, NULL}; /* selected effective users */
153 -static uidtbl_t ruid_tbl = {0, 0, NULL}; /* selected real users */
153 +static uidtbl_t euid_tbl = {0, 0, NULL}; /* selected effective users */
154 +static uidtbl_t ruid_tbl = {0, 0, NULL}; /* selected real users */
154 155
155 156 static uint_t total_procs; /* total number of procs */
156 157 static uint_t total_lwps; /* total number of lwps */
157 158 static float total_cpu; /* total cpu usage */
158 159 static float total_mem; /* total memory usage */
159 160
160 161 static list_t lwps; /* list of lwps/processes */
161 162 static list_t users; /* list of users */
162 163 static list_t tasks; /* list of tasks */
163 164 static list_t projects; /* list of projects */
164 165 static list_t zones; /* list of zones */
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
165 166 static list_t lgroups; /* list of lgroups */
166 167
167 168 static volatile uint_t sigwinch = 0;
168 169 static volatile uint_t sigtstp = 0;
169 170 static volatile uint_t sigterm = 0;
170 171
171 172 static long pagesize;
172 173
173 174 /* default settings */
174 175
175 -static optdesc_t opts = {
176 +optdesc_t opts = {
176 177 5, /* interval between updates, seconds */
177 178 15, /* number of lines in top part */
178 179 5, /* number of lines in bottom part */
179 180 -1, /* number of iterations; infinitely */
180 181 OPT_PSINFO | OPT_FULLSCREEN | OPT_USEHOME | OPT_TERMCAP,
181 182 -1 /* sort in decreasing order */
182 183 };
183 184
184 185 /*
185 186 * Print timestamp as decimal reprentation of time_t value (-d u was specified)
186 187 * or the standard date format (-d d was specified).
187 188 */
188 189 static void
189 190 print_timestamp(void)
190 191 {
191 192 time_t t = time(NULL);
192 193 static char *fmt = NULL;
193 194
194 195 /* We only need to retrieve this once per invocation */
195 196 if (fmt == NULL)
196 197 fmt = nl_langinfo(_DATE_FMT);
197 198
198 199 if (opts.o_outpmode & OPT_UDATE) {
199 200 (void) printf("%ld", t);
200 201 } else if (opts.o_outpmode & OPT_DDATE) {
201 202 char dstr[64];
202 203 int len;
203 204
204 205 len = strftime(dstr, sizeof (dstr), fmt, localtime(&t));
205 206 if (len > 0)
206 207 (void) printf("%s", dstr);
207 208 }
208 209 (void) putp(t_eol);
209 210 (void) putchar('\n');
210 211 }
211 212
212 213 static void
213 214 psetloadavg(long psetid, void *ptr)
214 215 {
215 216 double psetloadavg[3];
216 217 double *loadavg = ptr;
217 218
218 219 if (pset_getloadavg((psetid_t)psetid, psetloadavg, 3) != -1) {
219 220 *loadavg++ += psetloadavg[0];
220 221 *loadavg++ += psetloadavg[1];
221 222 *loadavg += psetloadavg[2];
222 223 }
223 224 }
224 225
225 226 /*
226 227 * Queries the memory virtual and rss size for each member of a list.
227 228 * This will override the values computed by /proc aggregation.
228 229 */
229 230 static void
230 231 list_getsize(list_t *list)
231 232 {
232 233 id_info_t *id;
233 234 vmusage_t *results, *next;
234 235 vmusage_t *match;
235 236 size_t nres = 0;
236 237 size_t i;
237 238 uint_t flags = 0;
238 239 int ret;
239 240 size_t physmem = sysconf(_SC_PHYS_PAGES) * pagesize;
240 241
241 242 /*
242 243 * Determine what swap/rss results to calculate. getvmusage() will
243 244 * prune results returned to non-global zones automatically, so
244 245 * there is no need to pass different flags when calling from a
245 246 * non-global zone.
246 247 *
247 248 * Currently list_getsize() is only called with a single flag. This
248 249 * is because -Z, -J, -T, and -a are mutually exclusive. Regardless
249 250 * of this, we handle multiple flags.
250 251 */
251 252 if (opts.o_outpmode & OPT_USERS) {
252 253 /*
253 254 * Gather rss for all users in all zones. Treat the same
254 255 * uid in different zones as the same user.
255 256 */
256 257 flags |= VMUSAGE_COL_RUSERS;
257 258
258 259 } else if (opts.o_outpmode & OPT_TASKS) {
259 260 /* Gather rss for all tasks in all zones */
260 261 flags |= VMUSAGE_ALL_TASKS;
261 262
262 263 } else if (opts.o_outpmode & OPT_PROJECTS) {
263 264 /*
264 265 * Gather rss for all projects in all zones. Treat the same
265 266 * projid in diffrent zones as the same project.
266 267 */
267 268 flags |= VMUSAGE_COL_PROJECTS;
268 269
269 270 } else if (opts.o_outpmode & OPT_ZONES) {
270 271 /* Gather rss for all zones */
271 272 flags |= VMUSAGE_ALL_ZONES;
272 273
273 274 } else {
274 275 Die(gettext(
275 276 "Cannot determine rss flags for output options %x\n"),
276 277 opts.o_outpmode);
277 278 }
278 279
279 280 /*
280 281 * getvmusage() returns an array of result structures. One for
281 282 * each zone, project, task, or user on the system, depending on
282 283 * flags.
283 284 *
284 285 * If getvmusage() fails, prstat will use the size already gathered
285 286 * from psinfo
286 287 */
287 288 if (getvmusage(flags, opts.o_interval, NULL, &nres) != 0)
288 289 return;
289 290
290 291 results = (vmusage_t *)Malloc(sizeof (vmusage_t) * nres);
291 292 for (;;) {
292 293 ret = getvmusage(flags, opts.o_interval, results, &nres);
293 294 if (ret == 0)
294 295 break;
295 296 if (errno == EOVERFLOW) {
296 297 results = (vmusage_t *)Realloc(results,
297 298 sizeof (vmusage_t) * nres);
298 299 continue;
299 300 }
300 301 /*
301 302 * Failure for some other reason. Prstat will use the size
302 303 * already gathered from psinfo.
303 304 */
304 305 free(results);
305 306 return;
306 307 }
307 308 for (id = list->l_head; id != NULL; id = id->id_next) {
308 309
309 310 match = NULL;
310 311 next = results;
311 312 for (i = 0; i < nres; i++, next++) {
312 313 switch (flags) {
313 314 case VMUSAGE_COL_RUSERS:
314 315 if (next->vmu_id == id->id_uid)
315 316 match = next;
316 317 break;
317 318 case VMUSAGE_ALL_TASKS:
318 319 if (next->vmu_id == id->id_taskid)
319 320 match = next;
320 321 break;
321 322 case VMUSAGE_COL_PROJECTS:
322 323 if (next->vmu_id == id->id_projid)
323 324 match = next;
324 325 break;
325 326 case VMUSAGE_ALL_ZONES:
326 327 if (next->vmu_id == id->id_zoneid)
327 328 match = next;
328 329 break;
329 330 default:
330 331 Die(gettext(
331 332 "Unknown vmusage flags %d\n"), flags);
332 333 }
333 334 }
334 335 if (match != NULL) {
335 336 id->id_size = match->vmu_swap_all / 1024;
336 337 id->id_rssize = match->vmu_rss_all / 1024;
337 338 id->id_pctmem = (100.0 * (float)match->vmu_rss_all) /
338 339 (float)physmem;
339 340 /* Output using data from getvmusage() */
340 341 id->id_sizematch = B_TRUE;
341 342 }
342 343 /*
343 344 * If no match is found, prstat will use the size already
344 345 * gathered from psinfo.
345 346 */
346 347 }
347 348 free(results);
348 349 }
349 350
350 351 /*
351 352 * A routine to display the contents of the list on the screen
352 353 */
353 354 static void
↓ open down ↓ |
168 lines elided |
↑ open up ↑ |
354 355 list_print(list_t *list)
355 356 {
356 357 lwp_info_t *lwp;
357 358 id_info_t *id;
358 359 char usr[4], sys[4], trp[4], tfl[4];
359 360 char dfl[4], lck[4], slp[4], lat[4];
360 361 char vcx[4], icx[4], scl[4], sig[4];
361 362 char psize[6], prssize[6], pmem[6], pcpu[6], ptime[12];
362 363 char pstate[7], pnice[4], ppri[4];
363 364 char pname[LOGNAME_MAX+1];
365 + char name[PRFNSZ + THREAD_NAME_MAX + 2];
364 366 char projname[PROJNAME_MAX+1];
365 367 char zonename[ZONENAME_MAX+1];
366 368 float cpu, mem;
367 369 double loadavg[3] = {0, 0, 0};
368 - int i, lwpid;
370 + int i, n;
369 371
370 372 if (list->l_size == 0)
371 373 return;
372 374
373 375 if (foreach_element(&set_tbl, &loadavg, psetloadavg) == 0) {
374 376 /*
375 377 * If processor sets aren't specified, we display system-wide
376 378 * load averages.
377 379 */
378 380 (void) getloadavg(loadavg, 3);
379 381 }
380 382
381 383 if (((opts.o_outpmode & OPT_UDATE) || (opts.o_outpmode & OPT_DDATE)) &&
382 384 ((list->l_type == LT_LWPS) || !(opts.o_outpmode & OPT_SPLIT)))
383 385 print_timestamp();
384 386 if (opts.o_outpmode & OPT_TTY)
385 387 (void) putchar('\r');
386 388 (void) putp(t_ulon);
387 389
390 + n = opts.o_cols;
388 391 switch (list->l_type) {
389 392 case LT_PROJECTS:
390 393 if (opts.o_outpmode & OPT_LWPS)
391 - (void) printf(PROJECT_HEADER_LWP);
394 + n = printf(PROJECT_HEADER_LWP);
392 395 else
393 - (void) printf(PROJECT_HEADER_PROC);
396 + n = printf(PROJECT_HEADER_PROC);
394 397 break;
395 398 case LT_TASKS:
396 399 if (opts.o_outpmode & OPT_LWPS)
397 - (void) printf(TASK_HEADER_LWP);
400 + n = printf(TASK_HEADER_LWP);
398 401 else
399 - (void) printf(TASK_HEADER_PROC);
402 + n = printf(TASK_HEADER_PROC);
400 403 break;
401 404 case LT_ZONES:
402 405 if (opts.o_outpmode & OPT_LWPS)
403 - (void) printf(ZONE_HEADER_LWP);
406 + n = printf(ZONE_HEADER_LWP);
404 407 else
405 - (void) printf(ZONE_HEADER_PROC);
408 + n = printf(ZONE_HEADER_PROC);
406 409 break;
407 410 case LT_USERS:
408 411 if (opts.o_outpmode & OPT_LWPS)
409 - (void) printf(USER_HEADER_LWP);
412 + n = printf(USER_HEADER_LWP);
410 413 else
411 - (void) printf(USER_HEADER_PROC);
414 + n = printf(USER_HEADER_PROC);
412 415 break;
413 416 case LT_LWPS:
414 417 if (opts.o_outpmode & OPT_LWPS) {
415 418 if (opts.o_outpmode & OPT_PSINFO) {
416 419 if (opts.o_outpmode & OPT_LGRP)
417 - (void) printf(PSINFO_HEADER_LWP_LGRP);
420 + n = printf(PSINFO_HEADER_LWP_LGRP);
418 421 else
419 - (void) printf(PSINFO_HEADER_LWP);
422 + n = printf(PSINFO_HEADER_LWP);
420 423 }
421 424 if (opts.o_outpmode & OPT_MSACCT)
422 - (void) printf(USAGE_HEADER_LWP);
425 + n = printf(USAGE_HEADER_LWP);
423 426 } else {
424 427 if (opts.o_outpmode & OPT_PSINFO) {
425 428 if (opts.o_outpmode & OPT_LGRP)
426 - (void) printf(PSINFO_HEADER_PROC_LGRP);
429 + n = printf(PSINFO_HEADER_PROC_LGRP);
427 430 else
428 - (void) printf(PSINFO_HEADER_PROC);
431 + n = printf(PSINFO_HEADER_PROC);
429 432 }
430 433 if (opts.o_outpmode & OPT_MSACCT)
431 - (void) printf(USAGE_HEADER_PROC);
434 + n = printf(USAGE_HEADER_PROC);
432 435 }
433 436 break;
434 437 }
435 438
439 + /* Pad out the header line so the underline spans the whole width */
440 + if ((opts.o_outpmode & OPT_TERMCAP) && n < opts.o_cols)
441 + (void) printf("%*s", (int)(opts.o_cols - n), "");
442 +
436 443 (void) putp(t_uloff);
437 444 (void) putp(t_eol);
438 445 (void) putchar('\n');
439 446
440 447 for (i = 0; i < list->l_used; i++) {
441 448 switch (list->l_type) {
442 449 case LT_PROJECTS:
443 450 case LT_TASKS:
444 451 case LT_USERS:
445 452 case LT_ZONES:
446 453 id = list->l_ptrs[i];
447 454 /*
448 455 * CPU usage and memory usage normalization
449 456 */
450 457 if (total_cpu >= 100)
451 458 cpu = (100 * id->id_pctcpu) / total_cpu;
452 459 else
453 460 cpu = id->id_pctcpu;
454 461 if (id->id_sizematch == B_FALSE && total_mem >= 100)
455 462 mem = (100 * id->id_pctmem) / total_mem;
456 463 else
457 464 mem = id->id_pctmem;
458 465 if (list->l_type == LT_USERS) {
459 466 pwd_getname(id->id_uid, pname, sizeof (pname),
460 467 opts.o_outpmode & OPT_NORESOLVE,
461 468 opts.o_outpmode & (OPT_TERMCAP|OPT_TRUNC),
462 469 LOGIN_WIDTH);
463 470 } else if (list->l_type == LT_ZONES) {
464 471 getzonename(id->id_zoneid, zonename,
465 472 sizeof (zonename),
466 473 opts.o_outpmode & (OPT_TERMCAP|OPT_TRUNC),
467 474 ZONE_WIDTH);
468 475 } else {
469 476 getprojname(id->id_projid, projname,
470 477 sizeof (projname),
471 478 opts.o_outpmode & OPT_NORESOLVE,
472 479 opts.o_outpmode & (OPT_TERMCAP|OPT_TRUNC),
473 480 PROJECT_WIDTH);
474 481 }
475 482 Format_size(psize, id->id_size, 6);
476 483 Format_size(prssize, id->id_rssize, 6);
477 484 Format_pct(pmem, mem, 4);
478 485 Format_pct(pcpu, cpu, 4);
479 486 Format_time(ptime, id->id_time, 10);
480 487 if (opts.o_outpmode & OPT_TTY)
481 488 (void) putchar('\r');
482 489 if (list->l_type == LT_PROJECTS)
483 490 (void) printf(PROJECT_LINE, (int)id->id_projid,
484 491 id->id_nproc, psize, prssize, pmem, ptime,
485 492 pcpu, projname);
486 493 else if (list->l_type == LT_TASKS)
487 494 (void) printf(TASK_LINE, (int)id->id_taskid,
488 495 id->id_nproc, psize, prssize, pmem, ptime,
489 496 pcpu, projname);
490 497 else if (list->l_type == LT_ZONES)
491 498 (void) printf(ZONE_LINE, (int)id->id_zoneid,
↓ open down ↓ |
46 lines elided |
↑ open up ↑ |
492 499 id->id_nproc, psize, prssize, pmem, ptime,
493 500 pcpu, zonename);
494 501 else
495 502 (void) printf(USER_LINE, id->id_nproc, pname,
496 503 psize, prssize, pmem, ptime, pcpu);
497 504 (void) putp(t_eol);
498 505 (void) putchar('\n');
499 506 break;
500 507 case LT_LWPS:
501 508 lwp = list->l_ptrs[i];
502 - if (opts.o_outpmode & OPT_LWPS)
503 - lwpid = lwp->li_info.pr_lwp.pr_lwpid;
504 - else
505 - lwpid = lwp->li_info.pr_nlwp +
506 - lwp->li_info.pr_nzomb;
509 +
510 + format_name(lwp, name, sizeof (name));
511 +
507 512 pwd_getname(lwp->li_info.pr_uid, pname, sizeof (pname),
508 513 opts.o_outpmode & OPT_NORESOLVE,
509 514 opts.o_outpmode & (OPT_TERMCAP|OPT_TRUNC),
510 515 LOGIN_WIDTH);
516 +
511 517 if (opts.o_outpmode & OPT_PSINFO) {
512 518 Format_size(psize, lwp->li_info.pr_size, 6);
513 519 Format_size(prssize, lwp->li_info.pr_rssize, 6);
514 520 Format_state(pstate,
515 521 lwp->li_info.pr_lwp.pr_sname,
516 522 lwp->li_info.pr_lwp.pr_onpro, 7);
517 523 if (strcmp(lwp->li_info.pr_lwp.pr_clname,
518 524 "RT") == 0 ||
519 525 strcmp(lwp->li_info.pr_lwp.pr_clname,
520 526 "SYS") == 0 ||
521 527 lwp->li_info.pr_lwp.pr_sname == 'Z')
522 528 (void) strcpy(pnice, " -");
523 529 else
524 530 Format_num(pnice,
525 531 lwp->li_info.pr_lwp.pr_nice - NZERO,
526 532 4);
527 533 Format_num(ppri, lwp->li_info.pr_lwp.pr_pri, 4);
528 534 Format_pct(pcpu,
↓ open down ↓ |
8 lines elided |
↑ open up ↑ |
529 535 FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu), 4);
530 536 if (opts.o_outpmode & OPT_LWPS)
531 537 Format_time(ptime,
532 538 lwp->li_info.pr_lwp.pr_time.tv_sec,
533 539 10);
534 540 else
535 541 Format_time(ptime,
536 542 lwp->li_info.pr_time.tv_sec, 10);
537 543 if (opts.o_outpmode & OPT_TTY)
538 544 (void) putchar('\r');
539 - stripfname(lwp->li_info.pr_fname);
540 545 if (opts.o_outpmode & OPT_LGRP) {
541 546 (void) printf(PSINFO_LINE_LGRP,
542 547 (int)lwp->li_info.pr_pid, pname,
543 548 psize, prssize, pstate,
544 549 ppri, pnice, ptime, pcpu,
545 - (int)lwp->li_info.pr_lwp.pr_lgrp,
546 - lwp->li_info.pr_fname, lwpid);
550 + lwp->li_info.pr_lwp.pr_lgrp, name);
547 551 } else {
548 552 (void) printf(PSINFO_LINE,
549 553 (int)lwp->li_info.pr_pid, pname,
550 - psize, prssize,
551 - pstate, ppri, pnice,
552 - ptime, pcpu,
553 - lwp->li_info.pr_fname, lwpid);
554 + psize, prssize, pstate, ppri, pnice,
555 + ptime, pcpu, name);
554 556 }
555 557 (void) putp(t_eol);
556 558 (void) putchar('\n');
557 559 }
558 560 if (opts.o_outpmode & OPT_MSACCT) {
559 561 Format_pct(usr, lwp->li_usr, 4);
560 562 Format_pct(sys, lwp->li_sys, 4);
561 563 Format_pct(slp, lwp->li_slp, 4);
562 564 Format_num(vcx, lwp->li_vcx, 4);
563 565 Format_num(icx, lwp->li_icx, 4);
564 566 Format_num(scl, lwp->li_scl, 4);
565 567 Format_num(sig, lwp->li_sig, 4);
566 568 Format_pct(trp, lwp->li_trp, 4);
567 569 Format_pct(tfl, lwp->li_tfl, 4);
568 570 Format_pct(dfl, lwp->li_dfl, 4);
569 571 Format_pct(lck, lwp->li_lck, 4);
570 572 Format_pct(lat, lwp->li_lat, 4);
571 573 if (opts.o_outpmode & OPT_TTY)
572 574 (void) putchar('\r');
573 - stripfname(lwp->li_info.pr_fname);
574 575 (void) printf(USAGE_LINE,
575 576 (int)lwp->li_info.pr_pid, pname,
576 577 usr, sys, trp, tfl, dfl, lck,
577 578 slp, lat, vcx, icx, scl, sig,
578 - lwp->li_info.pr_fname, lwpid);
579 + name);
579 580 (void) putp(t_eol);
580 581 (void) putchar('\n');
581 582 }
582 583 break;
583 584 }
584 585 }
585 586
586 587 if (opts.o_outpmode & OPT_TTY)
587 588 (void) putchar('\r');
588 589 if (opts.o_outpmode & OPT_TERMCAP) {
589 590 switch (list->l_type) {
590 591 case LT_PROJECTS:
591 592 case LT_USERS:
592 593 case LT_TASKS:
593 594 case LT_ZONES:
594 595 while (i++ < opts.o_nbottom) {
595 596 (void) putp(t_eol);
596 597 (void) putchar('\n');
597 598 }
598 599 break;
599 600 case LT_LWPS:
600 601 while (i++ < opts.o_ntop) {
601 602 (void) putp(t_eol);
602 603 (void) putchar('\n');
603 604 }
604 605 }
605 606 }
606 607
607 608 if (opts.o_outpmode & OPT_TTY)
608 609 (void) putchar('\r');
609 610
610 611 if ((opts.o_outpmode & OPT_SPLIT) && list->l_type == LT_LWPS)
611 612 return;
612 613
613 614 (void) printf(TOTAL_LINE, total_procs, total_lwps,
614 615 loadavg[LOADAVG_1MIN], loadavg[LOADAVG_5MIN],
615 616 loadavg[LOADAVG_15MIN]);
616 617 (void) putp(t_eol);
617 618 (void) putchar('\n');
618 619 if (opts.o_outpmode & OPT_TTY)
619 620 (void) putchar('\r');
620 621 (void) putp(t_eol);
621 622 (void) fflush(stdout);
622 623 }
623 624
624 625 static lwp_info_t *
625 626 list_add_lwp(list_t *list, pid_t pid, id_t lwpid)
626 627 {
627 628 lwp_info_t *lwp;
628 629
629 630 if (list->l_head == NULL) {
630 631 list->l_head = list->l_tail = lwp = Zalloc(sizeof (lwp_info_t));
631 632 } else {
632 633 lwp = Zalloc(sizeof (lwp_info_t));
633 634 lwp->li_prev = list->l_tail;
634 635 ((lwp_info_t *)list->l_tail)->li_next = lwp;
635 636 list->l_tail = lwp;
636 637 }
637 638 lwp->li_info.pr_pid = pid;
638 639 lwp->li_info.pr_lwp.pr_lwpid = lwpid;
639 640 lwpid_add(lwp, pid, lwpid);
640 641 list->l_count++;
641 642 return (lwp);
642 643 }
643 644
644 645 static void
645 646 list_remove_lwp(list_t *list, lwp_info_t *lwp)
646 647 {
647 648 if (lwp->li_prev)
648 649 lwp->li_prev->li_next = lwp->li_next;
649 650 else
650 651 list->l_head = lwp->li_next; /* removing the head */
651 652 if (lwp->li_next)
652 653 lwp->li_next->li_prev = lwp->li_prev;
653 654 else
654 655 list->l_tail = lwp->li_prev; /* removing the tail */
655 656 lwpid_del(lwp->li_info.pr_pid, lwp->li_info.pr_lwp.pr_lwpid);
656 657 if (lwpid_pidcheck(lwp->li_info.pr_pid) == 0)
657 658 fds_rm(lwp->li_info.pr_pid);
658 659 list->l_count--;
659 660 free(lwp);
660 661 }
661 662
662 663 static void
663 664 list_clear(list_t *list)
664 665 {
665 666 if (list->l_type == LT_LWPS) {
666 667 lwp_info_t *lwp = list->l_tail;
667 668 lwp_info_t *lwp_tmp;
668 669
669 670 fd_closeall();
670 671 while (lwp) {
671 672 lwp_tmp = lwp;
672 673 lwp = lwp->li_prev;
673 674 list_remove_lwp(&lwps, lwp_tmp);
674 675 }
675 676 } else {
676 677 id_info_t *id = list->l_head;
677 678 id_info_t *nextid;
678 679
679 680 while (id) {
680 681 nextid = id->id_next;
681 682 free(id);
682 683 id = nextid;
683 684 }
684 685 list->l_count = 0;
685 686 list->l_head = list->l_tail = NULL;
686 687 }
687 688 }
688 689
689 690 static void
690 691 list_update(list_t *list, lwp_info_t *lwp)
691 692 {
692 693 id_info_t *id;
693 694
694 695 if (list->l_head == NULL) { /* first element */
695 696 list->l_head = list->l_tail = id = Zalloc(sizeof (id_info_t));
696 697 goto update;
697 698 }
698 699
699 700 for (id = list->l_head; id; id = id->id_next) {
700 701 if ((list->l_type == LT_USERS) &&
701 702 (id->id_uid != lwp->li_info.pr_uid))
702 703 continue;
703 704 if ((list->l_type == LT_TASKS) &&
704 705 (id->id_taskid != lwp->li_info.pr_taskid))
705 706 continue;
706 707 if ((list->l_type == LT_PROJECTS) &&
707 708 (id->id_projid != lwp->li_info.pr_projid))
708 709 continue;
709 710 if ((list->l_type == LT_ZONES) &&
710 711 (id->id_zoneid != lwp->li_info.pr_zoneid))
711 712 continue;
712 713 if ((list->l_type == LT_LGRPS) &&
713 714 (id->id_lgroup != lwp->li_info.pr_lwp.pr_lgrp))
714 715 continue;
715 716 id->id_nproc++;
716 717 id->id_taskid = lwp->li_info.pr_taskid;
717 718 id->id_projid = lwp->li_info.pr_projid;
718 719 id->id_zoneid = lwp->li_info.pr_zoneid;
719 720 id->id_lgroup = lwp->li_info.pr_lwp.pr_lgrp;
720 721
721 722 if (lwp->li_flags & LWP_REPRESENT) {
722 723 id->id_size += lwp->li_info.pr_size;
723 724 id->id_rssize += lwp->li_info.pr_rssize;
724 725 }
725 726 id->id_pctcpu += FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu);
726 727 if (opts.o_outpmode & OPT_LWPS)
727 728 id->id_time += TIME2SEC(lwp->li_info.pr_lwp.pr_time);
728 729 else
729 730 id->id_time += TIME2SEC(lwp->li_info.pr_time);
730 731 id->id_pctmem += FRC2PCT(lwp->li_info.pr_pctmem);
731 732 id->id_key += lwp->li_key;
732 733 total_cpu += FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu);
733 734 total_mem += FRC2PCT(lwp->li_info.pr_pctmem);
734 735 return;
735 736 }
736 737
737 738 id = list->l_tail;
738 739 id->id_next = Zalloc(sizeof (id_info_t));
739 740 id->id_next->id_prev = list->l_tail;
740 741 id->id_next->id_next = NULL;
741 742 list->l_tail = id->id_next;
742 743 id = list->l_tail;
743 744 update:
744 745 id->id_uid = lwp->li_info.pr_uid;
745 746 id->id_projid = lwp->li_info.pr_projid;
746 747 id->id_taskid = lwp->li_info.pr_taskid;
747 748 id->id_zoneid = lwp->li_info.pr_zoneid;
748 749 id->id_lgroup = lwp->li_info.pr_lwp.pr_lgrp;
749 750 id->id_nproc++;
750 751 id->id_sizematch = B_FALSE;
751 752 if (lwp->li_flags & LWP_REPRESENT) {
752 753 id->id_size = lwp->li_info.pr_size;
753 754 id->id_rssize = lwp->li_info.pr_rssize;
754 755 }
755 756 id->id_pctcpu = FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu);
756 757 if (opts.o_outpmode & OPT_LWPS)
757 758 id->id_time = TIME2SEC(lwp->li_info.pr_lwp.pr_time);
758 759 else
759 760 id->id_time = TIME2SEC(lwp->li_info.pr_time);
760 761 id->id_pctmem = FRC2PCT(lwp->li_info.pr_pctmem);
761 762 id->id_key = lwp->li_key;
762 763 total_cpu += id->id_pctcpu;
763 764 total_mem += id->id_pctmem;
764 765 list->l_count++;
765 766 }
766 767
767 768 static void
768 769 lwp_update(lwp_info_t *lwp, pid_t pid, id_t lwpid, struct prusage *usage)
769 770 {
770 771 float period;
771 772
772 773 if (!lwpid_is_active(pid, lwpid)) {
773 774 /*
774 775 * If we are reading cpu times for the first time then
775 776 * calculate average cpu times based on whole process
776 777 * execution time.
777 778 */
778 779 (void) memcpy(&lwp->li_usage, usage, sizeof (prusage_t));
779 780 period = TIME2NSEC(usage->pr_rtime);
780 781 period = period/(float)100;
781 782
782 783 if (period == 0) { /* zombie */
783 784 period = 1;
784 785 lwp->li_usr = 0;
785 786 lwp->li_sys = 0;
786 787 lwp->li_slp = 0;
787 788 } else {
788 789 lwp->li_usr = TIME2NSEC(usage->pr_utime)/period;
789 790 lwp->li_sys = TIME2NSEC(usage->pr_stime)/period;
790 791 lwp->li_slp = TIME2NSEC(usage->pr_slptime)/period;
791 792 }
792 793 lwp->li_trp = TIME2NSEC(usage->pr_ttime)/period;
793 794 lwp->li_tfl = TIME2NSEC(usage->pr_tftime)/period;
794 795 lwp->li_dfl = TIME2NSEC(usage->pr_dftime)/period;
795 796 lwp->li_lck = TIME2NSEC(usage->pr_ltime)/period;
796 797 lwp->li_lat = TIME2NSEC(usage->pr_wtime)/period;
797 798 period = (period / NANOSEC)*(float)100; /* now in seconds */
798 799 lwp->li_vcx = (ulong_t)
799 800 (opts.o_interval * (usage->pr_vctx/period));
800 801 lwp->li_icx = (ulong_t)
801 802 (opts.o_interval * (usage->pr_ictx/period));
802 803 lwp->li_scl = (ulong_t)
803 804 (opts.o_interval * (usage->pr_sysc/period));
804 805 lwp->li_sig = (ulong_t)
805 806 (opts.o_interval * (usage->pr_sigs/period));
806 807 (void) lwpid_set_active(pid, lwpid);
807 808 } else {
808 809 /*
809 810 * If this is not a first time we are reading a process's
810 811 * CPU times then recalculate CPU times based on fresh data
811 812 * obtained from procfs and previous CPU time usage values.
812 813 */
813 814 period = TIME2NSEC(usage->pr_rtime)-
814 815 TIME2NSEC(lwp->li_usage.pr_rtime);
815 816 period = period/(float)100;
816 817
817 818 if (period == 0) { /* zombie */
818 819 period = 1;
819 820 lwp->li_usr = 0;
820 821 lwp->li_sys = 0;
821 822 lwp->li_slp = 0;
822 823 } else {
823 824 lwp->li_usr = (TIME2NSEC(usage->pr_utime)-
824 825 TIME2NSEC(lwp->li_usage.pr_utime))/period;
825 826 lwp->li_sys = (TIME2NSEC(usage->pr_stime) -
826 827 TIME2NSEC(lwp->li_usage.pr_stime))/period;
827 828 lwp->li_slp = (TIME2NSEC(usage->pr_slptime) -
828 829 TIME2NSEC(lwp->li_usage.pr_slptime))/period;
829 830 }
830 831 lwp->li_trp = (TIME2NSEC(usage->pr_ttime) -
831 832 TIME2NSEC(lwp->li_usage.pr_ttime))/period;
832 833 lwp->li_tfl = (TIME2NSEC(usage->pr_tftime) -
833 834 TIME2NSEC(lwp->li_usage.pr_tftime))/period;
834 835 lwp->li_dfl = (TIME2NSEC(usage->pr_dftime) -
835 836 TIME2NSEC(lwp->li_usage.pr_dftime))/period;
836 837 lwp->li_lck = (TIME2NSEC(usage->pr_ltime) -
837 838 TIME2NSEC(lwp->li_usage.pr_ltime))/period;
838 839 lwp->li_lat = (TIME2NSEC(usage->pr_wtime) -
839 840 TIME2NSEC(lwp->li_usage.pr_wtime))/period;
840 841 lwp->li_vcx = usage->pr_vctx - lwp->li_usage.pr_vctx;
841 842 lwp->li_icx = usage->pr_ictx - lwp->li_usage.pr_ictx;
842 843 lwp->li_scl = usage->pr_sysc - lwp->li_usage.pr_sysc;
843 844 lwp->li_sig = usage->pr_sigs - lwp->li_usage.pr_sigs;
844 845 (void) memcpy(&lwp->li_usage, usage, sizeof (prusage_t));
845 846 }
846 847 }
847 848
848 849 static int
849 850 read_procfile(fd_t **fd, char *pidstr, char *file, void *buf, size_t bufsize)
850 851 {
851 852 char procfile[MAX_PROCFS_PATH];
852 853
853 854 (void) snprintf(procfile, MAX_PROCFS_PATH,
854 855 "/proc/%s/%s", pidstr, file);
855 856 if ((*fd = fd_open(procfile, O_RDONLY, *fd)) == NULL)
856 857 return (1);
857 858 if (pread(fd_getfd(*fd), buf, bufsize, 0) != bufsize) {
858 859 fd_close(*fd);
859 860 return (1);
860 861 }
861 862 return (0);
862 863 }
863 864
864 865 static void
865 866 add_proc(psinfo_t *psinfo)
866 867 {
867 868 lwp_info_t *lwp;
868 869 id_t lwpid;
869 870 pid_t pid = psinfo->pr_pid;
↓ open down ↓ |
281 lines elided |
↑ open up ↑ |
870 871
871 872 lwpid = psinfo->pr_lwp.pr_lwpid;
872 873 if ((lwp = lwpid_get(pid, lwpid)) == NULL)
873 874 lwp = list_add_lwp(&lwps, pid, lwpid);
874 875 lwp->li_flags |= LWP_ALIVE | LWP_REPRESENT;
875 876 (void) memcpy(&lwp->li_info, psinfo, sizeof (psinfo_t));
876 877 lwp->li_info.pr_lwp.pr_pctcpu = lwp->li_info.pr_pctcpu;
877 878 }
878 879
879 880 static void
881 +get_lwpname(pid_t pid, id_t lwpid, char *buf, size_t bufsize)
882 +{
883 + char *path = NULL;
884 + int fd;
885 +
886 + buf[0] = '\0';
887 +
888 + if (asprintf(&path, "/proc/%d/lwp/%d/lwpname",
889 + (int)pid, (int)lwpid) == -1)
890 + return;
891 +
892 + if ((fd = open(path, O_RDONLY)) != -1) {
893 + (void) read(fd, buf, bufsize);
894 + buf[bufsize - 1] = '\0';
895 + (void) close(fd);
896 + }
897 +
898 + free(path);
899 +}
900 +
901 +static void
880 902 add_lwp(psinfo_t *psinfo, lwpsinfo_t *lwpsinfo, int flags)
881 903 {
882 904 lwp_info_t *lwp;
883 905 pid_t pid = psinfo->pr_pid;
884 906 id_t lwpid = lwpsinfo->pr_lwpid;
885 907
886 908 if ((lwp = lwpid_get(pid, lwpid)) == NULL)
887 909 lwp = list_add_lwp(&lwps, pid, lwpid);
888 910 lwp->li_flags &= ~LWP_REPRESENT;
889 911 lwp->li_flags |= LWP_ALIVE;
890 912 lwp->li_flags |= flags;
891 913 (void) memcpy(&lwp->li_info, psinfo,
892 914 sizeof (psinfo_t) - sizeof (lwpsinfo_t));
893 915 (void) memcpy(&lwp->li_info.pr_lwp, lwpsinfo, sizeof (lwpsinfo_t));
916 + get_lwpname(pid, lwpid, lwp->li_lwpname, sizeof (lwp->li_lwpname));
894 917 }
895 918
896 919 static void
897 920 prstat_scandir(DIR *procdir)
898 921 {
899 922 char *pidstr;
900 923 pid_t pid;
901 924 id_t lwpid;
902 925 size_t entsz;
903 926 long nlwps, nent, i;
904 927 char *buf, *ptr;
905 928
906 929 fds_t *fds;
907 930 lwp_info_t *lwp;
908 931 dirent_t *direntp;
909 932
910 933 prheader_t header;
911 934 psinfo_t psinfo;
912 935 prusage_t usage;
913 936 lwpsinfo_t *lwpsinfo;
914 937 prusage_t *lwpusage;
915 938
916 939 total_procs = 0;
917 940 total_lwps = 0;
918 941 total_cpu = 0;
919 942 total_mem = 0;
920 943
921 944 convert_zone(&zone_tbl);
922 945 for (rewinddir(procdir); (direntp = readdir(procdir)); ) {
923 946 pidstr = direntp->d_name;
924 947 if (pidstr[0] == '.') /* skip "." and ".." */
925 948 continue;
926 949 pid = atoi(pidstr);
927 950 if (pid == 0 || pid == 2 || pid == 3)
928 951 continue; /* skip sched, pageout and fsflush */
929 952 if (has_element(&pid_tbl, pid) == 0)
930 953 continue; /* check if we really want this pid */
931 954 fds = fds_get(pid); /* get ptr to file descriptors */
932 955
933 956 if (read_procfile(&fds->fds_psinfo, pidstr,
934 957 "psinfo", &psinfo, sizeof (psinfo_t)) != 0)
935 958 continue;
936 959 if (!has_uid(&ruid_tbl, psinfo.pr_uid) ||
937 960 !has_uid(&euid_tbl, psinfo.pr_euid) ||
938 961 !has_element(&prj_tbl, psinfo.pr_projid) ||
939 962 !has_element(&tsk_tbl, psinfo.pr_taskid) ||
940 963 !has_zone(&zone_tbl, psinfo.pr_zoneid)) {
941 964 fd_close(fds->fds_psinfo);
942 965 continue;
943 966 }
944 967 nlwps = psinfo.pr_nlwp + psinfo.pr_nzomb;
945 968
946 969 if (nlwps > 1 && (opts.o_outpmode & (OPT_LWPS | OPT_PSETS))) {
947 970 int rep_lwp = 0;
948 971
949 972 if (read_procfile(&fds->fds_lpsinfo, pidstr, "lpsinfo",
950 973 &header, sizeof (prheader_t)) != 0) {
951 974 fd_close(fds->fds_psinfo);
952 975 continue;
953 976 }
954 977
955 978 nent = header.pr_nent;
956 979 entsz = header.pr_entsize * nent;
957 980 ptr = buf = Malloc(entsz);
958 981 if (pread(fd_getfd(fds->fds_lpsinfo), buf,
959 982 entsz, sizeof (struct prheader)) != entsz) {
960 983 fd_close(fds->fds_lpsinfo);
961 984 fd_close(fds->fds_psinfo);
962 985 free(buf);
963 986 continue;
964 987 }
965 988
966 989 nlwps = 0;
967 990 for (i = 0; i < nent; i++, ptr += header.pr_entsize) {
968 991 /*LINTED ALIGNMENT*/
969 992 lwpsinfo = (lwpsinfo_t *)ptr;
970 993 if (!has_element(&cpu_tbl,
971 994 lwpsinfo->pr_onpro) ||
972 995 !has_element(&set_tbl,
973 996 lwpsinfo->pr_bindpset) ||
974 997 !has_element(&lgr_tbl, lwpsinfo->pr_lgrp))
975 998 continue;
976 999 nlwps++;
977 1000 if ((opts.o_outpmode & (OPT_PSETS | OPT_LWPS))
978 1001 == OPT_PSETS) {
979 1002 /*
980 1003 * If one of process's LWPs is bound
981 1004 * to a given processor set, report the
982 1005 * whole process. We may be doing this
983 1006 * a few times but we'll get an accurate
984 1007 * lwp count in return.
985 1008 */
986 1009 add_proc(&psinfo);
987 1010 } else {
988 1011 if (rep_lwp == 0) {
989 1012 rep_lwp = 1;
990 1013 add_lwp(&psinfo, lwpsinfo,
991 1014 LWP_REPRESENT);
992 1015 } else {
993 1016 add_lwp(&psinfo, lwpsinfo, 0);
994 1017 }
995 1018 }
996 1019 }
997 1020 free(buf);
998 1021 if (nlwps == 0) {
999 1022 fd_close(fds->fds_lpsinfo);
1000 1023 fd_close(fds->fds_psinfo);
1001 1024 continue;
1002 1025 }
1003 1026 } else {
1004 1027 if (!has_element(&cpu_tbl, psinfo.pr_lwp.pr_onpro) ||
1005 1028 !has_element(&set_tbl, psinfo.pr_lwp.pr_bindpset) ||
1006 1029 !has_element(&lgr_tbl, psinfo.pr_lwp.pr_lgrp)) {
1007 1030 fd_close(fds->fds_psinfo);
1008 1031 continue;
1009 1032 }
1010 1033 add_proc(&psinfo);
1011 1034 }
1012 1035 if (!(opts.o_outpmode & OPT_MSACCT)) {
1013 1036 total_procs++;
1014 1037 total_lwps += nlwps;
1015 1038 continue;
1016 1039 }
1017 1040 /*
1018 1041 * Get more information about processes from /proc/pid/usage.
1019 1042 * If process has more than one lwp, then we may have to
1020 1043 * also look at the /proc/pid/lusage file.
1021 1044 */
1022 1045 if ((opts.o_outpmode & OPT_LWPS) && (nlwps > 1)) {
1023 1046 if (read_procfile(&fds->fds_lusage, pidstr, "lusage",
1024 1047 &header, sizeof (prheader_t)) != 0) {
1025 1048 fd_close(fds->fds_lpsinfo);
1026 1049 fd_close(fds->fds_psinfo);
1027 1050 continue;
1028 1051 }
1029 1052 nent = header.pr_nent;
1030 1053 entsz = header.pr_entsize * nent;
1031 1054 buf = Malloc(entsz);
1032 1055 if (pread(fd_getfd(fds->fds_lusage), buf,
1033 1056 entsz, sizeof (struct prheader)) != entsz) {
1034 1057 fd_close(fds->fds_lusage);
1035 1058 fd_close(fds->fds_lpsinfo);
1036 1059 fd_close(fds->fds_psinfo);
1037 1060 free(buf);
1038 1061 continue;
1039 1062 }
1040 1063 for (i = 1, ptr = buf + header.pr_entsize; i < nent;
1041 1064 i++, ptr += header.pr_entsize) {
1042 1065 /*LINTED ALIGNMENT*/
1043 1066 lwpusage = (prusage_t *)ptr;
1044 1067 lwpid = lwpusage->pr_lwpid;
1045 1068 /*
1046 1069 * New LWPs created after we read lpsinfo
1047 1070 * will be ignored. Don't want to do
1048 1071 * everything all over again.
1049 1072 */
1050 1073 if ((lwp = lwpid_get(pid, lwpid)) == NULL)
1051 1074 continue;
1052 1075 lwp_update(lwp, pid, lwpid, lwpusage);
1053 1076 }
1054 1077 free(buf);
1055 1078 } else {
1056 1079 if (read_procfile(&fds->fds_usage, pidstr, "usage",
1057 1080 &usage, sizeof (prusage_t)) != 0) {
1058 1081 fd_close(fds->fds_lpsinfo);
1059 1082 fd_close(fds->fds_psinfo);
1060 1083 continue;
1061 1084 }
1062 1085 lwpid = psinfo.pr_lwp.pr_lwpid;
1063 1086 if ((lwp = lwpid_get(pid, lwpid)) == NULL)
1064 1087 continue;
1065 1088 lwp_update(lwp, pid, lwpid, &usage);
1066 1089 }
1067 1090 total_procs++;
1068 1091 total_lwps += nlwps;
1069 1092 }
1070 1093 fd_update();
1071 1094 }
1072 1095
1073 1096 /*
1074 1097 * This procedure removes all dead lwps from the linked list of all lwps.
1075 1098 * It also creates linked list of ids if necessary.
1076 1099 */
1077 1100 static void
1078 1101 list_refresh(list_t *list)
1079 1102 {
1080 1103 lwp_info_t *lwp, *lwp_next;
1081 1104
1082 1105 if (!(list->l_type & LT_LWPS))
1083 1106 return;
1084 1107
1085 1108 for (lwp = list->l_head; lwp != NULL; ) {
1086 1109 if (lwp->li_flags & LWP_ALIVE) {
1087 1110 /*
1088 1111 * Process all live LWPs.
1089 1112 * When we're done, mark them as dead.
1090 1113 * They will be marked "alive" on the next
1091 1114 * /proc scan if they still exist.
1092 1115 */
1093 1116 lwp->li_key = list_getkeyval(list, lwp);
1094 1117 if (opts.o_outpmode & OPT_USERS)
1095 1118 list_update(&users, lwp);
1096 1119 if (opts.o_outpmode & OPT_TASKS)
1097 1120 list_update(&tasks, lwp);
1098 1121 if (opts.o_outpmode & OPT_PROJECTS)
1099 1122 list_update(&projects, lwp);
1100 1123 if (opts.o_outpmode & OPT_ZONES)
1101 1124 list_update(&zones, lwp);
1102 1125 if (opts.o_outpmode & OPT_LGRP)
1103 1126 list_update(&lgroups, lwp);
1104 1127 lwp->li_flags &= ~LWP_ALIVE;
1105 1128 lwp = lwp->li_next;
↓ open down ↓ |
202 lines elided |
↑ open up ↑ |
1106 1129
1107 1130 } else {
1108 1131 lwp_next = lwp->li_next;
1109 1132 list_remove_lwp(&lwps, lwp);
1110 1133 lwp = lwp_next;
1111 1134 }
1112 1135 }
1113 1136 }
1114 1137
1115 1138 static void
1116 -curses_on()
1139 +curses_on(void)
1117 1140 {
1118 1141 if ((opts.o_outpmode & OPT_TERMCAP) && (is_curses_on == FALSE)) {
1119 1142 (void) initscr();
1120 1143 (void) nonl();
1121 1144 (void) putp(t_smcup);
1122 1145 is_curses_on = TRUE;
1123 1146 }
1124 1147 }
1125 1148
1126 1149 static void
1127 -curses_off()
1150 +curses_off(void)
1128 1151 {
1129 1152 if ((is_curses_on == TRUE) && (opts.o_outpmode & OPT_TERMCAP)) {
1130 1153 (void) putp(t_rmcup);
1131 1154 (void) endwin();
1132 1155 is_curses_on = FALSE;
1133 1156 }
1134 1157 (void) fflush(stdout);
1135 1158 }
1136 1159
1137 1160 static int
1138 -nlines()
1161 +nlines(int *linesp, int *colsp)
1139 1162 {
1140 1163 struct winsize ws;
1141 1164 char *envp;
1142 1165 int n;
1166 +
1167 + *linesp = -1;
1168 + *colsp = -1;
1143 1169 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) {
1144 1170 if (ws.ws_row > 0)
1145 - return (ws.ws_row);
1171 + *linesp = ws.ws_row;
1172 + if (ws.ws_col > 0)
1173 + *colsp = ws.ws_col;
1174 + if (ws.ws_row > 0 && ws.ws_col > 0)
1175 + return (0);
1146 1176 }
1147 - if (envp = getenv("LINES")) {
1177 +
1178 + if ((envp = getenv("LINES")) != NULL) {
1148 1179 if ((n = Atoi(envp)) > 0) {
1149 1180 opts.o_outpmode &= ~OPT_USEHOME;
1150 - return (n);
1181 + *linesp = n;
1151 1182 }
1152 1183 }
1153 - return (-1);
1184 + if ((envp = getenv("COLUMNS")) != NULL) {
1185 + if ((n = Atoi(envp)) > 0) {
1186 + *colsp = n;
1187 + }
1188 + }
1189 +
1190 + return ((*linesp > 0 && *colsp > 0) ? 0 : -1);
1154 1191 }
1155 1192
1156 1193 static void
1157 -setmovecur()
1194 +setmovecur(void)
1158 1195 {
1159 1196 int i, n;
1160 1197 if ((opts.o_outpmode & OPT_FULLSCREEN) &&
1161 1198 (opts.o_outpmode & OPT_USEHOME)) {
1162 1199 movecur = t_home;
1163 1200 return;
1164 1201 }
1165 1202 if (opts.o_outpmode & OPT_SPLIT) {
1166 1203 if (opts.o_ntop == 0)
1167 1204 n = opts.o_nbottom + 1;
1168 1205 else
1169 1206 n = opts.o_ntop + opts.o_nbottom + 2;
1170 1207 } else {
1171 1208 if (opts.o_outpmode & OPT_USERS)
1172 1209 n = opts.o_nbottom + 1;
1173 1210 else
1174 1211 n = opts.o_ntop + 1;
1175 1212 }
1176 1213 if (((opts.o_outpmode & OPT_UDATE) || (opts.o_outpmode & OPT_DDATE)))
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
1177 1214 n++;
1178 1215
1179 1216 if (movecur != NULL && movecur != empty_string && movecur != t_home)
1180 1217 free(movecur);
1181 1218 movecur = Zalloc(strlen(t_up) * (n + 5));
1182 1219 for (i = 0; i <= n; i++)
1183 1220 (void) strcat(movecur, t_up);
1184 1221 }
1185 1222
1186 1223 static int
1187 -setsize()
1224 +setsize(void)
1188 1225 {
1189 1226 static int oldn = 0;
1190 - int n;
1227 + int cols, n, ret;
1191 1228
1192 1229 if (opts.o_outpmode & OPT_FULLSCREEN) {
1193 - n = nlines();
1230 + ret = nlines(&n, &cols);
1231 + if (ret != -1)
1232 + opts.o_cols = cols;
1194 1233 if (n == oldn)
1195 1234 return (0);
1196 1235 oldn = n;
1197 - if (n == -1) {
1236 + if (ret == -1) {
1198 1237 opts.o_outpmode &= ~OPT_USEHOME;
1199 1238 setmovecur(); /* set default window size */
1200 1239 return (1);
1201 1240 }
1202 1241 n = n - 3; /* minus header, total and cursor lines */
1203 1242 if ((opts.o_outpmode & OPT_UDATE) ||
1204 1243 (opts.o_outpmode & OPT_DDATE))
1205 1244 n--; /* minus timestamp */
1206 1245 if (n < 1)
1207 1246 Die(gettext("window is too small (try -n)\n"));
1208 1247 if (opts.o_outpmode & OPT_SPLIT) {
1209 1248 if (n < 8) {
1210 1249 Die(gettext("window is too small (try -n)\n"));
1211 1250 } else {
1212 1251 opts.o_ntop = (n / 4) * 3;
1213 1252 opts.o_nbottom = n - 1 - opts.o_ntop;
1214 1253 }
1215 1254 } else {
1216 1255 if (opts.o_outpmode & OPT_USERS)
1217 1256 opts.o_nbottom = n;
1218 1257 else
1219 1258 opts.o_ntop = n;
1220 1259 }
1221 1260 }
1222 1261 setmovecur();
1223 1262 return (1);
1224 1263 }
1225 1264
1226 1265 static void
1227 1266 ldtermcap()
1228 1267 {
1229 1268 int err;
1230 1269 if (setupterm(NULL, STDIN_FILENO, &err) == ERR) {
1231 1270 switch (err) {
1232 1271 case 0:
1233 1272 Warn(gettext("failed to load terminal info, "
1234 1273 "defaulting to -c option\n"));
1235 1274 break;
1236 1275 case -1:
1237 1276 Warn(gettext("terminfo database not found, "
1238 1277 "defaulting to -c option\n"));
1239 1278 break;
1240 1279 default:
1241 1280 Warn(gettext("failed to initialize terminal, "
1242 1281 "defaulting to -c option\n"));
1243 1282 }
1244 1283 opts.o_outpmode &= ~OPT_TERMCAP;
1245 1284 t_up = t_eol = t_smcup = t_rmcup = movecur = empty_string;
1246 1285 t_ulon = t_uloff = empty_string;
1247 1286 return;
1248 1287 }
1249 1288 t_ulon = tigetstr("smul");
1250 1289 t_uloff = tigetstr("rmul");
1251 1290 t_up = tigetstr("cuu1");
1252 1291 t_eol = tigetstr("el");
1253 1292 t_smcup = tigetstr("smcup");
1254 1293 t_rmcup = tigetstr("rmcup");
1255 1294 t_home = tigetstr("home");
1256 1295 if ((t_up == (char *)-1) || (t_eol == (char *)-1) ||
1257 1296 (t_smcup == (char *)-1) || (t_rmcup == (char *)-1)) {
1258 1297 opts.o_outpmode &= ~OPT_TERMCAP;
1259 1298 t_up = t_eol = t_smcup = t_rmcup = movecur = empty_string;
1260 1299 return;
1261 1300 }
1262 1301 if (t_up == NULL || t_eol == NULL) {
1263 1302 opts.o_outpmode &= ~OPT_TERMCAP;
1264 1303 t_eol = t_up = movecur = empty_string;
1265 1304 return;
1266 1305 }
1267 1306 if (t_ulon == (char *)-1 || t_uloff == (char *)-1 ||
1268 1307 t_ulon == NULL || t_uloff == NULL) {
1269 1308 t_ulon = t_uloff = empty_string; /* can live without it */
1270 1309 }
1271 1310 if (t_smcup == NULL || t_rmcup == NULL)
1272 1311 t_smcup = t_rmcup = empty_string;
1273 1312 if (t_home == (char *)-1 || t_home == NULL) {
1274 1313 opts.o_outpmode &= ~OPT_USEHOME;
1275 1314 t_home = empty_string;
1276 1315 }
1277 1316 }
1278 1317
1279 1318 static void
1280 1319 sig_handler(int sig)
1281 1320 {
1282 1321 switch (sig) {
1283 1322 case SIGTSTP: sigtstp = 1;
1284 1323 break;
1285 1324 case SIGWINCH: sigwinch = 1;
1286 1325 break;
1287 1326 case SIGINT:
1288 1327 case SIGTERM: sigterm = 1;
1289 1328 break;
1290 1329 }
1291 1330 }
1292 1331
1293 1332 static void
1294 1333 set_signals()
1295 1334 {
1296 1335 (void) signal(SIGTSTP, sig_handler);
1297 1336 (void) signal(SIGINT, sig_handler);
1298 1337 (void) signal(SIGTERM, sig_handler);
1299 1338 if (opts.o_outpmode & OPT_FULLSCREEN)
1300 1339 (void) signal(SIGWINCH, sig_handler);
1301 1340 }
1302 1341
1303 1342 static void
1304 1343 fill_table(table_t *table, char *arg, char option)
1305 1344 {
1306 1345 char *p = strtok(arg, ", ");
1307 1346
1308 1347 if (p == NULL)
1309 1348 Die(gettext("invalid argument for -%c\n"), option);
1310 1349
1311 1350 add_element(table, (long)Atoi(p));
1312 1351 while (p = strtok(NULL, ", "))
1313 1352 add_element(table, (long)Atoi(p));
1314 1353 }
1315 1354
1316 1355 static void
1317 1356 fill_prj_table(char *arg)
1318 1357 {
1319 1358 projid_t projid;
1320 1359 char *p = strtok(arg, ", ");
1321 1360
1322 1361 if (p == NULL)
1323 1362 Die(gettext("invalid argument for -j\n"));
1324 1363
1325 1364 if ((projid = getprojidbyname(p)) == -1)
1326 1365 projid = Atoi(p);
1327 1366 add_element(&prj_tbl, (long)projid);
1328 1367
1329 1368 while (p = strtok(NULL, ", ")) {
1330 1369 if ((projid = getprojidbyname(p)) == -1)
1331 1370 projid = Atoi(p);
1332 1371 add_element(&prj_tbl, (long)projid);
1333 1372 }
1334 1373 }
1335 1374
1336 1375 static void
1337 1376 fill_set_table(char *arg)
1338 1377 {
1339 1378 char *p = strtok(arg, ", ");
1340 1379 psetid_t id;
1341 1380
1342 1381 if (p == NULL)
1343 1382 Die(gettext("invalid argument for -C\n"));
1344 1383
1345 1384 if ((id = Atoi(p)) == 0)
1346 1385 id = PS_NONE;
1347 1386 add_element(&set_tbl, id);
1348 1387 while (p = strtok(NULL, ", ")) {
1349 1388 if ((id = Atoi(p)) == 0)
1350 1389 id = PS_NONE;
1351 1390 if (!has_element(&set_tbl, id))
1352 1391 add_element(&set_tbl, id);
1353 1392 }
1354 1393 }
1355 1394
1356 1395 static void
1357 1396 Exit()
1358 1397 {
1359 1398 curses_off();
1360 1399 list_clear(&lwps);
1361 1400 list_clear(&users);
1362 1401 list_clear(&tasks);
1363 1402 list_clear(&projects);
1364 1403 list_clear(&zones);
1365 1404 fd_exit();
1366 1405 }
1367 1406
1368 1407
1369 1408 int
1370 1409 main(int argc, char **argv)
1371 1410 {
1372 1411 DIR *procdir;
1373 1412 char *p;
1374 1413 char *sortk = "cpu"; /* default sort key */
1375 1414 int opt;
1376 1415 int timeout;
1377 1416 struct pollfd pollset;
1378 1417 char key;
1379 1418
1380 1419 (void) setlocale(LC_ALL, "");
1381 1420 (void) textdomain(TEXT_DOMAIN);
1382 1421 Progname(argv[0]);
1383 1422 lwpid_init();
1384 1423 fd_init(Setrlimit());
1385 1424
1386 1425 pagesize = sysconf(_SC_PAGESIZE);
1387 1426
1388 1427 while ((opt = getopt(argc, argv,
1389 1428 "vcd:HmarRLtu:U:n:p:C:P:h:s:S:j:k:TJWz:Z")) != (int)EOF) {
1390 1429 switch (opt) {
1391 1430 case 'r':
1392 1431 opts.o_outpmode |= OPT_NORESOLVE;
1393 1432 break;
1394 1433 case 'R':
1395 1434 opts.o_outpmode |= OPT_REALTIME;
1396 1435 break;
1397 1436 case 'c':
1398 1437 opts.o_outpmode &= ~OPT_TERMCAP;
1399 1438 opts.o_outpmode &= ~OPT_FULLSCREEN;
1400 1439 break;
1401 1440 case 'd':
1402 1441 if (optarg) {
1403 1442 if (*optarg == 'u')
1404 1443 opts.o_outpmode |= OPT_UDATE;
1405 1444 else if (*optarg == 'd')
1406 1445 opts.o_outpmode |= OPT_DDATE;
1407 1446 else
1408 1447 Usage();
1409 1448 } else {
1410 1449 Usage();
1411 1450 }
1412 1451 break;
1413 1452 case 'h':
1414 1453 fill_table(&lgr_tbl, optarg, 'h');
1415 1454 break;
1416 1455 case 'H':
1417 1456 opts.o_outpmode |= OPT_LGRP;
1418 1457 break;
1419 1458 case 'm':
1420 1459 case 'v':
1421 1460 opts.o_outpmode &= ~OPT_PSINFO;
1422 1461 opts.o_outpmode |= OPT_MSACCT;
1423 1462 break;
1424 1463 case 't':
1425 1464 opts.o_outpmode &= ~OPT_PSINFO;
1426 1465 opts.o_outpmode |= OPT_USERS;
1427 1466 break;
1428 1467 case 'a':
1429 1468 opts.o_outpmode |= OPT_SPLIT | OPT_USERS;
1430 1469 break;
1431 1470 case 'T':
1432 1471 opts.o_outpmode |= OPT_SPLIT | OPT_TASKS;
1433 1472 break;
1434 1473 case 'J':
1435 1474 opts.o_outpmode |= OPT_SPLIT | OPT_PROJECTS;
1436 1475 break;
1437 1476 case 'n':
1438 1477 if ((p = strtok(optarg, ",")) == NULL)
1439 1478 Die(gettext("invalid argument for -n\n"));
1440 1479 opts.o_ntop = Atoi(p);
1441 1480 if (p = strtok(NULL, ","))
1442 1481 opts.o_nbottom = Atoi(p);
1443 1482 else if (opts.o_ntop == 0)
1444 1483 opts.o_nbottom = 5;
1445 1484 opts.o_outpmode &= ~OPT_FULLSCREEN;
1446 1485 break;
1447 1486 case 's':
1448 1487 opts.o_sortorder = -1;
1449 1488 sortk = optarg;
1450 1489 break;
1451 1490 case 'S':
1452 1491 opts.o_sortorder = 1;
1453 1492 sortk = optarg;
1454 1493 break;
1455 1494 case 'u':
1456 1495 if ((p = strtok(optarg, ", ")) == NULL)
1457 1496 Die(gettext("invalid argument for -u\n"));
1458 1497 add_uid(&euid_tbl, p);
1459 1498 while (p = strtok(NULL, ", "))
1460 1499 add_uid(&euid_tbl, p);
1461 1500 break;
1462 1501 case 'U':
1463 1502 if ((p = strtok(optarg, ", ")) == NULL)
1464 1503 Die(gettext("invalid argument for -U\n"));
1465 1504 add_uid(&ruid_tbl, p);
1466 1505 while (p = strtok(NULL, ", "))
1467 1506 add_uid(&ruid_tbl, p);
1468 1507 break;
1469 1508 case 'p':
1470 1509 fill_table(&pid_tbl, optarg, 'p');
1471 1510 break;
1472 1511 case 'C':
1473 1512 fill_set_table(optarg);
1474 1513 opts.o_outpmode |= OPT_PSETS;
1475 1514 break;
1476 1515 case 'P':
1477 1516 fill_table(&cpu_tbl, optarg, 'P');
1478 1517 break;
1479 1518 case 'k':
1480 1519 fill_table(&tsk_tbl, optarg, 'k');
1481 1520 break;
1482 1521 case 'j':
1483 1522 fill_prj_table(optarg);
1484 1523 break;
1485 1524 case 'L':
1486 1525 opts.o_outpmode |= OPT_LWPS;
1487 1526 break;
1488 1527 case 'W':
1489 1528 opts.o_outpmode |= OPT_TRUNC;
1490 1529 break;
1491 1530 case 'z':
1492 1531 if ((p = strtok(optarg, ", ")) == NULL)
1493 1532 Die(gettext("invalid argument for -z\n"));
1494 1533 add_zone(&zone_tbl, p);
1495 1534 while (p = strtok(NULL, ", "))
1496 1535 add_zone(&zone_tbl, p);
1497 1536 break;
1498 1537 case 'Z':
1499 1538 opts.o_outpmode |= OPT_SPLIT | OPT_ZONES;
1500 1539 break;
1501 1540 default:
1502 1541 Usage();
1503 1542 }
1504 1543 }
1505 1544
1506 1545 (void) atexit(Exit);
1507 1546 if ((opts.o_outpmode & OPT_USERS) &&
1508 1547 !(opts.o_outpmode & OPT_SPLIT))
1509 1548 opts.o_nbottom = opts.o_ntop;
1510 1549 if (!(opts.o_outpmode & OPT_SPLIT) && opts.o_ntop == 0)
1511 1550 Die(gettext("invalid argument for -n\n"));
1512 1551 if (opts.o_nbottom == 0)
1513 1552 Die(gettext("invalid argument for -n\n"));
1514 1553 if (!(opts.o_outpmode & OPT_SPLIT) && (opts.o_outpmode & OPT_USERS) &&
1515 1554 ((opts.o_outpmode & (OPT_PSINFO | OPT_MSACCT))))
1516 1555 Die(gettext("-t option cannot be used with -v or -m\n"));
1517 1556
1518 1557 if ((opts.o_outpmode & OPT_SPLIT) && (opts.o_outpmode & OPT_USERS) &&
1519 1558 !((opts.o_outpmode & (OPT_PSINFO | OPT_MSACCT))))
1520 1559 Die(gettext("-t option cannot be used with "
1521 1560 "-a, -J, -T or -Z\n"));
1522 1561
1523 1562 if ((opts.o_outpmode & OPT_USERS) &&
1524 1563 (opts.o_outpmode & (OPT_TASKS | OPT_PROJECTS | OPT_ZONES)))
1525 1564 Die(gettext("-a option cannot be used with "
1526 1565 "-t, -J, -T or -Z\n"));
1527 1566
1528 1567 if (((opts.o_outpmode & OPT_TASKS) &&
1529 1568 (opts.o_outpmode & (OPT_PROJECTS|OPT_ZONES))) ||
1530 1569 ((opts.o_outpmode & OPT_PROJECTS) &&
1531 1570 (opts.o_outpmode & (OPT_TASKS|OPT_ZONES)))) {
1532 1571 Die(gettext(
1533 1572 "-J, -T and -Z options are mutually exclusive\n"));
1534 1573 }
1535 1574
1536 1575 /*
1537 1576 * There is not enough space to combine microstate information and
1538 1577 * lgroup information and still fit in 80-column output.
1539 1578 */
1540 1579 if ((opts.o_outpmode & OPT_LGRP) && (opts.o_outpmode & OPT_MSACCT)) {
1541 1580 Die(gettext("-H and -m options are mutually exclusive\n"));
1542 1581 }
1543 1582
1544 1583 if (argc > optind)
1545 1584 opts.o_interval = Atoi(argv[optind++]);
1546 1585 if (argc > optind)
1547 1586 opts.o_count = Atoi(argv[optind++]);
1548 1587 if (opts.o_count == 0)
1549 1588 Die(gettext("invalid counter value\n"));
1550 1589 if (argc > optind)
1551 1590 Usage();
1552 1591 if (opts.o_outpmode & OPT_REALTIME)
1553 1592 Priocntl("RT");
1554 1593 if (isatty(STDOUT_FILENO) == 1 && isatty(STDIN_FILENO))
1555 1594 opts.o_outpmode |= OPT_TTY; /* interactive */
1556 1595 if (!(opts.o_outpmode & OPT_TTY)) {
1557 1596 opts.o_outpmode &= ~OPT_TERMCAP; /* no termcap for pipes */
1558 1597 opts.o_outpmode &= ~OPT_FULLSCREEN;
1559 1598 }
1560 1599 if (opts.o_outpmode & OPT_TERMCAP)
1561 1600 ldtermcap(); /* can turn OPT_TERMCAP off */
1562 1601 if (opts.o_outpmode & OPT_TERMCAP)
1563 1602 (void) setsize();
1564 1603 list_alloc(&lwps, opts.o_ntop);
1565 1604 list_alloc(&users, opts.o_nbottom);
1566 1605 list_alloc(&tasks, opts.o_nbottom);
1567 1606 list_alloc(&projects, opts.o_nbottom);
1568 1607 list_alloc(&zones, opts.o_nbottom);
1569 1608 list_alloc(&lgroups, opts.o_nbottom);
1570 1609 list_setkeyfunc(sortk, &opts, &lwps, LT_LWPS);
1571 1610 list_setkeyfunc(NULL, &opts, &users, LT_USERS);
1572 1611 list_setkeyfunc(NULL, &opts, &tasks, LT_TASKS);
1573 1612 list_setkeyfunc(NULL, &opts, &projects, LT_PROJECTS);
1574 1613 list_setkeyfunc(NULL, &opts, &zones, LT_ZONES);
1575 1614 list_setkeyfunc(NULL, &opts, &lgroups, LT_LGRPS);
1576 1615 if (opts.o_outpmode & OPT_TERMCAP)
1577 1616 curses_on();
1578 1617 if ((procdir = opendir("/proc")) == NULL)
1579 1618 Die(gettext("cannot open /proc directory\n"));
1580 1619 if (opts.o_outpmode & OPT_TTY) {
1581 1620 (void) printf(gettext("Please wait...\r"));
1582 1621 if (!(opts.o_outpmode & OPT_TERMCAP))
1583 1622 (void) putchar('\n');
1584 1623 (void) fflush(stdout);
1585 1624 }
1586 1625 set_signals();
1587 1626 pollset.fd = STDIN_FILENO;
1588 1627 pollset.events = POLLIN;
1589 1628 timeout = opts.o_interval * MILLISEC;
1590 1629
1591 1630 /*
1592 1631 * main program loop
1593 1632 */
1594 1633 do {
1595 1634 if (sigterm == 1)
1596 1635 break;
1597 1636 if (sigtstp == 1) {
1598 1637 curses_off();
1599 1638 (void) signal(SIGTSTP, SIG_DFL);
1600 1639 (void) kill(0, SIGTSTP);
1601 1640 /*
1602 1641 * prstat stops here until it receives SIGCONT signal.
1603 1642 */
1604 1643 sigtstp = 0;
1605 1644 (void) signal(SIGTSTP, sig_handler);
1606 1645 curses_on();
1607 1646 print_movecur = FALSE;
1608 1647 if (opts.o_outpmode & OPT_FULLSCREEN)
1609 1648 sigwinch = 1;
1610 1649 }
1611 1650 if (sigwinch == 1) {
1612 1651 if (setsize() == 1) {
1613 1652 list_free(&lwps);
1614 1653 list_free(&users);
1615 1654 list_free(&tasks);
1616 1655 list_free(&projects);
1617 1656 list_free(&zones);
1618 1657 list_alloc(&lwps, opts.o_ntop);
1619 1658 list_alloc(&users, opts.o_nbottom);
1620 1659 list_alloc(&tasks, opts.o_nbottom);
1621 1660 list_alloc(&projects, opts.o_nbottom);
1622 1661 list_alloc(&zones, opts.o_nbottom);
1623 1662 }
1624 1663 sigwinch = 0;
1625 1664 (void) signal(SIGWINCH, sig_handler);
1626 1665 }
1627 1666 prstat_scandir(procdir);
1628 1667 list_refresh(&lwps);
1629 1668 if (print_movecur)
1630 1669 (void) putp(movecur);
1631 1670 print_movecur = TRUE;
1632 1671 if ((opts.o_outpmode & OPT_PSINFO) ||
1633 1672 (opts.o_outpmode & OPT_MSACCT)) {
1634 1673 list_sort(&lwps);
1635 1674 list_print(&lwps);
1636 1675 }
1637 1676 if (opts.o_outpmode & OPT_USERS) {
1638 1677 list_getsize(&users);
1639 1678 list_sort(&users);
1640 1679 list_print(&users);
1641 1680 list_clear(&users);
1642 1681 }
1643 1682 if (opts.o_outpmode & OPT_TASKS) {
1644 1683 list_getsize(&tasks);
1645 1684 list_sort(&tasks);
1646 1685 list_print(&tasks);
1647 1686 list_clear(&tasks);
1648 1687 }
1649 1688 if (opts.o_outpmode & OPT_PROJECTS) {
1650 1689 list_getsize(&projects);
1651 1690 list_sort(&projects);
1652 1691 list_print(&projects);
1653 1692 list_clear(&projects);
1654 1693 }
1655 1694 if (opts.o_outpmode & OPT_ZONES) {
1656 1695 list_getsize(&zones);
1657 1696 list_sort(&zones);
1658 1697 list_print(&zones);
1659 1698 list_clear(&zones);
1660 1699 }
1661 1700 if (opts.o_count == 1)
1662 1701 break;
1663 1702 /*
1664 1703 * If poll() returns -1 and sets errno to EINTR here because
1665 1704 * the process received a signal, it is Ok to abort this
1666 1705 * timeout and loop around because we check the signals at the
1667 1706 * top of the loop.
1668 1707 */
1669 1708 if (opts.o_outpmode & OPT_TTY) {
1670 1709 if (poll(&pollset, (nfds_t)1, timeout) > 0) {
1671 1710 if (read(STDIN_FILENO, &key, 1) == 1) {
1672 1711 if (tolower(key) == 'q')
1673 1712 break;
1674 1713 }
1675 1714 }
1676 1715 } else {
1677 1716 (void) sleep(opts.o_interval);
1678 1717 }
1679 1718 } while (opts.o_count == (-1) || --opts.o_count);
1680 1719
1681 1720 if (opts.o_outpmode & OPT_TTY)
1682 1721 (void) putchar('\r');
1683 1722 return (0);
1684 1723 }
↓ open down ↓ |
477 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX