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