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