"Fossies" - the Fresh Open Source Software Archive

Member "atop-2.8.1/procdbase.c" (7 Jan 2023, 8257 Bytes) of package /linux/misc/atop-2.8.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "procdbase.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2 ** ATOP - System & Process Monitor 
    3 ** 
    4 ** The program 'atop' offers the possibility to view the activity of
    5 ** the system on system-level as well as process-level.
    6 ** 
    7 ** This source-file contains all functions required to manipulate the
    8 ** process-database. This database is implemented as a linked list of
    9 ** all running processes, needed to remember the process-counters from
   10 ** the previous sample.
   11 ** ==========================================================================
   12 ** Author:      Gerlof Langeveld
   13 ** E-mail:      gerlof.langeveld@atoptool.nl
   14 ** Date:        November 1996
   15 ** LINUX-port:  June 2000
   16 ** --------------------------------------------------------------------------
   17 ** Copyright (C) 2000-2012 Gerlof Langeveld
   18 **
   19 ** This program is free software; you can redistribute it and/or modify it
   20 ** under the terms of the GNU General Public License as published by the
   21 ** Free Software Foundation; either version 2, or (at your option) any
   22 ** later version.
   23 **
   24 ** This program is distributed in the hope that it will be useful, but
   25 ** WITHOUT ANY WARRANTY; without even the implied warranty of
   26 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   27 ** See the GNU General Public License for more details.
   28 **
   29 ** You should have received a copy of the GNU General Public License
   30 ** along with this program; if not, write to the Free Software
   31 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   32 ** --------------------------------------------------------------------------
   33 **
   34 ** $Log: procdbase.c,v $
   35 ** Revision 1.8  2010/04/23 12:19:35  gerlof
   36 ** Modified mail-address in header.
   37 **
   38 ** Revision 1.7  2007/11/05 12:12:31  gerlof
   39 ** Match processes not only on pid, but also on start time.
   40 **
   41 ** Revision 1.6  2005/10/21 09:50:19  gerlof
   42 ** Per-user accumulation of resource consumption.
   43 **
   44 ** Revision 1.5  2003/07/07 09:26:40  gerlof
   45 ** Cleanup code (-Wall proof).
   46 **
   47 ** Revision 1.4  2002/10/03 11:19:58  gerlof
   48 ** Modify (effective) uid/gid to real uid/gid.
   49 **
   50 ** Revision 1.3  2002/07/24 11:13:50  gerlof
   51 ** Changed to ease porting to other UNIX-platforms.
   52 **
   53 ** Revision 1.2  2002/07/08 09:29:07  root
   54 ** Call to calloc i.s.o. malloc + memset.
   55 **
   56 ** Revision 1.1  2001/10/02 10:43:33  gerlof
   57 ** Initial revision
   58 **
   59 */
   60 
   61 #include <sys/types.h>
   62 #include <sys/param.h>
   63 #include <stdio.h>
   64 #include <errno.h>
   65 #include <fcntl.h>
   66 #include <unistd.h>
   67 #include <string.h>
   68 #include <malloc.h>
   69 
   70 #include "atop.h"
   71 #include "photoproc.h"
   72 
   73 /*****************************************************************************/
   74 #define NPHASH  256     /* number of hash queues for process dbase   */
   75                 /* MUST be a power of 2 !!!                  */
   76 
   77     /* hash buckets for getting process-info     */
   78     /* for a given PID               */
   79 static struct pinfo *phash[NPHASH];
   80 
   81     /* cyclic list of all processes, to detect   */
   82     /* which processes were not referred         */
   83 static struct pinfo presidue;
   84 /*****************************************************************************/
   85 
   86 
   87 /*
   88 ** search process database for the given PID
   89 */
   90 int
   91 pdb_gettask(int pid, char isproc, time_t btime, struct pinfo **pinfopp)
   92 {
   93     register struct pinfo   *pp;
   94 
   95     pp = phash[pid&(NPHASH-1)]; /* get proper hash bucket   */
   96 
   97     /*
   98     ** scan all entries in hash Q
   99     */
  100     while (pp)
  101     {
  102         /*
  103         ** if this is required PID, unchain it from the RESIDUE-list
  104         ** and return info
  105         */
  106         if (pp->tstat.gen.pid    == pid    && 
  107             pp->tstat.gen.isproc == isproc   )
  108         {
  109             int diff = pp->tstat.gen.btime - btime;
  110 
  111             /*
  112             ** with longer intervals, the same PID might be
  113             ** found more than once, so also check the start
  114             ** time of the task
  115             */
  116             if (diff > 1 || diff < -1)
  117             {
  118                 pp = pp->phnext;
  119                 continue;
  120             }
  121 
  122             if (pp->prnext)     /* if part of RESIDUE-list   */
  123             {
  124                 (pp->prnext)->prprev = pp->prprev; /* unchain */
  125                 (pp->prprev)->prnext = pp->prnext;
  126             }
  127 
  128             pp->prnext = NULL;
  129             pp->prprev = NULL;
  130 
  131             *pinfopp = pp;
  132 
  133             return 1;
  134         }
  135 
  136         pp = pp->phnext;
  137     }
  138 
  139     /*
  140     ** end of list; PID not found
  141     */
  142     return 0;
  143 }
  144 
  145 /*
  146 ** add new process-info structure to the process database
  147 */
  148 void
  149 pdb_addtask(int pid, struct pinfo *pinfop)
  150 {
  151     register int i  = pid&(NPHASH-1);
  152 
  153     pinfop->phnext  = phash[i];
  154     phash[i]    = pinfop;
  155 }
  156 
  157 /*
  158 ** delete a process from the process database
  159 */
  160 int
  161 pdb_deltask(int pid, char isproc)
  162 {
  163     register struct pinfo   *pp, *ppp;
  164 
  165     pp = phash[pid&(NPHASH-1)]; /* get proper hash bucket   */
  166 
  167     /*
  168     ** check first entry in hash Q
  169     */
  170     if (pp->tstat.gen.pid == pid && pp->tstat.gen.isproc == isproc)
  171     {
  172         phash[pid&(NPHASH-1)] = pp->phnext;
  173 
  174         if ( pp->prnext )   /* still part of RESIDUE-list ? */
  175         {
  176             (pp->prprev)->prnext = pp->prnext;
  177             (pp->prnext)->prprev = pp->prprev;  /* unchain */
  178         }
  179 
  180         /*
  181         ** remove process-info from process-database
  182         */
  183         free(pp);
  184 
  185         return 1;
  186     }
  187 
  188     /*
  189     ** scan other entries of hash-list
  190     */
  191     ppp = pp;
  192     pp  = pp->phnext;
  193 
  194     while (pp)
  195     {
  196         /*
  197         ** if this is wanted PID, unchain it from the RESIDUE-list
  198         ** and return info
  199         */
  200         if (pp->tstat.gen.pid == pid && pp->tstat.gen.isproc == isproc)
  201         {
  202             ppp->phnext = pp->phnext;
  203 
  204             if ( pp->prnext )   /* part of RESIDUE-list ? */
  205             {
  206                 (pp->prnext)->prprev = pp->prprev;
  207                 (pp->prprev)->prnext = pp->prnext;
  208             }
  209 
  210             /*
  211             ** remove process-info from process-database
  212             */
  213             free(pp);
  214 
  215             return 1;
  216         }
  217 
  218         ppp = pp;
  219         pp  = pp->phnext;
  220     }
  221 
  222     return 0;   /* PID not found */
  223 }
  224 
  225 /*
  226 ** Chain all process-info structures into the RESIDUE-list;
  227 ** every process-info struct which is referenced later on by pdb_gettask(),
  228 ** will be removed from this list again. After that, the remaining
  229 ** (unreferred) process-info structs can be easily discovered and
  230 ** eventually removed.
  231 */
  232 int
  233 pdb_makeresidue(void)
  234 {
  235     register struct pinfo   *pp, *pr;
  236     register int        i;
  237 
  238     /*
  239     ** prepare RESIDUE-list anchor
  240     */
  241     pr = &presidue;
  242 
  243     pr->prnext  = pr;
  244     pr->prprev  = pr;
  245 
  246     /*
  247     ** check all entries in hash list
  248     */
  249     for (i=0; i < NPHASH; i++)
  250     {
  251         if (!phash[i])
  252             continue;   /* empty hash bucket */
  253 
  254         pp = phash[i];      /* get start of list */
  255 
  256         while (pp)      /* all entries in hash list */
  257         {
  258             pp->prnext      = pr->prnext;
  259             pr->prnext      = pp;
  260 
  261              pp->prprev     = (pp->prnext)->prprev;
  262             (pp->prnext)->prprev    = pp;
  263 
  264             pp = pp->phnext;    /* get next of hash list */
  265         }
  266     }
  267 
  268     /*
  269     ** all entries chained in doubly-linked RESIDUE-list
  270     */
  271     return 1;
  272 }
  273 
  274 /*
  275 ** remove all remaining entries in RESIDUE-list
  276 */
  277 int
  278 pdb_cleanresidue(void)
  279 {
  280     register struct pinfo   *pr;
  281     register int        pid;
  282         char            isproc;
  283 
  284     /*
  285     ** start at RESIDUE-list anchor and delete all entries
  286     */
  287     pr = presidue.prnext;
  288 
  289     while (pr != &presidue)
  290     {
  291         pid    = pr->tstat.gen.pid;
  292         isproc = pr->tstat.gen.isproc;
  293 
  294         pr  = pr->prnext;   /* MUST be done before deletion */
  295 
  296         pdb_deltask(pid, isproc);
  297     }
  298 
  299     return 1;
  300 }
  301 
  302 /*
  303 ** search in the RESIDUE-list for process-info which may fit to the
  304 ** given process-info, for which the PID is not known
  305 */
  306 int
  307 pdb_srchresidue(struct tstat *tstatp, struct pinfo **pinfopp)
  308 {
  309     register struct pinfo   *pr, *prmin=NULL;
  310     register long       btimediff;
  311 
  312     /*
  313     ** start at RESIDUE-list anchor and search through
  314     ** all remaining entries
  315     */
  316     pr = presidue.prnext;
  317 
  318     while (pr != &presidue) /* still entries left ? */
  319     {
  320         /*
  321         ** check if this entry matches searched info
  322         */
  323         if (    pr->tstat.gen.ruid   == tstatp->gen.ruid    && 
  324             pr->tstat.gen.rgid   == tstatp->gen.rgid    && 
  325             strcmp(pr->tstat.gen.name, tstatp->gen.name) == EQ  )
  326         {
  327             /*
  328             ** check if the start-time of the process is exactly
  329             ** the same ----> then we have a match;
  330             ** however sometimes the start-time may deviate a
  331             ** second although it IS the process we are looking
  332             ** for (depending on the rounding of the boot-time),
  333             ** so if we don't find the exact match, we will check
  334             ** later on if we found an almost-exact match
  335             */
  336             btimediff = pr->tstat.gen.btime - tstatp->gen.btime;
  337 
  338             if (btimediff == 0) /* gotcha !! */
  339             {
  340                 *pinfopp = pr;
  341                 return 1;
  342             }
  343 
  344             if ((btimediff== -1 || btimediff== 1) && prmin== NULL)
  345                 prmin = pr; /* remember this process */
  346         }
  347 
  348         pr = pr->prnext;
  349     }
  350 
  351     /*
  352     ** nothing found that matched exactly;
  353     ** do we remember a process that matched almost exactly?
  354     */
  355     if (prmin)
  356     {
  357         *pinfopp = prmin;
  358         return 1;
  359     }
  360 
  361     return 0;   /* even not almost */
  362 }