1bea45cddSEd Schouten /*- 251369649SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 351369649SPedro F. Giffuni * 4bea45cddSEd Schouten * Copyright (c) 1982, 1986, 1990, 1991, 1993 5bea45cddSEd Schouten * The Regents of the University of California. All rights reserved. 6bea45cddSEd Schouten * (c) UNIX System Laboratories, Inc. 7bea45cddSEd Schouten * All or some portions of this file are derived from material licensed 8bea45cddSEd Schouten * to the University of California by American Telephone and Telegraph 9bea45cddSEd Schouten * Co. or Unix System Laboratories, Inc. and are reproduced herein with 10bea45cddSEd Schouten * the permission of UNIX System Laboratories, Inc. 11bea45cddSEd Schouten * 12bea45cddSEd Schouten * Copyright (c) 2002 Networks Associates Technologies, Inc. 13bea45cddSEd Schouten * All rights reserved. 14bea45cddSEd Schouten * 15bea45cddSEd Schouten * Portions of this software were developed for the FreeBSD Project by 16bea45cddSEd Schouten * ThinkSec AS and NAI Labs, the Security Research Division of Network 17bea45cddSEd Schouten * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 18bea45cddSEd Schouten * ("CBOSS"), as part of the DARPA CHATS research program. 19bea45cddSEd Schouten * 20bea45cddSEd Schouten * Redistribution and use in source and binary forms, with or without 21bea45cddSEd Schouten * modification, are permitted provided that the following conditions 22bea45cddSEd Schouten * are met: 23bea45cddSEd Schouten * 1. Redistributions of source code must retain the above copyright 24bea45cddSEd Schouten * notice, this list of conditions and the following disclaimer. 25bea45cddSEd Schouten * 2. Redistributions in binary form must reproduce the above copyright 26bea45cddSEd Schouten * notice, this list of conditions and the following disclaimer in the 27bea45cddSEd Schouten * documentation and/or other materials provided with the distribution. 2869a28758SEd Maste * 3. Neither the name of the University nor the names of its contributors 29bea45cddSEd Schouten * may be used to endorse or promote products derived from this software 30bea45cddSEd Schouten * without specific prior written permission. 31bea45cddSEd Schouten * 32bea45cddSEd Schouten * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 33bea45cddSEd Schouten * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34bea45cddSEd Schouten * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35bea45cddSEd Schouten * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 36bea45cddSEd Schouten * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37bea45cddSEd Schouten * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38bea45cddSEd Schouten * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39bea45cddSEd Schouten * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40bea45cddSEd Schouten * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41bea45cddSEd Schouten * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42bea45cddSEd Schouten * SUCH DAMAGE. 43bea45cddSEd Schouten */ 44bea45cddSEd Schouten 45bea45cddSEd Schouten #include <sys/cdefs.h> 46bea45cddSEd Schouten __FBSDID("$FreeBSD$"); 47bea45cddSEd Schouten 486741ea08SMark Johnston #include "opt_stack.h" 496741ea08SMark Johnston 50bea45cddSEd Schouten #include <sys/param.h> 516858c2ccSConrad Meyer #include <sys/cons.h> 526858c2ccSConrad Meyer #include <sys/kdb.h> 53bea45cddSEd Schouten #include <sys/lock.h> 54d7aa89c3SConrad Meyer #include <sys/malloc.h> 55bea45cddSEd Schouten #include <sys/mutex.h> 56bea45cddSEd Schouten #include <sys/proc.h> 57bea45cddSEd Schouten #include <sys/resourcevar.h> 586858c2ccSConrad Meyer #include <sys/sbuf.h> 59bea45cddSEd Schouten #include <sys/sched.h> 60d7aa89c3SConrad Meyer #include <sys/stack.h> 61d7aa89c3SConrad Meyer #include <sys/sysctl.h> 62bea45cddSEd Schouten #include <sys/systm.h> 63bea45cddSEd Schouten #include <sys/tty.h> 64bea45cddSEd Schouten 65bea45cddSEd Schouten #include <vm/vm.h> 66bea45cddSEd Schouten #include <vm/pmap.h> 67bea45cddSEd Schouten #include <vm/vm_map.h> 68bea45cddSEd Schouten 69bea45cddSEd Schouten /* 70bea45cddSEd Schouten * Returns 1 if p2 is "better" than p1 71bea45cddSEd Schouten * 72bea45cddSEd Schouten * The algorithm for picking the "interesting" process is thus: 73bea45cddSEd Schouten * 74bea45cddSEd Schouten * 1) Only foreground processes are eligible - implied. 75bea45cddSEd Schouten * 2) Runnable processes are favored over anything else. The runner 76bea45cddSEd Schouten * with the highest cpu utilization is picked (p_estcpu). Ties are 77bea45cddSEd Schouten * broken by picking the highest pid. 78bea45cddSEd Schouten * 3) The sleeper with the shortest sleep time is next. With ties, 79bea45cddSEd Schouten * we pick out just "short-term" sleepers (P_SINTR == 0). 80bea45cddSEd Schouten * 4) Further ties are broken by picking the highest pid. 81bea45cddSEd Schouten */ 82bea45cddSEd Schouten 83bea45cddSEd Schouten #define TESTAB(a, b) ((a)<<1 | (b)) 84bea45cddSEd Schouten #define ONLYA 2 85bea45cddSEd Schouten #define ONLYB 1 86bea45cddSEd Schouten #define BOTH 3 87bea45cddSEd Schouten 88bea45cddSEd Schouten static int 899e577585SEd Schouten proc_sum(struct proc *p, fixpt_t *estcpup) 90bea45cddSEd Schouten { 91bea45cddSEd Schouten struct thread *td; 92bea45cddSEd Schouten int estcpu; 93bea45cddSEd Schouten int val; 94bea45cddSEd Schouten 95bea45cddSEd Schouten val = 0; 96bea45cddSEd Schouten estcpu = 0; 97bea45cddSEd Schouten FOREACH_THREAD_IN_PROC(p, td) { 98bea45cddSEd Schouten thread_lock(td); 99bea45cddSEd Schouten if (TD_ON_RUNQ(td) || 100bea45cddSEd Schouten TD_IS_RUNNING(td)) 101bea45cddSEd Schouten val = 1; 102bea45cddSEd Schouten estcpu += sched_pctcpu(td); 103bea45cddSEd Schouten thread_unlock(td); 104bea45cddSEd Schouten } 105bea45cddSEd Schouten *estcpup = estcpu; 106bea45cddSEd Schouten 107bea45cddSEd Schouten return (val); 108bea45cddSEd Schouten } 109bea45cddSEd Schouten 110bea45cddSEd Schouten static int 111bea45cddSEd Schouten thread_compare(struct thread *td, struct thread *td2) 112bea45cddSEd Schouten { 113bea45cddSEd Schouten int runa, runb; 114bea45cddSEd Schouten int slpa, slpb; 115bea45cddSEd Schouten fixpt_t esta, estb; 116bea45cddSEd Schouten 117bea45cddSEd Schouten if (td == NULL) 118bea45cddSEd Schouten return (1); 119bea45cddSEd Schouten 120bea45cddSEd Schouten /* 121bea45cddSEd Schouten * Fetch running stats, pctcpu usage, and interruptable flag. 122bea45cddSEd Schouten */ 123bea45cddSEd Schouten thread_lock(td); 124bea45cddSEd Schouten runa = TD_IS_RUNNING(td) | TD_ON_RUNQ(td); 125bea45cddSEd Schouten slpa = td->td_flags & TDF_SINTR; 126bea45cddSEd Schouten esta = sched_pctcpu(td); 127bea45cddSEd Schouten thread_unlock(td); 128bea45cddSEd Schouten thread_lock(td2); 129bea45cddSEd Schouten runb = TD_IS_RUNNING(td2) | TD_ON_RUNQ(td2); 130bea45cddSEd Schouten estb = sched_pctcpu(td2); 131bea45cddSEd Schouten slpb = td2->td_flags & TDF_SINTR; 132bea45cddSEd Schouten thread_unlock(td2); 133bea45cddSEd Schouten /* 134bea45cddSEd Schouten * see if at least one of them is runnable 135bea45cddSEd Schouten */ 136bea45cddSEd Schouten switch (TESTAB(runa, runb)) { 137bea45cddSEd Schouten case ONLYA: 138bea45cddSEd Schouten return (0); 139bea45cddSEd Schouten case ONLYB: 140bea45cddSEd Schouten return (1); 141bea45cddSEd Schouten case BOTH: 142bea45cddSEd Schouten break; 143bea45cddSEd Schouten } 144bea45cddSEd Schouten /* 145bea45cddSEd Schouten * favor one with highest recent cpu utilization 146bea45cddSEd Schouten */ 147bea45cddSEd Schouten if (estb > esta) 148bea45cddSEd Schouten return (1); 149bea45cddSEd Schouten if (esta > estb) 150bea45cddSEd Schouten return (0); 151bea45cddSEd Schouten /* 152bea45cddSEd Schouten * favor one sleeping in a non-interruptible sleep 153bea45cddSEd Schouten */ 154bea45cddSEd Schouten switch (TESTAB(slpa, slpb)) { 155bea45cddSEd Schouten case ONLYA: 156bea45cddSEd Schouten return (0); 157bea45cddSEd Schouten case ONLYB: 158bea45cddSEd Schouten return (1); 159bea45cddSEd Schouten case BOTH: 160bea45cddSEd Schouten break; 161bea45cddSEd Schouten } 162bea45cddSEd Schouten 163bea45cddSEd Schouten return (td < td2); 164bea45cddSEd Schouten } 165bea45cddSEd Schouten 166bea45cddSEd Schouten static int 167bea45cddSEd Schouten proc_compare(struct proc *p1, struct proc *p2) 168bea45cddSEd Schouten { 169bea45cddSEd Schouten 170bea45cddSEd Schouten int runa, runb; 171bea45cddSEd Schouten fixpt_t esta, estb; 172bea45cddSEd Schouten 173bea45cddSEd Schouten if (p1 == NULL) 174bea45cddSEd Schouten return (1); 175bea45cddSEd Schouten 176bea45cddSEd Schouten /* 177bea45cddSEd Schouten * Fetch various stats about these processes. After we drop the 178bea45cddSEd Schouten * lock the information could be stale but the race is unimportant. 179bea45cddSEd Schouten */ 180bea45cddSEd Schouten PROC_LOCK(p1); 181bea45cddSEd Schouten runa = proc_sum(p1, &esta); 182bea45cddSEd Schouten PROC_UNLOCK(p1); 183bea45cddSEd Schouten PROC_LOCK(p2); 184bea45cddSEd Schouten runb = proc_sum(p2, &estb); 185bea45cddSEd Schouten PROC_UNLOCK(p2); 186bea45cddSEd Schouten 187bea45cddSEd Schouten /* 188bea45cddSEd Schouten * see if at least one of them is runnable 189bea45cddSEd Schouten */ 190bea45cddSEd Schouten switch (TESTAB(runa, runb)) { 191bea45cddSEd Schouten case ONLYA: 192bea45cddSEd Schouten return (0); 193bea45cddSEd Schouten case ONLYB: 194bea45cddSEd Schouten return (1); 195bea45cddSEd Schouten case BOTH: 196bea45cddSEd Schouten break; 197bea45cddSEd Schouten } 198bea45cddSEd Schouten /* 199bea45cddSEd Schouten * favor one with highest recent cpu utilization 200bea45cddSEd Schouten */ 201bea45cddSEd Schouten if (estb > esta) 202bea45cddSEd Schouten return (1); 203bea45cddSEd Schouten if (esta > estb) 204bea45cddSEd Schouten return (0); 205bea45cddSEd Schouten /* 206bea45cddSEd Schouten * weed out zombies 207bea45cddSEd Schouten */ 208bea45cddSEd Schouten switch (TESTAB(p1->p_state == PRS_ZOMBIE, p2->p_state == PRS_ZOMBIE)) { 209bea45cddSEd Schouten case ONLYA: 210bea45cddSEd Schouten return (1); 211bea45cddSEd Schouten case ONLYB: 212bea45cddSEd Schouten return (0); 213bea45cddSEd Schouten case BOTH: 214bea45cddSEd Schouten break; 215bea45cddSEd Schouten } 216bea45cddSEd Schouten 217bea45cddSEd Schouten return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 218bea45cddSEd Schouten } 219bea45cddSEd Schouten 2206858c2ccSConrad Meyer static int 2216858c2ccSConrad Meyer sbuf_tty_drain(void *a, const char *d, int len) 2226858c2ccSConrad Meyer { 2236858c2ccSConrad Meyer struct tty *tp; 2246858c2ccSConrad Meyer int rc; 2256858c2ccSConrad Meyer 2266858c2ccSConrad Meyer tp = a; 2276858c2ccSConrad Meyer 2286858c2ccSConrad Meyer if (kdb_active) { 2296858c2ccSConrad Meyer cnputsn(d, len); 2306858c2ccSConrad Meyer return (len); 2316858c2ccSConrad Meyer } 232879e0604SMateusz Guzik if (tp != NULL && !KERNEL_PANICKED()) { 2336858c2ccSConrad Meyer rc = tty_putstrn(tp, d, len); 2346858c2ccSConrad Meyer if (rc != 0) 2356858c2ccSConrad Meyer return (-ENXIO); 2366858c2ccSConrad Meyer return (len); 2376858c2ccSConrad Meyer } 2386858c2ccSConrad Meyer return (-ENXIO); 2396858c2ccSConrad Meyer } 2406858c2ccSConrad Meyer 24193940996SConrad Meyer #ifdef STACK 242d7aa89c3SConrad Meyer static bool tty_info_kstacks = false; 243d7aa89c3SConrad Meyer SYSCTL_BOOL(_kern, OID_AUTO, tty_info_kstacks, CTLFLAG_RWTUN, 244d7aa89c3SConrad Meyer &tty_info_kstacks, 0, 245d7aa89c3SConrad Meyer "Enable printing kernel stack(9) traces on ^T (tty info)"); 24693940996SConrad Meyer #endif 247d7aa89c3SConrad Meyer 248bea45cddSEd Schouten /* 249bea45cddSEd Schouten * Report on state of foreground process group. 250bea45cddSEd Schouten */ 251bea45cddSEd Schouten void 252bc093719SEd Schouten tty_info(struct tty *tp) 253bea45cddSEd Schouten { 254dd970f41SEd Schouten struct timeval rtime, utime, stime; 25593940996SConrad Meyer #ifdef STACK 256d7aa89c3SConrad Meyer struct stack stack; 25793940996SConrad Meyer int sterr; 25893940996SConrad Meyer #endif 259dd970f41SEd Schouten struct proc *p, *ppick; 260dd970f41SEd Schouten struct thread *td, *tdpick; 261bea45cddSEd Schouten const char *stateprefix, *state; 2626858c2ccSConrad Meyer struct sbuf sb; 263bea45cddSEd Schouten long rss; 26493940996SConrad Meyer int load, pctcpu; 265bea45cddSEd Schouten pid_t pid; 266bea45cddSEd Schouten char comm[MAXCOMLEN + 1]; 267bea45cddSEd Schouten struct rusage ru; 268bea45cddSEd Schouten 269bc093719SEd Schouten tty_lock_assert(tp, MA_OWNED); 270bc093719SEd Schouten 271bc093719SEd Schouten if (tty_checkoutq(tp) == 0) 272bea45cddSEd Schouten return; 273bea45cddSEd Schouten 274f8a22201SMark Johnston (void)sbuf_new(&sb, tp->t_prbuf, tp->t_prbufsz, SBUF_FIXEDLEN); 2756858c2ccSConrad Meyer sbuf_set_drain(&sb, sbuf_tty_drain, tp); 2766858c2ccSConrad Meyer 277bea45cddSEd Schouten /* Print load average. */ 278bea45cddSEd Schouten load = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT; 2796858c2ccSConrad Meyer sbuf_printf(&sb, "%sload: %d.%02d ", tp->t_column == 0 ? "" : "\n", 280379affd5SEd Schouten load / 100, load % 100); 281bea45cddSEd Schouten 282bea45cddSEd Schouten if (tp->t_session == NULL) { 2836858c2ccSConrad Meyer sbuf_printf(&sb, "not a controlling terminal\n"); 2846858c2ccSConrad Meyer goto out; 285bea45cddSEd Schouten } 286bea45cddSEd Schouten if (tp->t_pgrp == NULL) { 2876858c2ccSConrad Meyer sbuf_printf(&sb, "no foreground process group\n"); 2886858c2ccSConrad Meyer goto out; 289bea45cddSEd Schouten } 290bea45cddSEd Schouten PGRP_LOCK(tp->t_pgrp); 291bea45cddSEd Schouten if (LIST_EMPTY(&tp->t_pgrp->pg_members)) { 292bea45cddSEd Schouten PGRP_UNLOCK(tp->t_pgrp); 2936858c2ccSConrad Meyer sbuf_printf(&sb, "empty foreground process group\n"); 2946858c2ccSConrad Meyer goto out; 295bea45cddSEd Schouten } 296bea45cddSEd Schouten 297bea45cddSEd Schouten /* 298bea45cddSEd Schouten * Pick the most interesting process and copy some of its 299bea45cddSEd Schouten * state for printing later. This operation could rely on stale 300bea45cddSEd Schouten * data as we can't hold the proc slock or thread locks over the 301bea45cddSEd Schouten * whole list. However, we're guaranteed not to reference an exited 302bea45cddSEd Schouten * thread or proc since we hold the tty locked. 303bea45cddSEd Schouten */ 304dd970f41SEd Schouten p = NULL; 305dd970f41SEd Schouten LIST_FOREACH(ppick, &tp->t_pgrp->pg_members, p_pglist) 306dd970f41SEd Schouten if (proc_compare(p, ppick)) 307dd970f41SEd Schouten p = ppick; 308bea45cddSEd Schouten 309dd970f41SEd Schouten PROC_LOCK(p); 310dd970f41SEd Schouten PGRP_UNLOCK(tp->t_pgrp); 311dd970f41SEd Schouten td = NULL; 312dd970f41SEd Schouten FOREACH_THREAD_IN_PROC(p, tdpick) 313dd970f41SEd Schouten if (thread_compare(td, tdpick)) 314dd970f41SEd Schouten td = tdpick; 315bea45cddSEd Schouten stateprefix = ""; 316bea45cddSEd Schouten thread_lock(td); 317bea45cddSEd Schouten if (TD_IS_RUNNING(td)) 318bea45cddSEd Schouten state = "running"; 319bea45cddSEd Schouten else if (TD_ON_RUNQ(td) || TD_CAN_RUN(td)) 320bea45cddSEd Schouten state = "runnable"; 321bea45cddSEd Schouten else if (TD_IS_SLEEPING(td)) { 322bea45cddSEd Schouten /* XXX: If we're sleeping, are we ever not in a queue? */ 323bea45cddSEd Schouten if (TD_ON_SLEEPQ(td)) 324bea45cddSEd Schouten state = td->td_wmesg; 325bea45cddSEd Schouten else 326bea45cddSEd Schouten state = "sleeping without queue"; 327bea45cddSEd Schouten } else if (TD_ON_LOCK(td)) { 328bea45cddSEd Schouten state = td->td_lockname; 329bea45cddSEd Schouten stateprefix = "*"; 330bea45cddSEd Schouten } else if (TD_IS_SUSPENDED(td)) 331bea45cddSEd Schouten state = "suspended"; 332bea45cddSEd Schouten else if (TD_AWAITING_INTR(td)) 333bea45cddSEd Schouten state = "intrwait"; 334dd970f41SEd Schouten else if (p->p_state == PRS_ZOMBIE) 335ad765b09SRobert Watson state = "zombie"; 336bea45cddSEd Schouten else 337bea45cddSEd Schouten state = "unknown"; 338bea45cddSEd Schouten pctcpu = (sched_pctcpu(td) * 10000 + FSCALE / 2) >> FSHIFT; 33993940996SConrad Meyer #ifdef STACK 340d7aa89c3SConrad Meyer if (tty_info_kstacks) { 3415d3bd9e2SMark Johnston if (TD_IS_SWAPPED(td)) 3425d3bd9e2SMark Johnston sterr = ENOENT; 343*1c29da02SMark Johnston else 344*1c29da02SMark Johnston sterr = stack_save_td(&stack, td); 345d7aa89c3SConrad Meyer } 34693940996SConrad Meyer #endif 347bea45cddSEd Schouten thread_unlock(td); 348dd970f41SEd Schouten if (p->p_state == PRS_NEW || p->p_state == PRS_ZOMBIE) 349bea45cddSEd Schouten rss = 0; 350bea45cddSEd Schouten else 351dd970f41SEd Schouten rss = pgtok(vmspace_resident_count(p->p_vmspace)); 352dd970f41SEd Schouten microuptime(&rtime); 353dd970f41SEd Schouten timevalsub(&rtime, &p->p_stats->p_start); 354dd970f41SEd Schouten rufetchcalc(p, &ru, &utime, &stime); 355dd970f41SEd Schouten pid = p->p_pid; 356dd970f41SEd Schouten strlcpy(comm, p->p_comm, sizeof comm); 357dd970f41SEd Schouten PROC_UNLOCK(p); 358bea45cddSEd Schouten 359dd970f41SEd Schouten /* Print command, pid, state, rtime, utime, stime, %cpu, and rss. */ 3606858c2ccSConrad Meyer sbuf_printf(&sb, 361dd970f41SEd Schouten " cmd: %s %d [%s%s] %ld.%02ldr %ld.%02ldu %ld.%02lds %d%% %ldk\n", 362bea45cddSEd Schouten comm, pid, stateprefix, state, 363dd970f41SEd Schouten (long)rtime.tv_sec, rtime.tv_usec / 10000, 364bea45cddSEd Schouten (long)utime.tv_sec, utime.tv_usec / 10000, 365bea45cddSEd Schouten (long)stime.tv_sec, stime.tv_usec / 10000, 366bea45cddSEd Schouten pctcpu / 100, rss); 3676858c2ccSConrad Meyer 36893940996SConrad Meyer #ifdef STACK 369d7aa89c3SConrad Meyer if (tty_info_kstacks && sterr == 0) 370d7aa89c3SConrad Meyer stack_sbuf_print_flags(&sb, &stack, M_NOWAIT); 37193940996SConrad Meyer #endif 372d7aa89c3SConrad Meyer 3736858c2ccSConrad Meyer out: 3746858c2ccSConrad Meyer sbuf_finish(&sb); 3756858c2ccSConrad Meyer sbuf_delete(&sb); 376bea45cddSEd Schouten } 377