Print this page
6535 Add pbind -e
Reviewed by: Mohamed Khalfella <khalfella@gmail.com>
Reviewed by: Cody Mello <melloc@joyent.com>
Reviewed by: Albert Lee <trisk@omniti.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/pbind/pbind.c
          +++ new/usr/src/cmd/pbind/pbind.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   *
  14   14   * When distributing Covered Code, include this CDDL HEADER in each
  15   15   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16   16   * If applicable, add the following below this CDDL HEADER, with the
  17   17   * fields enclosed by brackets "[]" replaced with your own identifying
  18   18   * information: Portions Copyright [yyyy] [name of copyright owner]
  19   19   *
  20   20   * CDDL HEADER END
  21   21   */
  22   22  /*
       23 + * Copyright 2015 Ryan Zezeski
  23   24   * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  24   25   * Use is subject to license terms.
  25   26   */
  26   27  
  27      -#pragma ident   "%Z%%M% %I%     %E% SMI"
  28      -
  29   28  /*
  30   29   * pbind - bind a process to a processor (non-exclusively)
  31   30   */
  32   31  
  33   32  #include <sys/types.h>
  34   33  #include <sys/procset.h>
  35   34  #include <sys/processor.h>
  36   35  #include <stdio.h>
  37   36  #include <stdlib.h>
  38   37  #include <string.h>
↓ open down ↓ 8 lines elided ↑ open up ↑
  47   46  #if !defined(TEXT_DOMAIN)               /* should be defined by cc -D */
  48   47  #define TEXT_DOMAIN     "SYS_TEST"      /* Use this only if it weren't */
  49   48  #endif
  50   49  
  51   50  #define ERR_OK          0               /* exit status for success */
  52   51  #define ERR_FAIL        1               /* exit status for errors */
  53   52  #define ERR_USAGE       2               /* exit status for usage errors */
  54   53  
  55   54  static char     *progname;
  56   55  static char     bflag;
       56 +static char     eflag;
  57   57  static char     qflag;
  58   58  static char     Qflag;
  59   59  static char     uflag;
  60   60  static char     Uflag;
  61   61  static int      errors;
  62   62  
  63   63  #define MAX_PROCFS_PATH 80
  64   64  
  65   65  /*PRINTFLIKE1*/
  66   66  static void
↓ open down ↓ 91 lines elided ↑ open up ↑
 158  158                  (void) snprintf(pidstr, 20, "%d", (int)pid);
 159  159                  proclwp = "process";
 160  160          } else {
 161  161                  (void) snprintf(pidstr, 20, "%d/%d", (int)pid, (int)lwpid);
 162  162                  proclwp = "lwp";
 163  163          }
 164  164  
 165  165          if (old == PBIND_NONE) {
 166  166                  if (new == PBIND_NONE)
 167  167                          (void) printf(gettext("%s id %s: was not bound, "
 168      -                                "now not bound\n"), proclwp, pidstr);
      168 +                            "now not bound\n"), proclwp, pidstr);
 169  169                  else
 170  170                          (void) printf(gettext("%s id %s: was not bound, "
 171      -                                "now %d\n"), proclwp, pidstr, new);
      171 +                            "now %d\n"), proclwp, pidstr, new);
 172  172          } else {
 173  173                  if (new == PBIND_NONE)
 174  174                          (void) printf(gettext("%s id %s: was %d, "
 175      -                                "now not bound\n"), proclwp, pidstr, old);
      175 +                            "now not bound\n"), proclwp, pidstr, old);
 176  176                  else
 177  177                          (void) printf(gettext("%s id %s: was %d, "
 178      -                                "now %d\n"), proclwp, pidstr, old, new);
      178 +                            "now %d\n"), proclwp, pidstr, old, new);
 179  179          }
 180  180  }
 181  181  
 182  182  static struct ps_prochandle *
 183  183  grab_proc(id_t pid)
 184  184  {
 185  185          int ret;
 186  186          struct ps_prochandle *Pr;
 187  187  
 188  188          if ((Pr = Pgrab(pid, 0, &ret)) == NULL) {
↓ open down ↓ 149 lines elided ↑ open up ↑
 338  338          processorid_t binding = lwpsinfo->pr_bindpro;
 339  339  
 340  340          if (psinfo->pr_nlwp == 1)
 341  341                  lwpid = -1;     /* report process bindings if only 1 lwp */
 342  342          if ((cpuid != NULL && *cpuid == binding) ||
 343  343              (cpuid == NULL && binding != PBIND_NONE))
 344  344                  query_out(pid, lwpid, binding);
 345  345          return (0);
 346  346  }
 347  347  
      348 +/*
      349 + * Execute the cmd with args while bound to cpu. Does not return:
      350 + * either executes cmd successfully or dies trying.
      351 + */
      352 +static void
      353 +exec_cmd(processorid_t cpu, char *cmd, char **args)
      354 +{
      355 +        if (processor_bind(P_PID, P_MYID, cpu, NULL) == -1) {
      356 +                bind_err(cpu, getpid(), -1, errno);
      357 +                exit(ERR_FAIL);
      358 +        }
      359 +
      360 +        if (execvp(cmd, args) == -1)
      361 +                die(gettext("failed to exec %s\n"), cmd);
      362 +}
      363 +
      364 +/*
      365 + * Attempt to parse str as a CPU identifier. Return the identifier or
      366 + * die.
      367 + */
      368 +static processorid_t
      369 +parse_cpu(char *str)
      370 +{
      371 +        processorid_t cpu;
      372 +        char *endstr;
      373 +
      374 +        cpu = strtol(str, &endstr, 10);
      375 +        if (endstr != NULL && *endstr != '\0' || cpu < 0)
      376 +                die(gettext("invalid processor ID %s\n"), optarg);
      377 +
      378 +        return (cpu);
      379 +}
      380 +
 348  381  static int
 349  382  usage(void)
 350  383  {
 351  384          (void) fprintf(stderr,
 352  385              gettext("usage: \n\t%1$s -b processor_id pid[/lwpids] ...\n"
      386 +            "\t%1$s -e processor_id cmd [args...]\n"
 353  387              "\t%1$s -U [processor_id] ...\n"
 354  388              "\t%1$s -Q [processor_id] ...\n"
 355  389              "\t%1$s -u pid[/lwpids] ...\n"
 356  390              "\t%1$s [-q] [pid[/lwpids] ...]\n"),
 357  391              progname);
 358  392          return (ERR_USAGE);
 359  393  }
 360  394  
 361  395  int
 362  396  main(int argc, char *argv[])
↓ open down ↓ 2 lines elided ↑ open up ↑
 365  399          int ret;
 366  400          id_t pid;
 367  401          processorid_t cpu, old_cpu;
 368  402          char *endstr;
 369  403  
 370  404          progname = argv[0];     /* put actual command name in messages */
 371  405  
 372  406          (void) setlocale(LC_ALL, "");   /* setup localization */
 373  407          (void) textdomain(TEXT_DOMAIN);
 374  408  
 375      -        while ((c = getopt(argc, argv, "b:qQuU")) != EOF) {
      409 +        while ((c = getopt(argc, argv, "b:e:qQuU")) != EOF) {
 376  410                  switch (c) {
 377  411  
 378  412                  case 'b':
 379  413                          bflag = 1;
 380      -                        cpu = strtol(optarg, &endstr, 10);
 381      -                        if (endstr != NULL && *endstr != '\0' || cpu < 0)
 382      -                                die(gettext("invalid processor ID %s\n"),
 383      -                                    optarg);
      414 +                        cpu = parse_cpu(optarg);
 384  415                          break;
 385  416  
      417 +                case 'e':
      418 +                        eflag = 1;
      419 +                        cpu = parse_cpu(optarg);
      420 +                        break;
      421 +
 386  422                  case 'q':
 387  423                          qflag = 1;
 388  424                          cpu = PBIND_QUERY;
 389  425                          break;
 390  426  
 391  427                  case 'Q':
 392  428                          Qflag = 1;
 393  429                          cpu = PBIND_QUERY;
 394  430                          break;
 395  431  
↓ open down ↓ 6 lines elided ↑ open up ↑
 402  438                          Uflag = 1;
 403  439                          break;
 404  440  
 405  441                  default:
 406  442                          return (usage());
 407  443                  }
 408  444          }
 409  445  
 410  446  
 411  447          /*
 412      -         * Make sure that at most one of the options b, q, Q, u, or U
 413      -         * was specified.
      448 +         * Make sure that at most one of the options b, e, q, Q, u, or
      449 +         * U was specified.
 414  450           */
 415      -        c = bflag + qflag + Qflag + uflag + Uflag;
      451 +        c = bflag + eflag + qflag + Qflag + uflag + Uflag;
 416  452          if (c < 1) {                            /* nothing specified */
 417  453                  qflag = 1;                      /* default to query */
 418  454                  cpu = PBIND_QUERY;
 419  455          } else if (c > 1) {
 420      -                warn(gettext("options -b, -q, -Q, -u and -U "
      456 +                warn(gettext("options -b, -e, -q, -Q, -u and -U "
 421  457                      "are mutually exclusive\n"));
 422  458                  return (usage());
 423  459          }
 424  460  
 425  461          errors = 0;
 426  462          argc -= optind;
 427  463          argv += optind;
 428  464  
 429  465          /*
 430  466           * Handle query of all processes.
 431  467           */
 432  468          if (argc == 0) {
 433  469                  if (bflag || uflag) {
 434  470                          warn(gettext("must specify at least one pid\n"));
 435  471                          return (usage());
 436  472                  }
      473 +                if (eflag) {
      474 +                        warn(gettext("must specify command\n"));
      475 +                        return (usage());
      476 +                }
 437  477                  if (Uflag) {
 438  478                          if (processor_bind(P_ALL, 0, PBIND_NONE, &old_cpu) != 0)
 439  479                                  die(gettext("failed to unbind some LWPs"));
 440  480                  }
 441  481                  if (Qflag) {
 442  482                          (void) proc_walk(query_all_lwp, NULL, PR_WALK_LWP);
 443  483                          return (errors);
 444  484                  } else {
 445  485                          (void) proc_walk(query_all_proc, NULL, PR_WALK_PROC);
 446  486                          return (errors);
 447  487                  }
 448  488          }
 449  489  
      490 +        if (eflag)
      491 +                exec_cmd(cpu, argv[0], argv);
      492 +
 450  493          if (Qflag || Uflag) {
 451  494                  /*
 452  495                   * Go through listed processor IDs.
 453  496                   */
 454  497                  for (; argc > 0; argv++, argc--) {
 455  498                          errno = 0;
 456  499                          cpu = (id_t)strtol(*argv, &endstr, 10);
 457  500                          if (errno != 0 || (endstr != NULL && *endstr != '\0') ||
 458  501                              p_online(cpu, P_STATUS) == -1) {
 459  502                                  warn(gettext("invalid processor ID\n"));
↓ open down ↓ 67 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX