]> git.saurik.com Git - apple/xnu.git/blame - tools/lldbmacros/workqueue.py
xnu-7195.101.1.tar.gz
[apple/xnu.git] / tools / lldbmacros / workqueue.py
CommitLineData
d9a64523
A
1from xnu import *
2from scheduler import GetRecentTimestamp
3import xnudefines
4
5def GetProcWorkqueue(proc):
6 wq = proc.p_wqptr;
7 if unsigned(wq):
8 return Cast(wq, "struct workqueue *");
9 return None
10
11@header("{:<20s} {:<20s} {:<20s} {:<10s} {:<10s} {:<10s} {:<10s} {:<10s} {:<10s} {:<30s}".format(
12 'task', 'proc', 'wq', 'sched', 'pending', 'idle', 'dying', 'creations', 'fulfilled', 'wq_flags'))
13def GetWorkqueueSummary(proc, wq):
14 wq_flags = []
15 if wq.wq_flags & GetEnumValue("workq_state_flags_t::WQ_EXITING"):
16 wq_flags.append("EXITING")
17 if wq.wq_flags & GetEnumValue("workq_state_flags_t::WQ_PROC_SUSPENDED"):
18 wq_flags.append("PROC_SUSPENDED")
19 if wq.wq_flags & GetEnumValue("workq_state_flags_t::WQ_DEATH_CALL_SCHEDULED"):
20 wq_flags.append("DEATH_CALL")
21
22 scheduled = GetEnumValue("workq_state_flags_t::WQ_DELAYED_CALL_SCHEDULED")
23 pended = GetEnumValue("workq_state_flags_t::WQ_DELAYED_CALL_PENDED")
24 if wq.wq_flags & (scheduled | pended):
25 s = "DELAYED_CALL["
26 if wq.wq_flags & scheduled: s += 'S'
27 if wq.wq_flags & pended: s += 'P'
28 s += ']'
29 wq_flags.append(s)
30
31 scheduled = GetEnumValue("workq_state_flags_t::WQ_IMMEDIATE_CALL_SCHEDULED")
32 pended = GetEnumValue("workq_state_flags_t::WQ_IMMEDIATE_CALL_PENDED")
33 if wq.wq_flags & (scheduled | pended):
34 s = "IMMEDIATE_CALL["
35 if wq.wq_flags & scheduled: s += 'S'
36 if wq.wq_flags & pended: s += 'P'
37 s += ']'
38 wq_flags.append(s)
39
40 return "{p.task: <#020x} {p: <#020x} {wq: <#020x} {wq.wq_threads_scheduled: <10d} {wq.wq_reqcount: <10d} {wq.wq_thidlecount: <10d} {wq.wq_thdying_count: <10d} {wq.wq_creations: <10d} {wq.wq_fulfilled: <10d} {wq_flags: <30s}".format(p=proc, wq=wq, wq_flags=" ".join(wq_flags));
41
42@header("{:<20s} {:<20s} {:>10s} {:9s} {:<20s} {:<10s} {:<30s}".format(
43 'thread', 'uthread', 'thport', 'kind', 'kqueue', 'idle (ms)', 'uu_workq_flags'))
44def GetWQThreadSummary(th, uth):
45 p = Cast(th.task.bsd_info, 'proc *')
46 wq = p.p_wqptr
47
48 uu_workq_flags = []
49 if uth.uu_workq_flags & 0x01: uu_workq_flags.append("NEW")
50 if uth.uu_workq_flags & 0x02:
51 uu_workq_flags.append("RUNNING")
52 if wq.wq_creator == uth:
53 kind = "creator"
54 else:
55 kind = "workq"
56 idle = ""
57 else:
58 ts = kern.GetNanotimeFromAbstime(GetRecentTimestamp() - uth.uu_save.uus_workq_park_data.idle_stamp) / 1e9
59 kind = "idle"
60 idle = "%#.03f" % (ts)
61 if uth.uu_workq_flags & 0x04: uu_workq_flags.append("DYING")
62 if uth.uu_workq_flags & 0x08: uu_workq_flags.append("OVERCOMMIT")
63 if uth.uu_workq_flags & 0x10: uu_workq_flags.append("OUTSIDE_QOS")
64 if uth.uu_workq_flags & 0x20: uu_workq_flags.append("IDLE_CLEANUP")
65 if uth.uu_workq_flags & 0x40: uu_workq_flags.append("EARLY_BOUND")
66 if uth.uu_workq_flags & 0x80: uu_workq_flags.append("CPU%")
67
68 kqr = uth.uu_kqr_bound
69 if not kqr:
70 kq = 0
cb323159
A
71 elif kqr.tr_flags & 0x1: # kevent
72 kq = p.p_fd.fd_wqkqueue
73 kind = "kqwq[%s]" % (xnudefines.thread_qos_short_strings[int(kqr.tr_kq_qos_index)])
74 elif kqr.tr_flags & 0x2: # workloop
d9a64523
A
75 kq = ContainerOf(kqr, 'struct kqworkloop', 'kqwl_request')
76 kind = "workloop"
77 else:
cb323159
A
78 kq = 0
79 kind = "???"
d9a64523
A
80
81 return "{th: <#020x} {uth: <#020x} {thport: >#010x} {kind: <9s} {kq: <#020x} {idle: <10s} {uu_workq_flags: <30s}".format(th=th, uth=uth, thport=uth.uu_workq_thport, kind=kind, kq=kq, idle=idle, uu_workq_flags=" ".join(uu_workq_flags))
82
cb323159
A
83@header("{:<20s} {:<20s} {:<20s} {:<10s} {:<4s} {:<6s} {:<6s} {:<6s} {:<30s}".format(
84 'request', 'kqueue', 'thread', 'state', '#', 'qos', 'kq_qos', 'kq_ovr', 'tr_flags'))
d9a64523
A
85def GetWorkqueueThreadRequestSummary(proc, req):
86 kq = 0
87 tr_flags = []
88
89 if req.tr_flags & 0x01:
90 tr_flags.append("KEVENT")
91 kq = proc.p_fd.fd_wqkqueue
92 if req.tr_flags & 0x02:
93 tr_flags.append("WORKLOOP")
cb323159 94 kq = ContainerOf(req, 'struct kqworkloop', 'kqwl_request')
d9a64523
A
95 if req.tr_flags & 0x04: tr_flags.append("OVERCOMMIT")
96 if req.tr_flags & 0x08: tr_flags.append("PARAMS")
97 if req.tr_flags & 0x10: tr_flags.append("OUTSIDE_QOS")
98
cb323159
A
99 state = {0: "IDLE", 1: "NEW", 2: "QUEUED", 3: "CANCELED", 4: "BINDING", 5: "BOUND" }[int(req.tr_state)]
100 if req.tr_kq_wakeup: state += "*"
101
102 thread = 0
f427ee49 103 if int(req.tr_state) in [4, 5]: # BINDING or BOUND
cb323159 104 thread = req.tr_thread
d9a64523
A
105
106 qos = int(req.tr_qos)
107 if qos == 8:
108 qos = "MG"
109 elif qos == 7:
110 qos = "SP"
111 else:
112 qos = xnudefines.thread_qos_short_strings[qos]
113
cb323159
A
114 kq_qos = xnudefines.thread_qos_short_strings[int(req.tr_kq_qos_index)]
115 kq_ovr = xnudefines.thread_qos_short_strings[int(req.tr_kq_override_index)]
116 req_addr = unsigned(addressof(req))
d9a64523 117
cb323159
A
118 return "{req_addr: <#020x} {kq: <#020x} {thread: <#020x} {state: <10s} {req.tr_count: <4d} {qos: <6s} {kq_qos: <6s} {kq_ovr: <6s} {tr_flags: <30s}".format(
119 req_addr=req_addr, req=req, kq=kq, thread=thread, state=state, qos=qos, kq_qos=kq_qos, kq_ovr=kq_ovr, tr_flags=" ".join(tr_flags))
120
121@lldb_command('showwqthread', fancy=True)
122def ShowWQThread(cmd_args=None, cmd_options={}, O=None):
d9a64523
A
123 """ Shows info about a workqueue thread
124
125 usage: showworkqthread <thread_t>
126 """
127
128 if not cmd_args:
cb323159 129 return O.error('missing struct proc * argument')
d9a64523
A
130
131 th = kern.GetValueFromAddress(cmd_args[0], "struct thread *")
132 if not (th.thread_tag & 0x20):
133 raise ArgumentError('not a workqueue thread')
134
cb323159
A
135 with O.table(GetWQThreadSummary.header):
136 print GetWQThreadSummary(th, Cast(th.uthread, 'struct uthread *'))
d9a64523
A
137
138
cb323159
A
139@lldb_command('showprocworkqueue', fancy=True)
140def ShowProcWorkqueue(cmd_args=None, cmd_options={}, O=None):
d9a64523
A
141 """ Shows the process workqueue
142
143 usage: showprocworkqueue <proc_t>
144 """
145
146 if not cmd_args:
cb323159 147 return O.error('missing struct proc * argument')
d9a64523
A
148
149 proc = kern.GetValueFromAddress(cmd_args[0], "proc_t")
150 wq = Cast(proc.p_wqptr, "struct workqueue *");
cb323159
A
151 if not wq:
152 return O.error("{:#x} doesn't have a workqueue", proc)
153
154 with O.table(GetWorkqueueSummary.header):
d9a64523
A
155 print GetWorkqueueSummary(proc, wq)
156
cb323159
A
157 with O.table(GetWorkqueueThreadRequestSummary.header, indent=True):
158 if wq.wq_reqcount:
159 print ""
d9a64523 160 if wq.wq_event_manager_threadreq:
cb323159 161 print GetWorkqueueThreadRequestSummary(proc, wq.wq_event_manager_threadreq)
f427ee49 162 for req in IterateSchedPriorityQueue(wq.wq_overcommit_queue, 'struct workq_threadreq_s', 'tr_entry'):
cb323159 163 print GetWorkqueueThreadRequestSummary(proc, req)
f427ee49 164 for req in IterateSchedPriorityQueue(wq.wq_constrained_queue, 'struct workq_threadreq_s', 'tr_entry'):
cb323159 165 print GetWorkqueueThreadRequestSummary(proc, req)
f427ee49 166 for req in IterateSchedPriorityQueue(wq.wq_special_queue, 'struct workq_threadreq_s', 'tr_entry'):
cb323159
A
167 print GetWorkqueueThreadRequestSummary(proc, req)
168
169 with O.table(GetWQThreadSummary.header, indent=True):
170 print ""
171 for uth in IterateTAILQ_HEAD(wq.wq_thrunlist, "uu_workq_entry"):
172 print GetWQThreadSummary(Cast(uth.uu_thread, 'struct thread *'), uth)
173 for uth in IterateTAILQ_HEAD(wq.wq_thidlelist, "uu_workq_entry"):
174 print GetWQThreadSummary(Cast(uth.uu_thread, 'struct thread *'), uth)
175 for uth in IterateTAILQ_HEAD(wq.wq_thnewlist, "uu_workq_entry"):
176 print GetWQThreadSummary(Cast(uth.uu_thread, 'struct thread *'), uth)
177
178@lldb_command('showallworkqueues', fancy=True)
179def ShowAllWorkqueues(cmd_args=None, cmd_options={}, O=None):
d9a64523
A
180 """ Display a summary of all the workqueues in the system
181
182 usage: showallworkqueues
183 """
184
cb323159
A
185 with O.table(GetWorkqueueSummary.header):
186 for t in kern.tasks:
187 proc = Cast(t.bsd_info, 'proc *')
188 wq = Cast(proc.p_wqptr, "struct workqueue *");
189 if wq:
190 print GetWorkqueueSummary(proc, wq)