Print this page
    
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/ptools/ptime/ptime.c
          +++ new/usr/src/cmd/ptools/ptime/ptime.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   *
  25   25   * Portions Copyright 2008 Chad Mynhier
  26   26   */
  27   27  /*
  28   28   * Copyright 2016 Joyent, Inc.
  29   29   */
  30   30  
  31   31  #include <stdio.h>
  32   32  #include <stdlib.h>
  33   33  #include <unistd.h>
  34   34  #include <fcntl.h>
  35   35  #include <string.h>
  36   36  #include <errno.h>
  37   37  #include <math.h>
  38   38  #include <wait.h>
  39   39  #include <signal.h>
  40   40  #include <sys/types.h>
  41   41  #include <sys/time.h>
  42   42  #include <signal.h>
  43   43  #include <libproc.h>
  44   44  #include <limits.h>
  45   45  #include "ptools_common.h"
  46   46  
  47   47  static  int     look(pid_t);
  48   48  static  void    hr_min_sec(char *, long);
  49   49  static  void    prtime(char *, timestruc_t *);
  50   50  static  int     perr(const char *);
  51   51  
  52   52  static  void    tsadd(timestruc_t *result, timestruc_t *a, timestruc_t *b);
  53   53  static  void    tssub(timestruc_t *result, timestruc_t *a, timestruc_t *b);
  54   54  static  void    hrt2ts(hrtime_t hrt, timestruc_t *tsp);
  55   55  
  56   56  static  char    *command;
  57   57  static  char    *pidarg;
  58   58  static  char    procname[64];
  59   59  
  60   60  static  int     Fflag;
  61   61  static  int     mflag;
  62   62  static  int     errflg;
  63   63  static  int     pflag;
  64   64  static  int     pfirst;
  65   65  
  66   66  static int
  67   67  ptime_pid(const char *pidstr)
  68   68  {
  69   69          struct ps_prochandle *Pr;
  70   70          pid_t pid;
  71   71          int gret;
  72   72  
  73   73          if ((Pr = proc_arg_grab(pidstr, PR_ARG_PIDS,
  74   74              Fflag | PGRAB_RDONLY, &gret)) == NULL) {
  75   75                  (void) fprintf(stderr, "%s: cannot examine %s: %s\n",
  76   76                      command, pidstr, Pgrab_error(gret));
  77   77                  return (1);
  78   78          }
  79   79  
  80   80          pid = Pstatus(Pr)->pr_pid;
  81   81          (void) sprintf(procname, "%d", (int)pid);       /* for perr() */
  82   82          (void) look(pid);
  83   83          Prelease(Pr, 0);
  84   84          return (0);
  85   85  }
  86   86  
  87   87  int
  88   88  main(int argc, char **argv)
  89   89  {
  90   90          int opt, exit;
  91   91          pid_t pid;
  92   92          struct siginfo info;
  93   93          int status;
  94   94          int gret;
  95   95          struct ps_prochandle *Pr;
  96   96  
  97   97          if ((command = strrchr(argv[0], '/')) != NULL)
  98   98                  command++;
  99   99          else
 100  100                  command = argv[0];
 101  101  
 102  102          while ((opt = getopt(argc, argv, "Fhmp:")) != EOF) {
 103  103                  switch (opt) {
 104  104                  case 'F':               /* force grabbing (no O_EXCL) */
 105  105                          Fflag = PGRAB_FORCE;
 106  106                          break;
 107  107                  case 'm':               /* microstate accounting */
 108  108                          mflag = 1;
 109  109                          break;
 110  110                  case 'p':
 111  111                          pflag = 1;
 112  112                          pidarg = optarg;
 113  113                          break;
 114  114                  default:
 115  115                          errflg = 1;
 116  116                          break;
 117  117                  }
 118  118          }
 119  119  
 120  120          argc -= optind;
 121  121          argv += optind;
 122  122  
 123  123          if (((pidarg != NULL) ^ (argc < 1)) || errflg) {
 124  124                  (void) fprintf(stderr,
 125  125                      "usage:\t%s [-mh] [-p pidlist | command [ args ... ]]\n",
 126  126                      command);
 127  127                  (void) fprintf(stderr,
 128  128                      "  (time a command using microstate accounting)\n");
 129  129                  return (1);
 130  130          }
 131  131  
 132  132          if (pflag) {
 133  133                  char *pp;
 134  134  
 135  135                  exit = 0;
 136  136                  (void) signal(SIGINT, SIG_IGN);
 137  137                  (void) signal(SIGQUIT, SIG_IGN);
 138  138  
 139  139                  pp = strtok(pidarg, ", ");
 140  140                  if (pp == NULL) {
 141  141                          (void) fprintf(stderr, "%s: invalid argument for -p\n",
 142  142                              command);
 143  143                          return (1);
 144  144                  }
 145  145                  exit = ptime_pid(pp);
 146  146                  while ((pp = strtok(NULL, ", ")) != NULL) {
 147  147                          exit |= ptime_pid(pp);
 148  148                  }
 149  149                  return (exit);
 150  150          }
 151  151  
 152  152  
 153  153          if ((Pr = Pcreate(argv[0], &argv[0], &gret, NULL, 0)) == NULL) {
 154  154                  (void) fprintf(stderr, "%s: failed to exec %s: %s\n",
 155  155                      command, argv[0], Pcreate_error(gret));
 156  156                  return (1);
 157  157          }
 158  158          if (Psetrun(Pr, 0, 0) == -1) {
 159  159                  (void) fprintf(stderr, "%s: failed to set running %s: "
 160  160                      "%s\n", command, argv[0], strerror(errno));
 161  161                  return (1);
 162  162          }
 163  163  
 164  164          pid = Pstatus(Pr)->pr_pid;
 165  165  
 166  166          (void) sprintf(procname, "%d", (int)pid);       /* for perr() */
 167  167          (void) signal(SIGINT, SIG_IGN);
 168  168          (void) signal(SIGQUIT, SIG_IGN);
 169  169  
 170  170          (void) waitid(P_PID, pid, &info, WEXITED | WNOWAIT);
 171  171  
 172  172          (void) look(pid);
 173  173  
 174  174          (void) waitpid(pid, &status, 0);
 175  175  
 176  176          if (WIFEXITED(status))
 177  177                  return (WEXITSTATUS(status));
 178  178  
 179  179          if (WIFSIGNALED(status)) {
 180  180                  int sig = WTERMSIG(status);
 181  181                  char name[SIG2STR_MAX];
 182  182  
 183  183                  (void) fprintf(stderr, "%s: command terminated "
 184  184                      "abnormally by %s\n", command,
 185  185                      proc_signame(sig, name, sizeof (name)));
 186  186          }
 187  187  
 188  188          return (status | WCOREFLG); /* see time(1) */
 189  189  }
 190  190  
 191  191  static int
 192  192  look(pid_t pid)
 193  193  {
 194  194          char pathname[PATH_MAX];
 195  195          int rval = 0;
 196  196          int fd;
 197  197          psinfo_t psinfo;
 198  198          prusage_t prusage;
 199  199          timestruc_t real, user, sys;
 200  200          hrtime_t hrtime;
 201  201          prusage_t *pup = &prusage;
 202  202  
 203  203          pfirst++;
 204  204  
 205  205          if (proc_get_psinfo(pid, &psinfo) < 0)
 206  206                  return (perr("read psinfo"));
 207  207  
 208  208          (void) proc_snprintf(pathname, sizeof (pathname), "/proc/%d/usage",
 209  209              (int)pid);
 210  210          if ((fd = open(pathname, O_RDONLY)) < 0)
 211  211                  return (perr("open usage"));
 212  212  
 213  213          if (read(fd, &prusage, sizeof (prusage)) != sizeof (prusage))
 214  214                  rval = perr("read usage");
 215  215          else {
 216  216                  if (pidarg) {
 217  217                          hrtime = gethrtime();
 218  218                          hrt2ts(hrtime, &real);
 219  219                  } else {
 220  220                          real = pup->pr_term;
 221  221                  }
 222  222                  tssub(&real, &real, &pup->pr_create);
 223  223                  user = pup->pr_utime;
 224  224                  sys = pup->pr_stime;
 225  225                  if (!mflag)
 226  226                          tsadd(&sys, &sys, &pup->pr_ttime);
 227  227  
 228  228                  if (!pflag || pfirst > 1)
 229  229                          (void) fprintf(stderr, "\n");
 230  230                  if (pflag)
 231  231                          (void) fprintf(stderr, "%d:\t%.70s\n",
 232  232                              (int)psinfo.pr_pid, psinfo.pr_psargs);
 233  233                  prtime("real", &real);
 234  234                  prtime("user", &user);
 235  235                  prtime("sys", &sys);
 236  236  
 237  237                  if (mflag) {
 238  238                          prtime("trap", &pup->pr_ttime);
 239  239                          prtime("tflt", &pup->pr_tftime);
 240  240                          prtime("dflt", &pup->pr_dftime);
 241  241                          prtime("kflt", &pup->pr_kftime);
 242  242                          prtime("lock", &pup->pr_ltime);
 243  243                          prtime("slp", &pup->pr_slptime);
 244  244                          prtime("lat", &pup->pr_wtime);
 245  245                          prtime("stop", &pup->pr_stoptime);
 246  246                  }
 247  247          }
 248  248  
 249  249          (void) close(fd);
 250  250          return (rval);
 251  251  }
 252  252  
 253  253  static void
 254  254  hr_min_sec(char *buf, long sec)
 255  255  {
 256  256          if (sec >= 3600)
 257  257                  (void) sprintf(buf, "%ld:%.2ld:%.2ld",
 258  258                      sec / 3600, (sec % 3600) / 60, sec % 60);
 259  259          else if (sec >= 60)
 260  260                  (void) sprintf(buf, "%ld:%.2ld",
 261  261                      sec / 60, sec % 60);
 262  262          else
 263  263                  (void) sprintf(buf, "%ld", sec);
 264  264  }
 265  265  
 266  266  static void
 267  267  prtime(char *name, timestruc_t *ts)
 268  268  {
 269  269          char buf[32];
 270  270  
 271  271          hr_min_sec(buf, ts->tv_sec);
 272  272  
 273  273          (void) fprintf(stderr, "%-4s %8s.%.9u\n",
 274  274              name, buf, (uint_t)ts->tv_nsec);
 275  275  }
 276  276  
 277  277  static int
 278  278  perr(const char *s)
 279  279  {
 280  280          if (s)
 281  281                  (void) fprintf(stderr, "%s: ", procname);
 282  282          else
 283  283                  s = procname;
 284  284          perror(s);
 285  285          return (1);
 286  286  }
 287  287  
 288  288  static  void
 289  289  tsadd(timestruc_t *result, timestruc_t *a, timestruc_t *b)
 290  290  {
 291  291          result->tv_sec = a->tv_sec + b->tv_sec;
 292  292          if ((result->tv_nsec = a->tv_nsec + b->tv_nsec) >= 1000000000) {
 293  293                  result->tv_nsec -= 1000000000;
 294  294                  result->tv_sec += 1;
 295  295          }
 296  296  }
 297  297  
 298  298  static  void
 299  299  tssub(timestruc_t *result, timestruc_t *a, timestruc_t *b)
 300  300  {
 301  301          result->tv_sec = a->tv_sec - b->tv_sec;
 302  302          if ((result->tv_nsec = a->tv_nsec - b->tv_nsec) < 0) {
 303  303                  result->tv_nsec += 1000000000;
 304  304                  result->tv_sec -= 1;
 305  305          }
 306  306  }
 307  307  
 308  308  static void
 309  309  hrt2ts(hrtime_t hrt, timestruc_t *tsp)
 310  310  {
 311  311          tsp->tv_sec = hrt / NANOSEC;
 312  312          tsp->tv_nsec = hrt % NANOSEC;
 313  313  }
  
    | 
      ↓ open down ↓ | 
    313 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX