home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume26 / cputt / main.c < prev    next >
C/C++ Source or Header  |  1992-04-18  |  7KB  |  201 lines

  1. #include        "cputt.h"
  2. #include        <kvm.h>
  3. #include        <fcntl.h>
  4. #include        <sys/stat.h>
  5. #include        <sys/types.h>
  6. #include        <sys/timeb.h>
  7. #include        <sys/resource.h>
  8.  
  9. /*
  10.    MAIN - Computes CPU utilization for all processes from two snapshots
  11.    of the kernel process table taken over a user supplied interval
  12.    (arg1).  Sorts and prints the top ten CPU using processes for that
  13.    interval.  Execution continues for a user supplied number of
  14.    iterations (arg2).
  15.  
  16.    The kernel process table snapshots are stored in two arrays,
  17.    'oldproc' and 'newproc'.  Resource utilization information is stored
  18.    in two arrays, 'oldusage' and 'newusage'.  The command strings for
  19.    each process are stored in a 2D array, 'cmds'.  CPU utilization for
  20.    each interval is stored in the 'pdata' array along with pointers to
  21.    the appropriate 'proc' and 'cmds' entries.
  22. */
  23.  
  24. main (argc, argv)
  25.  
  26. int argc; char *argv[];
  27.  
  28. {
  29.      extern struct info        Info;
  30.      extern kvm_t             *Flkvm;
  31.      extern union userstate    User;
  32.  
  33.      struct proc              *oldproc,*newproc,*tproc;
  34.      struct rusage            *oldusage,*newusage,*tusage;
  35.      struct procdata          *pdata;
  36.      struct hashtab           *hp;
  37.  
  38.      register long             time1,utime1,time2,utime2;
  39.      register long             s_delta, p_delta;
  40.      register int              i,j,k;
  41.  
  42.      struct timeb              ot,nt;
  43.      struct hashtab           *hashuid();
  44.      int                       trim=0,reps,cmp();
  45.      double                    percentmem();
  46.      char                     **cmds;
  47.  
  48.      if (argc != 3)
  49.         {
  50.          printf("usage: cputt <interval> <iterations>\n");
  51.          exit();
  52.         }
  53.  
  54.      setpriority(PRIO_PROCESS,0,-20);
  55.  
  56.      /* open kernel memory  */
  57.  
  58.      Flkvm = kvm_open(NULL, NULL, NULL, O_RDONLY, "cputt");
  59.  
  60.      /* get critical system parameters, build uid hash table */
  61.  
  62.      init();
  63.      initusers();
  64.  
  65.      /* truncate unused portion of the process table */
  66.  
  67.      Info.i_sproc = Info.i_nproc * sizeof(struct proc);
  68.      if (GROWTH_BUF)
  69.      {
  70.          oldproc = (struct proc *) getcore(Info.i_nproc*sizeof(struct proc));
  71.          readstatus(oldproc);
  72.          for (i=0; i<Info.i_nproc; i++)
  73.               if (oldproc[i].p_stat && getupage(oldproc[i]))
  74.                   j=i;
  75.          free(oldproc);
  76.          if (j+GROWTH_BUF < Info.i_nproc)
  77.          {
  78.              Info.i_nproc = j+GROWTH_BUF;
  79.              Info.i_sproc = Info.i_nproc * sizeof(struct proc);
  80.              trim = 1;
  81.          }
  82.      }
  83.  
  84.      /* allocate core for internal data structures */
  85.  
  86.      cmds = (char **) getcore(Info.i_nproc*sizeof(char *));
  87.      for (i=0;i<Info.i_nproc;i++)
  88.           cmds[i] = (char *) getcore(COMMAND_SIZE);
  89.  
  90.      pdata     = (struct procdata *)
  91.                   getcore(MAXACTIVE*sizeof(struct procdata));
  92.      oldusage  = (struct rusage *)
  93.                   getcore(Info.i_nproc*sizeof(struct rusage));
  94.      newusage  = (struct rusage *)
  95.                   getcore(Info.i_nproc*sizeof(struct rusage));
  96.      oldproc   = (struct proc *) getcore(Info.i_nproc*sizeof(struct proc));
  97.      newproc   = (struct proc *) getcore(Info.i_nproc*sizeof(struct proc));
  98.  
  99.      /* get initial time, process table, upage, and command strings */
  100.  
  101.      ftime(&ot);
  102.      readstatus(oldproc);
  103.      for (i=0;i<Info.i_nproc;i++) 
  104.           if (oldproc[i].p_stat && getupage(oldproc[i]))
  105.              {
  106.               oldusage[i] = User.u_us.u_ru;
  107.               getcmd(oldproc[i],cmds[i]);
  108.              }
  109.  
  110.      /* compare process tables every argv[1] seconds for argv[2] iterations */
  111.  
  112.      for (reps = 0; reps < atoi(argv[2]); reps++)
  113.      {    
  114.           sleep(atoi(argv[1]));        /* sleep for agrv[1] seconds */
  115.           ftime(&nt);                  /* get new time          */
  116.           readstatus(newproc);         /* get new process table */
  117.  
  118.           /* find matching pids, compute cpu usage, store results in pdata */
  119.  
  120.           for (i=k=0; i<Info.i_nproc; i++)
  121.                if (newproc[i].p_stat && getupage(newproc[i]))
  122.                {
  123.                    j=i; /* record latest proc table location */
  124.                    newusage[i] = User.u_us.u_ru;
  125.                    if (oldproc[i].p_pid==newproc[i].p_pid)
  126.                    {
  127.                        time1 =   oldusage[i].ru_utime.tv_sec +
  128.                                  oldusage[i].ru_stime.tv_sec;
  129.                        utime1 =  oldusage[i].ru_utime.tv_usec +
  130.                                  oldusage[i].ru_stime.tv_usec;
  131.                        time2 =   newusage[i].ru_utime.tv_sec +
  132.                                  newusage[i].ru_stime.tv_sec;
  133.                        utime2 =  newusage[i].ru_utime.tv_usec +
  134.                                  newusage[i].ru_stime.tv_usec;
  135.                        p_delta = (time2*1000000+utime2) -
  136.                                  (time1*1000000+utime1);
  137.                        if (p_delta)
  138.                        {
  139.                            s_delta = (nt.time*1000+nt.millitm) -
  140.                                      (ot.time*1000+ot.millitm);
  141.                            pdata[k].pctcpu = (p_delta*10)/s_delta;
  142.                            pdata[k].proc   = &oldproc[i];
  143.                            pdata[k].pr_cmd = i;
  144.                        /*
  145.  
  146.                        If you've settled on a reliable MAXACTIVE value,
  147. NOTE =>                you'll get a slight performance gain by replacing
  148.                        the following if-statement with this line:
  149.  
  150.                            k++;
  151.  
  152.                        */
  153.                            if (k < MAXACTIVE - 1)
  154.                                k++;
  155.                            else
  156.                                printf("\ncputt: MAXACTIVE limit exceeded.\n");
  157.                        }
  158.                    }
  159.                    else
  160.                    {
  161.                        getcmd(newproc[i],cmds[i]);
  162.                    }
  163.                } 
  164.  
  165.           /* check process table variance at each iteration */
  166.  
  167.           if (trim &&
  168.              (i-j < GROWTH_BUF - MAX_GROW || i-j > GROWTH_BUF + MAX_SHRINK))
  169.           {
  170.               printf("\nProcess table variance greater than %d, restarting..\n",
  171.                       MAX_GROW + MAX_SHRINK);
  172.               execvp(argv[0],argv);
  173.           }
  174.  
  175.           /* sort and print results */
  176.  
  177.           qsort(pdata,k,sizeof(struct procdata),cmp); 
  178.           printf("\n  PID USER        CPU    MEM  COMMANDS - %d %d\n",k,j);
  179.           for (i=--k; k>-1 && k>i-MAXOUT; --k)
  180.           {
  181.                printf("%5d ",pdata[k].proc->p_pid);
  182.                if (hp = hashuid(pdata[k].proc->p_suid))
  183.                    printf("%-8.8s ", hp->h_uname);
  184.                else
  185.                    printf("user%-4.4d ", pdata[k].proc->p_uid);
  186.                printf("%6.2f ",(float)pdata[k].pctcpu/100);
  187.                printf("%6.2f ",percentmem(pdata[k].proc));
  188.                printf(" %s\n",cmds[pdata[k].pr_cmd]);
  189.           }
  190.        
  191.           /* swap old and new pointers */
  192.  
  193.           tusage   = oldusage;   tproc   = oldproc;
  194.           oldusage = newusage;   oldproc = newproc;
  195.           newusage = tusage;     newproc = tproc;
  196.           ot = nt;
  197.  
  198.      }    /* for all iterations.. */
  199.  
  200. }    /* main */
  201.