home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / bin / csh / time.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-06  |  8.2 KB  |  317 lines

  1. /*-
  2.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)time.c    5.15 (Berkeley) 7/19/91";
  36. #endif /* not lint */
  37.  
  38. #include <sys/types.h>
  39. #if __STDC__
  40. # include <stdarg.h>
  41. #else
  42. # include <varargs.h>
  43. #endif
  44.  
  45. #include "csh.h"
  46. #include "extern.h"
  47.  
  48. /*
  49.  * C Shell - routines handling process timing and niceing
  50.  */
  51. static void    pdeltat __P((struct timeval *, struct timeval *));
  52.  
  53. void
  54. settimes()
  55. {
  56.     struct rusage ruch;
  57.  
  58.     (void) gettimeofday(&time0, NULL);
  59.     (void) getrusage(RUSAGE_SELF, &ru0);
  60.     (void) getrusage(RUSAGE_CHILDREN, &ruch);
  61.     ruadd(&ru0, &ruch);
  62. }
  63.  
  64. /*
  65.  * dotime is only called if it is truly a builtin function and not a
  66.  * prefix to another command
  67.  */
  68. void
  69. /*ARGSUSED*/
  70. dotime(v, t)
  71.     Char **v;
  72.     struct command *t;
  73. {
  74.     struct timeval timedol;
  75.     struct rusage ru1, ruch;
  76.  
  77.     (void) getrusage(RUSAGE_SELF, &ru1);
  78.     (void) getrusage(RUSAGE_CHILDREN, &ruch);
  79.     ruadd(&ru1, &ruch);
  80.     (void) gettimeofday(&timedol, NULL);
  81.     prusage(&ru0, &ru1, &timedol, &time0);
  82. }
  83.  
  84. /*
  85.  * donice is only called when it on the line by itself or with a +- value
  86.  */
  87. void
  88. /*ARGSUSED*/
  89. donice(v, t)
  90.     Char **v;
  91.     struct command *t;
  92. {
  93.     register Char *cp;
  94.     int     nval = 0;
  95.  
  96.     v++, cp = *v++;
  97.     if (cp == 0)
  98.     nval = 4;
  99.     else if (*v == 0 && any("+-", cp[0]))
  100.     nval = getn(cp);
  101.     (void) setpriority(PRIO_PROCESS, 0, nval);
  102. }
  103.  
  104. void
  105. ruadd(ru, ru2)
  106.     register struct rusage *ru, *ru2;
  107. {
  108.     tvadd(&ru->ru_utime, &ru2->ru_utime);
  109.     tvadd(&ru->ru_stime, &ru2->ru_stime);
  110.     if (ru2->ru_maxrss > ru->ru_maxrss)
  111.     ru->ru_maxrss = ru2->ru_maxrss;
  112.  
  113.     ru->ru_ixrss += ru2->ru_ixrss;
  114.     ru->ru_idrss += ru2->ru_idrss;
  115.     ru->ru_isrss += ru2->ru_isrss;
  116.     ru->ru_minflt += ru2->ru_minflt;
  117.     ru->ru_majflt += ru2->ru_majflt;
  118.     ru->ru_nswap += ru2->ru_nswap;
  119.     ru->ru_inblock += ru2->ru_inblock;
  120.     ru->ru_oublock += ru2->ru_oublock;
  121.     ru->ru_msgsnd += ru2->ru_msgsnd;
  122.     ru->ru_msgrcv += ru2->ru_msgrcv;
  123.     ru->ru_nsignals += ru2->ru_nsignals;
  124.     ru->ru_nvcsw += ru2->ru_nvcsw;
  125.     ru->ru_nivcsw += ru2->ru_nivcsw;
  126. }
  127.  
  128. void
  129. prusage(r0, r1, e, b)
  130.     register struct rusage *r0, *r1;
  131.     struct timeval *e, *b;
  132. {
  133.     register time_t t =
  134.     (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec) * 100 +
  135.     (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 +
  136.     (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec) * 100 +
  137.     (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000;
  138.     register char *cp;
  139.     register long i;
  140.     register struct varent *vp = adrof(STRtime);
  141.  
  142.     int     ms =
  143.     (e->tv_sec - b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000;
  144.  
  145.     cp = "%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww";
  146.  
  147.     if (vp && vp->vec[0] && vp->vec[1])
  148.     cp = short2str(vp->vec[1]);
  149.  
  150.     for (; *cp; cp++)
  151.     if (*cp != '%')
  152.         (void) fputc(*cp, cshout);
  153.     else if (cp[1])
  154.         switch (*++cp) {
  155.  
  156.         case 'U':        /* user CPU time used */
  157.         pdeltat(&r1->ru_utime, &r0->ru_utime);
  158.         break;
  159.  
  160.         case 'S':        /* system CPU time used */
  161.         pdeltat(&r1->ru_stime, &r0->ru_stime);
  162.         break;
  163.  
  164.         case 'E':        /* elapsed (wall-clock) time */
  165.         pcsecs((long) ms);
  166.         break;
  167.  
  168.         case 'P':        /* percent time spent running */
  169.         /* check if it did not run at all */
  170.         i = (ms == 0) ? 0 : (t * 1000 / ms);
  171.         /* nn.n% */
  172.         (void) fprintf(cshout, "%ld.%01ld%%", i / 10, i % 10);
  173.         break;
  174.  
  175.         case 'W':        /* number of swaps */
  176.         i = r1->ru_nswap - r0->ru_nswap;
  177.         (void) fprintf(cshout, "%ld", i);
  178.         break;
  179.  
  180.         case 'X':        /* (average) shared text size */
  181.         (void) fprintf(cshout, "%ld", t == 0 ? 0L : 
  182.                    (r1->ru_ixrss - r0->ru_ixrss) / t);
  183.         break;
  184.  
  185.         case 'D':        /* (average) unshared data size */
  186.         (void) fprintf(cshout, "%ld", t == 0 ? 0L :
  187.             (r1->ru_idrss + r1->ru_isrss -
  188.              (r0->ru_idrss + r0->ru_isrss)) / t);
  189.         break;
  190.  
  191.         case 'K':        /* (average) total data memory used  */
  192.         (void) fprintf(cshout, "%ld", t == 0 ? 0L :
  193.             ((r1->ru_ixrss + r1->ru_isrss + r1->ru_idrss) -
  194.              (r0->ru_ixrss + r0->ru_idrss + r0->ru_isrss)) / t);
  195.         break;
  196.  
  197.         case 'M':        /* max. Resident Set Size */
  198.         (void) fprintf(cshout, "%ld", r1->ru_maxrss / 2L);
  199.         break;
  200.  
  201.         case 'F':        /* page faults */
  202.         (void) fprintf(cshout, "%ld", r1->ru_majflt - r0->ru_majflt);
  203.         break;
  204.  
  205.         case 'R':        /* page reclaims */
  206.         (void) fprintf(cshout, "%ld", r1->ru_minflt - r0->ru_minflt);
  207.         break;
  208.  
  209.         case 'I':        /* FS blocks in */
  210.         (void) fprintf(cshout, "%ld", r1->ru_inblock - r0->ru_inblock);
  211.         break;
  212.  
  213.         case 'O':        /* FS blocks out */
  214.         (void) fprintf(cshout, "%ld", r1->ru_oublock - r0->ru_oublock);
  215.         break;
  216.  
  217.         case 'r':        /* socket messages recieved */
  218.         (void) fprintf(cshout, "%ld", r1->ru_msgrcv - r0->ru_msgrcv);
  219.         break;
  220.  
  221.         case 's':        /* socket messages sent */
  222.         (void) fprintf(cshout, "%ld", r1->ru_msgsnd - r0->ru_msgsnd);
  223.         break;
  224.  
  225.         case 'k':        /* number of signals recieved */
  226.         (void) fprintf(cshout, "%ld", r1->ru_nsignals-r0->ru_nsignals);
  227.         break;
  228.  
  229.         case 'w':        /* num. voluntary context switches (waits) */
  230.         (void) fprintf(cshout, "%ld", r1->ru_nvcsw - r0->ru_nvcsw);
  231.         break;
  232.  
  233.         case 'c':        /* num. involuntary context switches */
  234.         (void) fprintf(cshout, "%ld", r1->ru_nivcsw - r0->ru_nivcsw);
  235.         break;
  236.         }
  237.     (void) fputc('\n', cshout);
  238. }
  239.  
  240. static void
  241. pdeltat(t1, t0)
  242.     struct timeval *t1, *t0;
  243. {
  244.     struct timeval td;
  245.  
  246.     tvsub(&td, t1, t0);
  247.     (void) fprintf(cshout, "%d.%01d", td.tv_sec, td.tv_usec / 100000);
  248. }
  249.  
  250. void
  251. tvadd(tsum, t0)
  252.     struct timeval *tsum, *t0;
  253. {
  254.  
  255.     tsum->tv_sec += t0->tv_sec;
  256.     tsum->tv_usec += t0->tv_usec;
  257.     if (tsum->tv_usec > 1000000)
  258.     tsum->tv_sec++, tsum->tv_usec -= 1000000;
  259. }
  260.  
  261. void
  262. tvsub(tdiff, t1, t0)
  263.     struct timeval *tdiff, *t1, *t0;
  264. {
  265.  
  266.     tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
  267.     tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
  268.     if (tdiff->tv_usec < 0)
  269.     tdiff->tv_sec--, tdiff->tv_usec += 1000000;
  270. }
  271.  
  272. #define  P2DIG(i) (void) fprintf(cshout, "%d%d", (i) / 10, (i) % 10)
  273.  
  274. void
  275. psecs(l)
  276.     long    l;
  277. {
  278.     register int i;
  279.  
  280.     i = l / 3600;
  281.     if (i) {
  282.     (void) fprintf(cshout, "%d:", i);
  283.     i = l % 3600;
  284.     P2DIG(i / 60);
  285.     goto minsec;
  286.     }
  287.     i = l;
  288.     (void) fprintf(cshout, "%d", i / 60);
  289. minsec:
  290.     i %= 60;
  291.     (void) fputc(':', cshout);
  292.     P2DIG(i);
  293. }
  294.  
  295. void
  296. pcsecs(l)            /* PWP: print mm:ss.dd, l is in sec*100 */
  297.     long    l;
  298. {
  299.     register int i;
  300.  
  301.     i = l / 360000;
  302.     if (i) {
  303.     (void) fprintf(cshout, "%d:", i);
  304.     i = (l % 360000) / 100;
  305.     P2DIG(i / 60);
  306.     goto minsec;
  307.     }
  308.     i = l / 100;
  309.     (void) fprintf(cshout, "%d", i / 60);
  310. minsec:
  311.     i %= 60;
  312.     (void) fputc(':', cshout);
  313.     P2DIG(i);
  314.     (void) fputc('.', cshout);
  315.     P2DIG((int) (l % 100));
  316. }
  317.