1/* 2 * top - a top users display for Unix 3 * 4 * SYNOPSIS: For FreeBSD-2.x and later 5 * 6 * DESCRIPTION: 7 * Originally written for BSD4.4 system by Christos Zoulas. 8 * Ported to FreeBSD 2.x by Steven Wallace && Wolfram Schneider 9 * Order support hacked in from top-3.5beta6/machine/m_aix41.c 10 * by Monte Mitzelfelt (for latest top see http://www.groupsys.com/topinfo/) 11 * 12 * This is the machine-dependent module for FreeBSD 2.2 13 * Works for: 14 * FreeBSD 2.2.x, 3.x, 4.x, and probably FreeBSD 2.1.x 15 * 16 * LIBS: -lkvm 17 * 18 * AUTHOR: Christos Zoulas <christos@ee.cornell.edu> 19 * Steven Wallace <swallace@freebsd.org> 20 * Wolfram Schneider <wosch@FreeBSD.org> 21 * Thomas Moestl <tmoestl@gmx.net> 22 * 23 * $FreeBSD: stable/11/usr.bin/top/machine.c 362940 2020-07-05 06:51:39Z kib $ 24 */ 25 26#include <sys/param.h> 27#include <sys/errno.h> 28#include <sys/file.h> 29#include <sys/proc.h> 30#include <sys/resource.h> 31#include <sys/rtprio.h> 32#include <sys/signal.h> 33#include <sys/sysctl.h> 34#include <sys/time.h> 35#include <sys/user.h> 36#include <sys/vmmeter.h> 37 38#include <err.h> 39#include <kvm.h> 40#include <math.h> 41#include <nlist.h> 42#include <paths.h> 43#include <pwd.h> 44#include <stdio.h> 45#include <stdlib.h> 46#include <string.h> 47#include <strings.h> 48#include <unistd.h> 49#include <vis.h> 50 51#include "top.h" 52#include "machine.h" 53#include "screen.h" 54#include "utils.h" 55#include "layout.h" 56 57#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var)) 58#define SMPUNAMELEN 13 59#define UPUNAMELEN 15 60 61extern struct process_select ps; 62extern char* printable(char *); 63static int smpmode; 64enum displaymodes displaymode; 65#ifdef TOP_USERNAME_LEN 66static int namelength = TOP_USERNAME_LEN; 67#else 68static int namelength = 8; 69#endif 70/* TOP_JID_LEN based on max of 999999 */ 71#define TOP_JID_LEN 7 72#define TOP_SWAP_LEN 6 73static int jidlength; 74static int swaplength; 75static int cmdlengthdelta; 76 77/* Prototypes for top internals */ 78void quit(int); 79 80/* get_process_info passes back a handle. This is what it looks like: */ 81 82struct handle { 83 struct kinfo_proc **next_proc; /* points to next valid proc pointer */ 84 int remaining; /* number of pointers remaining */ 85}; 86 87/* declarations for load_avg */ 88#include "loadavg.h" 89 90/* define what weighted cpu is. */ 91#define weighted_cpu(pct, pp) ((pp)->ki_swtime == 0 ? 0.0 : \ 92 ((pct) / (1.0 - exp((pp)->ki_swtime * logcpu)))) 93 94/* what we consider to be process size: */ 95#define PROCSIZE(pp) ((pp)->ki_size / 1024) 96 97#define RU(pp) (&(pp)->ki_rusage) 98#define RUTOT(pp) \ 99 (RU(pp)->ru_inblock + RU(pp)->ru_oublock + RU(pp)->ru_majflt) 100 101#define PCTCPU(pp) (pcpu[pp - pbase]) 102 103/* definitions for indices in the nlist array */ 104 105/* 106 * These definitions control the format of the per-process area 107 */ 108 109static char io_header[] = 110 " PID%*s %-*.*s VCSW IVCSW READ WRITE FAULT TOTAL PERCENT COMMAND"; 111 112#define io_Proc_format \ 113 "%5d%*s %-*.*s %6ld %6ld %6ld %6ld %6ld %6ld %6.2f%% %.*s" 114 115static char smp_header_thr[] = 116 " PID%*s %-*.*s THR PRI NICE SIZE RES%*s STATE C TIME %7s COMMAND"; 117static char smp_header[] = 118 " PID%*s %-*.*s " "PRI NICE SIZE RES%*s STATE C TIME %7s COMMAND"; 119 120#define smp_Proc_format \ 121 "%5d%*s %-*.*s %s%3d %4s%7s %6s%*.*s %-6.6s %2d%7s %6.2f%% %.*s" 122 123static char up_header_thr[] = 124 " PID%*s %-*.*s THR PRI NICE SIZE RES%*s STATE TIME %7s COMMAND"; 125static char up_header[] = 126 " PID%*s %-*.*s " "PRI NICE SIZE RES%*s STATE TIME %7s COMMAND"; 127 128#define up_Proc_format \ 129 "%5d%*s %-*.*s %s%3d %4s%7s %6s%*.*s %-6.6s%.0d%7s %6.2f%% %.*s" 130 131 132/* process state names for the "STATE" column of the display */ 133/* the extra nulls in the string "run" are for adding a slash and 134 the processor number when needed */ 135 136char *state_abbrev[] = { 137 "", "START", "RUN\0\0\0", "SLEEP", "STOP", "ZOMB", "WAIT", "LOCK" 138}; 139 140 141static kvm_t *kd; 142 143/* values that we stash away in _init and use in later routines */ 144 145static double logcpu; 146 147/* these are retrieved from the kernel in _init */ 148 149static load_avg ccpu; 150 151/* these are used in the get_ functions */ 152 153static int lastpid; 154 155/* these are for calculating cpu state percentages */ 156 157static long cp_time[CPUSTATES]; 158static long cp_old[CPUSTATES]; 159static long cp_diff[CPUSTATES]; 160 161/* these are for detailing the process states */ 162 163int process_states[8]; 164char *procstatenames[] = { 165 "", " starting, ", " running, ", " sleeping, ", " stopped, ", 166 " zombie, ", " waiting, ", " lock, ", 167 NULL 168}; 169 170/* these are for detailing the cpu states */ 171 172int cpu_states[CPUSTATES]; 173char *cpustatenames[] = { 174 "user", "nice", "system", "interrupt", "idle", NULL 175}; 176 177/* these are for detailing the memory statistics */ 178 179int memory_stats[7]; 180char *memorynames[] = { 181 "K Active, ", "K Inact, ", "K Laundry, ", "K Wired, ", "K Buf, ", 182 "K Free", NULL 183}; 184 185int arc_stats[7]; 186char *arcnames[] = { 187 "K Total, ", "K MFU, ", "K MRU, ", "K Anon, ", "K Header, ", "K Other", 188 NULL 189}; 190 191int carc_stats[4]; 192char *carcnames[] = { 193 "K Compressed, ", "K Uncompressed, ", ":1 Ratio, ", 194 NULL 195}; 196 197int swap_stats[7]; 198char *swapnames[] = { 199 "K Total, ", "K Used, ", "K Free, ", "% Inuse, ", "K In, ", "K Out", 200 NULL 201}; 202 203 204/* these are for keeping track of the proc array */ 205 206static int nproc; 207static int onproc = -1; 208static int pref_len; 209static struct kinfo_proc *pbase; 210static struct kinfo_proc **pref; 211static struct kinfo_proc *previous_procs; 212static struct kinfo_proc **previous_pref; 213static int previous_proc_count = 0; 214static int previous_proc_count_max = 0; 215static int previous_thread; 216 217/* data used for recalculating pctcpu */ 218static double *pcpu; 219static struct timespec proc_uptime; 220static struct timeval proc_wall_time; 221static struct timeval previous_wall_time; 222static uint64_t previous_interval = 0; 223 224/* total number of io operations */ 225static long total_inblock; 226static long total_oublock; 227static long total_majflt; 228 229/* these are for getting the memory statistics */ 230 231static int arc_enabled; 232static int carc_enabled; 233static int pageshift; /* log base 2 of the pagesize */ 234 235/* define pagetok in terms of pageshift */ 236 237#define pagetok(size) ((size) << pageshift) 238 239/* swap usage */ 240#define ki_swap(kip) \ 241 ((kip)->ki_swrss > (kip)->ki_rssize ? (kip)->ki_swrss - (kip)->ki_rssize : 0) 242 243/* useful externals */ 244long percentages(); 245 246#ifdef ORDER 247/* 248 * Sorting orders. The first element is the default. 249 */ 250char *ordernames[] = { 251 "cpu", "size", "res", "time", "pri", "threads", 252 "total", "read", "write", "fault", "vcsw", "ivcsw", 253 "jid", "swap", "pid", NULL 254}; 255#endif 256 257/* Per-cpu time states */ 258static int maxcpu; 259static int maxid; 260static int ncpus; 261static u_long cpumask; 262static long *times; 263static long *pcpu_cp_time; 264static long *pcpu_cp_old; 265static long *pcpu_cp_diff; 266static int *pcpu_cpu_states; 267 268static int compare_swap(const void *a, const void *b); 269static int compare_jid(const void *a, const void *b); 270static int compare_pid(const void *a, const void *b); 271static int compare_tid(const void *a, const void *b); 272static const char *format_nice(const struct kinfo_proc *pp); 273static void getsysctl(const char *name, void *ptr, size_t len); 274static int swapmode(int *retavail, int *retfree); 275static void update_layout(void); 276static int find_uid(uid_t needle, int *haystack); 277 278static int 279find_uid(uid_t needle, int *haystack) 280{ 281 size_t i = 0; 282 283 for (; i < TOP_MAX_UIDS; ++i) 284 if ((uid_t)haystack[i] == needle) 285 return 1; 286 return 0; 287} 288 289void 290toggle_pcpustats(void) 291{ 292 293 if (ncpus == 1) 294 return; 295 update_layout(); 296} 297 298/* Adjust display based on ncpus and the ARC state. */ 299static void 300update_layout(void) 301{ 302 303 y_mem = 3; 304 y_arc = 4; 305 y_carc = 5; 306 y_swap = 4 + arc_enabled + carc_enabled; 307 y_idlecursor = 5 + arc_enabled + carc_enabled; 308 y_message = 5 + arc_enabled + carc_enabled; 309 y_header = 6 + arc_enabled + carc_enabled; 310 y_procs = 7 + arc_enabled + carc_enabled; 311 Header_lines = 7 + arc_enabled + carc_enabled; 312 313 if (pcpu_stats) { 314 y_mem += ncpus - 1; 315 y_arc += ncpus - 1; 316 y_carc += ncpus - 1; 317 y_swap += ncpus - 1; 318 y_idlecursor += ncpus - 1; 319 y_message += ncpus - 1; 320 y_header += ncpus - 1; 321 y_procs += ncpus - 1; 322 Header_lines += ncpus - 1; 323 } 324} 325 326int 327machine_init(struct statics *statics, char do_unames) 328{ 329 int i, j, empty, pagesize; 330 uint64_t arc_size; 331 boolean_t carc_en; 332 size_t size; 333 struct passwd *pw; 334 335 size = sizeof(smpmode); 336 if (sysctlbyname("kern.smp.active", &smpmode, &size, NULL, 0) != 0 || 337 size != sizeof(smpmode)) 338 smpmode = 0; 339 340 size = sizeof(arc_size); 341 if (sysctlbyname("kstat.zfs.misc.arcstats.size", &arc_size, &size, 342 NULL, 0) == 0 && arc_size != 0) 343 arc_enabled = 1; 344 size = sizeof(carc_en); 345 if (arc_enabled && 346 sysctlbyname("vfs.zfs.compressed_arc_enabled", &carc_en, &size, 347 NULL, 0) == 0 && carc_en == 1) 348 carc_enabled = 1; 349 350 if (do_unames) { 351 while ((pw = getpwent()) != NULL) { 352 if (strlen(pw->pw_name) > namelength) 353 namelength = strlen(pw->pw_name); 354 } 355 } 356 if (smpmode && namelength > SMPUNAMELEN) 357 namelength = SMPUNAMELEN; 358 else if (namelength > UPUNAMELEN) 359 namelength = UPUNAMELEN; 360 361 kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open"); 362 if (kd == NULL) 363 return (-1); 364 365 GETSYSCTL("kern.ccpu", ccpu); 366 367 /* this is used in calculating WCPU -- calculate it ahead of time */ 368 logcpu = log(loaddouble(ccpu)); 369 370 pbase = NULL; 371 pref = NULL; 372 pcpu = NULL; 373 nproc = 0; 374 onproc = -1; 375 376 /* get the page size and calculate pageshift from it */ 377 pagesize = getpagesize(); 378 pageshift = 0; 379 while (pagesize > 1) { 380 pageshift++; 381 pagesize >>= 1; 382 } 383 384 /* we only need the amount of log(2)1024 for our conversion */ 385 pageshift -= LOG1024; 386 387 /* fill in the statics information */ 388 statics->procstate_names = procstatenames; 389 statics->cpustate_names = cpustatenames; 390 statics->memory_names = memorynames; 391 if (arc_enabled) 392 statics->arc_names = arcnames; 393 else 394 statics->arc_names = NULL; 395 if (carc_enabled) 396 statics->carc_names = carcnames; 397 else 398 statics->carc_names = NULL; 399 statics->swap_names = swapnames; 400#ifdef ORDER 401 statics->order_names = ordernames; 402#endif 403 404 /* Allocate state for per-CPU stats. */ 405 cpumask = 0; 406 ncpus = 0; 407 GETSYSCTL("kern.smp.maxcpus", maxcpu); 408 size = sizeof(long) * maxcpu * CPUSTATES; 409 times = malloc(size); 410 if (times == NULL) 411 err(1, "malloc %zu bytes", size); 412 if (sysctlbyname("kern.cp_times", times, &size, NULL, 0) == -1) 413 err(1, "sysctlbyname kern.cp_times"); 414 pcpu_cp_time = calloc(1, size); 415 maxid = (size / CPUSTATES / sizeof(long)) - 1; 416 for (i = 0; i <= maxid; i++) { 417 empty = 1; 418 for (j = 0; empty && j < CPUSTATES; j++) { 419 if (times[i * CPUSTATES + j] != 0) 420 empty = 0; 421 } 422 if (!empty) { 423 cpumask |= (1ul << i); 424 ncpus++; 425 } 426 } 427 size = sizeof(long) * ncpus * CPUSTATES; 428 pcpu_cp_old = calloc(1, size); 429 pcpu_cp_diff = calloc(1, size); 430 pcpu_cpu_states = calloc(1, size); 431 statics->ncpus = ncpus; 432 433 update_layout(); 434 435 /* all done! */ 436 return (0); 437} 438 439char * 440format_header(char *uname_field) 441{ 442 static char Header[128]; 443 const char *prehead; 444 445 if (ps.jail) 446 jidlength = TOP_JID_LEN + 1; /* +1 for extra left space. */ 447 else 448 jidlength = 0; 449 450 if (ps.swap) 451 swaplength = TOP_SWAP_LEN + 1; /* +1 for extra left space */ 452 else 453 swaplength = 0; 454 455 switch (displaymode) { 456 case DISP_CPU: 457 /* 458 * The logic of picking the right header format seems reverse 459 * here because we only want to display a THR column when 460 * "thread mode" is off (and threads are not listed as 461 * separate lines). 462 */ 463 prehead = smpmode ? 464 (ps.thread ? smp_header : smp_header_thr) : 465 (ps.thread ? up_header : up_header_thr); 466 snprintf(Header, sizeof(Header), prehead, 467 jidlength, ps.jail ? " JID" : "", 468 namelength, namelength, uname_field, 469 swaplength, ps.swap ? " SWAP" : "", 470 ps.wcpu ? "WCPU" : "CPU"); 471 break; 472 case DISP_IO: 473 prehead = io_header; 474 snprintf(Header, sizeof(Header), prehead, 475 jidlength, ps.jail ? " JID" : "", 476 namelength, namelength, uname_field); 477 break; 478 } 479 cmdlengthdelta = strlen(Header) - 7; 480 return (Header); 481} 482 483static int swappgsin = -1; 484static int swappgsout = -1; 485extern struct timeval timeout; 486 487 488void 489get_system_info(struct system_info *si) 490{ 491 long total; 492 struct loadavg sysload; 493 int mib[2]; 494 struct timeval boottime; 495 uint64_t arc_stat, arc_stat2; 496 int i, j; 497 size_t size; 498 499 /* get the CPU stats */ 500 size = (maxid + 1) * CPUSTATES * sizeof(long); 501 if (sysctlbyname("kern.cp_times", pcpu_cp_time, &size, NULL, 0) == -1) 502 err(1, "sysctlbyname kern.cp_times"); 503 GETSYSCTL("kern.cp_time", cp_time); 504 GETSYSCTL("vm.loadavg", sysload); 505 GETSYSCTL("kern.lastpid", lastpid); 506 507 /* convert load averages to doubles */ 508 for (i = 0; i < 3; i++) 509 si->load_avg[i] = (double)sysload.ldavg[i] / sysload.fscale; 510 511 /* convert cp_time counts to percentages */ 512 for (i = j = 0; i <= maxid; i++) { 513 if ((cpumask & (1ul << i)) == 0) 514 continue; 515 percentages(CPUSTATES, &pcpu_cpu_states[j * CPUSTATES], 516 &pcpu_cp_time[j * CPUSTATES], 517 &pcpu_cp_old[j * CPUSTATES], 518 &pcpu_cp_diff[j * CPUSTATES]); 519 j++; 520 } 521 percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff); 522 523 /* sum memory & swap statistics */ 524 { 525 static unsigned int swap_delay = 0; 526 static int swapavail = 0; 527 static int swapfree = 0; 528 static long bufspace = 0; 529 static int nspgsin, nspgsout; 530 531 GETSYSCTL("vfs.bufspace", bufspace); 532 GETSYSCTL("vm.stats.vm.v_active_count", memory_stats[0]); 533 GETSYSCTL("vm.stats.vm.v_inactive_count", memory_stats[1]); 534 GETSYSCTL("vm.stats.vm.v_laundry_count", memory_stats[2]); 535 GETSYSCTL("vm.stats.vm.v_wire_count", memory_stats[3]); 536 GETSYSCTL("vm.stats.vm.v_free_count", memory_stats[5]); 537 GETSYSCTL("vm.stats.vm.v_swappgsin", nspgsin); 538 GETSYSCTL("vm.stats.vm.v_swappgsout", nspgsout); 539 /* convert memory stats to Kbytes */ 540 memory_stats[0] = pagetok(memory_stats[0]); 541 memory_stats[1] = pagetok(memory_stats[1]); 542 memory_stats[2] = pagetok(memory_stats[2]); 543 memory_stats[3] = pagetok(memory_stats[3]); 544 memory_stats[4] = bufspace / 1024; 545 memory_stats[5] = pagetok(memory_stats[5]); 546 memory_stats[6] = -1; 547 548 /* first interval */ 549 if (swappgsin < 0) { 550 swap_stats[4] = 0; 551 swap_stats[5] = 0; 552 } 553 554 /* compute differences between old and new swap statistic */ 555 else { 556 swap_stats[4] = pagetok(((nspgsin - swappgsin))); 557 swap_stats[5] = pagetok(((nspgsout - swappgsout))); 558 } 559 560 swappgsin = nspgsin; 561 swappgsout = nspgsout; 562 563 /* call CPU heavy swapmode() only for changes */ 564 if (swap_stats[4] > 0 || swap_stats[5] > 0 || swap_delay == 0) { 565 swap_stats[3] = swapmode(&swapavail, &swapfree); 566 swap_stats[0] = swapavail; 567 swap_stats[1] = swapavail - swapfree; 568 swap_stats[2] = swapfree; 569 } 570 swap_delay = 1; 571 swap_stats[6] = -1; 572 } 573 574 if (arc_enabled) { 575 GETSYSCTL("kstat.zfs.misc.arcstats.size", arc_stat); 576 arc_stats[0] = arc_stat >> 10; 577 GETSYSCTL("vfs.zfs.mfu_size", arc_stat); 578 arc_stats[1] = arc_stat >> 10; 579 GETSYSCTL("vfs.zfs.mru_size", arc_stat); 580 arc_stats[2] = arc_stat >> 10; 581 GETSYSCTL("vfs.zfs.anon_size", arc_stat); 582 arc_stats[3] = arc_stat >> 10; 583 GETSYSCTL("kstat.zfs.misc.arcstats.hdr_size", arc_stat); 584 GETSYSCTL("kstat.zfs.misc.arcstats.l2_hdr_size", arc_stat2); 585 arc_stats[4] = arc_stat + arc_stat2 >> 10; 586 GETSYSCTL("kstat.zfs.misc.arcstats.other_size", arc_stat); 587 arc_stats[5] = arc_stat >> 10; 588 si->arc = arc_stats; 589 } 590 if (carc_enabled) { 591 GETSYSCTL("kstat.zfs.misc.arcstats.compressed_size", arc_stat); 592 carc_stats[0] = arc_stat >> 10; 593 carc_stats[2] = arc_stat >> 10; /* For ratio */ 594 GETSYSCTL("kstat.zfs.misc.arcstats.uncompressed_size", arc_stat); 595 carc_stats[1] = arc_stat >> 10; 596 si->carc = carc_stats; 597 } 598 599 /* set arrays and strings */ 600 if (pcpu_stats) { 601 si->cpustates = pcpu_cpu_states; 602 si->ncpus = ncpus; 603 } else { 604 si->cpustates = cpu_states; 605 si->ncpus = 1; 606 } 607 si->memory = memory_stats; 608 si->swap = swap_stats; 609 610 611 if (lastpid > 0) { 612 si->last_pid = lastpid; 613 } else { 614 si->last_pid = -1; 615 } 616 617 /* 618 * Print how long system has been up. 619 * (Found by looking getting "boottime" from the kernel) 620 */ 621 mib[0] = CTL_KERN; 622 mib[1] = KERN_BOOTTIME; 623 size = sizeof(boottime); 624 if (sysctl(mib, nitems(mib), &boottime, &size, NULL, 0) != -1 && 625 boottime.tv_sec != 0) { 626 si->boottime = boottime; 627 } else { 628 si->boottime.tv_sec = -1; 629 } 630} 631 632#define NOPROC ((void *)-1) 633 634/* 635 * We need to compare data from the old process entry with the new 636 * process entry. 637 * To facilitate doing this quickly we stash a pointer in the kinfo_proc 638 * structure to cache the mapping. We also use a negative cache pointer 639 * of NOPROC to avoid duplicate lookups. 640 * XXX: this could be done when the actual processes are fetched, we do 641 * it here out of laziness. 642 */ 643const struct kinfo_proc * 644get_old_proc(struct kinfo_proc *pp) 645{ 646 struct kinfo_proc **oldpp, *oldp; 647 648 /* 649 * If this is the first fetch of the kinfo_procs then we don't have 650 * any previous entries. 651 */ 652 if (previous_proc_count == 0) 653 return (NULL); 654 /* negative cache? */ 655 if (pp->ki_udata == NOPROC) 656 return (NULL); 657 /* cached? */ 658 if (pp->ki_udata != NULL) 659 return (pp->ki_udata); 660 /* 661 * Not cached, 662 * 1) look up based on pid. 663 * 2) compare process start. 664 * If we fail here, then setup a negative cache entry, otherwise 665 * cache it. 666 */ 667 oldpp = bsearch(&pp, previous_pref, previous_proc_count, 668 sizeof(*previous_pref), ps.thread ? compare_tid : compare_pid); 669 if (oldpp == NULL) { 670 pp->ki_udata = NOPROC; 671 return (NULL); 672 } 673 oldp = *oldpp; 674 if (bcmp(&oldp->ki_start, &pp->ki_start, sizeof(pp->ki_start)) != 0) { 675 pp->ki_udata = NOPROC; 676 return (NULL); 677 } 678 pp->ki_udata = oldp; 679 return (oldp); 680} 681 682/* 683 * Return the total amount of IO done in blocks in/out and faults. 684 * store the values individually in the pointers passed in. 685 */ 686long 687get_io_stats(struct kinfo_proc *pp, long *inp, long *oup, long *flp, 688 long *vcsw, long *ivcsw) 689{ 690 const struct kinfo_proc *oldp; 691 static struct kinfo_proc dummy; 692 long ret; 693 694 oldp = get_old_proc(pp); 695 if (oldp == NULL) { 696 bzero(&dummy, sizeof(dummy)); 697 oldp = &dummy; 698 } 699 *inp = RU(pp)->ru_inblock - RU(oldp)->ru_inblock; 700 *oup = RU(pp)->ru_oublock - RU(oldp)->ru_oublock; 701 *flp = RU(pp)->ru_majflt - RU(oldp)->ru_majflt; 702 *vcsw = RU(pp)->ru_nvcsw - RU(oldp)->ru_nvcsw; 703 *ivcsw = RU(pp)->ru_nivcsw - RU(oldp)->ru_nivcsw; 704 ret = 705 (RU(pp)->ru_inblock - RU(oldp)->ru_inblock) + 706 (RU(pp)->ru_oublock - RU(oldp)->ru_oublock) + 707 (RU(pp)->ru_majflt - RU(oldp)->ru_majflt); 708 return (ret); 709} 710 711/* 712 * If there was a previous update, use the delta in ki_runtime over 713 * the previous interval to calculate pctcpu. Otherwise, fall back 714 * to using the kernel's ki_pctcpu. 715 */ 716static double 717proc_calc_pctcpu(struct kinfo_proc *pp) 718{ 719 const struct kinfo_proc *oldp; 720 721 if (previous_interval != 0) { 722 oldp = get_old_proc(pp); 723 if (oldp != NULL) 724 return ((double)(pp->ki_runtime - oldp->ki_runtime) 725 / previous_interval); 726 727 /* 728 * If this process/thread was created during the previous 729 * interval, charge it's total runtime to the previous 730 * interval. 731 */ 732 else if (pp->ki_start.tv_sec > previous_wall_time.tv_sec || 733 (pp->ki_start.tv_sec == previous_wall_time.tv_sec && 734 pp->ki_start.tv_usec >= previous_wall_time.tv_usec)) 735 return ((double)pp->ki_runtime / previous_interval); 736 } 737 return (pctdouble(pp->ki_pctcpu)); 738} 739 740/* 741 * Return true if this process has used any CPU time since the 742 * previous update. 743 */ 744static int 745proc_used_cpu(struct kinfo_proc *pp) 746{ 747 const struct kinfo_proc *oldp; 748 749 oldp = get_old_proc(pp); 750 if (oldp == NULL) 751 return (PCTCPU(pp) != 0); 752 return (pp->ki_runtime != oldp->ki_runtime || 753 RU(pp)->ru_nvcsw != RU(oldp)->ru_nvcsw || 754 RU(pp)->ru_nivcsw != RU(oldp)->ru_nivcsw); 755} 756 757/* 758 * Return the total number of block in/out and faults by a process. 759 */ 760long 761get_io_total(struct kinfo_proc *pp) 762{ 763 long dummy; 764 765 return (get_io_stats(pp, &dummy, &dummy, &dummy, &dummy, &dummy)); 766} 767 768static struct handle handle; 769 770caddr_t 771get_process_info(struct system_info *si, struct process_select *sel, 772 int (*compare)(const void *, const void *)) 773{ 774 int i; 775 int total_procs; 776 long p_io; 777 long p_inblock, p_oublock, p_majflt, p_vcsw, p_ivcsw; 778 long nsec; 779 int active_procs; 780 struct kinfo_proc **prefp; 781 struct kinfo_proc *pp; 782 struct timespec previous_proc_uptime; 783 784 /* these are copied out of sel for speed */ 785 int show_idle; 786 int show_jid; 787 int show_self; 788 int show_system; 789 int show_uid; 790 int show_command; 791 int show_kidle; 792 793 /* 794 * If thread state was toggled, don't cache the previous processes. 795 */ 796 if (previous_thread != sel->thread) 797 nproc = 0; 798 previous_thread = sel->thread; 799 800 /* 801 * Save the previous process info. 802 */ 803 if (previous_proc_count_max < nproc) { 804 free(previous_procs); 805 previous_procs = malloc(nproc * sizeof(*previous_procs)); 806 free(previous_pref); 807 previous_pref = malloc(nproc * sizeof(*previous_pref)); 808 if (previous_procs == NULL || previous_pref == NULL) { 809 (void) fprintf(stderr, "top: Out of memory.\n"); 810 quit(23); 811 } 812 previous_proc_count_max = nproc; 813 } 814 if (nproc) { 815 for (i = 0; i < nproc; i++) 816 previous_pref[i] = &previous_procs[i]; 817 bcopy(pbase, previous_procs, nproc * sizeof(*previous_procs)); 818 qsort(previous_pref, nproc, sizeof(*previous_pref), 819 ps.thread ? compare_tid : compare_pid); 820 } 821 previous_proc_count = nproc; 822 previous_proc_uptime = proc_uptime; 823 previous_wall_time = proc_wall_time; 824 previous_interval = 0; 825 826 pbase = kvm_getprocs(kd, sel->thread ? KERN_PROC_ALL : KERN_PROC_PROC, 827 0, &nproc); 828 (void)gettimeofday(&proc_wall_time, NULL); 829 if (clock_gettime(CLOCK_UPTIME, &proc_uptime) != 0) 830 memset(&proc_uptime, 0, sizeof(proc_uptime)); 831 else if (previous_proc_uptime.tv_sec != 0 && 832 previous_proc_uptime.tv_nsec != 0) { 833 previous_interval = (proc_uptime.tv_sec - 834 previous_proc_uptime.tv_sec) * 1000000; 835 nsec = proc_uptime.tv_nsec - previous_proc_uptime.tv_nsec; 836 if (nsec < 0) { 837 previous_interval -= 1000000; 838 nsec += 1000000000; 839 } 840 previous_interval += nsec / 1000; 841 } 842 if (nproc > onproc) { 843 pref = realloc(pref, sizeof(*pref) * nproc); 844 pcpu = realloc(pcpu, sizeof(*pcpu) * nproc); 845 onproc = nproc; 846 } 847 if (pref == NULL || pbase == NULL || pcpu == NULL) { 848 (void) fprintf(stderr, "top: Out of memory.\n"); 849 quit(23); 850 } 851 /* get a pointer to the states summary array */ 852 si->procstates = process_states; 853 854 /* set up flags which define what we are going to select */ 855 show_idle = sel->idle; 856 show_jid = sel->jid != -1; 857 show_self = sel->self == -1; 858 show_system = sel->system; 859 show_uid = sel->uid[0] != -1; 860 show_command = sel->command != NULL; 861 show_kidle = sel->kidle; 862 863 /* count up process states and get pointers to interesting procs */ 864 total_procs = 0; 865 active_procs = 0; 866 total_inblock = 0; 867 total_oublock = 0; 868 total_majflt = 0; 869 memset((char *)process_states, 0, sizeof(process_states)); 870 prefp = pref; 871 for (pp = pbase, i = 0; i < nproc; pp++, i++) { 872 873 if (pp->ki_stat == 0) 874 /* not in use */ 875 continue; 876 877 if (!show_self && pp->ki_pid == sel->self) 878 /* skip self */ 879 continue; 880 881 if (!show_system && (pp->ki_flag & P_SYSTEM)) 882 /* skip system process */ 883 continue; 884 885 p_io = get_io_stats(pp, &p_inblock, &p_oublock, &p_majflt, 886 &p_vcsw, &p_ivcsw); 887 total_inblock += p_inblock; 888 total_oublock += p_oublock; 889 total_majflt += p_majflt; 890 total_procs++; 891 process_states[pp->ki_stat]++; 892 893 if (pp->ki_stat == SZOMB) 894 /* skip zombies */ 895 continue; 896 897 if (!show_kidle && pp->ki_tdflags & TDF_IDLETD) 898 /* skip kernel idle process */ 899 continue; 900 901 PCTCPU(pp) = proc_calc_pctcpu(pp); 902 if (sel->thread && PCTCPU(pp) > 1.0) 903 PCTCPU(pp) = 1.0; 904 if (displaymode == DISP_CPU && !show_idle && 905 (!proc_used_cpu(pp) || 906 pp->ki_stat == SSTOP || pp->ki_stat == SIDL)) 907 /* skip idle or non-running processes */ 908 continue; 909 910 if (displaymode == DISP_IO && !show_idle && p_io == 0) 911 /* skip processes that aren't doing I/O */ 912 continue; 913 914 if (show_jid && pp->ki_jid != sel->jid) 915 /* skip proc. that don't belong to the selected JID */ 916 continue; 917 918 if (show_uid && !find_uid(pp->ki_ruid, sel->uid)) 919 /* skip proc. that don't belong to the selected UID */ 920 continue; 921 922 *prefp++ = pp; 923 active_procs++; 924 } 925 926 /* if requested, sort the "interesting" processes */ 927 if (compare != NULL) 928 qsort(pref, active_procs, sizeof(*pref), compare); 929 930 /* remember active and total counts */ 931 si->p_total = total_procs; 932 si->p_active = pref_len = active_procs; 933 934 /* pass back a handle */ 935 handle.next_proc = pref; 936 handle.remaining = active_procs; 937 return ((caddr_t)&handle); 938} 939 940static char fmt[512]; /* static area where result is built */ 941 942char * 943format_next_process(caddr_t handle, char *(*get_userid)(int), int flags) 944{ 945 struct kinfo_proc *pp; 946 const struct kinfo_proc *oldp; 947 long cputime; 948 double pct; 949 struct handle *hp; 950 char status[16]; 951 int cpu, state; 952 struct rusage ru, *rup; 953 long p_tot, s_tot; 954 char *proc_fmt, thr_buf[6]; 955 char jid_buf[TOP_JID_LEN + 1], swap_buf[TOP_SWAP_LEN + 1]; 956 char *cmdbuf = NULL; 957 char **args; 958 const int cmdlen = 128; 959 960 /* find and remember the next proc structure */ 961 hp = (struct handle *)handle; 962 pp = *(hp->next_proc++); 963 hp->remaining--; 964 965 /* get the process's command name */ 966 if ((pp->ki_flag & P_INMEM) == 0) { 967 /* 968 * Print swapped processes as <pname> 969 */ 970 size_t len; 971 972 len = strlen(pp->ki_comm); 973 if (len > sizeof(pp->ki_comm) - 3) 974 len = sizeof(pp->ki_comm) - 3; 975 memmove(pp->ki_comm + 1, pp->ki_comm, len); 976 pp->ki_comm[0] = '<'; 977 pp->ki_comm[len + 1] = '>'; 978 pp->ki_comm[len + 2] = '\0'; 979 } 980 981 /* 982 * Convert the process's runtime from microseconds to seconds. This 983 * time includes the interrupt time although that is not wanted here. 984 * ps(1) is similarly sloppy. 985 */ 986 cputime = (pp->ki_runtime + 500000) / 1000000; 987 988 /* calculate the base for cpu percentages */ 989 pct = PCTCPU(pp); 990 991 /* generate "STATE" field */ 992 switch (state = pp->ki_stat) { 993 case SRUN: 994 if (smpmode && pp->ki_oncpu != NOCPU) 995 sprintf(status, "CPU%d", pp->ki_oncpu); 996 else 997 strcpy(status, "RUN"); 998 break; 999 case SLOCK: 1000 if (pp->ki_kiflag & KI_LOCKBLOCK) { 1001 sprintf(status, "*%.6s", pp->ki_lockname); 1002 break; 1003 } 1004 /* fall through */ 1005 case SSLEEP: 1006 if (pp->ki_wmesg != NULL) { 1007 sprintf(status, "%.6s", pp->ki_wmesg); 1008 break; 1009 } 1010 /* FALLTHROUGH */ 1011 default: 1012 1013 if (state >= 0 && 1014 state < sizeof(state_abbrev) / sizeof(*state_abbrev)) 1015 sprintf(status, "%.6s", state_abbrev[state]); 1016 else 1017 sprintf(status, "?%5d", state); 1018 break; 1019 } 1020 1021 cmdbuf = (char *)malloc(cmdlen + 1); 1022 if (cmdbuf == NULL) { 1023 warn("malloc(%d)", cmdlen + 1); 1024 return NULL; 1025 } 1026 1027 if (!(flags & FMT_SHOWARGS)) { 1028 if (ps.thread && pp->ki_flag & P_HADTHREADS && 1029 pp->ki_tdname[0]) { 1030 snprintf(cmdbuf, cmdlen, "%s{%s%s}", pp->ki_comm, 1031 pp->ki_tdname, pp->ki_moretdname); 1032 } else { 1033 snprintf(cmdbuf, cmdlen, "%s", pp->ki_comm); 1034 } 1035 } else { 1036 if (pp->ki_flag & P_SYSTEM || 1037 (args = kvm_getargv(kd, pp, cmdlen)) == NULL || 1038 !(*args)) { 1039 if (ps.thread && pp->ki_flag & P_HADTHREADS && 1040 pp->ki_tdname[0]) { 1041 snprintf(cmdbuf, cmdlen, 1042 "[%s{%s%s}]", pp->ki_comm, pp->ki_tdname, 1043 pp->ki_moretdname); 1044 } else { 1045 snprintf(cmdbuf, cmdlen, 1046 "[%s]", pp->ki_comm); 1047 } 1048 } else { 1049 char *src, *dst, *argbuf; 1050 char *cmd; 1051 size_t argbuflen; 1052 size_t len; 1053 1054 argbuflen = cmdlen * 4; 1055 argbuf = (char *)malloc(argbuflen + 1); 1056 if (argbuf == NULL) { 1057 warn("malloc(%zu)", argbuflen + 1); 1058 free(cmdbuf); 1059 return NULL; 1060 } 1061 1062 dst = argbuf; 1063 1064 /* Extract cmd name from argv */ 1065 cmd = strrchr(*args, '/'); 1066 if (cmd == NULL) 1067 cmd = *args; 1068 else 1069 cmd++; 1070 1071 for (; (src = *args++) != NULL; ) { 1072 if (*src == '\0') 1073 continue; 1074 len = (argbuflen - (dst - argbuf) - 1) / 4; 1075 strvisx(dst, src, 1076 MIN(strlen(src), len), 1077 VIS_NL | VIS_CSTYLE); 1078 while (*dst != '\0') 1079 dst++; 1080 if ((argbuflen - (dst - argbuf) - 1) / 4 > 0) 1081 *dst++ = ' '; /* add delimiting space */ 1082 } 1083 if (dst != argbuf && dst[-1] == ' ') 1084 dst--; 1085 *dst = '\0'; 1086 1087 if (strcmp(cmd, pp->ki_comm) != 0) { 1088 if (ps.thread && pp->ki_flag & P_HADTHREADS && 1089 pp->ki_tdname[0]) 1090 snprintf(cmdbuf, cmdlen, 1091 "%s (%s){%s%s}", argbuf, 1092 pp->ki_comm, pp->ki_tdname, 1093 pp->ki_moretdname); 1094 else 1095 snprintf(cmdbuf, cmdlen, 1096 "%s (%s)", argbuf, pp->ki_comm); 1097 } else { 1098 if (ps.thread && pp->ki_flag & P_HADTHREADS && 1099 pp->ki_tdname[0]) 1100 snprintf(cmdbuf, cmdlen, 1101 "%s{%s%s}", argbuf, pp->ki_tdname, 1102 pp->ki_moretdname); 1103 else 1104 strlcpy(cmdbuf, argbuf, cmdlen); 1105 } 1106 free(argbuf); 1107 } 1108 } 1109 1110 if (ps.jail == 0) 1111 jid_buf[0] = '\0'; 1112 else 1113 snprintf(jid_buf, sizeof(jid_buf), "%*d", 1114 jidlength - 1, pp->ki_jid); 1115 1116 if (ps.swap == 0) 1117 swap_buf[0] = '\0'; 1118 else 1119 snprintf(swap_buf, sizeof(swap_buf), "%*s", 1120 swaplength - 1, 1121 format_k2(pagetok(ki_swap(pp)))); /* XXX */ 1122 1123 if (displaymode == DISP_IO) { 1124 oldp = get_old_proc(pp); 1125 if (oldp != NULL) { 1126 ru.ru_inblock = RU(pp)->ru_inblock - 1127 RU(oldp)->ru_inblock; 1128 ru.ru_oublock = RU(pp)->ru_oublock - 1129 RU(oldp)->ru_oublock; 1130 ru.ru_majflt = RU(pp)->ru_majflt - RU(oldp)->ru_majflt; 1131 ru.ru_nvcsw = RU(pp)->ru_nvcsw - RU(oldp)->ru_nvcsw; 1132 ru.ru_nivcsw = RU(pp)->ru_nivcsw - RU(oldp)->ru_nivcsw; 1133 rup = &ru; 1134 } else { 1135 rup = RU(pp); 1136 } 1137 p_tot = rup->ru_inblock + rup->ru_oublock + rup->ru_majflt; 1138 s_tot = total_inblock + total_oublock + total_majflt; 1139 1140 snprintf(fmt, sizeof(fmt), io_Proc_format, 1141 pp->ki_pid, 1142 jidlength, jid_buf, 1143 namelength, namelength, (*get_userid)(pp->ki_ruid), 1144 rup->ru_nvcsw, 1145 rup->ru_nivcsw, 1146 rup->ru_inblock, 1147 rup->ru_oublock, 1148 rup->ru_majflt, 1149 p_tot, 1150 s_tot == 0 ? 0.0 : (p_tot * 100.0 / s_tot), 1151 screen_width > cmdlengthdelta ? 1152 screen_width - cmdlengthdelta : 0, 1153 printable(cmdbuf)); 1154 1155 free(cmdbuf); 1156 1157 return (fmt); 1158 } 1159 1160 /* format this entry */ 1161 if (smpmode) { 1162 if (state == SRUN && pp->ki_oncpu != NOCPU) 1163 cpu = pp->ki_oncpu; 1164 else 1165 cpu = pp->ki_lastcpu; 1166 } else 1167 cpu = 0; 1168 proc_fmt = smpmode ? smp_Proc_format : up_Proc_format; 1169 if (ps.thread != 0) 1170 thr_buf[0] = '\0'; 1171 else 1172 snprintf(thr_buf, sizeof(thr_buf), "%*d ", 1173 (int)(sizeof(thr_buf) - 2), pp->ki_numthreads); 1174 1175 snprintf(fmt, sizeof(fmt), proc_fmt, 1176 pp->ki_pid, 1177 jidlength, jid_buf, 1178 namelength, namelength, (*get_userid)(pp->ki_ruid), 1179 thr_buf, 1180 pp->ki_pri.pri_level - PZERO, 1181 format_nice(pp), 1182 format_k2(PROCSIZE(pp)), 1183 format_k2(pagetok(pp->ki_rssize)), 1184 swaplength, swaplength, swap_buf, 1185 status, 1186 cpu, 1187 format_time(cputime), 1188 ps.wcpu ? 100.0 * weighted_cpu(pct, pp) : 100.0 * pct, 1189 screen_width > cmdlengthdelta ? screen_width - cmdlengthdelta : 0, 1190 printable(cmdbuf)); 1191 1192 free(cmdbuf); 1193 1194 /* return the result */ 1195 return (fmt); 1196} 1197 1198static void 1199getsysctl(const char *name, void *ptr, size_t len) 1200{ 1201 size_t nlen = len; 1202 1203 if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) { 1204 fprintf(stderr, "top: sysctl(%s...) failed: %s\n", name, 1205 strerror(errno)); 1206 quit(23); 1207 } 1208 if (nlen != len) { 1209 fprintf(stderr, "top: sysctl(%s...) expected %lu, got %lu\n", 1210 name, (unsigned long)len, (unsigned long)nlen); 1211 quit(23); 1212 } 1213} 1214 1215static const char * 1216format_nice(const struct kinfo_proc *pp) 1217{ 1218 const char *fifo, *kproc; 1219 int rtpri; 1220 static char nicebuf[4 + 1]; 1221 1222 fifo = PRI_NEED_RR(pp->ki_pri.pri_class) ? "" : "F"; 1223 kproc = (pp->ki_flag & P_KPROC) ? "k" : ""; 1224 switch (PRI_BASE(pp->ki_pri.pri_class)) { 1225 case PRI_ITHD: 1226 return ("-"); 1227 case PRI_REALTIME: 1228 /* 1229 * XXX: the kernel doesn't tell us the original rtprio and 1230 * doesn't really know what it was, so to recover it we 1231 * must be more chummy with the implementation than the 1232 * implementation is with itself. pri_user gives a 1233 * constant "base" priority, but is only initialized 1234 * properly for user threads. pri_native gives what the 1235 * kernel calls the "base" priority, but it isn't constant 1236 * since it is changed by priority propagation. pri_native 1237 * also isn't properly initialized for all threads, but it 1238 * is properly initialized for kernel realtime and idletime 1239 * threads. Thus we use pri_user for the base priority of 1240 * user threads (it is always correct) and pri_native for 1241 * the base priority of kernel realtime and idletime threads 1242 * (there is nothing better, and it is usually correct). 1243 * 1244 * The field width and thus the buffer are too small for 1245 * values like "kr31F", but such values shouldn't occur, 1246 * and if they do then the tailing "F" is not displayed. 1247 */ 1248 rtpri = ((pp->ki_flag & P_KPROC) ? pp->ki_pri.pri_native : 1249 pp->ki_pri.pri_user) - PRI_MIN_REALTIME; 1250 snprintf(nicebuf, sizeof(nicebuf), "%sr%d%s", 1251 kproc, rtpri, fifo); 1252 break; 1253 case PRI_TIMESHARE: 1254 if (pp->ki_flag & P_KPROC) 1255 return ("-"); 1256 snprintf(nicebuf, sizeof(nicebuf), "%d", pp->ki_nice - NZERO); 1257 break; 1258 case PRI_IDLE: 1259 /* XXX: as above. */ 1260 rtpri = ((pp->ki_flag & P_KPROC) ? pp->ki_pri.pri_native : 1261 pp->ki_pri.pri_user) - PRI_MIN_IDLE; 1262 snprintf(nicebuf, sizeof(nicebuf), "%si%d%s", 1263 kproc, rtpri, fifo); 1264 break; 1265 default: 1266 return ("?"); 1267 } 1268 return (nicebuf); 1269} 1270 1271/* comparison routines for qsort */ 1272 1273static int 1274compare_pid(const void *p1, const void *p2) 1275{ 1276 const struct kinfo_proc * const *pp1 = p1; 1277 const struct kinfo_proc * const *pp2 = p2; 1278 1279 if ((*pp2)->ki_pid < 0 || (*pp1)->ki_pid < 0) 1280 abort(); 1281 1282 return ((*pp1)->ki_pid - (*pp2)->ki_pid); 1283} 1284 1285static int 1286compare_tid(const void *p1, const void *p2) 1287{ 1288 const struct kinfo_proc * const *pp1 = p1; 1289 const struct kinfo_proc * const *pp2 = p2; 1290 1291 if ((*pp2)->ki_tid < 0 || (*pp1)->ki_tid < 0) 1292 abort(); 1293 1294 return ((*pp1)->ki_tid - (*pp2)->ki_tid); 1295} 1296 1297/* 1298 * proc_compare - comparison function for "qsort" 1299 * Compares the resource consumption of two processes using five 1300 * distinct keys. The keys (in descending order of importance) are: 1301 * percent cpu, cpu ticks, state, resident set size, total virtual 1302 * memory usage. The process states are ordered as follows (from least 1303 * to most important): WAIT, zombie, sleep, stop, start, run. The 1304 * array declaration below maps a process state index into a number 1305 * that reflects this ordering. 1306 */ 1307 1308static int sorted_state[] = { 1309 0, /* not used */ 1310 3, /* sleep */ 1311 1, /* ABANDONED (WAIT) */ 1312 6, /* run */ 1313 5, /* start */ 1314 2, /* zombie */ 1315 4 /* stop */ 1316}; 1317 1318 1319#define ORDERKEY_PCTCPU(a, b) do { \ 1320 double diff; \ 1321 if (ps.wcpu) \ 1322 diff = weighted_cpu(PCTCPU((b)), (b)) - \ 1323 weighted_cpu(PCTCPU((a)), (a)); \ 1324 else \ 1325 diff = PCTCPU((b)) - PCTCPU((a)); \ 1326 if (diff != 0) \ 1327 return (diff > 0 ? 1 : -1); \ 1328} while (0) 1329 1330#define ORDERKEY_CPTICKS(a, b) do { \ 1331 int64_t diff = (int64_t)(b)->ki_runtime - (int64_t)(a)->ki_runtime; \ 1332 if (diff != 0) \ 1333 return (diff > 0 ? 1 : -1); \ 1334} while (0) 1335 1336#define ORDERKEY_STATE(a, b) do { \ 1337 int diff = sorted_state[(b)->ki_stat] - sorted_state[(a)->ki_stat]; \ 1338 if (diff != 0) \ 1339 return (diff > 0 ? 1 : -1); \ 1340} while (0) 1341 1342#define ORDERKEY_PRIO(a, b) do { \ 1343 int diff = (int)(b)->ki_pri.pri_level - (int)(a)->ki_pri.pri_level; \ 1344 if (diff != 0) \ 1345 return (diff > 0 ? 1 : -1); \ 1346} while (0) 1347 1348#define ORDERKEY_THREADS(a, b) do { \ 1349 int diff = (int)(b)->ki_numthreads - (int)(a)->ki_numthreads; \ 1350 if (diff != 0) \ 1351 return (diff > 0 ? 1 : -1); \ 1352} while (0) 1353 1354#define ORDERKEY_RSSIZE(a, b) do { \ 1355 long diff = (long)(b)->ki_rssize - (long)(a)->ki_rssize; \ 1356 if (diff != 0) \ 1357 return (diff > 0 ? 1 : -1); \ 1358} while (0) 1359 1360#define ORDERKEY_MEM(a, b) do { \ 1361 long diff = (long)PROCSIZE((b)) - (long)PROCSIZE((a)); \ 1362 if (diff != 0) \ 1363 return (diff > 0 ? 1 : -1); \ 1364} while (0) 1365 1366#define ORDERKEY_JID(a, b) do { \ 1367 int diff = (int)(b)->ki_jid - (int)(a)->ki_jid; \ 1368 if (diff != 0) \ 1369 return (diff > 0 ? 1 : -1); \ 1370} while (0) 1371 1372#define ORDERKEY_SWAP(a, b) do { \ 1373 int diff = (int)ki_swap(b) - (int)ki_swap(a); \ 1374 if (diff != 0) \ 1375 return (diff > 0 ? 1 : -1); \ 1376} while (0) 1377 1378/* compare_cpu - the comparison function for sorting by cpu percentage */ 1379 1380int 1381#ifdef ORDER 1382compare_cpu(void *arg1, void *arg2) 1383#else 1384proc_compare(void *arg1, void *arg2) 1385#endif 1386{ 1387 struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1; 1388 struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2; 1389 1390 ORDERKEY_PCTCPU(p1, p2); 1391 ORDERKEY_CPTICKS(p1, p2); 1392 ORDERKEY_STATE(p1, p2); 1393 ORDERKEY_PRIO(p1, p2); 1394 ORDERKEY_RSSIZE(p1, p2); 1395 ORDERKEY_MEM(p1, p2); 1396 1397 return (0); 1398} 1399 1400#ifdef ORDER 1401/* "cpu" compare routines */ 1402int compare_size(), compare_res(), compare_time(), compare_prio(), 1403 compare_threads(); 1404 1405/* 1406 * "io" compare routines. Context switches aren't i/o, but are displayed 1407 * on the "io" display. 1408 */ 1409int compare_iototal(), compare_ioread(), compare_iowrite(), compare_iofault(), 1410 compare_vcsw(), compare_ivcsw(); 1411 1412int (*compares[])() = { 1413 compare_cpu, 1414 compare_size, 1415 compare_res, 1416 compare_time, 1417 compare_prio, 1418 compare_threads, 1419 compare_iototal, 1420 compare_ioread, 1421 compare_iowrite, 1422 compare_iofault, 1423 compare_vcsw, 1424 compare_ivcsw, 1425 compare_jid, 1426 compare_swap, 1427 NULL 1428}; 1429 1430/* compare_size - the comparison function for sorting by total memory usage */ 1431 1432int 1433compare_size(void *arg1, void *arg2) 1434{ 1435 struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1; 1436 struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2; 1437 1438 ORDERKEY_MEM(p1, p2); 1439 ORDERKEY_RSSIZE(p1, p2); 1440 ORDERKEY_PCTCPU(p1, p2); 1441 ORDERKEY_CPTICKS(p1, p2); 1442 ORDERKEY_STATE(p1, p2); 1443 ORDERKEY_PRIO(p1, p2); 1444 1445 return (0); 1446} 1447 1448/* compare_res - the comparison function for sorting by resident set size */ 1449 1450int 1451compare_res(void *arg1, void *arg2) 1452{ 1453 struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1; 1454 struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2; 1455 1456 ORDERKEY_RSSIZE(p1, p2); 1457 ORDERKEY_MEM(p1, p2); 1458 ORDERKEY_PCTCPU(p1, p2); 1459 ORDERKEY_CPTICKS(p1, p2); 1460 ORDERKEY_STATE(p1, p2); 1461 ORDERKEY_PRIO(p1, p2); 1462 1463 return (0); 1464} 1465 1466/* compare_time - the comparison function for sorting by total cpu time */ 1467 1468int 1469compare_time(void *arg1, void *arg2) 1470{ 1471 struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1; 1472 struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2; 1473 1474 ORDERKEY_CPTICKS(p1, p2); 1475 ORDERKEY_PCTCPU(p1, p2); 1476 ORDERKEY_STATE(p1, p2); 1477 ORDERKEY_PRIO(p1, p2); 1478 ORDERKEY_RSSIZE(p1, p2); 1479 ORDERKEY_MEM(p1, p2); 1480 1481 return (0); 1482} 1483 1484/* compare_prio - the comparison function for sorting by priority */ 1485 1486int 1487compare_prio(void *arg1, void *arg2) 1488{ 1489 struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1; 1490 struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2; 1491 1492 ORDERKEY_PRIO(p1, p2); 1493 ORDERKEY_CPTICKS(p1, p2); 1494 ORDERKEY_PCTCPU(p1, p2); 1495 ORDERKEY_STATE(p1, p2); 1496 ORDERKEY_RSSIZE(p1, p2); 1497 ORDERKEY_MEM(p1, p2); 1498 1499 return (0); 1500} 1501 1502/* compare_threads - the comparison function for sorting by threads */ 1503int 1504compare_threads(void *arg1, void *arg2) 1505{ 1506 struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1; 1507 struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2; 1508 1509 ORDERKEY_THREADS(p1, p2); 1510 ORDERKEY_PCTCPU(p1, p2); 1511 ORDERKEY_CPTICKS(p1, p2); 1512 ORDERKEY_STATE(p1, p2); 1513 ORDERKEY_PRIO(p1, p2); 1514 ORDERKEY_RSSIZE(p1, p2); 1515 ORDERKEY_MEM(p1, p2); 1516 1517 return (0); 1518} 1519 1520/* compare_jid - the comparison function for sorting by jid */ 1521static int 1522compare_jid(const void *arg1, const void *arg2) 1523{ 1524 struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1; 1525 struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2; 1526 1527 ORDERKEY_JID(p1, p2); 1528 ORDERKEY_PCTCPU(p1, p2); 1529 ORDERKEY_CPTICKS(p1, p2); 1530 ORDERKEY_STATE(p1, p2); 1531 ORDERKEY_PRIO(p1, p2); 1532 ORDERKEY_RSSIZE(p1, p2); 1533 ORDERKEY_MEM(p1, p2); 1534 1535 return (0); 1536} 1537 1538/* compare_swap - the comparison function for sorting by swap */ 1539static int 1540compare_swap(const void *arg1, const void *arg2) 1541{ 1542 struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1; 1543 struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2; 1544 1545 ORDERKEY_SWAP(p1, p2); 1546 ORDERKEY_PCTCPU(p1, p2); 1547 ORDERKEY_CPTICKS(p1, p2); 1548 ORDERKEY_STATE(p1, p2); 1549 ORDERKEY_PRIO(p1, p2); 1550 ORDERKEY_RSSIZE(p1, p2); 1551 ORDERKEY_MEM(p1, p2); 1552 1553 return (0); 1554} 1555#endif /* ORDER */ 1556 1557/* assorted comparison functions for sorting by i/o */ 1558 1559int 1560#ifdef ORDER 1561compare_iototal(void *arg1, void *arg2) 1562#else 1563io_compare(void *arg1, void *arg2) 1564#endif 1565{ 1566 struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1; 1567 struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2; 1568 1569 return (get_io_total(p2) - get_io_total(p1)); 1570} 1571 1572#ifdef ORDER 1573int 1574compare_ioread(void *arg1, void *arg2) 1575{ 1576 struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1; 1577 struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2; 1578 long dummy, inp1, inp2; 1579 1580 (void) get_io_stats(p1, &inp1, &dummy, &dummy, &dummy, &dummy); 1581 (void) get_io_stats(p2, &inp2, &dummy, &dummy, &dummy, &dummy); 1582 1583 return (inp2 - inp1); 1584} 1585 1586int 1587compare_iowrite(void *arg1, void *arg2) 1588{ 1589 struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1; 1590 struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2; 1591 long dummy, oup1, oup2; 1592 1593 (void) get_io_stats(p1, &dummy, &oup1, &dummy, &dummy, &dummy); 1594 (void) get_io_stats(p2, &dummy, &oup2, &dummy, &dummy, &dummy); 1595 1596 return (oup2 - oup1); 1597} 1598 1599int 1600compare_iofault(void *arg1, void *arg2) 1601{ 1602 struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1; 1603 struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2; 1604 long dummy, flp1, flp2; 1605 1606 (void) get_io_stats(p1, &dummy, &dummy, &flp1, &dummy, &dummy); 1607 (void) get_io_stats(p2, &dummy, &dummy, &flp2, &dummy, &dummy); 1608 1609 return (flp2 - flp1); 1610} 1611 1612int 1613compare_vcsw(void *arg1, void *arg2) 1614{ 1615 struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1; 1616 struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2; 1617 long dummy, flp1, flp2; 1618 1619 (void) get_io_stats(p1, &dummy, &dummy, &dummy, &flp1, &dummy); 1620 (void) get_io_stats(p2, &dummy, &dummy, &dummy, &flp2, &dummy); 1621 1622 return (flp2 - flp1); 1623} 1624 1625int 1626compare_ivcsw(void *arg1, void *arg2) 1627{ 1628 struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1; 1629 struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2; 1630 long dummy, flp1, flp2; 1631 1632 (void) get_io_stats(p1, &dummy, &dummy, &dummy, &dummy, &flp1); 1633 (void) get_io_stats(p2, &dummy, &dummy, &dummy, &dummy, &flp2); 1634 1635 return (flp2 - flp1); 1636} 1637#endif /* ORDER */ 1638 1639/* 1640 * proc_owner(pid) - returns the uid that owns process "pid", or -1 if 1641 * the process does not exist. 1642 * It is EXTREMELY IMPORTANT that this function work correctly. 1643 * If top runs setuid root (as in SVR4), then this function 1644 * is the only thing that stands in the way of a serious 1645 * security problem. It validates requests for the "kill" 1646 * and "renice" commands. 1647 */ 1648 1649int 1650proc_owner(int pid) 1651{ 1652 int cnt; 1653 struct kinfo_proc **prefp; 1654 struct kinfo_proc *pp; 1655 1656 prefp = pref; 1657 cnt = pref_len; 1658 while (--cnt >= 0) { 1659 pp = *prefp++; 1660 if (pp->ki_pid == (pid_t)pid) 1661 return ((int)pp->ki_ruid); 1662 } 1663 return (-1); 1664} 1665 1666static int 1667swapmode(int *retavail, int *retfree) 1668{ 1669 int n; 1670 struct kvm_swap swapary[1]; 1671 static int pagesize = 0; 1672 static u_long swap_maxpages = 0; 1673 1674 *retavail = 0; 1675 *retfree = 0; 1676 1677#define CONVERT(v) ((quad_t)(v) * pagesize / 1024) 1678 1679 n = kvm_getswapinfo(kd, swapary, 1, 0); 1680 if (n < 0 || swapary[0].ksw_total == 0) 1681 return (0); 1682 1683 if (pagesize == 0) 1684 pagesize = getpagesize(); 1685 if (swap_maxpages == 0) 1686 GETSYSCTL("vm.swap_maxpages", swap_maxpages); 1687 1688 /* ksw_total contains the total size of swap all devices which may 1689 exceed the maximum swap size allocatable in the system */ 1690 if ( swapary[0].ksw_total > swap_maxpages ) 1691 swapary[0].ksw_total = swap_maxpages; 1692 1693 *retavail = CONVERT(swapary[0].ksw_total); 1694 *retfree = CONVERT(swapary[0].ksw_total - swapary[0].ksw_used); 1695 1696 n = (int)(swapary[0].ksw_used * 100.0 / swapary[0].ksw_total); 1697 return (n); 1698} 1699