2 from scheduler
import GetRecentTimestamp
5 def GetProcWorkqueue(proc
):
8 return Cast(wq
, "struct workqueue *");
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'))
13 def GetWorkqueueSummary(proc
, wq
):
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")
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
):
26 if wq
.wq_flags
& scheduled
: s
+= 'S'
27 if wq
.wq_flags
& pended
: s
+= 'P'
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
):
35 if wq
.wq_flags
& scheduled
: s
+= 'S'
36 if wq
.wq_flags
& pended
: s
+= 'P'
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
));
42 @header("{:<20s} {:<20s} {:>10s} {:9s} {:<20s} {:<10s} {:<30s}".format(
43 'thread', 'uthread', 'thport', 'kind', 'kqueue', 'idle (ms)', 'uu_workq_flags'))
44 def GetWQThreadSummary(th
, uth
):
45 p
= Cast(th
.task
.bsd_info
, 'proc *')
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
:
58 ts
= kern
.GetNanotimeFromAbstime(GetRecentTimestamp() - uth
.uu_save
.uus_workq_park_data
.idle_stamp
) / 1e9
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%")
68 kqr
= uth
.uu_kqr_bound
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
75 kq
= ContainerOf(kqr
, 'struct kqworkloop', 'kqwl_request')
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
))
83 @header("{:<20s} {:<20s} {:<20s} {:<10s} {:<4s} {:<6s} {:<6s} {:<6s} {:<30s}".format(
84 'request', 'kqueue', 'thread', 'state', '#', 'qos', 'kq_qos', 'kq_ovr', 'tr_flags'))
85 def GetWorkqueueThreadRequestSummary(proc
, req
):
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")
94 kq
= ContainerOf(req
, 'struct kqworkloop', 'kqwl_request')
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")
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
+= "*"
103 if int(req
.tr_state
) in [4, 5]: # BINDING or BOUND
104 thread
= req
.tr_thread
106 qos
= int(req
.tr_qos
)
112 qos
= xnudefines
.thread_qos_short_strings
[qos
]
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
))
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
))
121 @lldb_command('showwqthread', fancy
=True)
122 def ShowWQThread(cmd_args
=None, cmd_options
={}, O
=None):
123 """ Shows info about a workqueue thread
125 usage: showworkqthread <thread_t>
129 return O
.error('missing struct proc * argument')
131 th
= kern
.GetValueFromAddress(cmd_args
[0], "struct thread *")
132 if not (th
.thread_tag
& 0x20):
133 raise ArgumentError('not a workqueue thread')
135 with O
.table(GetWQThreadSummary
.header
):
136 print GetWQThreadSummary(th
, Cast(th
.uthread
, 'struct uthread *'))
139 @lldb_command('showprocworkqueue', fancy
=True)
140 def ShowProcWorkqueue(cmd_args
=None, cmd_options
={}, O
=None):
141 """ Shows the process workqueue
143 usage: showprocworkqueue <proc_t>
147 return O
.error('missing struct proc * argument')
149 proc
= kern
.GetValueFromAddress(cmd_args
[0], "proc_t")
150 wq
= Cast(proc
.p_wqptr
, "struct workqueue *");
152 return O
.error("{:#x} doesn't have a workqueue", proc
)
154 with O
.table(GetWorkqueueSummary
.header
):
155 print GetWorkqueueSummary(proc
, wq
)
157 with O
.table(GetWorkqueueThreadRequestSummary
.header
, indent
=True):
160 if wq
.wq_event_manager_threadreq
:
161 print GetWorkqueueThreadRequestSummary(proc
, wq
.wq_event_manager_threadreq
)
162 for req
in IterateSchedPriorityQueue(wq
.wq_overcommit_queue
, 'struct workq_threadreq_s', 'tr_entry'):
163 print GetWorkqueueThreadRequestSummary(proc
, req
)
164 for req
in IterateSchedPriorityQueue(wq
.wq_constrained_queue
, 'struct workq_threadreq_s', 'tr_entry'):
165 print GetWorkqueueThreadRequestSummary(proc
, req
)
166 for req
in IterateSchedPriorityQueue(wq
.wq_special_queue
, 'struct workq_threadreq_s', 'tr_entry'):
167 print GetWorkqueueThreadRequestSummary(proc
, req
)
169 with O
.table(GetWQThreadSummary
.header
, indent
=True):
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
)
178 @lldb_command('showallworkqueues', fancy
=True)
179 def ShowAllWorkqueues(cmd_args
=None, cmd_options
={}, O
=None):
180 """ Display a summary of all the workqueues in the system
182 usage: showallworkqueues
185 with O
.table(GetWorkqueueSummary
.header
):
187 proc
= Cast(t
.bsd_info
, 'proc *')
188 wq
= Cast(proc
.p_wqptr
, "struct workqueue *");
190 print GetWorkqueueSummary(proc
, wq
)