New/Usr/Src/Cmd/Mdb/Common
Total Page:16
File Type:pdf, Size:1020Kb
new/usr/src/cmd/mdb/common/modules/genunix/findstack.c 1 new/usr/src/cmd/mdb/common/modules/genunix/findstack.c 2 ********************************************************** 642 return (DCMD_USAGE); 21346 Thu Feb 18 08:40:37 2016 new/usr/src/cmd/mdb/common/modules/genunix/findstack.c 644 if (interesting) { 6583 remove whole-process swapping 645 if (sobj != NULL || excl_sobj != NULL || ********************************************************** 646 tstate_str != NULL || excl_tstate_str != NULL) { ______unchanged_portion_omitted_ 647 mdb_warn( 648 "stacks: -i is incompatible with -[sStT]\n"); 583 /*ARGSUSED*/ 649 return (DCMD_USAGE); 584 int 650 } 585 stacks(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 651 excl_sobj = "CV"; 586 { 652 excl_tstate_str = "FREE"; 587 size_t idx; 653 } 589 char *seen = NULL; 655 if (caller_str != NULL) { 656 mdb_set_dot(0); 591 const char *caller_str = NULL; 657 if (mdb_eval(caller_str) != 0) { 592 const char *excl_caller_str = NULL; 658 mdb_warn("stacks: evaluation of \"%s\" failed", 593 uintptr_t caller = 0, excl_caller = 0; 659 caller_str); 594 const char *module_str = NULL; 660 return (DCMD_ABORT); 595 const char *excl_module_str = NULL; 661 } 596 stacks_module_t module, excl_module; 662 caller = mdb_get_dot(); 597 const char *sobj = NULL; 663 } 598 const char *excl_sobj = NULL; 599 uintptr_t sobj_ops = 0, excl_sobj_ops = 0; 665 if (excl_caller_str != NULL) { 600 const char *tstate_str = NULL; 666 mdb_set_dot(0); 601 const char *excl_tstate_str = NULL; 667 if (mdb_eval(excl_caller_str) != 0) { 602 uint_t tstate = -1U; 668 mdb_warn("stacks: evaluation of \"%s\" failed", 603 uint_t excl_tstate = -1U; 669 excl_caller_str); 604 uint_t printed = 0; 670 return (DCMD_ABORT); 671 } 606 uint_t all = 0; 672 excl_caller = mdb_get_dot(); 607 uint_t force = 0; 673 } 608 uint_t interesting = 0; 674 mdb_set_dot(addr); 609 uint_t verbose = 0; 676 if (module_str != NULL && stacks_module_find(module_str, &module) != 0) 611 /* 677 return (DCMD_ABORT); 612 * We have a slight behavior difference between having piped 613 * input and 'addr::stacks'. Without a pipe, we assume the 679 if (excl_module_str != NULL && 614 * thread pointer given is a representative thread, and so 680 stacks_module_find(excl_module_str, &excl_module) != 0) 615 * we include all similar threads in the system in our output. 681 return (DCMD_ABORT); 616 * 617 * With a pipe, we filter down to just the threads in our 683 if (sobj != NULL && text_to_sobj(sobj, &sobj_ops) != 0) 618 * input. 684 return (DCMD_USAGE); 619 */ 620 uint_t addrspec = (flags & DCMD_ADDRSPEC); 686 if (excl_sobj != NULL && text_to_sobj(excl_sobj, &excl_sobj_ops) != 0) 621 uint_t only_matching = addrspec && (flags & DCMD_PIPE); 687 return (DCMD_USAGE); 623 mdb_pipe_t p; 689 if (sobj_ops != 0 && excl_sobj_ops != 0) { 690 mdb_warn("stacks: only one of -s and -S can be specified\n"); 625 bzero(&module, sizeof (module)); 691 return (DCMD_USAGE); 626 bzero(&excl_module, sizeof (excl_module)); 692 } 628 if (mdb_getopts(argc, argv, 694 if (tstate_str != NULL && text_to_tstate(tstate_str, &tstate) != 0) 629 'a', MDB_OPT_SETBITS, TRUE, &all, 695 return (DCMD_USAGE); 630 'f', MDB_OPT_SETBITS, TRUE, &force, 631 'i', MDB_OPT_SETBITS, TRUE, &interesting, 697 if (excl_tstate_str != NULL && 632 'v', MDB_OPT_SETBITS, TRUE, &verbose, 698 text_to_tstate(excl_tstate_str, &excl_tstate) != 0) 633 'c', MDB_OPT_STR, &caller_str, 699 return (DCMD_USAGE); 634 'C', MDB_OPT_STR, &excl_caller_str, 635 'm', MDB_OPT_STR, &module_str, 701 if (tstate != -1U && excl_tstate != -1U) { 636 'M', MDB_OPT_STR, &excl_module_str, 702 mdb_warn("stacks: only one of -t and -T can be specified\n"); 637 's', MDB_OPT_STR, &sobj, 703 return (DCMD_USAGE); 638 'S', MDB_OPT_STR, &excl_sobj, 704 } 639 't', MDB_OPT_STR, &tstate_str, 640 'T', MDB_OPT_STR, &excl_tstate_str, 706 /* 641 NULL) != argc) 707 * If there's an address specified, we're going to further filter new/usr/src/cmd/mdb/common/modules/genunix/findstack.c 3 new/usr/src/cmd/mdb/common/modules/genunix/findstack.c 4 708 * to only entries which have an address in the input. To reduce 774 foundcount++; 709 * overhead (and make the sorted output come out right), we 775 seen[entry - p.pipe_data]++; 710 * use mdb_get_pipe() to grab the entire pipeline of input, then 776 if (head == NULL) 711 * use qsort() and bsearch() to speed up the search. 777 head = sp; 712 */ 778 else 713 if (addrspec) { 779 tail->se_next = sp; 714 mdb_get_pipe(&p); 780 tail = sp; 715 if (p.pipe_data == NULL || p.pipe_len == 0) { 781 sp->se_next = NULL; 716 p.pipe_data = &addr; 782 } 717 p.pipe_len = 1; 783 } 718 } 784 if (head == NULL) 719 qsort(p.pipe_data, p.pipe_len, sizeof (uintptr_t), 785 continue; /* no match, skip entry */ 720 uintptrcomp); 787 if (only_matching) { 722 /* remove any duplicates in the data */ 788 cur = sep = head; 723 idx = 0; 789 count = foundcount; 724 while (idx < p.pipe_len - 1) { 790 } 725 uintptr_t *data = &p.pipe_data[idx]; 791 } 726 size_t len = p.pipe_len - idx; 793 if (caller != 0 && !stacks_has_caller(sep, caller)) 728 if (data[0] == data[1]) { 794 continue; 729 memmove(data, data + 1, 730 (len - 1) * sizeof (*data)); 796 if (excl_caller != 0 && stacks_has_caller(sep, excl_caller)) 731 p.pipe_len--; 797 continue; 732 continue; /* repeat without incrementing idx */ 733 } 799 if (module.sm_size != 0 && !stacks_has_module(sep, &module)) 734 idx++; 800 continue; 735 } 802 if (excl_module.sm_size != 0 && 737 seen = mdb_zalloc(p.pipe_len, UM_SLEEP | UM_GC); 803 stacks_has_module(sep, &excl_module)) 738 } 804 continue; 740 /* 806 if (tstate != -1U) { 741 * Force a cleanup if we're connected to a live system. Never 807 if (tstate == TSTATE_PANIC) { 742 * do a cleanup after the first invocation around the loop. 808 if (!sep->se_panic) 743 */ 809 continue; 744 force |= (mdb_get_state() == MDB_STATE_RUNNING); 810 } else if (sep->se_panic || sep->se_tstate != tstate) 745 if (force && (flags & (DCMD_LOOPFIRST|DCMD_LOOP)) == DCMD_LOOP) 811 continue; 746 force = 0; 812 } 813 if (excl_tstate != -1U) { 748 stacks_cleanup(force); 814 if (excl_tstate == TSTATE_PANIC) { 815 if (sep->se_panic) 750 if (stacks_state == STACKS_STATE_CLEAN) { 816 continue; 751 int res = stacks_run(verbose, addrspec ? &p : NULL); 817 } else if (!sep->se_panic && 752 if (res != DCMD_OK) 818 sep->se_tstate == excl_tstate) 753 return (res); 819 continue; 754 } 820 } 756 for (idx = 0; idx < stacks_array_size; idx++) { 822 if (sobj_ops == SOBJ_ALL) { 757 stacks_entry_t *sep = stacks_array[idx]; 823 if (sep->se_sobj_ops == 0) 758 stacks_entry_t *cur = sep; 824 continue; 759 int frame; 825 } else if (sobj_ops != 0) { 760 size_t count = sep->se_count; 826 if (sobj_ops != sep->se_sobj_ops) 827 continue; 762 if (addrspec) { 828 } 763 stacks_entry_t *head = NULL, *tail = NULL, *sp; 764 size_t foundcount = 0; 830 if (!(interesting && sep->se_panic)) { 765 /* 831 if (excl_sobj_ops == SOBJ_ALL) { 766 * We use the now-unused hash chain field se_next to 832 if (sep->se_sobj_ops != 0) 767 * link together the dups which match our list. 833 continue; 768 */ 834 } else if (excl_sobj_ops != 0) { 769 for (sp = sep; sp != NULL; sp = sp->se_dup) { 835 if (excl_sobj_ops == sep->se_sobj_ops) 770 uintptr_t *entry = bsearch(&sp->se_thread, 836 continue; 771 p.pipe_data, p.pipe_len, sizeof (uintptr_t), 837 } 772 uintptrcomp); 838 } 773 if (entry != NULL) { new/usr/src/cmd/mdb/common/modules/genunix/findstack.c 5 new/usr/src/cmd/mdb/common/modules/genunix/findstack.c 6 840 if (flags & DCMD_PIPE_OUT) { 903 return (DCMD_OK); 841 while (sep != NULL) { 904 } 842 mdb_printf("%lr\n", sep->se_thread); ______unchanged_portion_omitted_ 843 sep = only_matching ? 844 sep->se_next : sep->se_dup; 845 } 846 continue; 847 } 849 if (all || !printed) { 850 mdb_printf("%<u>%-?s %-8s %-?s %8s%</u>\n", 851 "THREAD", "STATE", "SOBJ", "COUNT"); 852 printed = 1; 853 } 855 do { 856 char state[20]; 857 char sobj[100]; 859 tstate_to_text(cur->se_tstate, cur->se_panic, 860 state, sizeof (state)); 861 sobj_to_text(cur->se_sobj_ops, 862 sobj, sizeof (sobj)); 864 if (cur == sep) 865 mdb_printf("%-?p %-8s %-?s %8d\n", 866 cur->se_thread, state, sobj, count); 867 else 868 mdb_printf("%-?p %-8s %-?s %8s\n", 869 cur->se_thread, state, sobj, "-"); 871 cur = only_matching ? cur->se_next : cur->se_dup; 872 } while (all && cur != NULL); 874 if (sep->se_failed != 0) { 875 char *reason; 876 switch (sep->se_failed) { 877 case FSI_FAIL_NOTINMEMORY: 878 reason = "thread not in memory"; 879 break; 877 case FSI_FAIL_THREADCORRUPT: 878 reason = "thread structure stack info corrupt"; 879 break; 880 case FSI_FAIL_STACKNOTFOUND: 881 reason = "no consistent stack found"; 882 break; 883 default: 884 reason = "unknown failure"; 885 break; 886 } 887 mdb_printf("%?s <%s>\n", "", reason); 888 } 890 for (frame = 0; frame < sep->se_depth; frame++) 891 mdb_printf("%?s %a\n", "", sep->se_stack[frame]); 892 if (sep->se_overflow) 893 mdb_printf("%?s ... truncated ...\n", ""); 894 mdb_printf("\n"); 895 } 897 if (flags & DCMD_ADDRSPEC) { 898 for (idx = 0; idx < p.pipe_len; idx++) 899 if (seen[idx] == 0) 900 mdb_warn("stacks: %p not in thread list\n", 901 p.pipe_data[idx]); 902 } new/usr/src/cmd/mdb/common/modules/genunix/findstack.h 1 ********************************************************** 2801 Thu Feb 18 08:40:37 2016 new/usr/src/cmd/mdb/common/modules/genunix/findstack.h 6583 remove whole-process swapping ********************************************************** ______unchanged_portion_omitted_ 49 #define FSI_FAIL_BADTHREAD 1 50 #define FSI_FAIL_THREADCORRUPT 2 51 #define