Print this page
8158 Want named threads API
9857 proc manpages should have LIBRARY section

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/mdb/common/modules/genunix/thread.c
          +++ new/usr/src/cmd/mdb/common/modules/genunix/thread.c
↓ open down ↓ 16 lines elided ↑ open up ↑
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
  25   25  /*
  26   26   * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
       27 + * Copyright (c) 2018, Joyent, Inc.
  27   28   */
  28   29  
  29   30  
  30   31  #include <mdb/mdb_modapi.h>
  31   32  #include <mdb/mdb_ks.h>
       33 +#include <mdb/mdb_ctf.h>
  32   34  #include <sys/types.h>
  33   35  #include <sys/thread.h>
  34   36  #include <sys/lwp.h>
  35   37  #include <sys/proc.h>
  36   38  #include <sys/cpuvar.h>
  37   39  #include <sys/cpupart.h>
  38   40  #include <sys/disp.h>
  39   41  #include <sys/taskq_impl.h>
  40   42  #include <sys/stack.h>
       43 +#include "thread.h"
  41   44  
  42   45  #ifndef STACK_BIAS
  43   46  #define STACK_BIAS      0
  44   47  #endif
  45   48  
  46   49  typedef struct thread_walk {
  47   50          kthread_t *tw_thread;
  48   51          uintptr_t tw_last;
  49   52          uint_t tw_inproc;
  50   53          uint_t tw_step;
↓ open down ↓ 503 lines elided ↑ open up ↑
 554  557              "\t-b\tprint blocked thread state\n"
 555  558              "\t-d\tprint dispatcher state\n"
 556  559              "\t-f\tignore freed threads\n"
 557  560              "\t-i\tprint basic thread state (default)\n"
 558  561              "\t-m\tdisplay results on a single line\n"
 559  562              "\t-p\tprint process and lwp state\n"
 560  563              "\t-s\tprint signal state\n");
 561  564  }
 562  565  
 563  566  /*
      567 + * Return a string description of the thread, including the ID and the thread
      568 + * name.
      569 + *
      570 + * If ->t_name is NULL, and we're a system thread, we'll do a little more
      571 + * spelunking to find a useful string to return.
      572 + */
      573 +int
      574 +thread_getdesc(uintptr_t addr, boolean_t include_comm,
      575 +    char *buf, size_t bufsize)
      576 +{
      577 +        char name[THREAD_NAME_MAX] = "";
      578 +        kthread_t t;
      579 +        proc_t p;
      580 +
      581 +        bzero(buf, bufsize);
      582 +
      583 +        if (mdb_vread(&t, sizeof (kthread_t), addr) == -1) {
      584 +                mdb_warn("failed to read kthread_t at %p", addr);
      585 +                return (-1);
      586 +        }
      587 +
      588 +        if (t.t_tid == 0) {
      589 +                taskq_t tq;
      590 +
      591 +                if (mdb_vread(&tq, sizeof (taskq_t),
      592 +                    (uintptr_t)t.t_taskq) == -1)
      593 +                        tq.tq_name[0] = '\0';
      594 +
      595 +                if (t.t_name != NULL) {
      596 +                        if (mdb_readstr(buf, bufsize,
      597 +                            (uintptr_t)t.t_name) == -1) {
      598 +                                mdb_warn("error reading thread name");
      599 +                        }
      600 +                } else if (tq.tq_name[0] != '\0') {
      601 +                        (void) mdb_snprintf(buf, bufsize, "tq:%s", tq.tq_name);
      602 +                } else {
      603 +                        mdb_snprintf(buf, bufsize, "%a()", t.t_startpc);
      604 +                }
      605 +
      606 +                return (buf[0] == '\0' ? -1 : 0);
      607 +        }
      608 +
      609 +        if (include_comm && mdb_vread(&p, sizeof (proc_t),
      610 +            (uintptr_t)t.t_procp) == -1) {
      611 +                mdb_warn("failed to read proc at %p", t.t_procp);
      612 +                return (-1);
      613 +        }
      614 +
      615 +        if (t.t_name != NULL) {
      616 +                if (mdb_readstr(name, sizeof (name), (uintptr_t)t.t_name) == -1)
      617 +                        mdb_warn("error reading thread name");
      618 +
      619 +                /*
      620 +                 * Just to be safe -- if mdb_readstr() succeeds, it always NUL
      621 +                 * terminates the output, but is unclear what it does on
      622 +                 * failure.  In that case we attempt to show any partial content
      623 +                 * w/ the warning in case it's useful, but explicitly
      624 +                 * NUL-terminate to be safe.
      625 +                 */
      626 +                buf[bufsize - 1] = '\0';
      627 +        }
      628 +
      629 +        if (name[0] != '\0') {
      630 +                if (include_comm) {
      631 +                        (void) mdb_snprintf(buf, bufsize, "%s/%u [%s]",
      632 +                            p.p_user.u_comm, t.t_tid, name);
      633 +                } else {
      634 +                        (void) mdb_snprintf(buf, bufsize, "%u [%s]",
      635 +                            t.t_tid, name);
      636 +                }
      637 +        } else {
      638 +                if (include_comm) {
      639 +                        (void) mdb_snprintf(buf, bufsize, "%s/%u",
      640 +                            p.p_user.u_comm, t.t_tid);
      641 +                } else {
      642 +                        (void) mdb_snprintf(buf, bufsize, "%u", t.t_tid);
      643 +                }
      644 +        }
      645 +
      646 +        return (buf[0] == '\0' ? -1 : 0);
      647 +}
      648 +
      649 +/*
 564  650   * List a combination of kthread_t and proc_t. Add stack traces in verbose mode.
 565  651   */
 566  652  int
 567  653  threadlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 568  654  {
 569  655          int i;
 570  656          uint_t count =  0;
 571  657          uint_t verbose = FALSE;
 572  658          uint_t notaskq = FALSE;
 573  659          kthread_t t;
 574      -        taskq_t tq;
 575      -        proc_t p;
 576  660          char cmd[80];
 577  661          mdb_arg_t cmdarg;
 578  662  
 579  663          if (!(flags & DCMD_ADDRSPEC)) {
 580  664                  if (mdb_walk_dcmd("thread", "threadlist", argc, argv) == -1) {
 581  665                          mdb_warn("can't walk threads");
 582  666                          return (DCMD_ERR);
 583  667                  }
 584  668                  return (DCMD_OK);
 585  669          }
↓ open down ↓ 25 lines elided ↑ open up ↑
 611  695                  mdb_warn("failed to read kthread_t at %p", addr);
 612  696                  return (DCMD_ERR);
 613  697          }
 614  698  
 615  699          if (notaskq && t.t_taskq != NULL)
 616  700                  return (DCMD_OK);
 617  701  
 618  702          if (t.t_state == TS_FREE)
 619  703                  return (DCMD_OK);
 620  704  
 621      -        if (mdb_vread(&p, sizeof (proc_t), (uintptr_t)t.t_procp) == -1) {
 622      -                mdb_warn("failed to read proc at %p", t.t_procp);
 623      -                return (DCMD_ERR);
 624      -        }
      705 +        if (!verbose) {
      706 +                char desc[128];
 625  707  
 626      -        if (mdb_vread(&tq, sizeof (taskq_t), (uintptr_t)t.t_taskq) == -1)
 627      -                tq.tq_name[0] = '\0';
      708 +                if (thread_getdesc(addr, B_TRUE, desc, sizeof (desc)) == -1)
      709 +                        return (DCMD_ERR);
 628  710  
 629      -        if (verbose) {
 630      -                mdb_printf("%0?p %?p %?p %3u %3d %?p\n",
 631      -                    addr, t.t_procp, t.t_lwp, t.t_cid, t.t_pri, t.t_wchan);
      711 +                mdb_printf("%0?p %?p %?p %s\n", addr, t.t_procp, t.t_lwp, desc);
      712 +                return (DCMD_OK);
      713 +        }
 632  714  
 633      -                mdb_inc_indent(2);
      715 +        mdb_printf("%0?p %?p %?p %3u %3d %?p\n",
      716 +            addr, t.t_procp, t.t_lwp, t.t_cid, t.t_pri, t.t_wchan);
 634  717  
 635      -                mdb_printf("PC: %a", t.t_pc);
 636      -                if (t.t_tid == 0) {
 637      -                        if (tq.tq_name[0] != '\0')
 638      -                                mdb_printf("    TASKQ: %s\n", tq.tq_name);
 639      -                        else
 640      -                                mdb_printf("    THREAD: %a()\n", t.t_startpc);
 641      -                } else {
 642      -                        mdb_printf("    CMD: %s\n", p.p_user.u_psargs);
 643      -                }
      718 +        mdb_inc_indent(2);
 644  719  
 645      -                mdb_snprintf(cmd, sizeof (cmd), "<.$c%d", count);
 646      -                cmdarg.a_type = MDB_TYPE_STRING;
 647      -                cmdarg.a_un.a_str = cmd;
      720 +        mdb_printf("PC: %a\n", t.t_pc);
 648  721  
 649      -                (void) mdb_call_dcmd("findstack", addr, flags, 1, &cmdarg);
      722 +        mdb_snprintf(cmd, sizeof (cmd), "<.$c%d", count);
      723 +        cmdarg.a_type = MDB_TYPE_STRING;
      724 +        cmdarg.a_un.a_str = cmd;
 650  725  
 651      -                mdb_dec_indent(2);
      726 +        (void) mdb_call_dcmd("findstack", addr, flags, 1, &cmdarg);
 652  727  
 653      -                mdb_printf("\n");
 654      -        } else {
 655      -                mdb_printf("%0?p %?p %?p", addr, t.t_procp, t.t_lwp);
 656      -                if (t.t_tid == 0) {
 657      -                        if (tq.tq_name[0] != '\0')
 658      -                                mdb_printf(" tq:%s\n", tq.tq_name);
 659      -                        else
 660      -                                mdb_printf(" %a()\n", t.t_startpc);
 661      -                } else {
 662      -                        mdb_printf(" %s/%u\n", p.p_user.u_comm, t.t_tid);
 663      -                }
 664      -        }
      728 +        mdb_dec_indent(2);
 665  729  
      730 +        mdb_printf("\n");
      731 +
 666  732          return (DCMD_OK);
 667  733  }
 668  734  
 669  735  void
 670  736  threadlist_help(void)
 671  737  {
 672  738          mdb_printf(
 673  739              "   -v         print verbose output including C stack trace\n"
 674  740              "   -t         skip threads belonging to a taskq\n"
 675  741              "   count      print no more than count arguments (default 0)\n");
↓ open down ↓ 33 lines elided ↑ open up ↑
 709  775          return (percent);
 710  776  }
 711  777  
 712  778  /*
 713  779   * Display kthread stack infos.
 714  780   */
 715  781  int
 716  782  stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 717  783  {
 718  784          kthread_t t;
 719      -        proc_t p;
 720  785          uint64_t *ptr;  /* pattern pointer */
 721  786          caddr_t start;  /* kernel stack start */
 722  787          caddr_t end;    /* kernel stack end */
 723  788          caddr_t ustack; /* userland copy of kernel stack */
 724  789          size_t usize;   /* userland copy of kernel stack size */
 725  790          caddr_t ustart; /* userland copy of kernel stack, aligned start */
 726  791          caddr_t uend;   /* userland copy of kernel stack, aligned end */
 727  792          size_t percent = 0;
 728  793          uint_t all = FALSE; /* don't show TS_FREE kthread by default */
 729  794          uint_t history = FALSE;
 730  795          int i = 0;
 731  796          unsigned int ukmem_stackinfo;
 732  797          uintptr_t allthreads;
      798 +        char tdesc[128] = "";
 733  799  
 734  800          /* handle options */
 735  801          if (mdb_getopts(argc, argv,
 736  802              'a', MDB_OPT_SETBITS, TRUE, &all,
 737  803              'h', MDB_OPT_SETBITS, TRUE, &history, NULL) != argc) {
 738  804                  return (DCMD_USAGE);
 739  805          }
 740  806  
 741  807          /* walk all kthread if needed */
 742  808          if ((history == FALSE) && !(flags & DCMD_ADDRSPEC)) {
↓ open down ↓ 25 lines elided ↑ open up ↑
 768  834                  mdb_printf("Dead kthreads stack usage history:\n");
 769  835                  if (ukmem_stackinfo == 0) {
 770  836                          mdb_printf("Tunable kmem_stackinfo is unset, history ");
 771  837                          mdb_printf("feature is off.\nUse ::help stackinfo ");
 772  838                          mdb_printf("for more details.\n");
 773  839                          return (DCMD_OK);
 774  840                  }
 775  841  
 776  842                  mdb_printf("%<u>%?s%</u>", "THREAD");
 777  843                  mdb_printf(" %<u>%?s%</u>", "STACK");
 778      -                mdb_printf("%<u>%s%</u>", "   SIZE  MAX CMD/LWPID or STARTPC");
      844 +                mdb_printf("%<u>%s%</u>", "   SIZE  MAX LWP");
 779  845                  mdb_printf("\n");
 780  846                  usize = KMEM_STKINFO_LOG_SIZE * sizeof (kmem_stkinfo_t);
 781  847                  log = (kmem_stkinfo_t *)mdb_alloc(usize, UM_SLEEP);
 782  848                  if (mdb_readsym(&kaddr, sizeof (kaddr),
 783  849                      "kmem_stkinfo_log") == -1) {
 784  850                          mdb_free((void *)log, usize);
 785  851                          mdb_warn("failed to read 'kmem_stkinfo_log'\n");
 786  852                          return (DCMD_ERR);
 787  853                  }
 788  854                  if (kaddr == NULL) {
↓ open down ↓ 2 lines elided ↑ open up ↑
 791  857                  }
 792  858                  if (mdb_vread(log, usize, kaddr) == -1) {
 793  859                          mdb_free((void *)log, usize);
 794  860                          mdb_warn("failed to read %p\n", kaddr);
 795  861                          return (DCMD_ERR);
 796  862                  }
 797  863                  for (i = 0; i < KMEM_STKINFO_LOG_SIZE; i++) {
 798  864                          if (log[i].kthread == NULL) {
 799  865                                  continue;
 800  866                          }
 801      -                        mdb_printf("%0?p %0?p %6x %3d%%",
      867 +
      868 +                        (void) thread_getdesc((uintptr_t)log[i].kthread,
      869 +                            B_TRUE, tdesc, sizeof (tdesc));
      870 +
      871 +                        mdb_printf("%0?p %0?p %6x %3d%% %s\n",
 802  872                              log[i].kthread,
 803  873                              log[i].start,
 804  874                              (uint_t)log[i].stksz,
 805      -                            (int)log[i].percent);
 806      -                        if (log[i].t_tid != 0) {
 807      -                                mdb_printf(" %s/%u\n",
 808      -                                    log[i].cmd, log[i].t_tid);
 809      -                        } else {
 810      -                                mdb_printf(" %p (%a)\n", log[i].t_startpc,
 811      -                                    log[i].t_startpc);
 812      -                        }
      875 +                            (int)log[i].percent, tdesc);
 813  876                  }
 814  877                  mdb_free((void *)log, usize);
 815  878                  return (DCMD_OK);
 816  879          }
 817  880  
 818  881          /* display header */
 819  882          if (DCMD_HDRSPEC(flags)) {
 820  883                  if (ukmem_stackinfo == 0) {
 821  884                          mdb_printf("Tunable kmem_stackinfo is unset, ");
 822  885                          mdb_printf("MAX value is not available.\n");
 823  886                          mdb_printf("Use ::help stackinfo for more details.\n");
 824  887                  }
 825  888                  mdb_printf("%<u>%?s%</u>", "THREAD");
 826  889                  mdb_printf(" %<u>%?s%</u>", "STACK");
 827      -                mdb_printf("%<u>%s%</u>", "   SIZE  CUR  MAX CMD/LWPID");
      890 +                mdb_printf("%<u>%s%</u>", "   SIZE  CUR  MAX LWP");
 828  891                  mdb_printf("\n");
 829  892          }
 830  893  
 831  894          /* read kthread */
 832  895          if (mdb_vread(&t, sizeof (kthread_t), addr) == -1) {
 833  896                  mdb_warn("can't read kthread_t at %#lx\n", addr);
 834  897                  return (DCMD_ERR);
 835  898          }
 836  899  
 837  900          if (t.t_state == TS_FREE && all == FALSE) {
 838  901                  return (DCMD_OK);
 839  902          }
 840  903  
 841      -        /* read proc */
 842      -        if (mdb_vread(&p, sizeof (proc_t), (uintptr_t)t.t_procp) == -1) {
 843      -                mdb_warn("failed to read proc at %p\n", t.t_procp);
 844      -                return (DCMD_ERR);
 845      -        }
 846      -
 847  904          /*
 848  905           * Stack grows up or down, see thread_create(),
 849  906           * compute stack memory aera start and end (start < end).
 850  907           */
 851  908          if (t.t_stk > t.t_stkbase) {
 852  909                  /* stack grows down */
 853  910                  start = t.t_stkbase;
 854  911                  end = t.t_stk;
 855  912          } else {
 856  913                  /* stack grows up */
↓ open down ↓ 14 lines elided ↑ open up ↑
 871  928          /* display stack size */
 872  929          mdb_printf(" %6x", end - start);
 873  930  
 874  931          /* display current stack usage */
 875  932          percent = stk_compute_percent(t.t_stk, t.t_stkbase,
 876  933              (caddr_t)t.t_sp + STACK_BIAS);
 877  934  
 878  935          mdb_printf(" %3d%%", percent);
 879  936          percent = 0;
 880  937  
      938 +        (void) thread_getdesc(addr, B_TRUE, tdesc, sizeof (tdesc));
      939 +
 881  940          if (ukmem_stackinfo == 0) {
 882      -                mdb_printf("  n/a");
 883      -                if (t.t_tid == 0) {
 884      -                        mdb_printf(" %a()", t.t_startpc);
 885      -                } else {
 886      -                        mdb_printf(" %s/%u", p.p_user.u_comm, t.t_tid);
 887      -                }
 888      -                mdb_printf("\n");
      941 +                mdb_printf("  n/a %s\n", tdesc);
 889  942                  return (DCMD_OK);
 890  943          }
 891  944  
 892  945          if ((((uintptr_t)start) & 0x7) != 0) {
 893  946                  start = (caddr_t)((((uintptr_t)start) & (~0x7)) + 8);
 894  947          }
 895  948          end = (caddr_t)(((uintptr_t)end) & (~0x7));
 896  949          /* size to scan in userland copy of kernel stack */
 897  950          usize = end - start; /* is a multiple of 8 bytes */
 898  951  
↓ open down ↓ 52 lines elided ↑ open up ↑
 951 1004  
 952 1005          /* thread 't0' stack is not created by thread_create() */
 953 1006          if (addr == allthreads) {
 954 1007                  percent = 0;
 955 1008          }
 956 1009          if (percent != 0) {
 957 1010                  mdb_printf(" %3d%%", percent);
 958 1011          } else {
 959 1012                  mdb_printf("  n/a");
 960 1013          }
 961      -        if (t.t_tid == 0) {
 962      -                mdb_printf(" %a()", t.t_startpc);
 963      -        } else {
 964      -                mdb_printf(" %s/%u", p.p_user.u_comm, t.t_tid);
 965      -        }
 966      -        mdb_printf("\n");
     1014 +
     1015 +        mdb_printf(" %s\n", tdesc);
     1016 +
 967 1017          mdb_free((void *)ustack, usize + 8);
 968 1018          return (DCMD_OK);
 969 1019  }
 970 1020  
 971 1021  void
 972 1022  stackinfo_help(void)
 973 1023  {
 974 1024          mdb_printf(
 975 1025              "Shows kernel stacks real utilization, if /etc/system "
 976 1026              "kmem_stackinfo tunable\n");
 977 1027          mdb_printf(
 978 1028              "(an unsigned integer) is non zero at kthread creation time. ");
 979 1029          mdb_printf("For example:\n");
 980 1030          mdb_printf(
 981      -            "          THREAD            STACK   SIZE  CUR  MAX CMD/LWPID\n");
     1031 +            "          THREAD            STACK   SIZE  CUR  MAX LWP\n");
 982 1032          mdb_printf(
 983 1033              "ffffff014f5f2c20 ffffff0004153000   4f00   4%%  43%% init/1\n");
 984 1034          mdb_printf(
 985 1035              "The stack size utilization for this kthread is at 4%%"
 986 1036              " of its maximum size,\n");
 987 1037          mdb_printf(
 988 1038              "but has already used up to 43%%, stack size is 4f00 bytes.\n");
 989 1039          mdb_printf(
 990 1040              "MAX value can be shown as n/a (not available):\n");
 991 1041          mdb_printf(
↓ open down ↓ 3 lines elided ↑ open up ↑
 995 1045          mdb_printf(
 996 1046              "  - kthread has not yet run\n");
 997 1047          mdb_printf("\n");
 998 1048          mdb_printf("Options:\n");
 999 1049          mdb_printf(
1000 1050              "-a shows also TS_FREE kthreads (interrupt kthreads)\n");
1001 1051          mdb_printf(
1002 1052              "-h shows history, dead kthreads that used their "
1003 1053              "kernel stack the most\n");
1004 1054          mdb_printf(
1005      -            "\nSee Solaris Modular Debugger Guide for detailed usage.\n");
     1055 +            "\nSee illumos Modular Debugger Guide for detailed usage.\n");
1006 1056          mdb_flush();
1007 1057  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX