def ShowAllSetidLinks()

in tools/lldbmacros/waitq.py [0:0]


def ShowAllSetidLinks(cmd_args=None, cmd_options={}):
    """ Dump / summarize all waitq set linktable elements

        usage: showallsetidlinks [options]
            -V {0,1}  : only show [1 == valid/live links, 0 == invalid links]
            -T {type} : only display objects of type {type}
            -S {desc} : only display objects of type {type} which fit {desc}
                        -T LINK -S {desc} can be:
                            iL   : Invalid left-link pointer (only)
                            iR   : Invalid right-link pointer (only)
                            iLR  : Invalid left+right link pointers
                            iLRI : Invalid left+right link pointers AND dead allocating process
                        w/o "-T" -S {desc} can be:
                            iP   : Invalid / Dead allocating process
            -F n      : summarize the backtraces at frame level 'n'
            -X        : cross-check waitq pointers in link table
            -Q        : be quiet, only summarize
    """
    opt_summary = 0
    opt_type_filt = ""
    opt_valid_only = 0
    opt_invalid_only = 0
    opt_bt_idx = 0
    opt_cross_check = 0
    opt_validate_links = 0
    opt_subtype_filter = 0
    verbose = False
    if config['verbosity'] > vHUMAN:
        verbose = True
    if "-Q" in cmd_options:
        opt_summary = 1
    if "-V" in cmd_options:
        if int(cmd_options["-V"]) == 1:
            opt_valid_only = 1
        elif int(cmd_options["-V"]) == 0:
            opt_invalid_only = 1
        else:
            raise ArgumentError("Invalid parameter to -V '{:s}': expecting 0 or 1".format(cmd_options["-V"]))
    if "-X" in cmd_options:
        opt_cross_check = 1
        nunique_wqs = 0
        nduplicated_wqs = 0
        max_wqs_dupes = 0
    if "-F" in cmd_options:
        opt_bt_idx = unsigned(cmd_options["-F"])
        if hasattr(kern.globals, "g_nwaitq_btframes"):
            if opt_bt_idx >= unsigned(kern.globals.g_nwaitq_btframes):
                raise ArgumentError("Invalid BT index '{:s}' max:{:d}".format(cmd_options["-F"], unsigned(kern.globals.g_nwaitq_btframes) - 1))
    if "-T" in cmd_options:
        opt_type_filt = cmd_options["-T"]
        if opt_type_filt == "FREE" or opt_type_filt == "RSVD" or opt_type_filt == "LINK":
            pass
        elif opt_type_filt == "WQS":
            opt_type_filt = "ELEM"
        else:
            raise ArgumentError("Invalid type filter'{:s}'".format(cmd_options["-T"]))
    if "-S" in cmd_options:
        opt_subtype_filter = cmd_options["-S"]
        if opt_type_filt == "LINK":
            if not (opt_subtype_filter == "iL" or \
                    opt_subtype_filter == "iR" or \
                    opt_subtype_filter == "iLR" or \
                    opt_subtype_filter == "iLRI"):
                raise ArgumentError("Invalid LINK sub-type filter \{desc\}: {:s}".format(opt_subtype_filter))
        elif opt_type_filt == "":
            if not opt_subtype_filter == "iP":
                raise ArgumentError("Invalid sub-type filter \{desc\}: {:s}".format(opt_subtype_filter))
    table = kern.globals.g_wqlinktable
    nelem = int(table.nelem)
    wq_ptr = {}
    bt_summary = {}
    nfree = 0
    ninv = 0
    nwqs = 0
    nlink = 0
    nrsvd = 0
    hdr_str = "Looking through {:d} waitq_link objects from g_wqlinktable@{:<#x}".format(nelem, addressof(kern.globals.g_wqlinktable))
    if opt_type_filt != "" or opt_valid_only != 0:
        hdr_str += "\n\t`-> for "
        if opt_valid_only:
            hdr_str += "valid "
        else:
            hdr_str += "all "
        if opt_type_filt == "":
            hdr_str += "objects"
        else:
            hdr_str += "{:s} objects".format(opt_type_filt)
    else:
        if opt_valid_only:
            hdr_str += "\n\t`-> showing only VALID links"
        elif opt_invalid_only:
            hdr_str += "\n\t`-> showing only INVALID links"
    if opt_subtype_filter != 0:
        if opt_type_filt != "LINK" and opt_type_filt != "":
            raise ArgumentError("Subtype (-S {desc}) can only be used with (-T LINK) or no type filter at all")
        hdr_str += "\n\t`-> filtering {:s} objects through '{:s}'".format(opt_type_filt, opt_subtype_filter)
    if opt_cross_check:
        hdr_str += "\n\t`-> cross-checking WQS elements for duplicates"
    hdr_str += "\n\n"
    print hdr_str
    if not opt_summary:
        print GetWaitqSetidLinkSummary.header
    id = 0
    while id < nelem:
        if id == 0:
            # Set a generation count to differentiate from an invalid ID
            first_entry = Cast(kern.globals.g_wqlinktable.table[0], 'lt_elem *')
            link = GetWaitqLink(first_entry.lt_id.id)[0]
        else:
            link = GetWaitqLink(id)[0]
        if not link:
            print "<<<invalid link:{:d}>>>".format(id)
            ninv += 1
        else:
            lt = WaitqTableElemType(link)
            isvalid = WaitqTableElemValid(link)
            inconsistent = 0
            do_print = not ( (isvalid and opt_invalid_only) or (not isvalid and opt_valid_only) )
            if do_print and opt_subtype_filter != 0 and lt == "LINK":
                lID = link.wql_link.left_setid
                rID = link.wql_link.right_setid
                left = GetWaitqLink(lID)[0]
                right = GetWaitqLink(rID)[0]
                lValid = WaitqTableElemValid(left)
                rValid = WaitqTableElemValid(right)
                if opt_subtype_filter == "iL":
                    if lValid or (not lValid and not rValid):
                        do_print = False
                elif opt_subtype_filter == "iR":
                    if rValid or (not rValid and not lValid):
                        do_print = False
                elif opt_subtype_filter == "iLR":
                    if rValid or lValid:
                        do_print = False
                elif opt_subtype_filter == "iLRI" and hasattr(link, 'sl_alloc_task'):
                    # only print this if both left and right are invalid
                    # and the allocating task is unknown/dead
                    do_print = False
                    is_dead = 0
                    pid = -1
                    try:
                        pid = GetProcPIDForTask(link.sl_alloc_task)
                    except:
                        if link.sl_alloc_task:
                            pid = unsigned(link.sl_alloc_task.audit_token.val[5])
                    if pid < 0:
                        is_dead = 1
                    else:
                        pidnm = GetProcNameForPid(pid)
                        if pidnm == "Unknown":
                            is_dead = 1
                    if (not rValid) and (not lValid) and is_dead:
                        do_print = True

            if do_print and opt_type_filt == "" and opt_subtype_filter == "iP" and hasattr(link, 'sl_alloc_task'):
                # Only print non-free table objects that were allocated by
                # dead processes
                do_print = False
                is_dead = 0
                pid = -1
                try:
                    pid = GetProcPIDForTask(link.sl_alloc_task)
                except:
                    if link.sl_alloc_task:
                        pid = unsigned(link.sl_alloc_task.audit_token.val[5])
                if pid < 0:
                    is_dead = 1
                else:
                    pidnm = GetProcNameForPid(pid)
                    if pidnm == "Unknown":
                        is_dead = 1
                if is_dead:
                    do_print = True

            if (opt_type_filt == "" or opt_type_filt == lt) and do_print:
                if lt == "ELEM":
                    nwqs += 1
                elif lt == "LINK":
                    nlink += 1
                elif lt == "RSVD":
                    nrsvd += 1
                elif lt == "FREE":
                    nfree += 1
                else:
                    ninv += 1
                    inconsistent = 1
                if hasattr(link, 'sl_alloc_bt'):
                    pc = unsigned(link.sl_alloc_bt[opt_bt_idx])
                    pc_str = str(pc)
                    if pc > 0:
                        if pc_str in bt_summary:
                            bt_summary[pc_str] += 1
                        else:
                            bt_summary[pc_str] = 1
                if not opt_summary:
                    print GetWaitqSetidLinkSummary(link, verbose)
                if inconsistent:
                    ninconsistent += 1
                    # print out warnings about inconsistent state as we parse
                    # the list - even if the caller wants a summary
                    print "[WARNING] inconsistent state in idx: {:d} ({:s} element)".format(link.wqte.lt_id.idx, lt)
            if opt_cross_check == 1 and lt == "ELEM":
                wq = unsigned(addressof(link.wql_wqs.wql_set.wqset_q))
                if wq in wq_ptr:
                    wq_ptr[wq].append(id)
                    l = len(wq_ptr[wq])
                    if l == 2:
                        nduplicated_wqs += 1
                    if l > max_wqs_dupes:
                        max_wqs_dupes = l
                else:
                    wq_ptr[wq] = [ id ]
                    nunique_wqs += 1
        id += 1
        if opt_summary or verbose:
            if verbose and opt_cross_check:
                sys.stderr.write('[{:d}|{:d}|{:d}] id: {:d}/{:d}...          \r'.format(nunique_wqs, nduplicated_wqs, max_wqs_dupes, id, nelem))
            else:
                sys.stderr.write('id: {:d}/{:d}...          \r'.format(id, nelem))

    nused = nwqs + nlink + nrsvd
    nfound = nused + nfree + ninv
    print "\n\nFound {:d} objects: {:d} WQS, {:d} LINK, {:d} RSVD, {:d} FREE".format(nfound, nwqs, nlink, nrsvd, nfree)
    if (opt_type_filt == "" and opt_valid_only == 0) and (nused != table.used_elem):
        print"\tWARNING: inconsistent state! Table reports {:d}/{:d} used elem, found {:d}/{:d}".format(table.used_elem, nelem, nused, nfound)
    if len(bt_summary) > 0:
        print "Link allocation BT (frame={:d})".format(opt_bt_idx)
    for k,v in bt_summary.iteritems():
        print "\t[{:d}] from: {:s}".format(v, GetSourceInformationForAddress(unsigned(k)))
    if opt_cross_check:
        print "\n{:d} Duplicated WQS objects:".format(nduplicated_wqs)
        for wq in wq_ptr:
            l = len(wq_ptr[wq])
            if l > 1:
                print "\tWQS:{:#x} ({:d} {:s}".format(wq, l, str(wq_ptr[wq]))