kqr = uth.uu_kqr_bound
if not kqr:
kq = 0
- elif kqr.kqr_state & 0x1: # workloop
+ elif kqr.tr_flags & 0x1: # kevent
+ kq = p.p_fd.fd_wqkqueue
+ kind = "kqwq[%s]" % (xnudefines.thread_qos_short_strings[int(kqr.tr_kq_qos_index)])
+ elif kqr.tr_flags & 0x2: # workloop
kq = ContainerOf(kqr, 'struct kqworkloop', 'kqwl_request')
kind = "workloop"
else:
- kq = p.p_fd.fd_wqkqueue
- kind = "kqwq[%s]" % (xnudefines.thread_qos_short_strings[int(kqr.kqr_qos_index)])
+ kq = 0
+ kind = "???"
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))
-@header("{:<20s} {:<20s} {:<10s} {:<3s} {:<4s} {:<30s}".format(
- 'request', 'kqueue', 'state', '#', 'qos', 'tr_flags'))
+@header("{:<20s} {:<20s} {:<20s} {:<10s} {:<4s} {:<6s} {:<6s} {:<6s} {:<30s}".format(
+ 'request', 'kqueue', 'thread', 'state', '#', 'qos', 'kq_qos', 'kq_ovr', 'tr_flags'))
def GetWorkqueueThreadRequestSummary(proc, req):
kq = 0
tr_flags = []
kq = proc.p_fd.fd_wqkqueue
if req.tr_flags & 0x02:
tr_flags.append("WORKLOOP")
- kq = ContainerOf(req, 'struct kqworkloop', 'kqwl_request.kqr_req')
+ kq = ContainerOf(req, 'struct kqworkloop', 'kqwl_request')
if req.tr_flags & 0x04: tr_flags.append("OVERCOMMIT")
if req.tr_flags & 0x08: tr_flags.append("PARAMS")
if req.tr_flags & 0x10: tr_flags.append("OUTSIDE_QOS")
- state = {0: "IDLE", 1: "NEW", 2: "QUEUED", 4: "BINDING" }[int(req.tr_state)]
+ state = {0: "IDLE", 1: "NEW", 2: "QUEUED", 3: "CANCELED", 4: "BINDING", 5: "BOUND" }[int(req.tr_state)]
+ if req.tr_kq_wakeup: state += "*"
+
+ thread = 0
+ if int(req.tr_state) in [4, 5]: # BINDING or BOUND
+ thread = req.tr_thread
qos = int(req.tr_qos)
if qos == 8:
else:
qos = xnudefines.thread_qos_short_strings[qos]
- 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))
+ kq_qos = xnudefines.thread_qos_short_strings[int(req.tr_kq_qos_index)]
+ kq_ovr = xnudefines.thread_qos_short_strings[int(req.tr_kq_override_index)]
+ req_addr = unsigned(addressof(req))
-@lldb_command('showwqthread')
-def ShowWQThread(cmd_args=None):
+ 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(
+ 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))
+
+@lldb_command('showwqthread', fancy=True)
+def ShowWQThread(cmd_args=None, cmd_options={}, O=None):
""" Shows info about a workqueue thread
usage: showworkqthread <thread_t>
"""
if not cmd_args:
- raise ArgumentError('missing struct proc * argument')
+ return O.error('missing struct proc * argument')
th = kern.GetValueFromAddress(cmd_args[0], "struct thread *")
if not (th.thread_tag & 0x20):
raise ArgumentError('not a workqueue thread')
- print GetWQThreadSummary.header
- print GetWQThreadSummary(th, Cast(th.uthread, 'struct uthread *'))
+ with O.table(GetWQThreadSummary.header):
+ print GetWQThreadSummary(th, Cast(th.uthread, 'struct uthread *'))
-@lldb_command('showprocworkqueue')
-def ShowProcWorkqueue(cmd_args=None):
+@lldb_command('showprocworkqueue', fancy=True)
+def ShowProcWorkqueue(cmd_args=None, cmd_options={}, O=None):
""" Shows the process workqueue
usage: showprocworkqueue <proc_t>
"""
if not cmd_args:
- raise ArgumentError('missing struct proc * argument')
+ return O.error('missing struct proc * argument')
proc = kern.GetValueFromAddress(cmd_args[0], "proc_t")
wq = Cast(proc.p_wqptr, "struct workqueue *");
- if wq:
- print GetWorkqueueSummary.header
+ if not wq:
+ return O.error("{:#x} doesn't have a workqueue", proc)
+
+ with O.table(GetWorkqueueSummary.header):
print GetWorkqueueSummary(proc, wq)
- if wq.wq_reqcount:
- print " "
- print " " + GetWorkqueueThreadRequestSummary.header
+ with O.table(GetWorkqueueThreadRequestSummary.header, indent=True):
+ if wq.wq_reqcount:
+ print ""
if wq.wq_event_manager_threadreq:
- print " " + GetWorkqueueThreadRequestSummary(proc, wq.wq_event_manager_threadreq)
- for req in IteratePriorityQueueEntry(wq.wq_overcommit_queue, 'struct workq_threadreq_s', 'tr_entry'):
- print " " + GetWorkqueueThreadRequestSummary(proc, req)
- for req in IteratePriorityQueueEntry(wq.wq_constrained_queue, 'struct workq_threadreq_s', 'tr_entry'):
- print " " + GetWorkqueueThreadRequestSummary(proc, req)
- for req in IteratePriorityQueueEntry(wq.wq_special_queue, 'struct workq_threadreq_s', 'tr_entry'):
- print " " + GetWorkqueueThreadRequestSummary(proc, req)
-
- print " "
- print " " + GetWQThreadSummary.header
- for uth in IterateTAILQ_HEAD(wq.wq_thrunlist, "uu_workq_entry"):
- print " " + GetWQThreadSummary(Cast(uth.uu_thread, 'struct thread *'), uth)
- for uth in IterateTAILQ_HEAD(wq.wq_thidlelist, "uu_workq_entry"):
- print " " + GetWQThreadSummary(Cast(uth.uu_thread, 'struct thread *'), uth)
- for uth in IterateTAILQ_HEAD(wq.wq_thnewlist, "uu_workq_entry"):
- print " " + GetWQThreadSummary(Cast(uth.uu_thread, 'struct thread *'), uth)
-
-@lldb_command('showallworkqueues')
-def ShowAllWorkqueues(cmd_args=None):
+ print GetWorkqueueThreadRequestSummary(proc, wq.wq_event_manager_threadreq)
+ for req in IterateSchedPriorityQueue(wq.wq_overcommit_queue, 'struct workq_threadreq_s', 'tr_entry'):
+ print GetWorkqueueThreadRequestSummary(proc, req)
+ for req in IterateSchedPriorityQueue(wq.wq_constrained_queue, 'struct workq_threadreq_s', 'tr_entry'):
+ print GetWorkqueueThreadRequestSummary(proc, req)
+ for req in IterateSchedPriorityQueue(wq.wq_special_queue, 'struct workq_threadreq_s', 'tr_entry'):
+ print GetWorkqueueThreadRequestSummary(proc, req)
+
+ with O.table(GetWQThreadSummary.header, indent=True):
+ print ""
+ for uth in IterateTAILQ_HEAD(wq.wq_thrunlist, "uu_workq_entry"):
+ print GetWQThreadSummary(Cast(uth.uu_thread, 'struct thread *'), uth)
+ for uth in IterateTAILQ_HEAD(wq.wq_thidlelist, "uu_workq_entry"):
+ print GetWQThreadSummary(Cast(uth.uu_thread, 'struct thread *'), uth)
+ for uth in IterateTAILQ_HEAD(wq.wq_thnewlist, "uu_workq_entry"):
+ print GetWQThreadSummary(Cast(uth.uu_thread, 'struct thread *'), uth)
+
+@lldb_command('showallworkqueues', fancy=True)
+def ShowAllWorkqueues(cmd_args=None, cmd_options={}, O=None):
""" Display a summary of all the workqueues in the system
usage: showallworkqueues
"""
- print GetWorkqueueSummary.header
-
- for t in kern.tasks:
- proc = Cast(t.bsd_info, 'proc *')
- wq = Cast(proc.p_wqptr, "struct workqueue *");
- if wq:
- print GetWorkqueueSummary(proc, wq)
+ with O.table(GetWorkqueueSummary.header):
+ for t in kern.tasks:
+ proc = Cast(t.bsd_info, 'proc *')
+ wq = Cast(proc.p_wqptr, "struct workqueue *");
+ if wq:
+ print GetWorkqueueSummary(proc, wq)