1bea45cddSEd Schouten /*- 2*51369649SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*51369649SPedro 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 48bea45cddSEd Schouten #include <sys/param.h> 49bea45cddSEd Schouten #include <sys/lock.h> 50bea45cddSEd Schouten #include <sys/mutex.h> 51bea45cddSEd Schouten #include <sys/proc.h> 52bea45cddSEd Schouten #include <sys/resourcevar.h> 53bea45cddSEd Schouten #include <sys/sched.h> 54bea45cddSEd Schouten #include <sys/systm.h> 55bea45cddSEd Schouten #include <sys/tty.h> 56bea45cddSEd Schouten 57bea45cddSEd Schouten #include <vm/vm.h> 58bea45cddSEd Schouten #include <vm/pmap.h> 59bea45cddSEd Schouten #include <vm/vm_map.h> 60bea45cddSEd Schouten 61bea45cddSEd Schouten /* 62bea45cddSEd Schouten * Returns 1 if p2 is "better" than p1 63bea45cddSEd Schouten * 64bea45cddSEd Schouten * The algorithm for picking the "interesting" process is thus: 65bea45cddSEd Schouten * 66bea45cddSEd Schouten * 1) Only foreground processes are eligible - implied. 67bea45cddSEd Schouten * 2) Runnable processes are favored over anything else. The runner 68bea45cddSEd Schouten * with the highest cpu utilization is picked (p_estcpu). Ties are 69bea45cddSEd Schouten * broken by picking the highest pid. 70bea45cddSEd Schouten * 3) The sleeper with the shortest sleep time is next. With ties, 71bea45cddSEd Schouten * we pick out just "short-term" sleepers (P_SINTR == 0). 72bea45cddSEd Schouten * 4) Further ties are broken by picking the highest pid. 73bea45cddSEd Schouten */ 74bea45cddSEd Schouten 75bea45cddSEd Schouten #define TESTAB(a, b) ((a)<<1 | (b)) 76bea45cddSEd Schouten #define ONLYA 2 77bea45cddSEd Schouten #define ONLYB 1 78bea45cddSEd Schouten #define BOTH 3 79bea45cddSEd Schouten 80bea45cddSEd Schouten static int 819e577585SEd Schouten proc_sum(struct proc *p, fixpt_t *estcpup) 82bea45cddSEd Schouten { 83bea45cddSEd Schouten struct thread *td; 84bea45cddSEd Schouten int estcpu; 85bea45cddSEd Schouten int val; 86bea45cddSEd Schouten 87bea45cddSEd Schouten val = 0; 88bea45cddSEd Schouten estcpu = 0; 89bea45cddSEd Schouten FOREACH_THREAD_IN_PROC(p, td) { 90bea45cddSEd Schouten thread_lock(td); 91bea45cddSEd Schouten if (TD_ON_RUNQ(td) || 92bea45cddSEd Schouten TD_IS_RUNNING(td)) 93bea45cddSEd Schouten val = 1; 94bea45cddSEd Schouten estcpu += sched_pctcpu(td); 95bea45cddSEd Schouten thread_unlock(td); 96bea45cddSEd Schouten } 97bea45cddSEd Schouten *estcpup = estcpu; 98bea45cddSEd Schouten 99bea45cddSEd Schouten return (val); 100bea45cddSEd Schouten } 101bea45cddSEd Schouten 102bea45cddSEd Schouten static int 103bea45cddSEd Schouten thread_compare(struct thread *td, struct thread *td2) 104bea45cddSEd Schouten { 105bea45cddSEd Schouten int runa, runb; 106bea45cddSEd Schouten int slpa, slpb; 107bea45cddSEd Schouten fixpt_t esta, estb; 108bea45cddSEd Schouten 109bea45cddSEd Schouten if (td == NULL) 110bea45cddSEd Schouten return (1); 111bea45cddSEd Schouten 112bea45cddSEd Schouten /* 113bea45cddSEd Schouten * Fetch running stats, pctcpu usage, and interruptable flag. 114bea45cddSEd Schouten */ 115bea45cddSEd Schouten thread_lock(td); 116bea45cddSEd Schouten runa = TD_IS_RUNNING(td) | TD_ON_RUNQ(td); 117bea45cddSEd Schouten slpa = td->td_flags & TDF_SINTR; 118bea45cddSEd Schouten esta = sched_pctcpu(td); 119bea45cddSEd Schouten thread_unlock(td); 120bea45cddSEd Schouten thread_lock(td2); 121bea45cddSEd Schouten runb = TD_IS_RUNNING(td2) | TD_ON_RUNQ(td2); 122bea45cddSEd Schouten estb = sched_pctcpu(td2); 123bea45cddSEd Schouten slpb = td2->td_flags & TDF_SINTR; 124bea45cddSEd Schouten thread_unlock(td2); 125bea45cddSEd Schouten /* 126bea45cddSEd Schouten * see if at least one of them is runnable 127bea45cddSEd Schouten */ 128bea45cddSEd Schouten switch (TESTAB(runa, runb)) { 129bea45cddSEd Schouten case ONLYA: 130bea45cddSEd Schouten return (0); 131bea45cddSEd Schouten case ONLYB: 132bea45cddSEd Schouten return (1); 133bea45cddSEd Schouten case BOTH: 134bea45cddSEd Schouten break; 135bea45cddSEd Schouten } 136bea45cddSEd Schouten /* 137bea45cddSEd Schouten * favor one with highest recent cpu utilization 138bea45cddSEd Schouten */ 139bea45cddSEd Schouten if (estb > esta) 140bea45cddSEd Schouten return (1); 141bea45cddSEd Schouten if (esta > estb) 142bea45cddSEd Schouten return (0); 143bea45cddSEd Schouten /* 144bea45cddSEd Schouten * favor one sleeping in a non-interruptible sleep 145bea45cddSEd Schouten */ 146bea45cddSEd Schouten switch (TESTAB(slpa, slpb)) { 147bea45cddSEd Schouten case ONLYA: 148bea45cddSEd Schouten return (0); 149bea45cddSEd Schouten case ONLYB: 150bea45cddSEd Schouten return (1); 151bea45cddSEd Schouten case BOTH: 152bea45cddSEd Schouten break; 153bea45cddSEd Schouten } 154bea45cddSEd Schouten 155bea45cddSEd Schouten return (td < td2); 156bea45cddSEd Schouten } 157bea45cddSEd Schouten 158bea45cddSEd Schouten static int 159bea45cddSEd Schouten proc_compare(struct proc *p1, struct proc *p2) 160bea45cddSEd Schouten { 161bea45cddSEd Schouten 162bea45cddSEd Schouten int runa, runb; 163bea45cddSEd Schouten fixpt_t esta, estb; 164bea45cddSEd Schouten 165bea45cddSEd Schouten if (p1 == NULL) 166bea45cddSEd Schouten return (1); 167bea45cddSEd Schouten 168bea45cddSEd Schouten /* 169bea45cddSEd Schouten * Fetch various stats about these processes. After we drop the 170bea45cddSEd Schouten * lock the information could be stale but the race is unimportant. 171bea45cddSEd Schouten */ 172bea45cddSEd Schouten PROC_LOCK(p1); 173bea45cddSEd Schouten runa = proc_sum(p1, &esta); 174bea45cddSEd Schouten PROC_UNLOCK(p1); 175bea45cddSEd Schouten PROC_LOCK(p2); 176bea45cddSEd Schouten runb = proc_sum(p2, &estb); 177bea45cddSEd Schouten PROC_UNLOCK(p2); 178bea45cddSEd Schouten 179bea45cddSEd Schouten /* 180bea45cddSEd Schouten * see if at least one of them is runnable 181bea45cddSEd Schouten */ 182bea45cddSEd Schouten switch (TESTAB(runa, runb)) { 183bea45cddSEd Schouten case ONLYA: 184bea45cddSEd Schouten return (0); 185bea45cddSEd Schouten case ONLYB: 186bea45cddSEd Schouten return (1); 187bea45cddSEd Schouten case BOTH: 188bea45cddSEd Schouten break; 189bea45cddSEd Schouten } 190bea45cddSEd Schouten /* 191bea45cddSEd Schouten * favor one with highest recent cpu utilization 192bea45cddSEd Schouten */ 193bea45cddSEd Schouten if (estb > esta) 194bea45cddSEd Schouten return (1); 195bea45cddSEd Schouten if (esta > estb) 196bea45cddSEd Schouten return (0); 197bea45cddSEd Schouten /* 198bea45cddSEd Schouten * weed out zombies 199bea45cddSEd Schouten */ 200bea45cddSEd Schouten switch (TESTAB(p1->p_state == PRS_ZOMBIE, p2->p_state == PRS_ZOMBIE)) { 201bea45cddSEd Schouten case ONLYA: 202bea45cddSEd Schouten return (1); 203bea45cddSEd Schouten case ONLYB: 204bea45cddSEd Schouten return (0); 205bea45cddSEd Schouten case BOTH: 206bea45cddSEd Schouten break; 207bea45cddSEd Schouten } 208bea45cddSEd Schouten 209bea45cddSEd Schouten return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 210bea45cddSEd Schouten } 211bea45cddSEd Schouten 212bea45cddSEd Schouten /* 213bea45cddSEd Schouten * Report on state of foreground process group. 214bea45cddSEd Schouten */ 215bea45cddSEd Schouten void 216bc093719SEd Schouten tty_info(struct tty *tp) 217bea45cddSEd Schouten { 218dd970f41SEd Schouten struct timeval rtime, utime, stime; 219dd970f41SEd Schouten struct proc *p, *ppick; 220dd970f41SEd Schouten struct thread *td, *tdpick; 221bea45cddSEd Schouten const char *stateprefix, *state; 222bea45cddSEd Schouten long rss; 223bea45cddSEd Schouten int load, pctcpu; 224bea45cddSEd Schouten pid_t pid; 225bea45cddSEd Schouten char comm[MAXCOMLEN + 1]; 226bea45cddSEd Schouten struct rusage ru; 227bea45cddSEd Schouten 228bc093719SEd Schouten tty_lock_assert(tp, MA_OWNED); 229bc093719SEd Schouten 230bc093719SEd Schouten if (tty_checkoutq(tp) == 0) 231bea45cddSEd Schouten return; 232bea45cddSEd Schouten 233bea45cddSEd Schouten /* Print load average. */ 234bea45cddSEd Schouten load = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT; 235379affd5SEd Schouten ttyprintf(tp, "%sload: %d.%02d ", tp->t_column == 0 ? "" : "\n", 236379affd5SEd Schouten load / 100, load % 100); 237bea45cddSEd Schouten 238bea45cddSEd Schouten if (tp->t_session == NULL) { 239bea45cddSEd Schouten ttyprintf(tp, "not a controlling terminal\n"); 240bea45cddSEd Schouten return; 241bea45cddSEd Schouten } 242bea45cddSEd Schouten if (tp->t_pgrp == NULL) { 243bea45cddSEd Schouten ttyprintf(tp, "no foreground process group\n"); 244bea45cddSEd Schouten return; 245bea45cddSEd Schouten } 246bea45cddSEd Schouten PGRP_LOCK(tp->t_pgrp); 247bea45cddSEd Schouten if (LIST_EMPTY(&tp->t_pgrp->pg_members)) { 248bea45cddSEd Schouten PGRP_UNLOCK(tp->t_pgrp); 249bea45cddSEd Schouten ttyprintf(tp, "empty foreground process group\n"); 250bea45cddSEd Schouten return; 251bea45cddSEd Schouten } 252bea45cddSEd Schouten 253bea45cddSEd Schouten /* 254bea45cddSEd Schouten * Pick the most interesting process and copy some of its 255bea45cddSEd Schouten * state for printing later. This operation could rely on stale 256bea45cddSEd Schouten * data as we can't hold the proc slock or thread locks over the 257bea45cddSEd Schouten * whole list. However, we're guaranteed not to reference an exited 258bea45cddSEd Schouten * thread or proc since we hold the tty locked. 259bea45cddSEd Schouten */ 260dd970f41SEd Schouten p = NULL; 261dd970f41SEd Schouten LIST_FOREACH(ppick, &tp->t_pgrp->pg_members, p_pglist) 262dd970f41SEd Schouten if (proc_compare(p, ppick)) 263dd970f41SEd Schouten p = ppick; 264bea45cddSEd Schouten 265dd970f41SEd Schouten PROC_LOCK(p); 266dd970f41SEd Schouten PGRP_UNLOCK(tp->t_pgrp); 267dd970f41SEd Schouten td = NULL; 268dd970f41SEd Schouten FOREACH_THREAD_IN_PROC(p, tdpick) 269dd970f41SEd Schouten if (thread_compare(td, tdpick)) 270dd970f41SEd Schouten td = tdpick; 271bea45cddSEd Schouten stateprefix = ""; 272bea45cddSEd Schouten thread_lock(td); 273bea45cddSEd Schouten if (TD_IS_RUNNING(td)) 274bea45cddSEd Schouten state = "running"; 275bea45cddSEd Schouten else if (TD_ON_RUNQ(td) || TD_CAN_RUN(td)) 276bea45cddSEd Schouten state = "runnable"; 277bea45cddSEd Schouten else if (TD_IS_SLEEPING(td)) { 278bea45cddSEd Schouten /* XXX: If we're sleeping, are we ever not in a queue? */ 279bea45cddSEd Schouten if (TD_ON_SLEEPQ(td)) 280bea45cddSEd Schouten state = td->td_wmesg; 281bea45cddSEd Schouten else 282bea45cddSEd Schouten state = "sleeping without queue"; 283bea45cddSEd Schouten } else if (TD_ON_LOCK(td)) { 284bea45cddSEd Schouten state = td->td_lockname; 285bea45cddSEd Schouten stateprefix = "*"; 286bea45cddSEd Schouten } else if (TD_IS_SUSPENDED(td)) 287bea45cddSEd Schouten state = "suspended"; 288bea45cddSEd Schouten else if (TD_AWAITING_INTR(td)) 289bea45cddSEd Schouten state = "intrwait"; 290dd970f41SEd Schouten else if (p->p_state == PRS_ZOMBIE) 291ad765b09SRobert Watson state = "zombie"; 292bea45cddSEd Schouten else 293bea45cddSEd Schouten state = "unknown"; 294bea45cddSEd Schouten pctcpu = (sched_pctcpu(td) * 10000 + FSCALE / 2) >> FSHIFT; 295bea45cddSEd Schouten thread_unlock(td); 296dd970f41SEd Schouten if (p->p_state == PRS_NEW || p->p_state == PRS_ZOMBIE) 297bea45cddSEd Schouten rss = 0; 298bea45cddSEd Schouten else 299dd970f41SEd Schouten rss = pgtok(vmspace_resident_count(p->p_vmspace)); 300dd970f41SEd Schouten microuptime(&rtime); 301dd970f41SEd Schouten timevalsub(&rtime, &p->p_stats->p_start); 302dd970f41SEd Schouten rufetchcalc(p, &ru, &utime, &stime); 303dd970f41SEd Schouten pid = p->p_pid; 304dd970f41SEd Schouten strlcpy(comm, p->p_comm, sizeof comm); 305dd970f41SEd Schouten PROC_UNLOCK(p); 306bea45cddSEd Schouten 307dd970f41SEd Schouten /* Print command, pid, state, rtime, utime, stime, %cpu, and rss. */ 308bea45cddSEd Schouten ttyprintf(tp, 309dd970f41SEd Schouten " cmd: %s %d [%s%s] %ld.%02ldr %ld.%02ldu %ld.%02lds %d%% %ldk\n", 310bea45cddSEd Schouten comm, pid, stateprefix, state, 311dd970f41SEd Schouten (long)rtime.tv_sec, rtime.tv_usec / 10000, 312bea45cddSEd Schouten (long)utime.tv_sec, utime.tv_usec / 10000, 313bea45cddSEd Schouten (long)stime.tv_sec, stime.tv_usec / 10000, 314bea45cddSEd Schouten pctcpu / 100, rss); 315bea45cddSEd Schouten } 316