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
.kqr_state
& 0x1: # workloop
72 kq
= ContainerOf(kqr
, 'struct kqworkloop', 'kqwl_request')
75 kq
= p
.p_fd
.fd_wqkqueue
76 kind
= "kqwq[%s]" % (xnudefines
.thread_qos_short_strings
[int(kqr
.kqr_qos_index
)])
78 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
))
80 @header("{:<20s} {:<20s} {:<10s} {:<3s} {:<4s} {:<30s}".format(
81 'request', 'kqueue', 'state', '#', 'qos', 'tr_flags'))
82 def GetWorkqueueThreadRequestSummary(proc
, req
):
86 if req
.tr_flags
& 0x01:
87 tr_flags
.append("KEVENT")
88 kq
= proc
.p_fd
.fd_wqkqueue
89 if req
.tr_flags
& 0x02:
90 tr_flags
.append("WORKLOOP")
91 kq
= ContainerOf(req
, 'struct kqworkloop', 'kqwl_request.kqr_req')
92 if req
.tr_flags
& 0x04: tr_flags
.append("OVERCOMMIT")
93 if req
.tr_flags
& 0x08: tr_flags
.append("PARAMS")
94 if req
.tr_flags
& 0x10: tr_flags
.append("OUTSIDE_QOS")
96 state
= {0: "IDLE", 1: "NEW", 2: "QUEUED", 4: "BINDING" }
[int(req
.tr_state
)]
104 qos
= xnudefines
.thread_qos_short_strings
[qos
]
106 return "{req: <#020x} {kq: <#020x} {state: <10s} {req.tr_count: <3d} {qos: <4s} {tr_flags: <30s}".format(req
=req
, kq
=kq
, state
=state
, qos
=qos
, tr_flags
=" ".join(tr_flags
))
108 @lldb_command('showwqthread')
109 def ShowWQThread(cmd_args
=None):
110 """ Shows info about a workqueue thread
112 usage: showworkqthread <thread_t>
116 raise ArgumentError('missing struct proc * argument')
118 th
= kern
.GetValueFromAddress(cmd_args
[0], "struct thread *")
119 if not (th
.thread_tag
& 0x20):
120 raise ArgumentError('not a workqueue thread')
122 print GetWQThreadSummary
.header
123 print GetWQThreadSummary(th
, Cast(th
.uthread
, 'struct uthread *'))
126 @lldb_command('showprocworkqueue')
127 def ShowProcWorkqueue(cmd_args
=None):
128 """ Shows the process workqueue
130 usage: showprocworkqueue <proc_t>
134 raise ArgumentError('missing struct proc * argument')
136 proc
= kern
.GetValueFromAddress(cmd_args
[0], "proc_t")
137 wq
= Cast(proc
.p_wqptr
, "struct workqueue *");
139 print GetWorkqueueSummary
.header
140 print GetWorkqueueSummary(proc
, wq
)
144 print " " + GetWorkqueueThreadRequestSummary
.header
145 if wq
.wq_event_manager_threadreq
:
146 print " " + GetWorkqueueThreadRequestSummary(proc
, wq
.wq_event_manager_threadreq
)
147 for req
in IteratePriorityQueueEntry(wq
.wq_overcommit_queue
, 'struct workq_threadreq_s', 'tr_entry'):
148 print " " + GetWorkqueueThreadRequestSummary(proc
, req
)
149 for req
in IteratePriorityQueueEntry(wq
.wq_constrained_queue
, 'struct workq_threadreq_s', 'tr_entry'):
150 print " " + GetWorkqueueThreadRequestSummary(proc
, req
)
151 for req
in IteratePriorityQueueEntry(wq
.wq_special_queue
, 'struct workq_threadreq_s', 'tr_entry'):
152 print " " + GetWorkqueueThreadRequestSummary(proc
, req
)
155 print " " + GetWQThreadSummary
.header
156 for uth
in IterateTAILQ_HEAD(wq
.wq_thrunlist
, "uu_workq_entry"):
157 print " " + GetWQThreadSummary(Cast(uth
.uu_thread
, 'struct thread *'), uth
)
158 for uth
in IterateTAILQ_HEAD(wq
.wq_thidlelist
, "uu_workq_entry"):
159 print " " + GetWQThreadSummary(Cast(uth
.uu_thread
, 'struct thread *'), uth
)
160 for uth
in IterateTAILQ_HEAD(wq
.wq_thnewlist
, "uu_workq_entry"):
161 print " " + GetWQThreadSummary(Cast(uth
.uu_thread
, 'struct thread *'), uth
)
163 @lldb_command('showallworkqueues')
164 def ShowAllWorkqueues(cmd_args
=None):
165 """ Display a summary of all the workqueues in the system
167 usage: showallworkqueues
170 print GetWorkqueueSummary
.header
173 proc
= Cast(t
.bsd_info
, 'proc *')
174 wq
= Cast(proc
.p_wqptr
, "struct workqueue *");
176 print GetWorkqueueSummary(proc
, wq
)