X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/d9a64523371fa019c4575bb400cbbc3a50ac9903..refs/heads/master:/tools/lldbmacros/workqueue.py diff --git a/tools/lldbmacros/workqueue.py b/tools/lldbmacros/workqueue.py index dae699f27..a3b91bf26 100755 --- a/tools/lldbmacros/workqueue.py +++ b/tools/lldbmacros/workqueue.py @@ -68,17 +68,20 @@ def GetWQThreadSummary(th, uth): 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 = [] @@ -88,12 +91,17 @@ def GetWorkqueueThreadRequestSummary(proc, req): 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: @@ -103,74 +111,80 @@ def GetWorkqueueThreadRequestSummary(proc, req): 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 """ 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 """ 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)