"Fossies" - the Fresh Open Source Software Archive 
Member "atop-2.8.1/showlinux.c" (7 Jan 2023, 89772 Bytes) of package /linux/misc/atop-2.8.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "showlinux.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
2.7.1_vs_2.8.0.
1 /*
2 ** ATOP - System & Process Monitor
3 **
4 ** The program 'atop' offers the possibility to view the activity of
5 ** the system on system-level as well as process-level.
6 **
7 ** This source-file contains the Linux-specific functions to calculate
8 ** figures to be visualized.
9 ** ==========================================================================
10 ** Author: Gerlof Langeveld
11 ** Original version.
12 ** E-mail: gerlof.langeveld@atoptool.nl
13 ** Date: July 2002
14 **
15 ** Author: JC van Winkel - AT Computing, Nijmegen, Holland
16 ** Complete redesign.
17 ** Date: November 2009
18 ** --------------------------------------------------------------------------
19 ** Copyright (C) 2009-2010 JC van Winkel
20 **
21 ** This program is free software; you can redistribute it and/or modify it
22 ** under the terms of the GNU General Public License as published by the
23 ** Free Software Foundation; either version 2, or (at your option) any
24 ** later version.
25 **
26 ** This program is distributed in the hope that it will be useful, but
27 ** WITHOUT ANY WARRANTY; without even the implied warranty of
28 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
29 ** See the GNU General Public License for more details.
30 **
31 ** You should have received a copy of the GNU General Public License
32 ** along with this program; if not, write to the Free Software
33 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 ** --------------------------------------------------------------------------
35 **
36 ** $Log: showlinux.c,v $
37 ** Revision 1.70 2010/10/23 14:04:12 gerlof
38 ** Counters for total number of running and sleep threads (JC van Winkel).
39 **
40 ** Revision 1.69 2010/05/18 19:20:08 gerlof
41 ** Introduce CPU frequency and scaling (JC van Winkel).
42 **
43 ** Revision 1.68 2010/04/23 12:19:35 gerlof
44 ** Modified mail-address in header.
45 **
46 ** Revision 1.67 2010/04/17 17:20:33 gerlof
47 ** Allow modifying the layout of the columns in the system lines.
48 **
49 ** Revision 1.66 2010/03/16 21:14:46 gerlof
50 ** Program and user selection can be combined with program and user
51 ** accumulation.
52 **
53 ** Revision 1.65 2010/03/04 10:53:26 gerlof
54 ** Support I/O-statistics on logical volumes and MD devices.
55 **
56 ** Revision 1.64 2010/01/18 18:06:28 gerlof
57 ** Modified priorities for system-level columns.
58 **
59 ** Revision 1.63 2010/01/16 12:54:33 gerlof
60 ** Corrected order of columns.
61 **
62 ** Revision 1.62 2010/01/16 11:38:02 gerlof
63 ** Corrected counters for patched kernels (JC van Winkel).
64 **
65 ** Revision 1.61 2010/01/08 11:25:56 gerlof
66 ** Corrected column-width and priorities of network-stats.
67 **
68 ** Revision 1.60 2010/01/03 18:27:19 gerlof
69 ** *** empty log message ***
70 **
71 ** Revision 1.59 2009/12/19 21:01:28 gerlof
72 ** Improved syntax checking for ownprocline keyword (JC van Winkel).
73 **
74 ** Revision 1.58 2009/12/17 11:59:28 gerlof
75 ** Gather and display new counters: dirty cache and guest cpu usage.
76 **
77 ** Revision 1.57 2009/12/17 10:51:19 gerlof
78 ** Allow own defined process line with key 'o' and a definition
79 ** in the atoprc file.
80 **
81 ** Revision 1.56 2009/12/17 09:13:19 gerlof
82 ** Reformatted some fields for better grouping of info.
83 **
84 ** Revision 1.55 2009/12/12 10:11:18 gerlof
85 ** Register and display end date and end time for process.
86 **
87 ** Revision 1.54 2009/12/12 09:06:48 gerlof
88 ** \Corrected cumulated disk I/O per user/program (JC van Winkel).
89 **
90 ** Revision 1.53 2009/12/10 14:02:39 gerlof
91 ** Add EUID, SUID and FSUID (and similar for GID's).
92 **
93 ** Revision 1.52 2009/12/10 11:56:34 gerlof
94 ** Various bug-solutions.
95 **
96 ** Revision 1.51 2009/12/10 10:08:01 gerlof
97 ** Major redesign for improved user interface (variable number of columns).
98 ** Made by JC van Winkel.
99 **
100 ** Revision 1.49 2008/03/06 08:38:28 gerlof
101 ** Register/show ppid of a process.
102 **
103 ** Revision 1.48 2008/01/18 07:37:05 gerlof
104 ** Show information about the state of the individual threads
105 ** in the scheduling report shown with keystroke 's'.
106 **
107 ** Revision 1.47 2008/01/07 11:34:18 gerlof
108 ** Correct the sort-order of network-interfaces (on busy-percentage).
109 **
110 ** Revision 1.46 2007/11/07 09:23:29 gerlof
111 ** Modified format for avg1, avg5 and avg15 (CPL) when counters too large.
112 **
113 ** Revision 1.45 2007/11/05 11:43:25 gerlof
114 ** Bug-solution for new-process indicator on 64-bits machines.
115 **
116 ** Revision 1.44 2007/11/05 10:57:56 gerlof
117 ** Bug-solution for huge exit code on 64-bits machines.
118 **
119 ** Revision 1.43 2007/08/17 09:45:57 gerlof
120 ** Experimental: gather info about HTTP statistics.
121 **
122 ** Revision 1.42 2007/08/16 12:02:04 gerlof
123 ** Add support for atopsar reporting.
124 ** Concerns modification of networking-counters.
125 **
126 ** Revision 1.41 2007/07/04 10:18:16 gerlof
127 ** Bug-solution for division by zero.
128 **
129 ** Revision 1.40 2007/07/03 09:02:29 gerlof
130 ** Support Apache-statistics.
131 **
132 ** Revision 1.39 2007/03/22 10:12:54 gerlof
133 ** Support for io counters (>= kernel 2.6.20).
134 **
135 ** Revision 1.38 2007/03/21 14:22:24 gerlof
136 ** Handle io counters maintained from 2.6.20
137 **
138 ** Revision 1.37 2007/02/13 10:36:09 gerlof
139 ** Removal of external declarations.
140 ** Use of hertz variable instead of HZ.
141 **
142 ** Revision 1.36 2007/01/26 12:11:07 gerlof
143 ** Add configuration-value 'swoutcritsec'.
144 **
145 ** Revision 1.35 2007/01/26 10:25:42 gerlof
146 ** Introduce steal percentage for virtual machines.
147 ** Correct bug: when one interface is colored all subsequent interfaces
148 ** are colored.
149 **
150 ** Revision 1.34 2007/01/18 10:58:45 gerlof
151 ** Only check for committed limit if it is not zero.
152 **
153 ** Revision 1.33 2007/01/18 10:37:09 gerlof
154 ** Add support for colors.
155 ** Add support for automatic determination of most critical resource.
156 ** Add support for parsing of new arguments in ~/.atoprc
157 **
158 ** Revision 1.32 2006/11/13 13:48:46 gerlof
159 ** Implement load-average counters, context-switches and interrupts.
160 **
161 ** Revision 1.31 2006/02/07 08:38:49 gerlof
162 ** Swapped the zombie counter and exit counter in the PRC-line.
163 **
164 ** Revision 1.30 2006/02/07 08:30:07 gerlof
165 ** Add possibility to show counters per second.
166 ** Ease parsing of output-lines by fixed number of columns per line.
167 **
168 ** Revision 1.29 2006/01/30 09:24:12 gerlof
169 ** PRC-line: 'exits' modified to 'exit' to save space.
170 **
171 ** Revision 1.28 2006/01/30 09:14:26 gerlof
172 ** Extend memory counters (a.o. page scans).
173 **
174 ** Revision 1.27 2005/11/04 14:16:45 gerlof
175 ** Minor bug-solutions.
176 **
177 ** Revision 1.26 2005/10/28 09:51:29 gerlof
178 ** All flags/subcommands are defined as macro's.
179 ** Subcommand 'p' has been changed to 'z' (pause).
180 **
181 ** Revision 1.25 2005/10/21 09:51:11 gerlof
182 ** Per-user accumulation of resource consumption.
183 **
184 ** Revision 1.24 2004/12/14 15:06:48 gerlof
185 ** Implementation of patch-recognition for disk and network-statistics.
186 **
187 ** Revision 1.23 2004/10/28 08:31:41 gerlof
188 ** New counter: vm committed space
189 **
190 ** Revision 1.22 2004/09/24 10:02:46 gerlof
191 ** Wrong cpu-numbers for system level statistics.
192 **
193 ** Revision 1.21 2004/09/23 08:21:10 gerlof
194 ** Added wait-percentage per cpu.
195 **
196 ** Revision 1.20 2004/09/23 07:37:34 gerlof
197 ** Consistent handling of CPU percentages on system-level and process-level.
198 **
199 ** Revision 1.19 2004/09/13 09:20:21 gerlof
200 ** Modify subcommands (former 's' -> 'v', 'v' -> 'V', new 's').
201 **
202 ** Revision 1.18 2004/09/02 10:55:21 root
203 ** Added sleep-average to process-info.
204 **
205 ** Revision 1.17 2004/08/31 09:53:31 gerlof
206 ** Show information about underlying threads.
207 **
208 ** Revision 1.16 2004/06/01 11:58:34 gerlof
209 ** Regular expressions for selections on process-name and user-name.
210 **
211 ** Revision 1.15 2004/05/06 09:47:59 gerlof
212 ** Ported to kernel-version 2.6.
213 **
214 ** Revision 1.14 2003/07/07 09:27:34 gerlof
215 ** Cleanup code (-Wall proof).
216 **
217 ** Revision 1.13 2003/07/03 12:04:25 gerlof
218 ** Minor bug fixes.
219 **
220 ** Revision 1.12 2003/06/30 11:29:57 gerlof
221 ** Enlarge counters to 'long long'.
222 **
223 ** Revision 1.11 2003/06/24 06:22:10 gerlof
224 ** Limit number of system resource lines.
225 **
226 ** Revision 1.10 2003/02/07 10:43:22 gerlof
227 ** Solved a division-by-zero bug for process-percentage.
228 **
229 ** Revision 1.9 2003/01/24 14:20:57 gerlof
230 ** If possible, also show commandline when process has exited.
231 **
232 ** Revision 1.8 2003/01/17 07:32:49 gerlof
233 ** Show the full command-line per process (option 'c').
234 **
235 ** Revision 1.7 2002/10/04 10:05:54 gerlof
236 ** Bug-solution: New process indicator in static output set when needed.
237 **
238 ** Revision 1.6 2002/10/03 11:14:42 gerlof
239 ** Modify (effective) uid/gid to real uid/gid.
240 **
241 ** Revision 1.5 2002/09/26 13:52:51 gerlof
242 ** Limit header lines by not showing disks.
243 ** Limit header lines by not showing disks.
244 **
245 ** Revision 1.4 2002/09/16 08:59:13 gerlof
246 ** Change field EXCODE to STATUS for support of indicator of newly created
247 ** processes.
248 **
249 ** Revision 1.3 2002/09/02 08:42:44 gerlof
250 ** Bug-solution: blank line after header when more than 999 screens of
251 ** process-list information.
252 **
253 ** Revision 1.2 2002/08/30 07:11:20 gerlof
254 ** Minor changes in the header-line of the process list.
255 **
256 ** Revision 1.1 2002/07/24 11:14:16 gerlof
257 ** Initial revision
258 **
259 **
260 ** Initial
261 **
262 */
263
264 #include <sys/types.h>
265 #include <sys/param.h>
266 #include <sys/stat.h>
267 #include <signal.h>
268 #include <time.h>
269 #include <stdio.h>
270 #include <stdlib.h>
271 #include <string.h>
272 #include <errno.h>
273 #include <fcntl.h>
274 #include <unistd.h>
275 #include <stdarg.h>
276 #include <curses.h>
277 #include <pwd.h>
278 #include <grp.h>
279 #include <regex.h>
280
281 #include "atop.h"
282 #include "photoproc.h"
283 #include "photosyst.h"
284 #include "showgeneric.h"
285 #include "showlinux.h"
286
287 static void make_proc_dynamicgen(void);
288
289 /*
290 ** critical percentages for occupation-percentage;
291 ** these defaults can be overruled via the config-file
292 */
293 int cpubadness = 90; /* percentage */
294 int gpubadness = 100; /* percentage */
295 int membadness = 90; /* percentage */
296 int swpbadness = 80; /* percentage */
297 int dskbadness = 70; /* percentage */
298 int netbadness = 90; /* percentage */
299 int pagbadness = 10; /* number per second */
300
301 int almostcrit = 80; /* percentage */
302
303 /*
304 * tables with all sys_printdefs
305 */
306 sys_printdef *prcsyspdefs[] = {
307 &syspdef_PRCSYS,
308 &syspdef_PRCUSER,
309 &syspdef_PRCNPROC,
310 &syspdef_PRCNRUNNING,
311 &syspdef_PRCNSLEEPING,
312 &syspdef_PRCNDSLEEPING,
313 &syspdef_PRCNZOMBIE,
314 &syspdef_PRCCLONES,
315 &syspdef_PRCNNEXIT,
316 &syspdef_BLANKBOX,
317 0
318 };
319 sys_printdef *cpusyspdefs[] = {
320 &syspdef_CPUSYS,
321 &syspdef_CPUUSER,
322 &syspdef_CPUIRQ,
323 &syspdef_CPUIDLE,
324 &syspdef_CPUWAIT,
325 &syspdef_BLANKBOX,
326 &syspdef_CPUIPC,
327 &syspdef_CPUCYCLE,
328 &syspdef_CPUFREQ,
329 &syspdef_CPUSCALE,
330 &syspdef_CPUSTEAL,
331 &syspdef_CPUGUEST,
332 &syspdef_BLANKBOX,
333 0
334 };
335 sys_printdef *cpisyspdefs[] = {
336 &syspdef_CPUISYS,
337 &syspdef_CPUIUSER,
338 &syspdef_CPUIIRQ,
339 &syspdef_CPUIIDLE,
340 &syspdef_CPUIWAIT,
341 &syspdef_BLANKBOX,
342 &syspdef_CPUIIPC,
343 &syspdef_CPUICYCLE,
344 &syspdef_CPUIFREQ,
345 &syspdef_CPUISCALE,
346 &syspdef_CPUISTEAL,
347 &syspdef_CPUIGUEST,
348 &syspdef_BLANKBOX,
349 0
350 };
351 sys_printdef *cplsyspdefs[] = {
352 &syspdef_CPLNUMCPU,
353 &syspdef_CPLAVG1,
354 &syspdef_CPLAVG5,
355 &syspdef_CPLAVG15,
356 &syspdef_CPLCSW,
357 &syspdef_CPLINTR,
358 &syspdef_BLANKBOX,
359 0
360 };
361 sys_printdef *gpusyspdefs[] = {
362 &syspdef_GPUBUS,
363 &syspdef_GPUGPUPERC,
364 &syspdef_GPUMEMPERC,
365 &syspdef_GPUMEMOCC,
366 &syspdef_GPUMEMTOT,
367 &syspdef_GPUMEMUSE,
368 &syspdef_GPUMEMAVG,
369 &syspdef_GPUTYPE,
370 &syspdef_GPUNRPROC,
371 &syspdef_BLANKBOX,
372 0
373 };
374 sys_printdef *memsyspdefs1[] = {
375 &syspdef_MEMTOT,
376 &syspdef_MEMFREE,
377 &syspdef_BLANKBOX,
378 &syspdef_MEMCACHE,
379 &syspdef_MEMDIRTY,
380 &syspdef_MEMBUFFER,
381 &syspdef_BLANKBOX,
382 &syspdef_MEMSLAB,
383 &syspdef_RECSLAB,
384 &syspdef_BLANKBOX,
385 &syspdef_PAGETABS,
386 &syspdef_BLANKBOX,
387 &syspdef_HUPTOT,
388 &syspdef_HUPUSE,
389 0
390 };
391 sys_printdef *memsyspdefs2[] = {
392 &syspdef_NUMNUMA,
393 &syspdef_BLANKBOX,
394 &syspdef_TCPSOCK,
395 &syspdef_UDPSOCK,
396 &syspdef_BLANKBOX,
397 &syspdef_SHMEM,
398 &syspdef_SHMRSS,
399 &syspdef_SHMSWP,
400 &syspdef_BLANKBOX,
401 &syspdef_VMWBAL,
402 &syspdef_BLANKBOX,
403 &syspdef_ZFSARC,
404 0
405 };
406 sys_printdef *swpsyspdefs[] = {
407 &syspdef_SWPTOT,
408 &syspdef_SWPFREE,
409 &syspdef_SWPCACHE,
410 &syspdef_BLANKBOX,
411 &syspdef_ZSWTOTAL,
412 &syspdef_ZSWSTORED,
413 &syspdef_KSMSHARING,
414 &syspdef_KSMSHARED,
415 &syspdef_BLANKBOX,
416 &syspdef_SWPCOMMITTED,
417 &syspdef_SWPCOMMITLIM,
418 &syspdef_BLANKBOX,
419 0
420 };
421 sys_printdef *pagsyspdefs[] = {
422 &syspdef_PAGSCAN,
423 &syspdef_PAGSTEAL,
424 &syspdef_PAGSTALL,
425 &syspdef_PAGCOMPACT,
426 &syspdef_PGMIGRATE,
427 &syspdef_NUMAMIGRATE,
428 &syspdef_PAGSWIN,
429 &syspdef_PAGSWOUT,
430 &syspdef_OOMKILLS,
431 &syspdef_PAGPGIN,
432 &syspdef_PAGPGOUT,
433 &syspdef_BLANKBOX,
434 0
435 };
436 sys_printdef *memnumasyspdefs[] = {
437 &syspdef_NUMATOT,
438 &syspdef_NUMAFREE,
439 &syspdef_NUMAFILEPAGE,
440 &syspdef_NUMANR,
441 &syspdef_NUMADIRTY,
442 &syspdef_NUMAACTIVE,
443 &syspdef_NUMAINACTIVE,
444 &syspdef_NUMASLAB,
445 &syspdef_NUMASLABRECLAIM,
446 &syspdef_NUMASHMEM,
447 &syspdef_NUMAFRAG,
448 &syspdef_NUMAHUPTOT,
449 0
450 };
451 sys_printdef *cpunumasyspdefs[] = {
452 &syspdef_NUMACPUSYS,
453 &syspdef_NUMACPUUSER,
454 &syspdef_NUMACPUNICE,
455 &syspdef_NUMACPUIRQ,
456 &syspdef_NUMACPUSOFTIRQ,
457 &syspdef_NUMACPUIDLE,
458 &syspdef_NUMACPUWAIT,
459 &syspdef_NUMACPUSTEAL,
460 &syspdef_NUMACPUGUEST,
461 &syspdef_NUMANUMCPU,
462 0
463 };
464 sys_printdef *llcsyspdefs[] = {
465 &syspdef_LLCMBMTOTAL,
466 &syspdef_LLCMBMLOCAL,
467 &syspdef_NUMLLC,
468 &syspdef_BLANKBOX,
469 0
470 };
471 sys_printdef *psisyspdefs[] = {
472 &syspdef_PSICPUSTOT,
473 &syspdef_PSIMEMSTOT,
474 &syspdef_PSIMEMFTOT,
475 &syspdef_PSIIOSTOT,
476 &syspdef_PSIIOFTOT,
477 &syspdef_PSICPUS,
478 &syspdef_PSIMEMS,
479 &syspdef_PSIMEMF,
480 &syspdef_PSIIOS,
481 &syspdef_PSIIOF,
482 &syspdef_BLANKBOX,
483 0
484 };
485 sys_printdef *contsyspdefs[] = {
486 &syspdef_CONTNAME,
487 &syspdef_CONTNPROC,
488 &syspdef_CONTCPU,
489 &syspdef_CONTMEM,
490 &syspdef_BLANKBOX,
491 0
492 };
493 sys_printdef *dsksyspdefs[] = {
494 &syspdef_DSKNAME,
495 &syspdef_DSKBUSY,
496 &syspdef_DSKNREAD,
497 &syspdef_DSKNWRITE,
498 &syspdef_DSKNDISC,
499 &syspdef_DSKMBPERSECWR,
500 &syspdef_DSKMBPERSECRD,
501 &syspdef_DSKKBPERRD,
502 &syspdef_DSKKBPERWR,
503 &syspdef_DSKKBPERDS,
504 &syspdef_DSKINFLIGHT,
505 &syspdef_DSKAVQUEUE,
506 &syspdef_DSKAVIO,
507 &syspdef_BLANKBOX,
508 0
509 };
510 sys_printdef *nfsmntsyspdefs[] = {
511 &syspdef_NFMPATH,
512 &syspdef_NFMSERVER,
513 &syspdef_NFMTOTREAD,
514 &syspdef_NFMTOTWRITE,
515 &syspdef_NFMNREAD,
516 &syspdef_NFMNWRITE,
517 &syspdef_NFMDREAD,
518 &syspdef_NFMDWRITE,
519 &syspdef_NFMMREAD,
520 &syspdef_NFMMWRITE,
521 &syspdef_BLANKBOX,
522 0
523 };
524 sys_printdef *nfcsyspdefs[] = {
525 &syspdef_NFCRPCCNT,
526 &syspdef_NFCRPCREAD,
527 &syspdef_NFCRPCWRITE,
528 &syspdef_NFCRPCRET,
529 &syspdef_NFCRPCARF,
530 &syspdef_BLANKBOX,
531 0
532 };
533 sys_printdef *nfssyspdefs[] = {
534 &syspdef_NFSRPCCNT,
535 &syspdef_NFSRPCREAD,
536 &syspdef_NFSRPCWRITE,
537 &syspdef_NFSNRBYTES,
538 &syspdef_NFSNWBYTES,
539 &syspdef_NFSNETTCP,
540 &syspdef_NFSNETUDP,
541 &syspdef_NFSBADFMT,
542 &syspdef_NFSBADAUT,
543 &syspdef_NFSBADCLN,
544 &syspdef_NFSRCHITS,
545 &syspdef_NFSRCMISS,
546 &syspdef_NFSRCNOCA,
547 &syspdef_BLANKBOX,
548 0
549 };
550 sys_printdef *nettranssyspdefs[] = {
551 &syspdef_NETTRANSPORT,
552 &syspdef_NETTCPI,
553 &syspdef_NETTCPO,
554 &syspdef_NETUDPI,
555 &syspdef_NETUDPO,
556 &syspdef_NETTCPACTOPEN,
557 &syspdef_NETTCPPASVOPEN,
558 &syspdef_NETTCPRETRANS,
559 &syspdef_NETTCPINERR,
560 &syspdef_NETTCPORESET,
561 &syspdef_NETUDPNOPORT,
562 &syspdef_NETUDPINERR,
563 &syspdef_BLANKBOX,
564 0
565 };
566 sys_printdef *netnetsyspdefs[] = {
567 &syspdef_NETNETWORK,
568 &syspdef_NETIPI,
569 &syspdef_NETIPO,
570 &syspdef_NETIPFRW,
571 &syspdef_NETIPDELIV,
572 &syspdef_NETICMPIN,
573 &syspdef_NETICMPOUT,
574 &syspdef_BLANKBOX,
575 0
576 };
577 sys_printdef *netintfsyspdefs[] = {
578 &syspdef_NETNAME,
579 &syspdef_NETPCKI,
580 &syspdef_NETPCKO,
581 &syspdef_NETSPEEDMAX,
582 &syspdef_NETSPEEDIN,
583 &syspdef_NETSPEEDOUT,
584 &syspdef_NETCOLLIS,
585 &syspdef_NETMULTICASTIN,
586 &syspdef_NETRCVERR,
587 &syspdef_NETSNDERR,
588 &syspdef_NETRCVDROP,
589 &syspdef_NETSNDDROP,
590 &syspdef_BLANKBOX,
591 0
592 };
593
594 sys_printdef *infinisyspdefs[] = {
595 &syspdef_IFBNAME,
596 &syspdef_IFBPCKI,
597 &syspdef_IFBPCKO,
598 &syspdef_IFBSPEEDMAX,
599 &syspdef_IFBSPEEDIN,
600 &syspdef_IFBSPEEDOUT,
601 &syspdef_IFBLANES,
602 &syspdef_BLANKBOX,
603 0
604 };
605
606 /*
607 * table with all proc_printdefs
608 */
609 proc_printdef *allprocpdefs[]=
610 {
611 &procprt_PID,
612 &procprt_TID,
613 &procprt_PPID,
614 &procprt_SYSCPU,
615 &procprt_USRCPU,
616 &procprt_RUNDELAY,
617 &procprt_BLKDELAY,
618 &procprt_WCHAN,
619 &procprt_VGROW,
620 &procprt_RGROW,
621 &procprt_MINFLT,
622 &procprt_MAJFLT,
623 &procprt_VSTEXT,
624 &procprt_VSIZE,
625 &procprt_RSIZE,
626 &procprt_PSIZE,
627 &procprt_VSLIBS,
628 &procprt_VDATA,
629 &procprt_VSTACK,
630 &procprt_SWAPSZ,
631 &procprt_LOCKSZ,
632 &procprt_CMD,
633 &procprt_RUID,
634 &procprt_EUID,
635 &procprt_SUID,
636 &procprt_FSUID,
637 &procprt_RGID,
638 &procprt_EGID,
639 &procprt_SGID,
640 &procprt_FSGID,
641 &procprt_CTID,
642 &procprt_VPID,
643 &procprt_CID,
644 &procprt_STDATE,
645 &procprt_STTIME,
646 &procprt_ENDATE,
647 &procprt_ENTIME,
648 &procprt_THR,
649 &procprt_TRUN,
650 &procprt_TSLPI,
651 &procprt_TSLPU,
652 &procprt_POLI,
653 &procprt_NICE,
654 &procprt_PRI,
655 &procprt_RTPR,
656 &procprt_CURCPU,
657 &procprt_ST,
658 &procprt_EXC,
659 &procprt_S,
660 &procprt_COMMAND_LINE,
661 &procprt_NPROCS,
662 &procprt_RDDSK,
663 &procprt_WRDSK,
664 &procprt_CWRDSK,
665 &procprt_WCANCEL,
666 &procprt_TCPRCV,
667 &procprt_TCPRASZ,
668 &procprt_TCPSND,
669 &procprt_TCPSASZ,
670 &procprt_UDPRCV,
671 &procprt_UDPRASZ,
672 &procprt_UDPSND,
673 &procprt_UDPSASZ,
674 &procprt_RNET,
675 &procprt_SNET,
676 &procprt_BANDWI,
677 &procprt_BANDWO,
678 &procprt_GPULIST,
679 &procprt_GPUMEMNOW,
680 &procprt_GPUMEMAVG,
681 &procprt_GPUGPUBUSY,
682 &procprt_GPUMEMBUSY,
683 &procprt_CGROUP_PATH,
684 &procprt_CGRCPUWGT,
685 &procprt_CGRCPUMAX,
686 &procprt_CGRCPUMAXR,
687 &procprt_CGRMEMMAX,
688 &procprt_CGRMEMMAXR,
689 &procprt_CGRSWPMAX,
690 &procprt_CGRSWPMAXR,
691 &procprt_SORTITEM,
692 0
693 };
694
695 /*
696 * table with all proc_printdefs with PID/TID width to be initialized
697 */
698 proc_printdef *idprocpdefs[]=
699 {
700 &procprt_PID,
701 &procprt_TID,
702 &procprt_PPID,
703 &procprt_VPID,
704 0
705 };
706
707
708 /***************************************************************/
709 /*
710 * output definitions for process data
711 * these should be user configurable
712 */
713 proc_printpair userprocs[MAXITEMS];
714 proc_printpair memprocs[MAXITEMS];
715 proc_printpair schedprocs[MAXITEMS];
716 proc_printpair genprocs[MAXITEMS];
717 proc_printpair dskprocs[MAXITEMS];
718 proc_printpair netprocs[MAXITEMS];
719 proc_printpair gpuprocs[MAXITEMS];
720 proc_printpair varprocs[MAXITEMS];
721 proc_printpair cmdprocs[MAXITEMS];
722 proc_printpair cgrprocs[MAXITEMS];
723 proc_printpair ownprocs[MAXITEMS];
724 proc_printpair totusers[MAXITEMS];
725 proc_printpair totprocs[MAXITEMS];
726 proc_printpair totconts[MAXITEMS];
727
728
729 /*****************************************************************/
730 /*
731 * output definitions for system data
732 * these should be user configurable
733 */
734 sys_printpair sysprcline[MAXITEMS];
735 sys_printpair allcpuline[MAXITEMS];
736 sys_printpair indivcpuline[MAXITEMS];
737 sys_printpair cplline[MAXITEMS];
738 sys_printpair gpuline[MAXITEMS];
739 sys_printpair memline1[MAXITEMS];
740 sys_printpair memline2[MAXITEMS];
741 sys_printpair swpline[MAXITEMS];
742 sys_printpair memnumaline[MAXITEMS];
743 sys_printpair cpunumaline[MAXITEMS];
744 sys_printpair llcline[MAXITEMS];
745 sys_printpair pagline[MAXITEMS];
746 sys_printpair psiline[MAXITEMS];
747 sys_printpair contline[MAXITEMS];
748 sys_printpair dskline[MAXITEMS];
749 sys_printpair nettransportline[MAXITEMS];
750 sys_printpair netnetline[MAXITEMS];
751 sys_printpair netinterfaceline[MAXITEMS];
752 sys_printpair infinibandline[MAXITEMS];
753 sys_printpair nfsmountline[MAXITEMS];
754 sys_printpair nfcline[MAXITEMS];
755 sys_printpair nfsline[MAXITEMS];
756
757 typedef struct {
758 const char *name;
759 int prio;
760 } name_prio;
761
762 /*
763 ** make an string,int pair array from a string. chop based on spaces/tabs
764 ** example: input: "ABCD:3 EFG:1 QWE:16"
765 ** output: { { "ABCD", 3 }, {"EFG", 1}, { "QWE", 16}, { 0, 0 } }
766 */
767 static void
768 makeargv(char *line, const char *linename, name_prio *vec)
769 {
770 int i=0;
771 char *p=line;
772 char *name=0;
773 char *prio=0;
774
775 // find pair and scan it
776 while (*p && i<MAXITEMS-1)
777 {
778 // skip initial spaces
779 while (*p && (*p==' ' || *p=='\t'))
780 {
781 ++p;
782 }
783 if (! *p)
784 {
785 break;
786 }
787 name=p;
788 // found a new word; let's chop!
789 while (*p && *p !=':')
790 {
791 ++p;
792 }
793 if (*p==':')
794 {
795 *p=0;
796 }
797 else
798 mcleanstop(1, "atoprc - %s: no name:prio pair for "
799 "`%s'\n", name, linename);
800
801 /* now get number */
802 p++;
803 prio=p;
804 errno = 0; /* To distinguish success/failure after call */
805
806 long lprio=strtol(p, &p, 10);
807
808 if (prio==p || errno == ERANGE || lprio >= INT_MAX || lprio <0)
809 {
810 fprintf(stderr,
811 "atoprc - %s: item `%s` has "
812 "invalid priority `", linename, name);
813 while (*prio && *prio !=' ') {
814 fputc(*prio, stderr);
815 prio++;
816 }
817 fprintf(stderr, "'\n");
818 cleanstop(1);
819 }
820 vec[i].name=name;
821 vec[i].prio=lprio;
822
823 ++i;
824 }
825
826 vec[i].name=0;
827 }
828
829
830 /*
831 * make_sys_prints: make array of sys_printpairs
832 * input: string, sys_printpair array, maxentries
833 */
834 static void
835 make_sys_prints(sys_printpair *ar, int maxn, const char *pairs,
836 sys_printdef *permissables[], const char *linename,
837 struct sstat *sstat, extraparam *extra)
838 {
839 name_prio items[MAXITEMS];
840 int i, a, n=strlen(pairs);
841 char str[n+1];
842
843 strcpy(str, pairs);
844
845 makeargv(str, linename, items);
846
847 for(i=a=0; items[i].name && i<maxn-1; i++)
848 {
849 const char *name=items[i].name;
850 int j;
851
852 for (j=0; permissables[j] != 0; ++j)
853 {
854 if (strcmp(permissables[j]->configname, name) == 0)
855 {
856 // call validate function to see if this
857 // counter is relevant
858 //
859 if (sstat != NULL &&
860 permissables[j]->dovalidate != NULL &&
861 permissables[j]->dovalidate(sstat) == 0)
862 break;
863
864 ar[a].f = permissables[j];
865 ar[a].prio = items[i].prio;
866 a++;
867 break;
868 }
869 }
870
871 if (permissables[j]==0)
872 {
873 mcleanstop(1,
874 "atoprc - own system line: item %s invalid in %s line\n",
875 name, linename);
876 }
877 }
878
879 ar[a].f=0;
880 ar[a].prio=0;
881 }
882
883
884
885 /*
886 * init_proc_prints: determine width of columns that are
887 * dependent of dynamic values
888 */
889 static void
890 init_proc_prints(count_t numcpu)
891 {
892 char linebuf[64];
893 int i;
894
895 /*
896 ** fill number of digits for various PID/TID columns
897 ** and reformat header to new width
898 */
899 for (i=0; idprocpdefs[i] != 0; i++)
900 {
901 idprocpdefs[i]->width = pidwidth;
902
903 if ( strlen(idprocpdefs[i]->head) < pidwidth)
904 {
905 char *p = malloc(pidwidth+1);
906
907 ptrverify(p, "Malloc failed for formatted header\n");
908
909 sprintf(p, "%*s", pidwidth, idprocpdefs[i]->head);
910 idprocpdefs[i]->head = p;
911 }
912 }
913
914 /*
915 ** fill number of positions for the SORTITEM (percentage),
916 ** depending on the number of CPUs (e.g. with 10+ CPUs a process
917 ** can reach a CPU percentage of 1000% and with 100+ CPUs a
918 ** CPU percentage of 10000%).
919 */
920 procprt_SORTITEM.width =
921 snprintf(linebuf, sizeof linebuf, "%lld", numcpu*100) + 1;
922 }
923
924 /*
925 * make_proc_prints: make array of proc_printpairs
926 * input: string, proc_printpair array, maxentries
927 */
928 void
929 make_proc_prints(proc_printpair *ar, int maxn, const char *pairs,
930 const char *linename)
931 {
932 name_prio items[MAXITEMS];
933 int n=strlen(pairs);
934
935 char str[n+1];
936 strcpy(str, pairs);
937
938 makeargv(str, linename, items);
939
940 int i;
941 for(i=0; items[i].name && i<maxn-1; ++i)
942 {
943 const char *name=items[i].name;
944 int j;
945 for (j=0; allprocpdefs[j] != 0; ++j)
946 {
947 if (strcmp(allprocpdefs[j]->configname, name)==0)
948 {
949 ar[i].f=allprocpdefs[j];
950 ar[i].prio=items[i].prio;
951 break;
952 }
953 }
954 if (allprocpdefs[j]==0)
955 {
956 mcleanstop(1,
957 "atoprc - ownprocline: item %s invalid!\n",
958 name);
959 }
960 }
961 ar[i].f=0;
962 ar[i].prio=0;
963 }
964
965 /*
966 ** calculate the total consumption on system-level for the
967 ** four main resources
968 */
969 void
970 totalcap(struct syscap *psc, struct sstat *sstat,
971 struct tstat **proclist, int nactproc)
972 {
973 register int i;
974
975 psc->nrcpu = sstat->cpu.nrcpu;
976
977 psc->availcpu = sstat->cpu.all.stime +
978 sstat->cpu.all.utime +
979 sstat->cpu.all.ntime +
980 sstat->cpu.all.itime +
981 sstat->cpu.all.wtime +
982 sstat->cpu.all.Itime +
983 sstat->cpu.all.Stime +
984 sstat->cpu.all.steal;
985
986 psc->availmem = sstat->mem.physmem * pagesize/1024;
987
988 /*
989 ** calculate total transfer issued by the active processes
990 ** for disk and for network
991 */
992 for (psc->availnet=psc->availdsk=0, i=0; i < nactproc; i++)
993 {
994 struct tstat *curstat = *(proclist+i);
995 count_t nett_wsz;
996
997 psc->availnet += curstat->net.tcpssz;
998 psc->availnet += curstat->net.tcprsz;
999 psc->availnet += curstat->net.udpssz;
1000 psc->availnet += curstat->net.udprsz;
1001
1002 if (curstat->dsk.wsz > curstat->dsk.cwsz)
1003 nett_wsz = curstat->dsk.wsz -
1004 curstat->dsk.cwsz;
1005 else
1006 nett_wsz = 0;
1007
1008 psc->availdsk += curstat->dsk.rsz;
1009 psc->availdsk += nett_wsz;
1010 }
1011
1012 for (psc->availgpumem=i=0; i < sstat->gpu.nrgpus; i++)
1013 psc->availgpumem += sstat->gpu.gpu[i].memtotnow;
1014
1015 psc->nrgpu = sstat->gpu.nrgpus;
1016
1017 psc->nrmemnuma = sstat->memnuma.nrnuma;
1018 psc->nrcpunuma = sstat->cpunuma.nrnuma;
1019 }
1020
1021 /*
1022 ** calculate cumulative system- and user-time for all active processes
1023 ** besides, initialize all counter lines on system level
1024 */
1025 void
1026 pricumproc(struct sstat *sstat, struct devtstat *devtstat,
1027 int nexit, unsigned int noverflow, int avgval, int nsecs)
1028 {
1029 static int firsttime=1;
1030 int i;
1031 extraparam extra;
1032
1033 for (i=0, extra.totut=extra.totst=0; i < devtstat->nprocactive; i++)
1034 {
1035 struct tstat *curstat = *(devtstat->procactive+i);
1036
1037 extra.totut += curstat->cpu.utime;
1038 extra.totst += curstat->cpu.stime;
1039 }
1040
1041 extra.nproc = devtstat->nprocall;
1042 extra.ntrun = devtstat->totrun;
1043 extra.ntslpi = devtstat->totslpi;
1044 extra.ntslpu = devtstat->totslpu;
1045 extra.nzomb = devtstat->totzombie;
1046 extra.nexit = nexit;
1047 extra.noverflow = noverflow;
1048 extra.avgval = avgval;
1049 extra.nsecs = nsecs;
1050 extra.index = 0;
1051
1052 if (firsttime)
1053 {
1054 firsttime=0;
1055
1056 if (sysprcline[0].f == 0)
1057 {
1058 make_sys_prints(sysprcline, MAXITEMS,
1059 "PRCSYS:8 "
1060 "PRCUSER:8 "
1061 "BLANKBOX:0 "
1062 "PRCNPROC:7 "
1063 "PRCNRUNNING:5 "
1064 "PRCNSLEEPING:5 "
1065 "PRCNDSLEEPING:5 "
1066 "PRCNZOMBIE:5 "
1067 "PRCCLONES:4 "
1068 "BLANKBOX:0 "
1069 "PRCNNEXIT:6",
1070 prcsyspdefs, "builtin sysprcline",
1071 sstat, &extra);
1072 }
1073
1074 if (allcpuline[0].f == 0)
1075 {
1076 make_sys_prints(allcpuline, MAXITEMS,
1077 "CPUSYS:9 "
1078 "CPUUSER:8 "
1079 "CPUIRQ:6 "
1080 "BLANKBOX:0 "
1081 "CPUIDLE:7 "
1082 "CPUWAIT:7 "
1083 "CPUSTEAL:2 "
1084 "CPUGUEST:3 "
1085 "BLANKBOX:0 "
1086 "CPUIPC:5 "
1087 "CPUCYCLE:4 "
1088 "CPUFREQ:4 "
1089 "CPUSCALE:4 ",
1090 cpusyspdefs, "builtin allcpuline",
1091 sstat, &extra);
1092 }
1093
1094 if (indivcpuline[0].f == 0)
1095 {
1096 make_sys_prints(indivcpuline, MAXITEMS,
1097 "CPUISYS:9 "
1098 "CPUIUSER:8 "
1099 "CPUIIRQ:6 "
1100 "BLANKBOX:0 "
1101 "CPUIIDLE:7 "
1102 "CPUIWAIT:7 "
1103 "CPUISTEAL:2 "
1104 "CPUIGUEST:3 "
1105 "BLANKBOX:0 "
1106 "CPUIIPC:5 "
1107 "CPUICYCLE:4 "
1108 "CPUIFREQ:4 "
1109 "CPUISCALE:4 ",
1110 cpisyspdefs, "builtin indivcpuline",
1111 sstat, &extra);
1112 }
1113
1114 if (cplline[0].f == 0)
1115 {
1116 make_sys_prints(cplline, MAXITEMS,
1117 "CPLNUMCPU:7"
1118 "BLANKBOX:0 "
1119 "CPLAVG1:4 "
1120 "CPLAVG5:3 "
1121 "CPLAVG15:2 "
1122 "BLANKBOX:0 "
1123 "CPLCSW:6 "
1124 "CPLINTR:5 ",
1125 cplsyspdefs, "builtin cplline",
1126 sstat, &extra);
1127 }
1128
1129 if (gpuline[0].f == 0)
1130 {
1131 make_sys_prints(gpuline, MAXITEMS,
1132 "GPUBUS:8 "
1133 "GPUGPUPERC:7 "
1134 "GPUMEMPERC:6 "
1135 "GPUMEMOCC:5 "
1136 "GPUMEMTOT:3 "
1137 "GPUMEMUSE:4 "
1138 "GPUMEMAVG:2 "
1139 "GPUNRPROC:2 "
1140 "BLANKBOX:0 "
1141 "GPUTYPE:1 ",
1142 gpusyspdefs, "builtin gpuline",
1143 NULL, NULL);
1144 }
1145
1146 if (memline1[0].f == 0)
1147 {
1148 make_sys_prints(memline1, MAXITEMS,
1149 "MEMTOT:8 "
1150 "MEMFREE:9 "
1151 "BLANKBOX:0 "
1152 "MEMCACHE:8 "
1153 "MEMDIRTY:6 "
1154 "MEMBUFFER:7 "
1155 "BLANKBOX:0 "
1156 "MEMSLAB:7 "
1157 "RECSLAB:3 "
1158 "BLANKBOX:0 "
1159 "PAGETABS:4 "
1160 "BLANKBOX:0 "
1161 "HUPTOT:5 "
1162 "HUPUSE:2 ",
1163 memsyspdefs1, "builtin memline1",
1164 sstat, &extra);
1165 }
1166
1167 if (memline2[0].f == 0)
1168 {
1169 make_sys_prints(memline2, MAXITEMS,
1170 "NUMNUMA:6 "
1171 "BLANKBOX:1 "
1172 "SHMEM:3 "
1173 "SHMRSS:3 "
1174 "SHMSWP:2 "
1175 "BLANKBOX:0 "
1176 "TCPSOCK:5 "
1177 "UDPSOCK:2 "
1178 "BLANKBOX:0 "
1179 "VMWBAL:4 "
1180 "BLANKBOX:0 "
1181 "ZFSARC:5 ",
1182 memsyspdefs2, "builtin memline2",
1183 sstat, &extra);
1184 }
1185
1186 if (swpline[0].f == 0)
1187 {
1188 make_sys_prints(swpline, MAXITEMS,
1189 "SWPTOT:5 "
1190 "SWPFREE:6 "
1191 "SWPCACHE:4 "
1192 "BLANKBOX:0 "
1193 "ZSWTOTAL:3 "
1194 "ZSWSTORED:3 "
1195 "BLANKBOX:0 "
1196 "KSMSHARED:2 "
1197 "KSMSHARING:2 "
1198 "BLANKBOX:0 "
1199 "SWPCOMMITTED:7 "
1200 "SWPCOMMITLIM:8",
1201 swpsyspdefs, "builtin swpline",
1202 sstat, &extra);
1203 }
1204
1205 if (memnumaline[0].f == 0)
1206 {
1207 make_sys_prints(memnumaline, MAXITEMS,
1208 "NUMATOT:8 "
1209 "NUMAFREE:9 "
1210 "NUMAFILEPAGE:9 "
1211 "NUMANR:7 "
1212 "NUMADIRTY:5 "
1213 "NUMAACTIVE:5 "
1214 "NUMAINACTIVE:5 "
1215 "NUMASLAB:7 "
1216 "NUMASLABRECLAIM:4 "
1217 "NUMASHMEM:4 "
1218 "NUMAFRAG:6 "
1219 "NUMAHUPTOT:3 ",
1220 memnumasyspdefs, "builtin memnumaline",
1221 sstat, &extra);
1222 }
1223
1224 if (cpunumaline[0].f == 0)
1225 {
1226 make_sys_prints(cpunumaline, MAXITEMS,
1227 "NUMACPUSYS:9 "
1228 "NUMACPUUSER:8 "
1229 "NUMACPUNICE:8 "
1230 "NUMACPUIRQ:6 "
1231 "NUMACPUSOFTIRQ:6 "
1232 "NUMACPUIDLE:7 "
1233 "NUMACPUWAIT:7 "
1234 "NUMACPUSTEAL:2 "
1235 "NUMACPUGUEST:3 "
1236 "NUMANUMCPU:5",
1237 cpunumasyspdefs, "builtin cpunumaline",
1238 NULL, NULL);
1239 }
1240
1241 if (llcline[0].f == 0)
1242 {
1243 make_sys_prints(llcline, MAXITEMS,
1244 "LLCMBMTOTAL:9 "
1245 "LLCMBMLOCAL:8 "
1246 "NUMLLC:7 "
1247 "BLANKBOX:0 ",
1248 llcsyspdefs, "builtin llcline",
1249 sstat, &extra);
1250 }
1251
1252 if (pagline[0].f == 0)
1253 {
1254 make_sys_prints(pagline, MAXITEMS,
1255 "PAGSCAN:3 "
1256 "PAGSTEAL:2 "
1257 "PAGSTALL:1 "
1258 "PAGCOMPACT:5 "
1259 "NUMAMIGRATE:5"
1260 "PGMIGRATE:6"
1261 "PAGPGIN:7 "
1262 "PAGPGOUT:7 "
1263 "PAGSWIN:5 "
1264 "PAGSWOUT:8 "
1265 "OOMKILLS:9 ",
1266 pagsyspdefs, "builtin pagline",
1267 sstat, &extra);
1268 }
1269
1270 if (psiline[0].f == 0)
1271 {
1272 make_sys_prints(psiline, MAXITEMS,
1273 "PSICPUSTOT:7 "
1274 "PSIMEMSTOT:7 "
1275 "PSIMEMFTOT:8 "
1276 "PSIIOSTOT:7 "
1277 "PSIIOFTOT:8 "
1278 "PSICPUS:6 "
1279 "PSIMEMS:5 "
1280 "PSIMEMF:3 "
1281 "PSIIOS:4 "
1282 "PSIIOF:2 "
1283 "BLANKBOX:0 ",
1284 psisyspdefs, "builtin psiline",
1285 sstat, &extra);
1286 }
1287
1288 if (contline[0].f == 0)
1289 {
1290 make_sys_prints(contline, MAXITEMS,
1291 "CONTNAME:8 "
1292 "CONTNPROC:7 "
1293 "CONTCPU:6 "
1294 "CONTMEM:6 "
1295 "BLANKBOX:0 "
1296 "BLANKBOX:0 ",
1297 contsyspdefs, "builtin contline",
1298 NULL, NULL);
1299 }
1300
1301 if (dskline[0].f == 0)
1302 {
1303 make_sys_prints(dskline, MAXITEMS,
1304 "DSKNAME:9 "
1305 "DSKBUSY:8 "
1306 "DSKNREAD:7 "
1307 "DSKNWRITE:7 "
1308 "DSKNDISC:6 "
1309 "DSKKBPERRD:5 "
1310 "DSKKBPERWR:5 "
1311 "DSKKBPERDS:4 "
1312 "DSKMBPERSECRD:6 "
1313 "DSKMBPERSECWR:6 "
1314 "DSKINFLIGHT:2 "
1315 "DSKAVQUEUE:1 "
1316 "DSKAVIO:6",
1317 dsksyspdefs, "builtin dskline",
1318 sstat, &extra);
1319 }
1320
1321 if (nfsmountline[0].f == 0)
1322 {
1323 make_sys_prints(nfsmountline, MAXITEMS,
1324 "NFMPATH:8 "
1325 "NFMSERVER:8 "
1326 "NFMTOTREAD:8 "
1327 "NFMTOTWRITE:8 "
1328 "BLANKBOX:0 "
1329 "NFMNREAD:7 "
1330 "NFMNWRITE:6 "
1331 "BLANKBOX:0 "
1332 "NFMDREAD:5 "
1333 "NFMDWRITE:4 "
1334 "BLANKBOX:0 "
1335 "NFMMREAD:3 "
1336 "NFMMWRITE:2 "
1337 "BLANKBOX:0 "
1338 "BLANKBOX:0",
1339 nfsmntsyspdefs, "builtin nfsmountline",
1340 NULL, NULL);
1341 }
1342
1343 if (nfcline[0].f == 0)
1344 {
1345 make_sys_prints(nfcline, MAXITEMS,
1346 "NFCRPCCNT:8 "
1347 "NFCRPCREAD:7 "
1348 "NFCRPCWRITE:7 "
1349 "NFCRPCRET:5 "
1350 "NFCRPCARF:5 "
1351 "BLANKBOX:0 "
1352 "BLANKBOX:0 "
1353 "BLANKBOX:0 "
1354 "BLANKBOX:0 "
1355 "BLANKBOX:0 ",
1356 nfcsyspdefs, "builtin nfcline",
1357 sstat, &extra);
1358 }
1359
1360 if (nfsline[0].f == 0)
1361 {
1362 make_sys_prints(nfsline, MAXITEMS,
1363 "NFSRPCCNT:8 "
1364 "NFSRPCREAD:6 "
1365 "NFSRPCWRITE:6 "
1366 "BLANKBOX:0 "
1367 "NFSNRBYTES:7 "
1368 "NFSNWBYTES:7 "
1369 "BLANKBOX:0 "
1370 "NFSNETTCP:5 "
1371 "NFSNETUDP:5 "
1372 "BLANKBOX:0 "
1373 "NFSRCHITS:3 "
1374 "NFSRCMISS:2 "
1375 "NFSRCNOCA:1 "
1376 "BLANKBOX:0 "
1377 "NFSBADFMT:4 "
1378 "NFSBADAUT:4 "
1379 "NFSBADCLN:4 ",
1380 nfssyspdefs, "builtin nfsline",
1381 sstat, &extra);
1382 }
1383
1384 if (nettransportline[0].f == 0)
1385 {
1386 make_sys_prints(nettransportline, MAXITEMS,
1387 "NETTRANSPORT:9 "
1388 "NETTCPI:8 "
1389 "NETTCPO:8 "
1390 "NETUDPI:8 "
1391 "NETUDPO:8 "
1392 "NETTCPACTOPEN:6 "
1393 "NETTCPPASVOPEN:5 "
1394 "NETTCPRETRANS:4 "
1395 "NETTCPINERR:3 "
1396 "NETTCPORESET:2 "
1397 "NETUDPNOPORT:1 "
1398 "NETUDPINERR:3",
1399 nettranssyspdefs, "builtin nettransportline",
1400 sstat, &extra);
1401 }
1402
1403 if (netnetline[0].f == 0)
1404 {
1405 make_sys_prints(netnetline, MAXITEMS,
1406 "NETNETWORK:5 "
1407 "NETIPI:4 "
1408 "NETIPO:4 "
1409 "NETIPFRW:4 "
1410 "NETIPDELIV:4 "
1411 "BLANKBOX:0 "
1412 "BLANKBOX:0 "
1413 "BLANKBOX:0 "
1414 "NETICMPIN:1 "
1415 "NETICMPOUT:1 ",
1416 netnetsyspdefs, "builtin netnetline",
1417 sstat, &extra);
1418 }
1419
1420 if (netinterfaceline[0].f == 0)
1421 {
1422 make_sys_prints(netinterfaceline, MAXITEMS,
1423 "NETNAME:8 "
1424 "BLANKBOX:0 "
1425 "NETPCKI:7 "
1426 "NETPCKO:7 "
1427 "BLANKBOX:0 "
1428 "NETSPEEDMAX:5 "
1429 "NETSPEEDIN:6 "
1430 "NETSPEEDOUT:6 "
1431 "BLANKBOX:0 "
1432 "NETCOLLIS:2 "
1433 "NETMULTICASTIN:2 "
1434 "NETRCVERR:4 "
1435 "NETSNDERR:4 "
1436 "NETRCVDROP:3 "
1437 "NETSNDDROP:3",
1438 netintfsyspdefs, "builtin netinterfaceline",
1439 NULL, NULL);
1440 }
1441
1442 if (infinibandline[0].f == 0)
1443 {
1444 make_sys_prints(infinibandline, MAXITEMS,
1445 "IFBNAME:8 "
1446 "BLANKBOX:0 "
1447 "IFBPCKI:7 "
1448 "IFBPCKO:7 "
1449 "BLANKBOX:0 "
1450 "IFBSPEEDMAX:5 "
1451 "IFBSPEEDIN:6 "
1452 "IFBSPEEDOUT:6 "
1453 "IFBLANES:4 "
1454 "BLANKBOX:0 "
1455 "BLANKBOX:0 "
1456 "BLANKBOX:0 "
1457 "BLANKBOX:0 "
1458 "BLANKBOX:0 "
1459 "BLANKBOX:0 ",
1460 infinisyspdefs, "builtin infinibandline",
1461 NULL, NULL);
1462 }
1463 } // firsttime
1464
1465 move(1, 0);
1466 showsysline(sysprcline, sstat, &extra, "PRC", 0);
1467 }
1468
1469 /*
1470 ** print the header for the process list
1471 */
1472 void
1473 priphead(int curlist, int totlist, char *showtype, char *showorder,
1474 char autosort, count_t numcpu)
1475 {
1476 static int firsttime=1;
1477 static int prev_supportflags = -1, prev_threadview = -1;
1478
1479 /*
1480 ** determine once the layout of all per-process reports
1481 ** except for the generic report (might change dynamically)
1482 */
1483 if (firsttime)
1484 {
1485 init_proc_prints(numcpu);
1486
1487 make_proc_prints(memprocs, MAXITEMS,
1488 "PID:10 TID:3 MINFLT:2 MAJFLT:2 VSTEXT:4 VSLIBS:4 "
1489 "VDATA:4 VSTACK:4 LOCKSZ:3 VSIZE:6 RSIZE:7 PSIZE:5 "
1490 "VGROW:7 RGROW:8 SWAPSZ:5 RUID:1 EUID:0 "
1491 "SORTITEM:9 CMD:10",
1492 "built-in memprocs");
1493
1494 make_proc_prints(schedprocs, MAXITEMS,
1495 "PID:10 TID:6 CID:4 VPID:3 CTID:3 TRUN:7 TSLPI:7 "
1496 "TSLPU:7 POLI:8 NICE:9 PRI:5 RTPR:9 CPUNR:8 ST:8 "
1497 "EXC:8 S:8 RDELAY:8 BDELAY:7 WCHAN:5 SORTITEM:10 CMD:10",
1498 "built-in schedprocs");
1499
1500 make_proc_prints(dskprocs, MAXITEMS,
1501 "PID:10 TID:4 RDDSK:9 "
1502 "WRDSK:9 WCANCL:8 "
1503 "SORTITEM:10 CMD:10",
1504 "built-in dskprocs");
1505
1506 make_proc_prints(netprocs, MAXITEMS,
1507 "PID:10 TID:6 "
1508 "TCPRCV:9 TCPRASZ:4 TCPSND:9 TCPSASZ:4 "
1509 "UDPRCV:8 UDPRASZ:3 UDPSND:8 UDPSASZ:3 "
1510 "BANDWI:10 BANDWO:10 "
1511 "SORTITEM:10 CMD:10",
1512 "built-in netprocs");
1513
1514 make_proc_prints(gpuprocs, MAXITEMS,
1515 "PID:10 TID:5 CID:4 GPULIST:8 GPUGPUBUSY:8 GPUMEMBUSY:8 "
1516 "GPUMEM:7 GPUMEMAVG:6 S:8 SORTITEM:10 CMD:10",
1517 "built-in gpuprocs");
1518
1519 make_proc_prints(varprocs, MAXITEMS,
1520 "PID:10 TID:4 PPID:9 CID:2 VPID:1 CTID:1 "
1521 "RUID:8 RGID:8 EUID:5 EGID:4 "
1522 "SUID:3 SGID:2 FSUID:3 FSGID:2 "
1523 "STDATE:7 STTIME:7 ENDATE:5 ENTIME:5 "
1524 "ST:6 EXC:6 S:6 SORTITEM:10 CMD:10",
1525 "built-in varprocs");
1526
1527 make_proc_prints(cmdprocs, MAXITEMS,
1528 "PID:10 TID:4 S:8 SORTITEM:10 COMMAND-LINE:10",
1529 "built-in cmdprocs");
1530
1531 make_proc_prints(cgrprocs, MAXITEMS,
1532 "PID:10 CPUWGT:9 CPUMAX:9 CPUMAXR:9 MEMMAX:8 MMMAXR:8 "
1533 "SWPMAX:7 SWMAXR:7 SORTITEM:6 CMD:9 CGROUP-PATH:10",
1534 "built-in cgrprocs");
1535
1536 make_proc_prints(totusers, MAXITEMS,
1537 "NPROCS:10 SYSCPU:9 USRCPU:9 VSIZE:6 "
1538 "RSIZE:8 PSIZE:8 LOCKSZ:3 SWAPSZ:5 RDDSK:7 CWRDSK:7 "
1539 "RNET:6 SNET:6 SORTITEM:10 RUID:10",
1540 "built-in totusers");
1541
1542 make_proc_prints(totprocs, MAXITEMS,
1543 "NPROCS:10 SYSCPU:9 USRCPU:9 VSIZE:6 "
1544 "RSIZE:8 PSIZE:8 LOCKSZ:3 SWAPSZ:5 RDDSK:7 CWRDSK:7 "
1545 "RNET:6 SNET:6 SORTITEM:10 CMD:10",
1546 "built-in totprocs");
1547
1548 make_proc_prints(totconts, MAXITEMS,
1549 "NPROCS:10 SYSCPU:9 USRCPU:9 VSIZE:6 "
1550 "RSIZE:8 PSIZE:8 LOCKSZ:3 SWAPSZ:5 RDDSK:7 CWRDSK:7 "
1551 "RNET:6 SNET:6 SORTITEM:10 CID:10",
1552 "built-in totconts");
1553 }
1554
1555 /*
1556 ** update the generic report if needed
1557 */
1558 if (prev_supportflags != supportflags || prev_threadview != threadview)
1559 {
1560 make_proc_dynamicgen();
1561
1562 prev_supportflags = supportflags;
1563 prev_threadview = threadview;
1564
1565 if (*showtype == MPROCNET && !(supportflags&NETATOP) )
1566 {
1567 *showtype = MPROCGEN;
1568 *showorder = MSORTCPU;
1569 }
1570 }
1571
1572 /*
1573 ** print the header line
1574 */
1575 switch (*showtype)
1576 {
1577 case MPROCGEN:
1578 showhdrline(genprocs, curlist, totlist, *showorder, autosort);
1579 break;
1580
1581 case MPROCMEM:
1582 showhdrline(memprocs, curlist, totlist, *showorder, autosort);
1583 break;
1584
1585 case MPROCDSK:
1586 showhdrline(dskprocs, curlist, totlist, *showorder, autosort);
1587 break;
1588
1589 case MPROCNET:
1590 showhdrline(netprocs, curlist, totlist, *showorder, autosort);
1591 break;
1592
1593 case MPROCGPU:
1594 showhdrline(gpuprocs, curlist, totlist, *showorder, autosort);
1595 break;
1596
1597 case MPROCVAR:
1598 showhdrline(varprocs, curlist, totlist, *showorder, autosort);
1599 break;
1600
1601 case MPROCARG:
1602 showhdrline(cmdprocs, curlist, totlist, *showorder, autosort);
1603 break;
1604
1605 case MPROCCGR:
1606 showhdrline(cgrprocs, curlist, totlist, *showorder, autosort);
1607 break;
1608
1609 case MPROCOWN:
1610 showhdrline(ownprocs, curlist, totlist, *showorder, autosort);
1611 break;
1612
1613 case MPROCSCH:
1614 showhdrline(schedprocs, curlist, totlist, *showorder, autosort);
1615 break;
1616
1617 case MCUMUSER:
1618 showhdrline(totusers, curlist, totlist, *showorder, autosort);
1619 break;
1620
1621 case MCUMPROC:
1622 showhdrline(totprocs, curlist, totlist, *showorder, autosort);
1623 break;
1624
1625 case MCUMCONT:
1626 showhdrline(totconts, curlist, totlist, *showorder, autosort);
1627 break;
1628 }
1629 }
1630
1631 /*
1632 ** assemble the layout of the generic line,
1633 ** depending on the supported features (like
1634 ** I/O stats, network stats) and current view
1635 */
1636 #define FORMPID "PID:10 "
1637 #define FORMTID "TID:6 "
1638 #define FORMCID "CID:5 "
1639 #define FORMCPU "SYSCPU:9 USRCPU:9 "
1640 #define FORMDEL "RDELAY:4 "
1641 #define FORMBDL "BDELAY:4 "
1642 #define FORMMEM "VGROW:8 RGROW:8 "
1643 #define FORMDSK "RDDSK:7 CWRDSK:7 "
1644 #define FORMNET "RNET:6 SNET:6 "
1645 #define FORMMSC "RUID:2 EUID:1 ST:3 EXC:3 THR:3 S:3 CPUNR:3 "
1646 #define FORMEND "SORTITEM:10 CMD:10"
1647
1648 static void
1649 make_proc_dynamicgen()
1650 {
1651 char format[300], *p = format;
1652
1653 memcpy(p, FORMPID, sizeof FORMPID -1);
1654 p += sizeof FORMPID -1;
1655
1656 if (threadview)
1657 {
1658 memcpy(p, FORMTID, sizeof FORMTID -1);
1659 p += sizeof FORMTID -1;
1660 }
1661
1662 if (supportflags & DOCKSTAT)
1663 {
1664 memcpy(p, FORMCID, sizeof FORMCID -1);
1665 p += sizeof FORMCID -1;
1666 }
1667
1668 memcpy(p, FORMCPU, sizeof FORMCPU -1);
1669 p += sizeof FORMCPU -1;
1670
1671 memcpy(p, FORMDEL, sizeof FORMDEL -1);
1672 p += sizeof FORMDEL -1;
1673
1674 memcpy(p, FORMBDL, sizeof FORMBDL -1);
1675 p += sizeof FORMBDL -1;
1676
1677 memcpy(p, FORMMEM, sizeof FORMMEM -1);
1678 p += sizeof FORMMEM -1;
1679
1680 if (supportflags & IOSTAT)
1681 {
1682 memcpy(p, FORMDSK, sizeof FORMDSK -1);
1683 p += sizeof FORMDSK -1;
1684 }
1685
1686 if (supportflags & NETATOP)
1687 {
1688 memcpy(p, FORMNET, sizeof FORMNET -1);
1689 p += sizeof FORMNET -1;
1690 }
1691
1692 memcpy(p, FORMMSC, sizeof FORMMSC -1);
1693 p += sizeof FORMMSC -1;
1694
1695 memcpy(p, FORMEND, sizeof FORMEND);
1696 p += sizeof FORMEND;
1697
1698 make_proc_prints(genprocs, MAXITEMS, format, "built-in genprocs");
1699 }
1700
1701 /*
1702 ** print the list of processes from the deviation-list
1703 */
1704 int
1705 priproc(struct tstat **proclist, int firstproc, int lastproc, int curline,
1706 int curlist, int totlist, char showtype, char showorder,
1707 struct syscap *sb, int nsecs, int avgval)
1708 {
1709 register int i;
1710 register struct tstat *curstat;
1711 double perc;
1712
1713 /*
1714 ** print info per actual process and maintain totals
1715 */
1716 for (i=firstproc; i < lastproc; i++)
1717 {
1718 curstat = *(proclist+i);
1719
1720 if (screen && curline >= LINES) /* screen filled entirely ? */
1721 break;
1722
1723 /*
1724 ** calculate occupation-percentage of this process
1725 ** depending on selected resource
1726 */
1727 switch (showorder)
1728 {
1729 case MSORTCPU:
1730 perc = 0.0;
1731
1732 if (sb->availcpu)
1733 {
1734 perc = (double)(curstat->cpu.stime +
1735 curstat->cpu.utime ) * 100 /
1736 (sb->availcpu / sb->nrcpu);
1737
1738 if (perc > 100.0 * sb->nrcpu)
1739 perc = 100.0 * sb->nrcpu;
1740
1741 if (perc > 100.0 * curstat->gen.nthr)
1742 perc = 100.0 * curstat->gen.nthr;
1743 }
1744 break;
1745
1746 case MSORTMEM:
1747 perc = 0.0;
1748
1749 if (sb->availmem)
1750 {
1751 perc = (double)curstat->mem.rmem *
1752 100.0 / sb->availmem;
1753
1754 if (perc > 100.0)
1755 perc = 100.0;
1756 }
1757 break;
1758
1759 case MSORTDSK:
1760 perc = 0.0;
1761
1762 if (sb->availdsk)
1763 {
1764 count_t nett_wsz;
1765
1766
1767 if (curstat->dsk.wsz > curstat->dsk.cwsz)
1768 nett_wsz = curstat->dsk.wsz -
1769 curstat->dsk.cwsz;
1770 else
1771 nett_wsz = 0;
1772
1773 perc = (double)(curstat->dsk.rsz + nett_wsz) *
1774 100.0 / sb->availdsk;
1775
1776 if (perc > 100.0)
1777 perc = 100.0;
1778 }
1779 break;
1780
1781 case MSORTNET:
1782 perc = 0.0;
1783
1784 if (sb->availnet)
1785 {
1786 perc = (double)(curstat->net.tcpssz +
1787 curstat->net.tcprsz +
1788 curstat->net.udpssz +
1789 curstat->net.udprsz ) *
1790 100.0 / sb->availnet;
1791
1792 if (perc > 100.0)
1793 perc = 100.0;
1794 }
1795 break;
1796
1797 case MSORTGPU:
1798 perc = 0.0;
1799
1800 if (!curstat->gpu.state)
1801 break;
1802
1803 if (curstat->gpu.gpubusy != -1)
1804 {
1805 perc = curstat->gpu.gpubusy;
1806 }
1807 else
1808 {
1809 perc = curstat->gpu.memnow*100 *
1810 sb->nrgpu / sb->availgpumem;
1811 }
1812 break;
1813
1814 default:
1815 perc = 0.0;
1816 }
1817
1818 /*
1819 ** now do the formatting of output
1820 */
1821 if (screen) {
1822 move(curline,0);
1823 }
1824
1825 switch (showtype)
1826 {
1827 case MPROCGEN:
1828 showprocline(genprocs, curstat, perc, nsecs, avgval);
1829 break;
1830
1831 case MPROCMEM:
1832 showprocline(memprocs, curstat, perc, nsecs, avgval);
1833 break;
1834
1835 case MPROCDSK:
1836 showprocline(dskprocs, curstat, perc, nsecs, avgval);
1837 break;
1838
1839 case MPROCNET:
1840 showprocline(netprocs, curstat, perc, nsecs, avgval);
1841 break;
1842
1843 case MPROCGPU:
1844 showprocline(gpuprocs, curstat, perc, nsecs, avgval);
1845 break;
1846
1847 case MPROCVAR:
1848 showprocline(varprocs, curstat, perc, nsecs, avgval);
1849 break;
1850
1851 case MPROCARG:
1852 showprocline(cmdprocs, curstat, perc, nsecs, avgval);
1853 break;
1854
1855 case MPROCCGR:
1856 showprocline(cgrprocs, curstat, perc, nsecs, avgval);
1857 break;
1858
1859 case MPROCOWN:
1860 showprocline(ownprocs, curstat, perc, nsecs, avgval);
1861 break;
1862
1863 case MPROCSCH:
1864 showprocline(schedprocs, curstat, perc, nsecs, avgval);
1865 break;
1866
1867 case MCUMUSER:
1868 showprocline(totusers, curstat, perc, nsecs, avgval);
1869 break;
1870
1871 case MCUMPROC:
1872 showprocline(totprocs, curstat, perc, nsecs, avgval);
1873 break;
1874
1875 case MCUMCONT:
1876 showprocline(totconts, curstat, perc, nsecs, avgval);
1877 break;
1878 }
1879
1880 curline++;
1881 }
1882
1883 return curline;
1884 }
1885
1886
1887 /*
1888 ** print the system-wide statistics
1889 */
1890 static void pridisklike(extraparam *, struct perdsk *, char *,
1891 char *, int, unsigned int *, int *, int, regex_t *);
1892
1893 int
1894 prisyst(struct sstat *sstat, int curline, int nsecs, int avgval,
1895 int fixedhead, struct sselection *selp, char *highorderp,
1896 int maxcpulines, int maxgpulines, int maxdsklines, int maxmddlines,
1897 int maxlvmlines, int maxintlines, int maxifblines,
1898 int maxnfslines, int maxcontlines, int maxnumalines, int maxllclines)
1899 {
1900 extraparam extra;
1901 int lin;
1902 count_t busy;
1903 unsigned int badness, highbadness=0;
1904
1905 extra.nsecs = nsecs;
1906 extra.avgval = avgval;
1907
1908 /*
1909 ** CPU statistics
1910 */
1911 extra.cputot = sstat->cpu.all.stime + sstat->cpu.all.utime +
1912 sstat->cpu.all.ntime + sstat->cpu.all.itime +
1913 sstat->cpu.all.wtime + sstat->cpu.all.Itime +
1914 sstat->cpu.all.Stime + sstat->cpu.all.steal;
1915
1916 busy = (extra.cputot - sstat->cpu.all.itime - sstat->cpu.all.wtime)
1917 * 100.0 / extra.cputot;
1918
1919 if (cpubadness)
1920 badness = busy * 100 / cpubadness;
1921 else
1922 badness = 0;
1923
1924 if (highbadness < badness)
1925 {
1926 highbadness = badness;
1927 *highorderp = MSORTCPU;
1928 }
1929
1930 if (extra.cputot == 0)
1931 extra.cputot = 1; /* avoid divide-by-zero */
1932
1933 extra.percputot = extra.cputot / sstat->cpu.nrcpu;
1934
1935 if (extra.percputot == 0)
1936 extra.percputot = 1; /* avoid divide-by-zero */
1937
1938 if (screen)
1939 move(curline, 0);
1940
1941 showsysline(allcpuline, sstat, &extra, "CPU", badness);
1942 curline++;
1943
1944 if (sstat->cpu.nrcpu > 1)
1945 {
1946 for (extra.index=lin=0;
1947 extra.index < sstat->cpu.nrcpu && lin < maxcpulines;
1948 extra.index++)
1949 {
1950 extra.percputot = sstat->cpu.cpu[extra.index].stime +
1951 sstat->cpu.cpu[extra.index].utime +
1952 sstat->cpu.cpu[extra.index].ntime +
1953 sstat->cpu.cpu[extra.index].itime +
1954 sstat->cpu.cpu[extra.index].wtime +
1955 sstat->cpu.cpu[extra.index].Itime +
1956 sstat->cpu.cpu[extra.index].Stime +
1957 sstat->cpu.cpu[extra.index].steal;
1958
1959 if (extra.percputot ==
1960 (sstat->cpu.cpu[extra.index].itime +
1961 sstat->cpu.cpu[extra.index].wtime ) &&
1962 !fixedhead )
1963 continue; /* inactive cpu */
1964
1965 busy = (extra.percputot -
1966 sstat->cpu.cpu[extra.index].itime -
1967 sstat->cpu.cpu[extra.index].wtime)
1968 * 100.0 / extra.percputot;
1969
1970 if (cpubadness)
1971 badness = busy * 100 / cpubadness;
1972 else
1973 badness = 0;
1974
1975 if (highbadness < badness)
1976 {
1977 highbadness = badness;
1978 *highorderp = MSORTCPU;
1979 }
1980
1981 if (extra.percputot == 0)
1982 extra.percputot = 1; /* avoid divide-by-zero */
1983
1984
1985 if (screen)
1986 move(curline, 0);
1987
1988 showsysline(indivcpuline, sstat, &extra, "cpu",
1989 badness);
1990 curline++;
1991 lin++;
1992 }
1993 }
1994
1995 /*
1996 ** other CPU-related statistics
1997 */
1998 if (screen)
1999 move(curline, 0);
2000
2001 showsysline(cplline, sstat, &extra, "CPL", 0);
2002 curline++;
2003
2004 /*
2005 ** GPU statistics
2006 */
2007 if (sstat->gpu.nrgpus)
2008 {
2009 for (extra.index=0, lin=0;
2010 extra.index < sstat->gpu.nrgpus && lin < maxgpulines;
2011 extra.index++)
2012 {
2013 int totbusy;
2014 count_t avgmemuse;
2015
2016 // notice that GPU percentage and memory percentage
2017 // are not always available; in that case both
2018 // values have the value -1
2019 //
2020 totbusy = sstat->gpu.gpu[extra.index].gpuperccum +
2021 sstat->gpu.gpu[extra.index].memperccum;
2022
2023 if (totbusy == -2) // metrics available?
2024 totbusy= 0;
2025
2026 if (sstat->gpu.gpu[extra.index].samples == 0)
2027 {
2028 totbusy =
2029 sstat->gpu.gpu[extra.index].gpupercnow +
2030 sstat->gpu.gpu[extra.index].mempercnow;
2031
2032 avgmemuse =
2033 sstat->gpu.gpu[extra.index].memusenow;
2034 }
2035 else
2036 {
2037 totbusy = totbusy /
2038 sstat->gpu.gpu[extra.index].samples;
2039
2040 avgmemuse =
2041 sstat->gpu.gpu[extra.index].memusecum/
2042 sstat->gpu.gpu[extra.index].samples;
2043 }
2044
2045 if (gpubadness)
2046 badness = totbusy * 100 / gpubadness;
2047 else
2048 badness = 0;
2049
2050 if ( totbusy > 0 ||
2051 // memusage > 512 MiB (rather arbitrary)?
2052 avgmemuse > 512*1024 ||
2053 fixedhead )
2054 {
2055 showsysline(gpuline, sstat,
2056 &extra, "GPU", badness);
2057 curline++;
2058 lin++;
2059 }
2060 }
2061 }
2062
2063 /*
2064 ** MEMORY statistics
2065 */
2066 busy = (sstat->mem.physmem - sstat->mem.freemem
2067 - sstat->mem.cachemem
2068 - sstat->mem.buffermem
2069 - sstat->mem.slabreclaim
2070 + sstat->mem.shmem)
2071 * 100.0 / sstat->mem.physmem;
2072
2073 if (membadness)
2074 badness = busy * 100 / membadness;
2075 else
2076 badness = 0;
2077
2078 if (highbadness < badness)
2079 {
2080 highbadness = badness;
2081 *highorderp = MSORTMEM;
2082 }
2083
2084 if (screen)
2085 move(curline, 0);
2086
2087 showsysline(memline1, sstat, &extra, "MEM", badness);
2088 curline++;
2089
2090 showsysline(memline2, sstat, &extra, "MEM", badness);
2091 curline++;
2092
2093 /*
2094 ** SWAP statistics
2095 */
2096 busy = (sstat->mem.totswap - sstat->mem.freeswap)
2097 * 100.0 / sstat->mem.totswap;
2098
2099 if (swpbadness)
2100 {
2101 badness = busy * 100 / swpbadness;
2102 }
2103 else
2104 {
2105 badness = 0;
2106 }
2107
2108 if (highbadness < badness)
2109 {
2110 highbadness = badness;
2111 *highorderp = MSORTMEM;
2112 }
2113
2114 if (screen)
2115 move(curline, 0);
2116
2117 showsysline(swpline, sstat, &extra, "SWP", badness);
2118 curline++;
2119
2120 /*
2121 ** memory info related for per NUMA
2122 */
2123 if (sstat->memnuma.nrnuma > 1)
2124 {
2125 for (extra.index=lin=0;
2126 extra.index < sstat->memnuma.nrnuma && lin < maxnumalines;
2127 extra.index++)
2128 {
2129 busy = (sstat->memnuma.numa[extra.index].totmem
2130 - sstat->memnuma.numa[extra.index].freemem
2131 - sstat->memnuma.numa[extra.index].filepage
2132 - sstat->memnuma.numa[extra.index].slabreclaim
2133 + sstat->memnuma.numa[extra.index].shmem)
2134 * 100.0 / sstat->memnuma.numa[extra.index].totmem;
2135
2136 if (membadness)
2137 badness = busy * 100 / membadness;
2138 else
2139 badness = 0;
2140
2141 if (highbadness < badness)
2142 {
2143 highbadness = badness;
2144 *highorderp = MSORTMEM;
2145 }
2146
2147 if (screen)
2148 move(curline, 0);
2149
2150 showsysline(memnumaline, sstat, &extra, "NUM", badness);
2151 curline++;
2152 lin++;
2153 }
2154 }
2155
2156 /*
2157 ** Accumulate each cpu statistic for per NUMA
2158 */
2159 if (sstat->cpunuma.nrnuma > 1)
2160 {
2161 for (extra.index=lin=0;
2162 extra.index < sstat->cpunuma.nrnuma && lin < maxnumalines;
2163 extra.index++)
2164 {
2165 extra.pernumacputot = sstat->cpunuma.numa[extra.index].stime +
2166 sstat->cpunuma.numa[extra.index].utime +
2167 sstat->cpunuma.numa[extra.index].ntime +
2168 sstat->cpunuma.numa[extra.index].itime +
2169 sstat->cpunuma.numa[extra.index].wtime +
2170 sstat->cpunuma.numa[extra.index].Itime +
2171 sstat->cpunuma.numa[extra.index].Stime +
2172 sstat->cpunuma.numa[extra.index].steal;
2173
2174 if (extra.pernumacputot ==
2175 (sstat->cpunuma.numa[extra.index].itime +
2176 sstat->cpunuma.numa[extra.index].wtime ) &&
2177 !fixedhead )
2178 continue; /* inactive cpu */
2179
2180 if (extra.pernumacputot == 0)
2181 extra.pernumacputot = 1; /* avoid divide-by-zero */
2182
2183 busy = (extra.pernumacputot -
2184 sstat->cpunuma.numa[extra.index].itime -
2185 sstat->cpunuma.numa[extra.index].wtime)
2186 * 100.0 / extra.pernumacputot;
2187
2188 if (cpubadness)
2189 badness = busy * 100 / cpubadness;
2190 else
2191 badness = 0;
2192
2193 if (highbadness < badness)
2194 {
2195 highbadness = badness;
2196 *highorderp = MSORTCPU;
2197 }
2198
2199 extra.percputot = extra.pernumacputot /
2200 (sstat->cpu.nrcpu/sstat->cpunuma.nrnuma);
2201 if (extra.percputot == 0)
2202 extra.percputot = 1; /* avoid divide-by-zero */
2203
2204 if (screen)
2205 move(curline, 0);
2206
2207 showsysline(cpunumaline, sstat, &extra, "NUC", badness);
2208 curline++;
2209 lin++;
2210 }
2211 }
2212
2213 /*
2214 ** LLC statistics (if supported by kernel and
2215 ** pseudo filesystem mounted)
2216 */
2217 for (extra.index=0, lin=0;
2218 extra.index < sstat->llc.nrllcs && lin < maxllclines;
2219 extra.index++)
2220 {
2221 if (fixedhead ||
2222 sstat->llc.perllc[extra.index].mbm_local ||
2223 sstat->llc.perllc[extra.index].mbm_total )
2224 {
2225 if (screen)
2226 move(curline, 0);
2227
2228 showsysline(llcline, sstat, &extra, "LLC", 0);
2229 curline++;
2230 lin++;
2231 }
2232 }
2233
2234 /*
2235 ** PAGING statistics
2236 */
2237 if (fixedhead ||
2238 sstat->mem.pgscans ||
2239 sstat->mem.pgsteal ||
2240 sstat->mem.allocstall ||
2241 sstat->mem.compactstall ||
2242 sstat->mem.pgins ||
2243 sstat->mem.pgouts ||
2244 sstat->mem.tcpsock ||
2245 sstat->mem.udpsock ||
2246 sstat->mem.swins ||
2247 sstat->mem.swouts ||
2248 sstat->mem.oomkills > 0 ||
2249 sstat->mem.pgmigrate ||
2250 sstat->mem.numamigrate )
2251 {
2252 busy = sstat->mem.swouts / nsecs * pagbadness;
2253
2254 if (busy > 100)
2255 busy = 100;
2256
2257 if (membadness)
2258 badness = busy * 100 / membadness;
2259 else
2260 badness = 0;
2261
2262 if (highbadness < badness)
2263 {
2264 highbadness = badness;
2265 *highorderp = MSORTMEM;
2266 }
2267
2268 /*
2269 ** take care that this line is anyhow colored for
2270 ** 'almost critical' in case of swapouts > 1 per second
2271 */
2272 if (sstat->mem.swouts / nsecs > 0 &&
2273 pagbadness && almostcrit && badness < almostcrit)
2274 badness = almostcrit;
2275
2276 if (screen)
2277 move(curline, 0);
2278
2279 showsysline(pagline, sstat, &extra, "PAG", badness);
2280 curline++;
2281 }
2282
2283 /*
2284 ** Pressure statistics
2285 */
2286 if (sstat->psi.present)
2287 {
2288 if (fixedhead ||
2289 sstat->psi.cpusome.avg10 || sstat->psi.memsome.avg10 ||
2290 sstat->psi.iosome.avg10 ||
2291 sstat->psi.cpusome.avg60 || sstat->psi.memsome.avg60 ||
2292 sstat->psi.iosome.avg60 ||
2293 sstat->psi.cpusome.avg300 || sstat->psi.memsome.avg300 ||
2294 sstat->psi.iosome.avg300 )
2295 {
2296 badness = sstat->psi.cpusome.avg10 >
2297 sstat->psi.cpusome.avg60 ?
2298 sstat->psi.cpusome.avg10 :
2299 sstat->psi.cpusome.avg60;
2300
2301 if (badness < sstat->psi.cpusome.avg300)
2302 badness = sstat->psi.cpusome.avg300;
2303
2304 if (screen)
2305 move(curline, 0);
2306
2307 showsysline(psiline, sstat, &extra,"PSI", badness);
2308 curline++;
2309 }
2310 }
2311
2312 /*
2313 ** Container statistics (if any)
2314 */
2315 for (extra.index=0, lin=0;
2316 extra.index < sstat->cfs.nrcontainer && lin < maxcontlines;
2317 extra.index++)
2318 {
2319 if (fixedhead ||
2320 sstat->cfs.cont[extra.index].system ||
2321 sstat->cfs.cont[extra.index].user ||
2322 sstat->cfs.cont[extra.index].nice )
2323 {
2324 if (screen)
2325 move(curline, 0);
2326
2327 showsysline(contline, sstat, &extra, "CON", 0);
2328 curline++;
2329 lin++;
2330 }
2331 }
2332
2333 /*
2334 ** DISK statistics
2335 */
2336 extra.mstot = extra.cputot * 1000 / hertz / sstat->cpu.nrcpu;
2337
2338 pridisklike(&extra, sstat->dsk.lvm, "LVM", highorderp, maxlvmlines,
2339 &highbadness, &curline, fixedhead,
2340 selp->lvmnamesz ? &(selp->lvmregex) : (void *) 0);
2341
2342 pridisklike(&extra, sstat->dsk.mdd, "MDD", highorderp, maxmddlines,
2343 &highbadness, &curline, fixedhead, (void *) 0);
2344
2345 pridisklike(&extra, sstat->dsk.dsk, "DSK", highorderp, maxdsklines,
2346 &highbadness, &curline, fixedhead,
2347 selp->dsknamesz ? &(selp->dskregex) : (void *) 0);
2348
2349 /*
2350 ** NFS server and client statistics
2351 */
2352 for (extra.index=0, lin=0;
2353 extra.index < sstat->nfs.nfsmounts.nrmounts && lin < maxnfslines;
2354 extra.index++)
2355 {
2356 int i = extra.index;
2357
2358 if ( (sstat->nfs.nfsmounts.nfsmnt[i].bytesread +
2359 sstat->nfs.nfsmounts.nfsmnt[i].byteswrite +
2360 sstat->nfs.nfsmounts.nfsmnt[i].bytesdread +
2361 sstat->nfs.nfsmounts.nfsmnt[i].bytesdwrite +
2362 sstat->nfs.nfsmounts.nfsmnt[i].bytestotread +
2363 sstat->nfs.nfsmounts.nfsmnt[i].bytestotwrite +
2364 sstat->nfs.nfsmounts.nfsmnt[i].pagesmread +
2365 sstat->nfs.nfsmounts.nfsmnt[i].pagesmwrite ) ||
2366 sstat->nfs.nfsmounts.nfsmnt[i].age < nsecs ||
2367 fixedhead )
2368 {
2369 if (screen)
2370 move(curline, 0);
2371
2372 showsysline(nfsmountline, sstat, &extra, "NFM", 0);
2373 curline++;
2374 lin++;
2375 }
2376 }
2377
2378 if (sstat->nfs.client.rpccnt || fixedhead )
2379 {
2380 if (screen)
2381 move(curline, 0);
2382
2383 showsysline(nfcline, sstat, &extra, "NFC", 0);
2384 curline++;
2385 }
2386
2387 if (sstat->nfs.server.rpccnt || fixedhead )
2388 {
2389 if (screen)
2390 move(curline, 0);
2391
2392 showsysline(nfsline, sstat, &extra, "NFS", 0);
2393 curline++;
2394 }
2395
2396 /*
2397 ** NET statistics: transport
2398 */
2399 if (sstat->net.tcp.InSegs ||
2400 sstat->net.tcp.OutSegs ||
2401 sstat->net.udpv4.InDatagrams ||
2402 sstat->net.udpv6.Udp6InDatagrams ||
2403 sstat->net.udpv4.OutDatagrams ||
2404 sstat->net.udpv6.Udp6OutDatagrams ||
2405 fixedhead )
2406 {
2407 if (screen)
2408 move(curline, 0);
2409
2410 showsysline(nettransportline, sstat, &extra, "NET", 0);
2411 curline++;
2412 }
2413
2414 /*
2415 ** NET statistics: network
2416 */
2417 if (sstat->net.ipv4.InReceives ||
2418 sstat->net.ipv6.Ip6InReceives ||
2419 sstat->net.ipv4.OutRequests ||
2420 sstat->net.ipv6.Ip6OutRequests ||
2421 fixedhead )
2422 {
2423 if (screen)
2424 move(curline, 0);
2425
2426 showsysline(netnetline, sstat, &extra, "NET", 0);
2427 curline++;
2428 }
2429
2430 /*
2431 ** NET statistics: interfaces
2432 */
2433 for (extra.index=0, lin=0;
2434 sstat->intf.intf[extra.index].name[0] && lin < maxintlines;
2435 extra.index++)
2436 {
2437 if (sstat->intf.intf[extra.index].rpack ||
2438 sstat->intf.intf[extra.index].spack || fixedhead)
2439 {
2440 if (selp->itfnamesz && regexec(&(selp->itfregex),
2441 sstat->intf.intf[extra.index].name, 0, NULL, 0))
2442 continue; // suppress (not selected)
2443
2444 /*
2445 ** calculate busy-percentage for interface
2446 */
2447
2448 count_t ival, oval;
2449
2450 /*
2451 ** convert byte-transfers to bit-transfers (* 8)
2452 ** convert bit-transfers to kilobit-transfers (/ 1000)
2453 ** per second
2454 */
2455 ival = sstat->intf.intf[extra.index].rbyte/125/nsecs;
2456 oval = sstat->intf.intf[extra.index].sbyte/125/nsecs;
2457
2458 /* speed known? */
2459 if (sstat->intf.intf[extra.index].speed)
2460 {
2461 if (sstat->intf.intf[extra.index].duplex)
2462 busy = (ival > oval ? ival : oval) /
2463 (sstat->intf.intf[extra.index].speed
2464 *10);
2465 else
2466 busy = (ival + oval) /
2467 (sstat->intf.intf[extra.index].speed
2468 *10);
2469
2470 }
2471 else
2472 {
2473 busy = 0;
2474 }
2475
2476 if (netbadness)
2477 badness = busy * 100 / netbadness;
2478 else
2479 badness = 0;
2480
2481 if (highbadness < badness && (supportflags & NETATOP) )
2482 {
2483 highbadness = badness;
2484 *highorderp = MSORTNET;
2485 }
2486
2487 if (screen)
2488 move(curline, 0);
2489
2490 showsysline(netinterfaceline, sstat, &extra,
2491 "NET", badness);
2492 curline++;
2493 lin++;
2494 }
2495 }
2496
2497 /*
2498 ** NET statistics: InfiniBand
2499 */
2500 for (extra.index=0, lin=0;
2501 extra.index < sstat->ifb.nrports && lin < maxifblines;
2502 extra.index++)
2503 {
2504 if (sstat->ifb.ifb[extra.index].rcvb ||
2505 sstat->ifb.ifb[extra.index].sndb || fixedhead)
2506 {
2507 /*
2508 ** calculate busy-percentage for IB port
2509 */
2510 count_t ival, oval;
2511
2512 /*
2513 ** convert byte-transfers to bit-transfers (* 8)
2514 ** convert bit-transfers to kilobit-transfers (/ 1000)
2515 ** per second
2516 */
2517 ival = sstat->ifb.ifb[extra.index].rcvb/125/nsecs;
2518 oval = sstat->ifb.ifb[extra.index].sndb/125/nsecs;
2519
2520 busy = (ival > oval ? ival : oval) *
2521 sstat->ifb.ifb[extra.index].lanes /
2522 (sstat->ifb.ifb[extra.index].rate * 10);
2523
2524 if (netbadness)
2525 badness = busy * 100 / netbadness;
2526 else
2527 badness = 0;
2528
2529 if (highbadness < badness)
2530 {
2531 highbadness = badness;
2532 *highorderp = MSORTNET;
2533 }
2534
2535 if (screen)
2536 move(curline, 0);
2537
2538 showsysline(infinibandline, sstat, &extra,
2539 "IFB", badness);
2540 curline++;
2541 lin++;
2542 }
2543 }
2544
2545 /*
2546 ** application statistics
2547 **
2548 ** WWW: notice that we cause one access ourselves by fetching
2549 ** the statistical counters
2550 */
2551 #if HTTPSTATS
2552 if (sstat->www.accesses > 1 || fixedhead )
2553 {
2554 char format1[8], format2[8], format3[8], format4[8], format5[8];
2555
2556 if (screen)
2557 move(curline, 0);
2558
2559 printg("WWW | reqs %s | totKB %s | byt/rq %s | iwork %s |"
2560 " bwork %s |",
2561 val2valstr(sstat->www.accesses, format1, 6,
2562 avgval, nsecs),
2563 val2valstr(sstat->www.totkbytes, format2, 6,
2564 avgval, nsecs),
2565 val2valstr(sstat->www.accesses ?
2566 sstat->www.totkbytes*1024/sstat->www.accesses : 0,
2567 format3, 5, 0, 0),
2568 val2valstr(sstat->www.iworkers, format4, 6, 0, 0),
2569 val2valstr(sstat->www.bworkers, format5, 6, 0, 0) );
2570 if (!screen)
2571 {
2572 printg("\n");
2573 }
2574 curline++;
2575 }
2576 #endif
2577
2578 /*
2579 ** if the system is hardly loaded, still CPU-ordering of
2580 ** processes is most interesting (instead of memory)
2581 */
2582 if (highbadness < 70 && *highorderp == MSORTMEM)
2583 *highorderp = MSORTCPU;
2584
2585 return curline;
2586 }
2587
2588 /*
2589 ** handle all instances of a specific disk-like device
2590 */
2591 static void
2592 pridisklike(extraparam *ep, struct perdsk *dp, char *lp, char *highorderp,
2593 int maxlines, unsigned int *highbadp, int *curlinp, int fixedhead,
2594 regex_t *rep)
2595 {
2596 int lin;
2597 count_t busy;
2598 unsigned int badness;
2599
2600 for (ep->perdsk = dp, ep->index=0, lin=0;
2601 ep->perdsk[ep->index].name[0] && lin < maxlines; ep->index++)
2602 {
2603 if (rep && regexec(rep, ep->perdsk[ep->index].name, 0, NULL, 0))
2604 continue; // suppress (not selected)
2605
2606 ep->iotot = ep->perdsk[ep->index].nread +
2607 ep->perdsk[ep->index].nwrite;
2608
2609 busy = (double)(ep->perdsk[ep->index].io_ms *
2610 100.0 / ep->mstot);
2611
2612 if (dskbadness)
2613 badness = busy * 100 / dskbadness;
2614 else
2615 badness = 0;
2616
2617 if (*highbadp < badness && (supportflags & IOSTAT) )
2618 {
2619 *highbadp = badness;
2620 *highorderp = MSORTDSK;
2621 }
2622
2623 if (ep->iotot || fixedhead)
2624 {
2625 move(*curlinp, 0);
2626 showsysline(dskline, 0, ep, lp, badness);
2627 (*curlinp)++;
2628 lin++;
2629 }
2630 }
2631 }
2632
2633
2634 /*
2635 ** process-level sort functions
2636 */
2637 int
2638 compcpu(const void *a, const void *b)
2639 {
2640 register count_t acpu = (*(struct tstat **)a)->cpu.stime +
2641 (*(struct tstat **)a)->cpu.utime;
2642 register count_t bcpu = (*(struct tstat **)b)->cpu.stime +
2643 (*(struct tstat **)b)->cpu.utime;
2644
2645 if (acpu < bcpu)
2646 return 1;
2647
2648 if (acpu > bcpu)
2649 return -1;
2650
2651 return compmem(a, b);
2652 }
2653
2654 int
2655 compdsk(const void *a, const void *b)
2656 {
2657 struct tstat *ta = *(struct tstat **)a;
2658 struct tstat *tb = *(struct tstat **)b;
2659
2660 count_t adsk;
2661 count_t bdsk;
2662
2663 if (ta->dsk.wsz > ta->dsk.cwsz)
2664 adsk = ta->dsk.rio + ta->dsk.wsz - ta->dsk.cwsz;
2665 else
2666 adsk = ta->dsk.rio;
2667
2668 if (tb->dsk.wsz > tb->dsk.cwsz)
2669 bdsk = tb->dsk.rio + tb->dsk.wsz - tb->dsk.cwsz;
2670 else
2671 bdsk = tb->dsk.rio;
2672
2673 if (adsk < bdsk)
2674 return 1;
2675
2676 if (adsk > bdsk)
2677 return -1;
2678
2679 return compcpu(a, b);
2680 }
2681
2682 int
2683 compmem(const void *a, const void *b)
2684 {
2685 register count_t amem = (*(struct tstat **)a)->mem.rmem;
2686 register count_t bmem = (*(struct tstat **)b)->mem.rmem;
2687
2688 if (amem < bmem)
2689 return 1;
2690
2691 if (amem > bmem)
2692 return -1;
2693
2694 return 0;
2695 }
2696
2697 int
2698 compgpu(const void *a, const void *b)
2699 {
2700 register char astate = (*(struct tstat **)a)->gpu.state;
2701 register char bstate = (*(struct tstat **)b)->gpu.state;
2702 register count_t abusy = (*(struct tstat **)a)->gpu.gpubusy;
2703 register count_t bbusy = (*(struct tstat **)b)->gpu.gpubusy;
2704 register count_t amem = (*(struct tstat **)a)->gpu.memnow;
2705 register count_t bmem = (*(struct tstat **)b)->gpu.memnow;
2706
2707 if (!astate) // no GPU usage?
2708 abusy = amem = -2;
2709
2710 if (!bstate) // no GPU usage?
2711 bbusy = bmem = -2;
2712
2713 if (abusy == -1 || bbusy == -1)
2714 {
2715 if (amem < bmem)
2716 return 1;
2717
2718 if (amem > bmem)
2719 return -1;
2720
2721 return 0;
2722 }
2723 else
2724 {
2725 if (abusy < bbusy)
2726 return 1;
2727
2728 if (abusy > bbusy)
2729 return -1;
2730
2731 return 0;
2732 }
2733 }
2734
2735 int
2736 compnet(const void *a, const void *b)
2737 {
2738 register count_t anet = (*(struct tstat **)a)->net.tcpssz +
2739 (*(struct tstat **)a)->net.tcprsz +
2740 (*(struct tstat **)a)->net.udpssz +
2741 (*(struct tstat **)a)->net.udprsz ;
2742 register count_t bnet = (*(struct tstat **)b)->net.tcpssz +
2743 (*(struct tstat **)b)->net.tcprsz +
2744 (*(struct tstat **)b)->net.udpssz +
2745 (*(struct tstat **)b)->net.udprsz ;
2746
2747 if (anet < bnet)
2748 return 1;
2749
2750 if (anet > bnet)
2751 return -1;
2752
2753 return compcpu(a, b);
2754 }
2755
2756 int
2757 compusr(const void *a, const void *b)
2758 {
2759 register int uida = (*(struct tstat **)a)->gen.ruid;
2760 register int uidb = (*(struct tstat **)b)->gen.ruid;
2761
2762 if (uida > uidb)
2763 return 1;
2764
2765 if (uida < uidb)
2766 return -1;
2767
2768 return 0;
2769 }
2770
2771 int
2772 compnam(const void *a, const void *b)
2773 {
2774 register char *nama = (*(struct tstat **)a)->gen.name;
2775 register char *namb = (*(struct tstat **)b)->gen.name;
2776
2777 return strcmp(nama, namb);
2778 }
2779
2780 int
2781 compcon(const void *a, const void *b)
2782 {
2783 register char *containera = (*(struct tstat **)a)->gen.container;
2784 register char *containerb = (*(struct tstat **)b)->gen.container;
2785
2786 return strcmp(containera, containerb);
2787 }
2788
2789 /*
2790 ** system-level sort functions
2791 */
2792 int
2793 cpucompar(const void *a, const void *b)
2794 {
2795 register count_t aidle = ((struct percpu *)a)->itime +
2796 ((struct percpu *)a)->wtime;
2797 register count_t bidle = ((struct percpu *)b)->itime +
2798 ((struct percpu *)b)->wtime;
2799
2800 if (aidle < bidle)
2801 return -1;
2802
2803 if (aidle > bidle)
2804 return 1;
2805
2806 return 0;
2807 }
2808
2809 int
2810 gpucompar(const void *a, const void *b)
2811 {
2812 register count_t agpuperc = ((struct pergpu *)a)->gpuperccum;
2813 register count_t bgpuperc = ((struct pergpu *)b)->gpuperccum;
2814 register count_t amemuse = ((struct pergpu *)a)->memusenow;
2815 register count_t bmemuse = ((struct pergpu *)b)->memusenow;
2816
2817 if (agpuperc == -1 || bgpuperc == -1)
2818 {
2819 if (amemuse < bmemuse)
2820 return 1;
2821
2822 if (amemuse > bmemuse)
2823 return -1;
2824
2825 return 0;
2826 }
2827 else
2828 {
2829 if (agpuperc < bgpuperc)
2830 return 1;
2831
2832 if (agpuperc > bgpuperc)
2833 return -1;
2834
2835 return 0;
2836 }
2837 }
2838
2839 int
2840 diskcompar(const void *a, const void *b)
2841 {
2842 register count_t amsio = ((struct perdsk *)a)->io_ms;
2843 register count_t bmsio = ((struct perdsk *)b)->io_ms;
2844
2845 if (amsio < bmsio)
2846 return 1;
2847
2848 if (amsio > bmsio)
2849 return -1;
2850
2851 return 0;
2852 }
2853
2854 int
2855 intfcompar(const void *a, const void *b)
2856 {
2857 register count_t afactor=0, bfactor=0;
2858
2859 count_t aspeed = ((struct perintf *)a)->speed;
2860 count_t bspeed = ((struct perintf *)b)->speed;
2861 char aduplex = ((struct perintf *)a)->duplex;
2862 char bduplex = ((struct perintf *)b)->duplex;
2863 count_t arbyte = ((struct perintf *)a)->rbyte;
2864 count_t brbyte = ((struct perintf *)b)->rbyte;
2865 count_t asbyte = ((struct perintf *)a)->sbyte;
2866 count_t bsbyte = ((struct perintf *)b)->sbyte;
2867
2868 /*
2869 ** if speed of first interface known, calculate busy factor
2870 */
2871 if (aspeed)
2872 {
2873 if (aduplex)
2874 afactor = (arbyte > asbyte ? arbyte : asbyte)
2875 * 10 / aspeed;
2876 else
2877 afactor = (arbyte + asbyte) * 10 / aspeed;
2878 }
2879
2880 /*
2881 ** if speed of second interface known, calculate busy factor
2882 */
2883 if (bspeed)
2884 {
2885 if (bduplex)
2886 bfactor = (brbyte > bsbyte ? brbyte : bsbyte)
2887 * 10 / bspeed;
2888 else
2889 bfactor = (brbyte + bsbyte) * 10 / bspeed;
2890 }
2891
2892 /*
2893 ** compare interfaces
2894 */
2895 if (aspeed && bspeed)
2896 {
2897 if (afactor < bfactor)
2898 return 1;
2899
2900 if (afactor > bfactor)
2901 return -1;
2902
2903 return 0;
2904 }
2905
2906 if (!aspeed && !bspeed)
2907 {
2908 if ((arbyte + asbyte) < (brbyte + bsbyte))
2909 return 1;
2910
2911 if ((arbyte + asbyte) > (brbyte + bsbyte))
2912 return -1;
2913
2914 return 0;
2915 }
2916
2917 if (aspeed)
2918 return -1;
2919 else
2920 return 1;
2921 }
2922
2923
2924 int
2925 ifbcompar(const void *a, const void *b)
2926 {
2927 count_t atransfer = ((struct perifb *)a)->rcvb +
2928 ((struct perifb *)a)->sndb;
2929 count_t btransfer = ((struct perifb *)b)->rcvb +
2930 ((struct perifb *)b)->sndb;
2931
2932 if (atransfer < btransfer)
2933 return 1;
2934
2935 if (atransfer > btransfer)
2936 return -1;
2937
2938 return 0;
2939 }
2940
2941
2942 int
2943 nfsmcompar(const void *a, const void *b)
2944 {
2945 const struct pernfsmount *na = a;
2946 const struct pernfsmount *nb = b;
2947
2948 register count_t aused = na->bytesread + na->byteswrite +
2949 na->bytesdread + na->bytesdwrite +
2950 na->bytestotread + na->bytestotwrite +
2951 na->pagesmread + na->pagesmwrite;
2952 register count_t bused = nb->bytesread + nb->byteswrite +
2953 nb->bytesdread + nb->bytesdwrite +
2954 nb->bytestotread + nb->bytestotwrite +
2955 nb->pagesmread + nb->pagesmwrite;
2956
2957 if (aused < bused)
2958 return 1;
2959
2960 if (aused > bused)
2961 return -1;
2962
2963 return 0;
2964 }
2965
2966 int
2967 contcompar(const void *a, const void *b)
2968 {
2969 const struct percontainer *ca = a;
2970 const struct percontainer *cb = b;
2971
2972 register count_t aused = ca->system + ca->user + ca->nice;
2973 register count_t bused = cb->system + cb->user + cb->nice;
2974
2975 if (aused < bused)
2976 return 1;
2977
2978 if (aused > bused)
2979 return -1;
2980
2981 return 0;
2982 }
2983
2984 int
2985 memnumacompar(const void *a, const void *b)
2986 {
2987 register count_t aused = ((struct mempernuma *)a)->totmem -
2988 ((struct mempernuma *)a)->freemem;
2989 register count_t bused = ((struct mempernuma *)b)->totmem -
2990 ((struct mempernuma *)b)->freemem;
2991
2992 if (aused < bused)
2993 return 1;
2994
2995 if (aused > bused)
2996 return -1;
2997
2998 return 0;
2999 }
3000
3001 int
3002 cpunumacompar(const void *a, const void *b)
3003 {
3004 register count_t aidle = ((struct cpupernuma *)a)->itime +
3005 ((struct cpupernuma *)a)->wtime;
3006 register count_t bidle = ((struct cpupernuma *)b)->itime +
3007 ((struct cpupernuma *)b)->wtime;
3008
3009 if (aidle < bidle)
3010 return -1;
3011
3012 if (aidle > bidle)
3013 return 1;
3014
3015 return 0;
3016 }
3017
3018 int
3019 llccompar(const void *a, const void *b)
3020 {
3021 const struct perllc *ca = a;
3022 const struct perllc *cb = b;
3023
3024 register count_t aused = ca->mbm_local + ca->mbm_total;
3025 register count_t bused = cb->mbm_local + cb->mbm_total;
3026
3027 if (aused < bused)
3028 return 1;
3029
3030 if (aused > bused)
3031 return -1;
3032
3033 return 0;
3034 }
3035
3036 /*
3037 ** handle modifications from the /etc/atoprc and ~/.atoprc file
3038 */
3039 int
3040 get_posval(char *name, char *val)
3041 {
3042 int value = atoi(val);
3043
3044 if ( !numeric(val))
3045 {
3046 fprintf(stderr, "atoprc: %s value %s not a (positive) numeric\n",
3047 name, val);
3048 exit(1);
3049 }
3050
3051 if (value < 0)
3052 {
3053 fprintf(stderr,
3054 "atoprc: %s value %d not positive\n",
3055 name, value);
3056 exit(1);
3057 }
3058
3059 return value;
3060 }
3061
3062 int
3063 get_perc(char *name, char *val)
3064 {
3065 int value = get_posval(name, val);
3066
3067 if (value < 0 || value > 100)
3068 {
3069 fprintf(stderr, "atoprc: %s value %d not in range 0-100\n",
3070 name, value);
3071 exit(1);
3072 }
3073
3074 return value;
3075 }
3076
3077 void
3078 do_cpucritperc(char *name, char *val)
3079 {
3080 cpubadness = get_perc(name, val);
3081 }
3082
3083 void
3084 do_gpucritperc(char *name, char *val)
3085 {
3086 gpubadness = get_perc(name, val);
3087 }
3088
3089 void
3090 do_memcritperc(char *name, char *val)
3091 {
3092 membadness = get_perc(name, val);
3093 }
3094
3095 void
3096 do_swpcritperc(char *name, char *val)
3097 {
3098 swpbadness = get_perc(name, val);
3099 }
3100
3101 void
3102 do_dskcritperc(char *name, char *val)
3103 {
3104 dskbadness = get_perc(name, val);
3105 }
3106
3107 void
3108 do_netcritperc(char *name, char *val)
3109 {
3110 netbadness = get_perc(name, val);
3111 }
3112
3113 void
3114 do_swoutcritsec(char *name, char *val)
3115 {
3116 pagbadness = get_posval(name, val);
3117 }
3118
3119 void
3120 do_almostcrit(char *name, char *val)
3121 {
3122 almostcrit = get_perc(name, val);
3123 }
3124
3125 void
3126 do_ownsysprcline(char *name, char *val)
3127 {
3128 make_sys_prints(sysprcline, MAXITEMS, val, prcsyspdefs, name,
3129 NULL, NULL);
3130 }
3131
3132 void
3133 do_ownallcpuline(char *name, char *val)
3134 {
3135 make_sys_prints(allcpuline, MAXITEMS, val, cpusyspdefs, name,
3136 NULL, NULL);
3137 }
3138
3139 void
3140 do_ownindivcpuline(char *name, char *val)
3141 {
3142 make_sys_prints(indivcpuline, MAXITEMS, val, cpisyspdefs, name,
3143 NULL, NULL);
3144 }
3145
3146 void
3147 do_owncplline(char *name, char *val)
3148 {
3149 make_sys_prints(cplline, MAXITEMS, val, cplsyspdefs, name,
3150 NULL, NULL);
3151 }
3152
3153 void
3154 do_owngpuline(char *name, char *val)
3155 {
3156 make_sys_prints(gpuline, MAXITEMS, val, gpusyspdefs, name,
3157 NULL, NULL);
3158 }
3159
3160 void
3161 do_ownmemline(char *name, char *val)
3162 {
3163 make_sys_prints(memline1, MAXITEMS, val, memsyspdefs1, name,
3164 NULL, NULL);
3165 }
3166
3167 void
3168 do_ownswpline(char *name, char *val)
3169 {
3170 make_sys_prints(swpline, MAXITEMS, val, swpsyspdefs, name,
3171 NULL, NULL);
3172 }
3173
3174 void
3175 do_ownpagline(char *name, char *val)
3176 {
3177 make_sys_prints(pagline, MAXITEMS, val, pagsyspdefs, name,
3178 NULL, NULL);
3179 }
3180
3181 void
3182 do_ownmemnumaline(char *name, char *val)
3183 {
3184 make_sys_prints(memnumaline, MAXITEMS, val, memnumasyspdefs, name,
3185 NULL, NULL);
3186 }
3187
3188 void
3189 do_owncpunumaline(char *name, char *val)
3190 {
3191 make_sys_prints(cpunumaline, MAXITEMS, val, cpunumasyspdefs, name,
3192 NULL, NULL);
3193 }
3194
3195 void
3196 do_ownllcline(char *name, char *val)
3197 {
3198 make_sys_prints(llcline, MAXITEMS, val, llcsyspdefs, name,
3199 NULL, NULL);
3200 }
3201
3202 void
3203 do_owndskline(char *name, char *val)
3204 {
3205 make_sys_prints(dskline, MAXITEMS, val, dsksyspdefs, name,
3206 NULL, NULL);
3207 }
3208
3209 void
3210 do_ownnettransportline(char *name, char *val)
3211 {
3212 make_sys_prints(nettransportline, MAXITEMS, val, nettranssyspdefs, name,
3213 NULL, NULL);
3214 }
3215
3216 void
3217 do_ownnetnetline(char *name, char *val)
3218 {
3219 make_sys_prints(netnetline, MAXITEMS, val, netnetsyspdefs, name,
3220 NULL, NULL);
3221 }
3222
3223 void
3224 do_ownnetinterfaceline(char *name, char *val)
3225 {
3226 make_sys_prints(netinterfaceline, MAXITEMS, val, netintfsyspdefs, name,
3227 NULL, NULL);
3228 }
3229
3230 void
3231 do_owninfinibandline(char *name, char *val)
3232 {
3233 make_sys_prints(infinibandline, MAXITEMS, val, infinisyspdefs, name,
3234 NULL, NULL);
3235 }
3236
3237 void
3238 do_ownprocline(char *name, char *val)
3239 {
3240 make_proc_prints(ownprocs, MAXITEMS, val, name);
3241 }