1bea45cddSEd Schouten /*- 2bea45cddSEd Schouten * Copyright (c) 1982, 1986, 1990, 1991, 1993 3bea45cddSEd Schouten * The Regents of the University of California. All rights reserved. 4bea45cddSEd Schouten * (c) UNIX System Laboratories, Inc. 5bea45cddSEd Schouten * All or some portions of this file are derived from material licensed 6bea45cddSEd Schouten * to the University of California by American Telephone and Telegraph 7bea45cddSEd Schouten * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8bea45cddSEd Schouten * the permission of UNIX System Laboratories, Inc. 9bea45cddSEd Schouten * 10bea45cddSEd Schouten * Copyright (c) 2002 Networks Associates Technologies, Inc. 11bea45cddSEd Schouten * All rights reserved. 12bea45cddSEd Schouten * 13bea45cddSEd Schouten * Portions of this software were developed for the FreeBSD Project by 14bea45cddSEd Schouten * ThinkSec AS and NAI Labs, the Security Research Division of Network 15bea45cddSEd Schouten * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 16bea45cddSEd Schouten * ("CBOSS"), as part of the DARPA CHATS research program. 17bea45cddSEd Schouten * 18bea45cddSEd Schouten * Redistribution and use in source and binary forms, with or without 19bea45cddSEd Schouten * modification, are permitted provided that the following conditions 20bea45cddSEd Schouten * are met: 21bea45cddSEd Schouten * 1. Redistributions of source code must retain the above copyright 22bea45cddSEd Schouten * notice, this list of conditions and the following disclaimer. 23bea45cddSEd Schouten * 2. Redistributions in binary form must reproduce the above copyright 24bea45cddSEd Schouten * notice, this list of conditions and the following disclaimer in the 25bea45cddSEd Schouten * documentation and/or other materials provided with the distribution. 26bea45cddSEd Schouten * 4. Neither the name of the University nor the names of its contributors 27bea45cddSEd Schouten * may be used to endorse or promote products derived from this software 28bea45cddSEd Schouten * without specific prior written permission. 29bea45cddSEd Schouten * 30bea45cddSEd Schouten * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 31bea45cddSEd Schouten * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32bea45cddSEd Schouten * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33bea45cddSEd Schouten * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 34bea45cddSEd Schouten * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35bea45cddSEd Schouten * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36bea45cddSEd Schouten * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37bea45cddSEd Schouten * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38bea45cddSEd Schouten * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39bea45cddSEd Schouten * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40bea45cddSEd Schouten * SUCH DAMAGE. 41bea45cddSEd Schouten */ 42bea45cddSEd Schouten 43bea45cddSEd Schouten #include <sys/cdefs.h> 44bea45cddSEd Schouten __FBSDID("$FreeBSD$"); 45bea45cddSEd Schouten 46bea45cddSEd Schouten #include <sys/param.h> 47bea45cddSEd Schouten #include <sys/lock.h> 48bea45cddSEd Schouten #include <sys/mutex.h> 49bea45cddSEd Schouten #include <sys/proc.h> 50bea45cddSEd Schouten #include <sys/resourcevar.h> 51bea45cddSEd Schouten #include <sys/sched.h> 52bea45cddSEd Schouten #include <sys/systm.h> 53bea45cddSEd Schouten #include <sys/tty.h> 54bea45cddSEd Schouten 55bea45cddSEd Schouten #include <vm/vm.h> 56bea45cddSEd Schouten #include <vm/pmap.h> 57bea45cddSEd Schouten #include <vm/vm_map.h> 58bea45cddSEd Schouten 59bea45cddSEd Schouten /* 60bea45cddSEd Schouten * Returns 1 if p2 is "better" than p1 61bea45cddSEd Schouten * 62bea45cddSEd Schouten * The algorithm for picking the "interesting" process is thus: 63bea45cddSEd Schouten * 64bea45cddSEd Schouten * 1) Only foreground processes are eligible - implied. 65bea45cddSEd Schouten * 2) Runnable processes are favored over anything else. The runner 66bea45cddSEd Schouten * with the highest cpu utilization is picked (p_estcpu). Ties are 67bea45cddSEd Schouten * broken by picking the highest pid. 68bea45cddSEd Schouten * 3) The sleeper with the shortest sleep time is next. With ties, 69bea45cddSEd Schouten * we pick out just "short-term" sleepers (P_SINTR == 0). 70bea45cddSEd Schouten * 4) Further ties are broken by picking the highest pid. 71bea45cddSEd Schouten */ 72bea45cddSEd Schouten 73bea45cddSEd Schouten #define TESTAB(a, b) ((a)<<1 | (b)) 74bea45cddSEd Schouten #define ONLYA 2 75bea45cddSEd Schouten #define ONLYB 1 76bea45cddSEd Schouten #define BOTH 3 77bea45cddSEd Schouten 78bea45cddSEd Schouten static int 799e577585SEd Schouten proc_sum(struct proc *p, fixpt_t *estcpup) 80bea45cddSEd Schouten { 81bea45cddSEd Schouten struct thread *td; 82bea45cddSEd Schouten int estcpu; 83bea45cddSEd Schouten int val; 84bea45cddSEd Schouten 85bea45cddSEd Schouten val = 0; 86bea45cddSEd Schouten estcpu = 0; 87bea45cddSEd Schouten FOREACH_THREAD_IN_PROC(p, td) { 88bea45cddSEd Schouten thread_lock(td); 89bea45cddSEd Schouten if (TD_ON_RUNQ(td) || 90bea45cddSEd Schouten TD_IS_RUNNING(td)) 91bea45cddSEd Schouten val = 1; 92bea45cddSEd Schouten estcpu += sched_pctcpu(td); 93bea45cddSEd Schouten thread_unlock(td); 94bea45cddSEd Schouten } 95bea45cddSEd Schouten *estcpup = estcpu; 96bea45cddSEd Schouten 97bea45cddSEd Schouten return (val); 98bea45cddSEd Schouten } 99bea45cddSEd Schouten 100bea45cddSEd Schouten static int 101bea45cddSEd Schouten thread_compare(struct thread *td, struct thread *td2) 102bea45cddSEd Schouten { 103bea45cddSEd Schouten int runa, runb; 104bea45cddSEd Schouten int slpa, slpb; 105bea45cddSEd Schouten fixpt_t esta, estb; 106bea45cddSEd Schouten 107bea45cddSEd Schouten if (td == NULL) 108bea45cddSEd Schouten return (1); 109bea45cddSEd Schouten 110bea45cddSEd Schouten /* 111bea45cddSEd Schouten * Fetch running stats, pctcpu usage, and interruptable flag. 112bea45cddSEd Schouten */ 113bea45cddSEd Schouten thread_lock(td); 114bea45cddSEd Schouten runa = TD_IS_RUNNING(td) | TD_ON_RUNQ(td); 115bea45cddSEd Schouten slpa = td->td_flags & TDF_SINTR; 116bea45cddSEd Schouten esta = sched_pctcpu(td); 117bea45cddSEd Schouten thread_unlock(td); 118bea45cddSEd Schouten thread_lock(td2); 119bea45cddSEd Schouten runb = TD_IS_RUNNING(td2) | TD_ON_RUNQ(td2); 120bea45cddSEd Schouten estb = sched_pctcpu(td2); 121bea45cddSEd Schouten slpb = td2->td_flags & TDF_SINTR; 122bea45cddSEd Schouten thread_unlock(td2); 123bea45cddSEd Schouten /* 124bea45cddSEd Schouten * see if at least one of them is runnable 125bea45cddSEd Schouten */ 126bea45cddSEd Schouten switch (TESTAB(runa, runb)) { 127bea45cddSEd Schouten case ONLYA: 128bea45cddSEd Schouten return (0); 129bea45cddSEd Schouten case ONLYB: 130bea45cddSEd Schouten return (1); 131bea45cddSEd Schouten case BOTH: 132bea45cddSEd Schouten break; 133bea45cddSEd Schouten } 134bea45cddSEd Schouten /* 135bea45cddSEd Schouten * favor one with highest recent cpu utilization 136bea45cddSEd Schouten */ 137bea45cddSEd Schouten if (estb > esta) 138bea45cddSEd Schouten return (1); 139bea45cddSEd Schouten if (esta > estb) 140bea45cddSEd Schouten return (0); 141bea45cddSEd Schouten /* 142bea45cddSEd Schouten * favor one sleeping in a non-interruptible sleep 143bea45cddSEd Schouten */ 144bea45cddSEd Schouten switch (TESTAB(slpa, slpb)) { 145bea45cddSEd Schouten case ONLYA: 146bea45cddSEd Schouten return (0); 147bea45cddSEd Schouten case ONLYB: 148bea45cddSEd Schouten return (1); 149bea45cddSEd Schouten case BOTH: 150bea45cddSEd Schouten break; 151bea45cddSEd Schouten } 152bea45cddSEd Schouten 153bea45cddSEd Schouten return (td < td2); 154bea45cddSEd Schouten } 155bea45cddSEd Schouten 156bea45cddSEd Schouten static int 157bea45cddSEd Schouten proc_compare(struct proc *p1, struct proc *p2) 158bea45cddSEd Schouten { 159bea45cddSEd Schouten 160bea45cddSEd Schouten int runa, runb; 161bea45cddSEd Schouten fixpt_t esta, estb; 162bea45cddSEd Schouten 163bea45cddSEd Schouten if (p1 == NULL) 164bea45cddSEd Schouten return (1); 165bea45cddSEd Schouten 166bea45cddSEd Schouten /* 167bea45cddSEd Schouten * Fetch various stats about these processes. After we drop the 168bea45cddSEd Schouten * lock the information could be stale but the race is unimportant. 169bea45cddSEd Schouten */ 170bea45cddSEd Schouten PROC_LOCK(p1); 171bea45cddSEd Schouten runa = proc_sum(p1, &esta); 172bea45cddSEd Schouten PROC_UNLOCK(p1); 173bea45cddSEd Schouten PROC_LOCK(p2); 174bea45cddSEd Schouten runb = proc_sum(p2, &estb); 175bea45cddSEd Schouten PROC_UNLOCK(p2); 176bea45cddSEd Schouten 177bea45cddSEd Schouten /* 178bea45cddSEd Schouten * see if at least one of them is runnable 179bea45cddSEd Schouten */ 180bea45cddSEd Schouten switch (TESTAB(runa, runb)) { 181bea45cddSEd Schouten case ONLYA: 182bea45cddSEd Schouten return (0); 183bea45cddSEd Schouten case ONLYB: 184bea45cddSEd Schouten return (1); 185bea45cddSEd Schouten case BOTH: 186bea45cddSEd Schouten break; 187bea45cddSEd Schouten } 188bea45cddSEd Schouten /* 189bea45cddSEd Schouten * favor one with highest recent cpu utilization 190bea45cddSEd Schouten */ 191bea45cddSEd Schouten if (estb > esta) 192bea45cddSEd Schouten return (1); 193bea45cddSEd Schouten if (esta > estb) 194bea45cddSEd Schouten return (0); 195bea45cddSEd Schouten /* 196bea45cddSEd Schouten * weed out zombies 197bea45cddSEd Schouten */ 198bea45cddSEd Schouten switch (TESTAB(p1->p_state == PRS_ZOMBIE, p2->p_state == PRS_ZOMBIE)) { 199bea45cddSEd Schouten case ONLYA: 200bea45cddSEd Schouten return (1); 201bea45cddSEd Schouten case ONLYB: 202bea45cddSEd Schouten return (0); 203bea45cddSEd Schouten case BOTH: 204bea45cddSEd Schouten break; 205bea45cddSEd Schouten } 206bea45cddSEd Schouten 207bea45cddSEd Schouten return (p2->p_pid > p1->p_pid); /* tie - return highest pid */ 208bea45cddSEd Schouten } 209bea45cddSEd Schouten 210bea45cddSEd Schouten /* 211bea45cddSEd Schouten * Report on state of foreground process group. 212bea45cddSEd Schouten */ 213bea45cddSEd Schouten void 214bc093719SEd Schouten tty_info(struct tty *tp) 215bea45cddSEd Schouten { 216dd970f41SEd Schouten struct timeval rtime, utime, stime; 217dd970f41SEd Schouten struct proc *p, *ppick; 218dd970f41SEd Schouten struct thread *td, *tdpick; 219bea45cddSEd Schouten const char *stateprefix, *state; 220bea45cddSEd Schouten long rss; 221bea45cddSEd Schouten int load, pctcpu; 222bea45cddSEd Schouten pid_t pid; 223bea45cddSEd Schouten char comm[MAXCOMLEN + 1]; 224bea45cddSEd Schouten struct rusage ru; 225bea45cddSEd Schouten 226bc093719SEd Schouten tty_lock_assert(tp, MA_OWNED); 227bc093719SEd Schouten 228bc093719SEd Schouten if (tty_checkoutq(tp) == 0) 229bea45cddSEd Schouten return; 230bea45cddSEd Schouten 231bea45cddSEd Schouten /* Print load average. */ 232bea45cddSEd Schouten load = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT; 233379affd5SEd Schouten ttyprintf(tp, "%sload: %d.%02d ", tp->t_column == 0 ? "" : "\n", 234379affd5SEd Schouten load / 100, load % 100); 235bea45cddSEd Schouten 236bea45cddSEd Schouten if (tp->t_session == NULL) { 237bea45cddSEd Schouten ttyprintf(tp, "not a controlling terminal\n"); 238bea45cddSEd Schouten return; 239bea45cddSEd Schouten } 240bea45cddSEd Schouten if (tp->t_pgrp == NULL) { 241bea45cddSEd Schouten ttyprintf(tp, "no foreground process group\n"); 242bea45cddSEd Schouten return; 243bea45cddSEd Schouten } 244bea45cddSEd Schouten PGRP_LOCK(tp->t_pgrp); 245bea45cddSEd Schouten if (LIST_EMPTY(&tp->t_pgrp->pg_members)) { 246bea45cddSEd Schouten PGRP_UNLOCK(tp->t_pgrp); 247bea45cddSEd Schouten ttyprintf(tp, "empty foreground process group\n"); 248bea45cddSEd Schouten return; 249bea45cddSEd Schouten } 250bea45cddSEd Schouten 251bea45cddSEd Schouten /* 252bea45cddSEd Schouten * Pick the most interesting process and copy some of its 253bea45cddSEd Schouten * state for printing later. This operation could rely on stale 254bea45cddSEd Schouten * data as we can't hold the proc slock or thread locks over the 255bea45cddSEd Schouten * whole list. However, we're guaranteed not to reference an exited 256bea45cddSEd Schouten * thread or proc since we hold the tty locked. 257bea45cddSEd Schouten */ 258dd970f41SEd Schouten p = NULL; 259dd970f41SEd Schouten LIST_FOREACH(ppick, &tp->t_pgrp->pg_members, p_pglist) 260dd970f41SEd Schouten if (proc_compare(p, ppick)) 261dd970f41SEd Schouten p = ppick; 262bea45cddSEd Schouten 263dd970f41SEd Schouten PROC_LOCK(p); 264dd970f41SEd Schouten PGRP_UNLOCK(tp->t_pgrp); 265dd970f41SEd Schouten td = NULL; 266dd970f41SEd Schouten FOREACH_THREAD_IN_PROC(p, tdpick) 267dd970f41SEd Schouten if (thread_compare(td, tdpick)) 268dd970f41SEd Schouten td = tdpick; 269bea45cddSEd Schouten stateprefix = ""; 270bea45cddSEd Schouten thread_lock(td); 271bea45cddSEd Schouten if (TD_IS_RUNNING(td)) 272bea45cddSEd Schouten state = "running"; 273bea45cddSEd Schouten else if (TD_ON_RUNQ(td) || TD_CAN_RUN(td)) 274bea45cddSEd Schouten state = "runnable"; 275bea45cddSEd Schouten else if (TD_IS_SLEEPING(td)) { 276bea45cddSEd Schouten /* XXX: If we're sleeping, are we ever not in a queue? */ 277bea45cddSEd Schouten if (TD_ON_SLEEPQ(td)) 278bea45cddSEd Schouten state = td->td_wmesg; 279bea45cddSEd Schouten else 280bea45cddSEd Schouten state = "sleeping without queue"; 281bea45cddSEd Schouten } else if (TD_ON_LOCK(td)) { 282bea45cddSEd Schouten state = td->td_lockname; 283bea45cddSEd Schouten stateprefix = "*"; 284bea45cddSEd Schouten } else if (TD_IS_SUSPENDED(td)) 285bea45cddSEd Schouten state = "suspended"; 286bea45cddSEd Schouten else if (TD_AWAITING_INTR(td)) 287bea45cddSEd Schouten state = "intrwait"; 288dd970f41SEd Schouten else if (p->p_state == PRS_ZOMBIE) 289ad765b09SRobert Watson state = "zombie"; 290bea45cddSEd Schouten else 291bea45cddSEd Schouten state = "unknown"; 292bea45cddSEd Schouten pctcpu = (sched_pctcpu(td) * 10000 + FSCALE / 2) >> FSHIFT; 293bea45cddSEd Schouten thread_unlock(td); 294dd970f41SEd Schouten if (p->p_state == PRS_NEW || p->p_state == PRS_ZOMBIE) 295bea45cddSEd Schouten rss = 0; 296bea45cddSEd Schouten else 297dd970f41SEd Schouten rss = pgtok(vmspace_resident_count(p->p_vmspace)); 298dd970f41SEd Schouten microuptime(&rtime); 299dd970f41SEd Schouten timevalsub(&rtime, &p->p_stats->p_start); 300dd970f41SEd Schouten rufetchcalc(p, &ru, &utime, &stime); 301dd970f41SEd Schouten pid = p->p_pid; 302dd970f41SEd Schouten strlcpy(comm, p->p_comm, sizeof comm); 303dd970f41SEd Schouten PROC_UNLOCK(p); 304bea45cddSEd Schouten 305dd970f41SEd Schouten /* Print command, pid, state, rtime, utime, stime, %cpu, and rss. */ 306bea45cddSEd Schouten ttyprintf(tp, 307dd970f41SEd Schouten " cmd: %s %d [%s%s] %ld.%02ldr %ld.%02ldu %ld.%02lds %d%% %ldk\n", 308bea45cddSEd Schouten comm, pid, stateprefix, state, 309dd970f41SEd Schouten (long)rtime.tv_sec, rtime.tv_usec / 10000, 310bea45cddSEd Schouten (long)utime.tv_sec, utime.tv_usec / 10000, 311bea45cddSEd Schouten (long)stime.tv_sec, stime.tv_usec / 10000, 312bea45cddSEd Schouten pctcpu / 100, rss); 313bea45cddSEd Schouten } 314