xref: /xnu-8792.81.2/tools/lldbmacros/turnstile.py (revision 19c3b8c28c31cb8130e034cfb5df6bf9ba342d90)
1from __future__ import absolute_import, print_function
2
3from builtins import range
4
5from xnu import *
6import sys, shlex
7from utils import *
8from waitq import *
9from memory import GetZoneByName, IterateZoneElements
10import xnudefines
11
12@lldb_type_summary(['struct turnstile *'])
13@header("{0: <20s} {1: <5s} {2: <20s} {3: <8s} {4: <8s} {5: <23s} {6: <20s} {7: <10s} {8: <10s} {9: <20s} {10: <20s}".format(
14    "turnstile", "pri", "waitq", "type", "state", "inheritor", "proprietor", "gen cnt", "prim cnt", "thread", "prev_thread"))
15def GetTurnstileSummary(turnstile):
16    """ Summarizes the turnstile
17        params: turnstile = value of the object of type struct turnstile *
18        returns: String with summary of the type.
19    """
20
21    type_and_gencount = Cast(addressof(turnstile.ts_type_gencount), 'union turnstile_type_gencount *')
22    turnstile_type = ""
23
24    if type_and_gencount.ts_type == GetEnumValue('turnstile_type_t::TURNSTILE_NONE'):
25      turnstile_type = "none   "
26    elif type_and_gencount.ts_type == GetEnumValue('turnstile_type_t::TURNSTILE_KERNEL_MUTEX'):
27      turnstile_type = "knl_mtx"
28    elif type_and_gencount.ts_type == GetEnumValue('turnstile_type_t::TURNSTILE_ULOCK'):
29      turnstile_type = "ulock  "
30    elif type_and_gencount.ts_type == GetEnumValue('turnstile_type_t::TURNSTILE_PTHREAD_MUTEX'):
31      turnstile_type = "pth_mtx"
32    elif type_and_gencount.ts_type == GetEnumValue('turnstile_type_t::TURNSTILE_SYNC_IPC'):
33      turnstile_type = "syn_ipc"
34    elif type_and_gencount.ts_type == GetEnumValue('turnstile_type_t::TURNSTILE_WORKLOOPS'):
35      turnstile_type = "kqwl   "
36    elif type_and_gencount.ts_type == GetEnumValue('turnstile_type_t::TURNSTILE_WORKQS'):
37      turnstile_type = "workq  "
38    elif type_and_gencount.ts_type == GetEnumValue('turnstile_type_t::TURNSTILE_KNOTE'):
39      turnstile_type = "knote  "
40    elif type_and_gencount.ts_type == GetEnumValue('turnstile_type_t::TURNSTILE_SLEEP_INHERITOR'):
41      turnstile_type = "slp_inh"
42
43    turnstile_state = ""
44    if turnstile.ts_state & 0x1:
45        turnstile_state += "T"
46    elif turnstile.ts_state & 0x2:
47        turnstile_state += "F"
48    elif turnstile.ts_state & 0x4:
49        turnstile_state += "H"
50    elif turnstile.ts_state & 0x8:
51        turnstile_state += "P"
52
53    if turnstile.ts_inheritor_flags & 0x4:
54        inheritor_type = "th"
55    elif turnstile.ts_inheritor_flags & 0x8:
56        inheritor_type = "ts"
57    elif turnstile.ts_inheritor_flags & 0x40:
58        inheritor_type = "wq"
59    else:
60        inheritor_type = "--"
61
62    format_str = "{0: <#020x} {1: <5d} {2: <#020x} {3: <8s} {4: <8s} {6: <2s}:{5: <#020x} {7: <#020x} {8: <10d} {9: <10d}"
63    out_string = format_str.format(turnstile, turnstile.ts_priority, addressof(turnstile.ts_waitq),
64            turnstile_type, turnstile_state, turnstile.ts_waitq.waitq_inheritor, inheritor_type,
65            turnstile.ts_proprietor, type_and_gencount.ts_gencount, turnstile.ts_prim_count)
66
67    #if DEVELOPMENT
68    format_str = " {0: <#020x} {1: <#020x}"
69    if hasattr(turnstile, 'ts_thread'):
70      out_string += format_str.format(turnstile.ts_thread, turnstile.ts_prev_thread)
71    #endif
72    return out_string
73
74def PrintTurnstile(turnstile):
75    """ print turnstile and it's free list.
76        params:
77            turnstile - turnstile to print
78    """
79    print(GetTurnstileSummary(turnstile))
80
81    """ print turnstile freelist if its not on a thread or freelist """
82    if turnstile.ts_state & 0x3 == 0:
83      needsHeader = True
84      for free_turnstile in IterateListEntry(turnstile.ts_free_turnstiles, 'struct turnstile *', 'ts_free_elm', 's'):
85        if needsHeader:
86          print("    Turnstile free List")
87          header_str = "    " + GetTurnstileSummary.header
88          print(header_str)
89          needsHeader = False
90        print("    " + GetTurnstileSummary(free_turnstile))
91        print("")
92
93# Macro: showturnstile
94@lldb_command('showturnstile', fancy=True)
95def ShowTurnstile(cmd_args=None, cmd_options={}, O=None):
96    """ show the turnstile and all free turnstiles hanging off the turnstile.
97        Usage: (lldb)showturnstile <struct turnstile *>
98    """
99    if not cmd_args:
100      raise ArgumentError("Please provide arguments")
101
102    turnstile = kern.GetValueFromAddress(cmd_args[0], 'struct turnstile *')
103    with O.table(GetTurnstileSummary.header):
104        PrintTurnstile(turnstile)
105# EndMacro: showturnstile
106
107@lldb_command('showturnstilehashtable', fancy=True)
108def ShowTurnstileHashTable(cmd_args=None, cmd_options={}, O=None):
109    """ show the global hash table for turnstiles.
110        Usage: (lldb)showturnstilehashtable
111    """
112    with O.table(GetTurnstileSummary.header):
113        turnstile_htable_buckets = kern.globals.ts_htable_buckets
114        for index in range(0, turnstile_htable_buckets):
115            turnstile_bucket = GetObjectAtIndexFromArray(kern.globals.turnstile_htable, index)
116            for turnstile in IterateQueue(turnstile_bucket.ts_ht_bucket_list, 'struct turnstile *', 'ts_htable_link'):
117                PrintTurnstile(turnstile)
118
119# Macro: showallturnstiles
120@lldb_command('showallturnstiles', fancy=True)
121def ShowAllTurnstiles(cmd_args=None, cmd_options={}, O=None):
122    """ A macro that walks the list of all allocated turnstile objects and prints them.
123        usage: (lldb) showallturnstiles
124    """
125    with O.table(GetTurnstileSummary.header):
126        for turnstile in IterateZoneElements(GetZoneByName("turnstiles"), 'struct turnstile *'):
127            PrintTurnstile(turnstile)
128# EndMacro showallturnstiles
129
130# Macro: showallbusyturnstiles
131@lldb_command('showallbusyturnstiles', 'V', fancy=True)
132def ShowAllTurnstiles(cmd_args=None, cmd_options={}, O=None):
133    """ A macro that walks the list of all allocated turnstile objects
134        and prints them.
135        usage: (lldb) showallbusyturnstiles [-V]
136
137        -V     Even show turnstiles with no waiters (but with a proprietor)
138    """
139
140    verbose = "-V" in cmd_options
141
142    def ts_is_interesting(ts):
143        if not unsigned(ts.ts_proprietor):
144            # not owned by any primitive
145            return False
146        if verbose:
147            return True
148        return unsigned(turnstile.ts_waitq.waitq_prio_queue.pq_root)
149
150    with O.table(GetTurnstileSummary.header):
151        for turnstile in IterateZoneElements(GetZoneByName("turnstiles"), 'struct turnstile *'):
152            if ts_is_interesting(turnstile):
153                PrintTurnstile(turnstile)
154# EndMacro showallbusyturnstiles
155
156@lldb_command('showthreadbaseturnstiles', fancy=True)
157def ShowThreadInheritorBase(cmd_args=None, cmd_options={}, O=None):
158    """ A macro that walks the list of userspace turnstiles pushing on a thread and prints them.
159        usage: (lldb) showthreadbaseturnstiles thread_pointer
160    """
161    if not cmd_args:
162        return O.error('invalid thread pointer')
163
164    thread = kern.GetValueFromAddress(cmd_args[0], "thread_t")
165    with O.table(GetTurnstileSummary.header):
166        for turnstile in IterateSchedPriorityQueue(thread.base_inheritor_queue, 'struct turnstile', 'ts_inheritor_links'):
167            PrintTurnstile(turnstile)
168
169@lldb_command('showthreadschedturnstiles', fancy=True)
170def ShowThreadInheritorSched(cmd_args=None, cmd_options={}, O=None):
171    """ A macro that walks the list of kernelspace turnstiles pushing on a thread
172        and prints them.
173        usage: (lldb) showthreadschedturnstiles thread_pointer
174    """
175    if not cmd_args:
176        return O.error('invalid thread pointer')
177
178    thread = kern.GetValueFromAddress(cmd_args[0], "thread_t")
179    with O.table(GetTurnstileSummary.header):
180        for turnstile in IterateSchedPriorityQueue(thread.sched_inheritor_queue, 'struct turnstile', 'ts_inheritor_links'):
181            PrintTurnstile(turnstile)
182