The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/tty_info.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 04201c66b708f8b20c9205f7ea06a3d1


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.