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

Cache object: 658861112c6473f5fb774be8395e2de6


[ 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.