schedgraph.py revision 173568
1139313Sjeff#!/usr/local/bin/python 2139313Sjeff 3139313Sjeff# Copyright (c) 2002-2003, Jeffrey Roberson <jeff@freebsd.org> 4139313Sjeff# All rights reserved. 5139313Sjeff# 6139313Sjeff# Redistribution and use in source and binary forms, with or without 7139313Sjeff# modification, are permitted provided that the following conditions 8139313Sjeff# are met: 9139313Sjeff# 1. Redistributions of source code must retain the above copyright 10139313Sjeff# notice unmodified, this list of conditions, and the following 11139313Sjeff# disclaimer. 12139313Sjeff# 2. Redistributions in binary form must reproduce the above copyright 13139313Sjeff# notice, this list of conditions and the following disclaimer in the 14139313Sjeff# documentation and/or other materials provided with the distribution. 15139313Sjeff# 16139313Sjeff# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17139313Sjeff# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18139313Sjeff# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19139313Sjeff# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20139313Sjeff# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21139313Sjeff# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22139313Sjeff# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23139313Sjeff# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24139313Sjeff# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25139313Sjeff# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26139313Sjeff# 27139313Sjeff# $FreeBSD: head/tools/sched/schedgraph.py 173568 2007-11-12 17:33:07Z jeff $ 28139313Sjeff 29139313Sjeffimport sys 30139313Sjeffimport re 31139313Sjefffrom Tkinter import * 32139313Sjeff 33139366Sarr# To use: 34139366Sarr# - Install the ports/x11-toolkits/py-tkinter package. 35139366Sarr# - Add KTR_SCHED to KTR_COMPILE and KTR_MASK in your KERNCONF 36139366Sarr# - It is encouraged to increase KTR_ENTRIES size to 32768 to gather 37139366Sarr# enough information for analysis. 38168940Skris# - Rebuild kernel with proper changes to KERNCONF and boot new kernel. 39168940Skris# - Run your workload to be profiled. 40168940Skris# - While the workload is continuing (i.e. before it finishes), disable 41168940Skris# KTR tracing by setting 'sysctl debug.ktr.mask=0'. This is necessary 42168940Skris# to avoid a race condition while running ktrdump, i.e. the KTR ring buffer 43168940Skris# will cycle a bit while ktrdump runs, and this confuses schedgraph because 44168940Skris# the timestamps appear to go backwards at some point. Stopping KTR logging 45168940Skris# while the workload is still running is to avoid wasting log entries on 46168940Skris# "idle" time at the end. 47139366Sarr# - Dump the trace to a file: 'ktrdump -ct > ktr.out' 48139366Sarr# - Run the python script: 'python schedgraph.py ktr.out' 49139366Sarr# 50139366Sarr# To do: 51139313Sjeff# 1) Add a per-thread summary display 52139313Sjeff# 2) Add bounding box style zoom. 53139313Sjeff# 3) Click to center. 54139313Sjeff# 4) Implement some sorting mechanism. 55168940Skris# 56168940Skris# BUGS: 1) Only 8 CPUs are supported, more CPUs require more choices of 57168940Skris# colours to represent them ;-) 58168940Skris# 2) Extremely short traces may cause a crash because the code 59168940Skris# assumes there is always at least one stathz entry logged, and 60168940Skris# the number of such events is used as a denominator 61139313Sjeff 62139313Sjeffticksps = None 63139313Sjeffstatus = None 64139313Sjeffconfigtypes = [] 65139313Sjeff 66139313Sjeffdef ticks2sec(ticks): 67166203Sjeff us = ticksps / 1000000 68166203Sjeff ticks /= us 69139313Sjeff if (ticks < 1000): 70139313Sjeff return (str(ticks) + "us") 71139313Sjeff ticks /= 1000 72139313Sjeff if (ticks < 1000): 73139313Sjeff return (str(ticks) + "ms") 74139313Sjeff ticks /= 1000 75139313Sjeff return (str(ticks) + "s") 76139313Sjeff 77139313Sjeffclass Scaler(Frame): 78139313Sjeff def __init__(self, master, target): 79139313Sjeff Frame.__init__(self, master) 80139313Sjeff self.scale = Scale(self, command=self.scaleset, 81166209Sjeff from_=1000, to_=10000000, orient=HORIZONTAL, 82166209Sjeff resolution=1000) 83139313Sjeff self.label = Label(self, text="Ticks per pixel") 84139313Sjeff self.label.pack(side=LEFT) 85139313Sjeff self.scale.pack(fill="both", expand=1) 86139313Sjeff self.target = target 87139313Sjeff self.scale.set(target.scaleget()) 88139313Sjeff self.initialized = 1 89139313Sjeff 90139313Sjeff def scaleset(self, value): 91139313Sjeff self.target.scaleset(int(value)) 92139313Sjeff 93139313Sjeff def set(self, value): 94139313Sjeff self.scale.set(value) 95139313Sjeff 96139313Sjeffclass Status(Frame): 97139313Sjeff def __init__(self, master): 98139313Sjeff Frame.__init__(self, master) 99139313Sjeff self.label = Label(self, bd=1, relief=SUNKEN, anchor=W) 100139313Sjeff self.label.pack(fill="both", expand=1) 101139313Sjeff self.clear() 102139313Sjeff 103139313Sjeff def set(self, str): 104139313Sjeff self.label.config(text=str) 105139313Sjeff 106139313Sjeff def clear(self): 107139313Sjeff self.label.config(text="") 108139313Sjeff 109139313Sjeff def startup(self, str): 110139313Sjeff self.set(str) 111139313Sjeff root.update() 112139313Sjeff 113139313Sjeffclass EventConf(Frame): 114139313Sjeff def __init__(self, master, name, color, enabled): 115139313Sjeff Frame.__init__(self, master) 116139313Sjeff self.name = name 117139313Sjeff self.color = StringVar() 118139313Sjeff self.color_default = color 119139313Sjeff self.color_current = color 120139313Sjeff self.color.set(color) 121139313Sjeff self.enabled = IntVar() 122139313Sjeff self.enabled_default = enabled 123139313Sjeff self.enabled_current = enabled 124139313Sjeff self.enabled.set(enabled) 125139313Sjeff self.draw() 126139313Sjeff 127139313Sjeff def draw(self): 128139313Sjeff self.label = Label(self, text=self.name, anchor=W) 129139313Sjeff self.sample = Canvas(self, width=24, height=24, 130139313Sjeff bg='grey') 131139313Sjeff self.rect = self.sample.create_rectangle(0, 0, 24, 24, 132139313Sjeff fill=self.color.get()) 133139313Sjeff self.list = OptionMenu(self, self.color, 134139313Sjeff "dark red", "red", "pink", 135139313Sjeff "dark orange", "orange", 136139313Sjeff "yellow", "light yellow", 137139313Sjeff "dark green", "green", "light green", 138139313Sjeff "dark blue", "blue", "light blue", 139139313Sjeff "dark violet", "violet", "purple", 140139313Sjeff "dark grey", "light grey", 141139313Sjeff "white", "black", 142139313Sjeff command=self.setcolor) 143139313Sjeff self.checkbox = Checkbutton(self, text="enabled", 144139313Sjeff variable=self.enabled) 145139313Sjeff self.label.grid(row=0, column=0, sticky=E+W) 146139313Sjeff self.sample.grid(row=0, column=1) 147139313Sjeff self.list.grid(row=0, column=2, sticky=E+W) 148139313Sjeff self.checkbox.grid(row=0, column=3) 149139313Sjeff self.columnconfigure(0, weight=1) 150139313Sjeff self.columnconfigure(2, minsize=110) 151139313Sjeff 152139313Sjeff def setcolor(self, color): 153139313Sjeff self.color.set(color) 154139313Sjeff self.sample.itemconfigure(self.rect, fill=color) 155139313Sjeff 156139313Sjeff def apply(self): 157139313Sjeff cchange = 0 158139313Sjeff echange = 0 159139313Sjeff if (self.color_current != self.color.get()): 160139313Sjeff cchange = 1 161139313Sjeff if (self.enabled_current != self.enabled.get()): 162139313Sjeff echange = 1 163139313Sjeff self.color_current = self.color.get() 164139313Sjeff self.enabled_current = self.enabled.get() 165139313Sjeff if (echange != 0): 166139313Sjeff if (self.enabled_current): 167139313Sjeff graph.setcolor(self.name, self.color_current) 168139313Sjeff else: 169139313Sjeff graph.hide(self.name) 170139313Sjeff return 171139313Sjeff if (cchange != 0): 172139313Sjeff graph.setcolor(self.name, self.color_current) 173139313Sjeff 174139313Sjeff def revert(self): 175139313Sjeff self.setcolor(self.color_current) 176139313Sjeff self.enabled.set(self.enabled_current) 177139313Sjeff 178139313Sjeff def default(self): 179139313Sjeff self.setcolor(self.color_default) 180139313Sjeff self.enabled.set(self.enabled_default) 181139313Sjeff 182139313Sjeffclass EventConfigure(Toplevel): 183139313Sjeff def __init__(self): 184139313Sjeff Toplevel.__init__(self) 185139313Sjeff self.resizable(0, 0) 186139313Sjeff self.title("Event Configuration") 187139313Sjeff self.items = LabelFrame(self, text="Event Type") 188139313Sjeff self.buttons = Frame(self) 189139313Sjeff self.drawbuttons() 190139313Sjeff self.items.grid(row=0, column=0, sticky=E+W) 191139313Sjeff self.columnconfigure(0, weight=1) 192139313Sjeff self.buttons.grid(row=1, column=0, sticky=E+W) 193139313Sjeff self.types = [] 194139313Sjeff self.irow = 0 195139313Sjeff for type in configtypes: 196139313Sjeff self.additem(type.name, type.color, type.enabled) 197139313Sjeff 198139313Sjeff def additem(self, name, color, enabled=1): 199139313Sjeff item = EventConf(self.items, name, color, enabled) 200139313Sjeff self.types.append(item) 201139313Sjeff item.grid(row=self.irow, column=0, sticky=E+W) 202139313Sjeff self.irow += 1 203139313Sjeff 204139313Sjeff def drawbuttons(self): 205139313Sjeff self.apply = Button(self.buttons, text="Apply", 206139313Sjeff command=self.apress) 207139313Sjeff self.revert = Button(self.buttons, text="Revert", 208139313Sjeff command=self.rpress) 209139313Sjeff self.default = Button(self.buttons, text="Default", 210139313Sjeff command=self.dpress) 211139313Sjeff self.apply.grid(row=0, column=0, sticky=E+W) 212139313Sjeff self.revert.grid(row=0, column=1, sticky=E+W) 213139313Sjeff self.default.grid(row=0, column=2, sticky=E+W) 214139313Sjeff self.buttons.columnconfigure(0, weight=1) 215139313Sjeff self.buttons.columnconfigure(1, weight=1) 216139313Sjeff self.buttons.columnconfigure(2, weight=1) 217139313Sjeff 218139313Sjeff def apress(self): 219139313Sjeff for item in self.types: 220139313Sjeff item.apply() 221139313Sjeff 222139313Sjeff def rpress(self): 223139313Sjeff for item in self.types: 224139313Sjeff item.revert() 225139313Sjeff 226139313Sjeff def dpress(self): 227139313Sjeff for item in self.types: 228139313Sjeff item.default() 229139313Sjeff 230139313Sjeffclass EventView(Toplevel): 231139313Sjeff def __init__(self, event, canvas): 232139313Sjeff Toplevel.__init__(self) 233139313Sjeff self.resizable(0, 0) 234139313Sjeff self.title("Event") 235139313Sjeff self.event = event 236139313Sjeff self.frame = Frame(self) 237139313Sjeff self.frame.grid(row=0, column=0, sticky=N+S+E+W) 238139313Sjeff self.buttons = Frame(self) 239139313Sjeff self.buttons.grid(row=1, column=0, sticky=E+W) 240139313Sjeff self.canvas = canvas 241139313Sjeff self.drawlabels() 242139313Sjeff self.drawbuttons() 243139313Sjeff event.displayref(canvas) 244139313Sjeff self.bind("<Destroy>", self.destroycb) 245139313Sjeff 246139313Sjeff def destroycb(self, event): 247139313Sjeff self.unbind("<Destroy>") 248139313Sjeff if (self.event != None): 249139313Sjeff self.event.displayunref(self.canvas) 250139313Sjeff self.event = None 251139313Sjeff self.destroy() 252139313Sjeff 253139313Sjeff def clearlabels(self): 254139313Sjeff for label in self.frame.grid_slaves(): 255139313Sjeff label.grid_remove() 256139313Sjeff 257139313Sjeff def drawlabels(self): 258139313Sjeff ypos = 0 259139313Sjeff labels = self.event.labels() 260139313Sjeff while (len(labels) < 7): 261139313Sjeff labels.append(("", "", 0)) 262139313Sjeff for label in labels: 263139313Sjeff name, value, linked = label 264139313Sjeff l = Label(self.frame, text=name, bd=1, width=15, 265139313Sjeff relief=SUNKEN, anchor=W) 266139313Sjeff if (linked): 267139313Sjeff fgcolor = "blue" 268139313Sjeff else: 269139313Sjeff fgcolor = "black" 270139313Sjeff r = Label(self.frame, text=value, bd=1, 271139313Sjeff relief=SUNKEN, anchor=W, fg=fgcolor) 272139313Sjeff l.grid(row=ypos, column=0, sticky=E+W) 273139313Sjeff r.grid(row=ypos, column=1, sticky=E+W) 274139313Sjeff if (linked): 275139313Sjeff r.bind("<Button-1>", self.linkpress) 276139313Sjeff ypos += 1 277139313Sjeff self.frame.columnconfigure(1, minsize=80) 278139313Sjeff 279139313Sjeff def drawbuttons(self): 280139313Sjeff self.back = Button(self.buttons, text="<", command=self.bpress) 281139313Sjeff self.forw = Button(self.buttons, text=">", command=self.fpress) 282139313Sjeff self.new = Button(self.buttons, text="new", command=self.npress) 283139313Sjeff self.back.grid(row=0, column=0, sticky=E+W) 284139313Sjeff self.forw.grid(row=0, column=1, sticky=E+W) 285139313Sjeff self.new.grid(row=0, column=2, sticky=E+W) 286139313Sjeff self.buttons.columnconfigure(2, weight=1) 287139313Sjeff 288139313Sjeff def newevent(self, event): 289139313Sjeff self.event.displayunref(self.canvas) 290139313Sjeff self.clearlabels() 291139313Sjeff self.event = event 292139313Sjeff self.event.displayref(self.canvas) 293139313Sjeff self.drawlabels() 294139313Sjeff 295139313Sjeff def npress(self): 296139313Sjeff EventView(self.event, self.canvas) 297139313Sjeff 298139313Sjeff def bpress(self): 299139313Sjeff prev = self.event.prev() 300139313Sjeff if (prev == None): 301139313Sjeff return 302139313Sjeff while (prev.real == 0): 303139313Sjeff prev = prev.prev() 304139313Sjeff if (prev == None): 305139313Sjeff return 306139313Sjeff self.newevent(prev) 307139313Sjeff 308139313Sjeff def fpress(self): 309139313Sjeff next = self.event.next() 310139313Sjeff if (next == None): 311139313Sjeff return 312139313Sjeff while (next.real == 0): 313139313Sjeff next = next.next() 314139313Sjeff if (next == None): 315139313Sjeff return 316139313Sjeff self.newevent(next) 317139313Sjeff 318139313Sjeff def linkpress(self, wevent): 319139313Sjeff event = self.event.getlinked() 320139313Sjeff if (event != None): 321139313Sjeff self.newevent(event) 322139313Sjeff 323139313Sjeffclass Event: 324139313Sjeff name = "none" 325139313Sjeff color = "grey" 326139313Sjeff def __init__(self, source, cpu, timestamp, last=0): 327139313Sjeff self.source = source 328139313Sjeff self.cpu = cpu 329139313Sjeff self.timestamp = int(timestamp) 330139313Sjeff self.entries = [] 331139313Sjeff self.real = 1 332139313Sjeff self.idx = None 333139313Sjeff self.state = 0 334139313Sjeff self.item = None 335139313Sjeff self.dispcnt = 0 336139313Sjeff self.linked = None 337139313Sjeff if (last): 338139313Sjeff source.lastevent(self) 339139313Sjeff else: 340139313Sjeff source.event(self) 341139313Sjeff 342139313Sjeff def status(self): 343139313Sjeff statstr = self.name + " " + self.source.name 344139313Sjeff statstr += " on: cpu" + str(self.cpu) 345139313Sjeff statstr += " at: " + str(self.timestamp) 346139313Sjeff statstr += self.stattxt() 347139313Sjeff status.set(statstr) 348139313Sjeff 349139313Sjeff def stattxt(self): 350139313Sjeff return "" 351139313Sjeff 352139313Sjeff def textadd(self, tuple): 353139313Sjeff pass 354139313Sjeff self.entries.append(tuple) 355139313Sjeff 356139313Sjeff def labels(self): 357139313Sjeff return [("Source:", self.source.name, 0), 358139313Sjeff ("Event:", self.name, 0), 359139313Sjeff ("CPU:", self.cpu, 0), 360139313Sjeff ("Timestamp:", self.timestamp, 0)] + self.entries 361139313Sjeff def mouseenter(self, canvas, item): 362139313Sjeff self.displayref(canvas) 363139313Sjeff self.status() 364139313Sjeff 365139313Sjeff def mouseexit(self, canvas, item): 366139313Sjeff self.displayunref(canvas) 367139313Sjeff status.clear() 368139313Sjeff 369139313Sjeff def mousepress(self, canvas, item): 370139313Sjeff EventView(self, canvas) 371139313Sjeff 372139313Sjeff def next(self): 373139313Sjeff return self.source.eventat(self.idx + 1) 374139313Sjeff 375139313Sjeff def prev(self): 376139313Sjeff return self.source.eventat(self.idx - 1) 377139313Sjeff 378139313Sjeff def displayref(self, canvas): 379139313Sjeff if (self.dispcnt == 0): 380139313Sjeff canvas.itemconfigure(self.item, width=2) 381139313Sjeff self.dispcnt += 1 382139313Sjeff 383139313Sjeff def displayunref(self, canvas): 384139313Sjeff self.dispcnt -= 1 385139313Sjeff if (self.dispcnt == 0): 386139313Sjeff canvas.itemconfigure(self.item, width=0) 387139313Sjeff canvas.tag_raise("point", "state") 388139313Sjeff 389139313Sjeff def getlinked(self): 390139313Sjeff return self.linked.findevent(self.timestamp) 391139313Sjeff 392139313Sjeffclass PointEvent(Event): 393139313Sjeff def __init__(self, thread, cpu, timestamp, last=0): 394139313Sjeff Event.__init__(self, thread, cpu, timestamp, last) 395139313Sjeff 396139313Sjeff def draw(self, canvas, xpos, ypos): 397139313Sjeff l = canvas.create_oval(xpos - 6, ypos + 1, xpos + 6, ypos - 11, 398139313Sjeff fill=self.color, tags=("all", "point", "event") 399139313Sjeff + (self.name,), width=0) 400139313Sjeff canvas.events[l] = self 401139313Sjeff self.item = l 402139313Sjeff if (self.enabled == 0): 403139313Sjeff canvas.itemconfigure(l, state="hidden") 404139313Sjeff 405139313Sjeff return (xpos) 406139313Sjeff 407139313Sjeffclass StateEvent(Event): 408139313Sjeff def __init__(self, thread, cpu, timestamp, last=0): 409139313Sjeff Event.__init__(self, thread, cpu, timestamp, last) 410139313Sjeff self.duration = 0 411139313Sjeff self.skipnext = 0 412139313Sjeff self.skipself = 0 413139313Sjeff self.state = 1 414139313Sjeff 415139313Sjeff def draw(self, canvas, xpos, ypos): 416139313Sjeff next = self.nextstate() 417139313Sjeff if (self.skipself == 1 or next == None): 418139313Sjeff return (xpos) 419139321Sjeff while (self.skipnext): 420139313Sjeff skipped = next 421139313Sjeff next.skipself = 1 422139313Sjeff next.real = 0 423139313Sjeff next = next.nextstate() 424139313Sjeff if (next == None): 425139313Sjeff next = skipped 426139321Sjeff self.skipnext -= 1 427139313Sjeff self.duration = next.timestamp - self.timestamp 428166209Sjeff if (self.duration < 0): 429166209Sjeff self.duration = 0 430166209Sjeff print "Unsynchronized timestamp" 431166209Sjeff print self.cpu, self.timestamp 432166209Sjeff print next.cpu, next.timestamp 433139313Sjeff delta = self.duration / canvas.ratio 434139313Sjeff l = canvas.create_rectangle(xpos, ypos, 435139313Sjeff xpos + delta, ypos - 10, fill=self.color, width=0, 436139313Sjeff tags=("all", "state", "event") + (self.name,)) 437139313Sjeff canvas.events[l] = self 438139313Sjeff self.item = l 439139313Sjeff if (self.enabled == 0): 440139313Sjeff canvas.itemconfigure(l, state="hidden") 441139313Sjeff 442139313Sjeff return (xpos + delta) 443139313Sjeff 444139313Sjeff def stattxt(self): 445139313Sjeff return " duration: " + ticks2sec(self.duration) 446139313Sjeff 447139313Sjeff def nextstate(self): 448139313Sjeff next = self.next() 449139313Sjeff while (next != None and next.state == 0): 450139313Sjeff next = next.next() 451139313Sjeff return (next) 452139313Sjeff 453139313Sjeff def labels(self): 454139313Sjeff return [("Source:", self.source.name, 0), 455139313Sjeff ("Event:", self.name, 0), 456139313Sjeff ("Timestamp:", self.timestamp, 0), 457139313Sjeff ("CPU:", self.cpu, 0), 458139313Sjeff ("Duration:", ticks2sec(self.duration), 0)] \ 459139313Sjeff + self.entries 460139313Sjeff 461139313Sjeffclass Count(Event): 462139313Sjeff name = "Count" 463139313Sjeff color = "red" 464139313Sjeff enabled = 1 465139313Sjeff def __init__(self, source, cpu, timestamp, count): 466139313Sjeff self.count = int(count) 467139313Sjeff Event.__init__(self, source, cpu, timestamp) 468139313Sjeff self.duration = 0 469139313Sjeff self.textadd(("count:", self.count, 0)) 470139313Sjeff 471139313Sjeff def draw(self, canvas, xpos, ypos): 472139313Sjeff next = self.next() 473139313Sjeff self.duration = next.timestamp - self.timestamp 474139313Sjeff delta = self.duration / canvas.ratio 475139313Sjeff yhight = self.source.yscale() * self.count 476139313Sjeff l = canvas.create_rectangle(xpos, ypos - yhight, 477139313Sjeff xpos + delta, ypos, fill=self.color, width=0, 478139313Sjeff tags=("all", "count", "event") + (self.name,)) 479139313Sjeff canvas.events[l] = self 480139313Sjeff self.item = l 481139313Sjeff if (self.enabled == 0): 482139313Sjeff canvas.itemconfigure(l, state="hidden") 483139313Sjeff return (xpos + delta) 484139313Sjeff 485139313Sjeff def stattxt(self): 486139313Sjeff return " count: " + str(self.count) 487139313Sjeff 488139313Sjeffconfigtypes.append(Count) 489139313Sjeff 490139313Sjeffclass Running(StateEvent): 491139313Sjeff name = "running" 492139313Sjeff color = "green" 493139313Sjeff enabled = 1 494139313Sjeff def __init__(self, thread, cpu, timestamp, prio): 495139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 496139313Sjeff self.prio = prio 497139313Sjeff self.textadd(("prio:", self.prio, 0)) 498139313Sjeff 499139313Sjeffconfigtypes.append(Running) 500139313Sjeff 501139313Sjeffclass Idle(StateEvent): 502139313Sjeff name = "idle" 503139313Sjeff color = "grey" 504139313Sjeff enabled = 0 505139313Sjeff def __init__(self, thread, cpu, timestamp, prio): 506139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 507139313Sjeff self.prio = prio 508139313Sjeff self.textadd(("prio:", self.prio, 0)) 509139313Sjeff 510139313Sjeffconfigtypes.append(Idle) 511139313Sjeff 512139313Sjeffclass Yielding(StateEvent): 513139313Sjeff name = "yielding" 514139313Sjeff color = "yellow" 515139313Sjeff enabled = 1 516139313Sjeff def __init__(self, thread, cpu, timestamp, prio): 517139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 518173568Sjeff self.skipnext = 0 519139313Sjeff self.prio = prio 520139313Sjeff self.textadd(("prio:", self.prio, 0)) 521139313Sjeff 522139313Sjeffconfigtypes.append(Yielding) 523139313Sjeff 524139313Sjeffclass Swapped(StateEvent): 525139313Sjeff name = "swapped" 526139313Sjeff color = "violet" 527139313Sjeff enabled = 1 528139313Sjeff def __init__(self, thread, cpu, timestamp, prio): 529139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 530139313Sjeff self.prio = prio 531139313Sjeff self.textadd(("prio:", self.prio, 0)) 532139313Sjeff 533139313Sjeffconfigtypes.append(Swapped) 534139313Sjeff 535139313Sjeffclass Suspended(StateEvent): 536139313Sjeff name = "suspended" 537139313Sjeff color = "purple" 538139313Sjeff enabled = 1 539139313Sjeff def __init__(self, thread, cpu, timestamp, prio): 540139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 541139313Sjeff self.prio = prio 542139313Sjeff self.textadd(("prio:", self.prio, 0)) 543139313Sjeff 544139313Sjeffconfigtypes.append(Suspended) 545139313Sjeff 546139313Sjeffclass Iwait(StateEvent): 547139313Sjeff name = "iwait" 548139313Sjeff color = "grey" 549139313Sjeff enabled = 0 550139313Sjeff def __init__(self, thread, cpu, timestamp, prio): 551139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 552139313Sjeff self.prio = prio 553139313Sjeff self.textadd(("prio:", self.prio, 0)) 554139313Sjeff 555139313Sjeffconfigtypes.append(Iwait) 556139313Sjeff 557139313Sjeffclass Preempted(StateEvent): 558139313Sjeff name = "preempted" 559139313Sjeff color = "red" 560139313Sjeff enabled = 1 561139313Sjeff def __init__(self, thread, cpu, timestamp, prio, bythread): 562139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 563166203Sjeff self.skipnext = 1 564139313Sjeff self.prio = prio 565139313Sjeff self.linked = bythread 566139313Sjeff self.textadd(("prio:", self.prio, 0)) 567139313Sjeff self.textadd(("by thread:", self.linked.name, 1)) 568139313Sjeff 569139313Sjeffconfigtypes.append(Preempted) 570139313Sjeff 571139313Sjeffclass Sleep(StateEvent): 572139313Sjeff name = "sleep" 573139313Sjeff color = "blue" 574139313Sjeff enabled = 1 575139313Sjeff def __init__(self, thread, cpu, timestamp, prio, wmesg): 576139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 577139313Sjeff self.prio = prio 578139313Sjeff self.wmesg = wmesg 579139313Sjeff self.textadd(("prio:", self.prio, 0)) 580139313Sjeff self.textadd(("wmesg:", self.wmesg, 0)) 581139313Sjeff 582139313Sjeff def stattxt(self): 583139313Sjeff statstr = StateEvent.stattxt(self) 584139313Sjeff statstr += " sleeping on: " + self.wmesg 585139313Sjeff return (statstr) 586139313Sjeff 587139313Sjeffconfigtypes.append(Sleep) 588139313Sjeff 589139313Sjeffclass Blocked(StateEvent): 590139313Sjeff name = "blocked" 591139313Sjeff color = "dark red" 592139313Sjeff enabled = 1 593139313Sjeff def __init__(self, thread, cpu, timestamp, prio, lock): 594139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 595139313Sjeff self.prio = prio 596139313Sjeff self.lock = lock 597139313Sjeff self.textadd(("prio:", self.prio, 0)) 598139313Sjeff self.textadd(("lock:", self.lock, 0)) 599139313Sjeff 600139313Sjeff def stattxt(self): 601139313Sjeff statstr = StateEvent.stattxt(self) 602139313Sjeff statstr += " blocked on: " + self.lock 603139313Sjeff return (statstr) 604139313Sjeff 605139313Sjeffconfigtypes.append(Blocked) 606139313Sjeff 607139313Sjeffclass KsegrpRunq(StateEvent): 608139313Sjeff name = "KsegrpRunq" 609139313Sjeff color = "orange" 610139313Sjeff enabled = 1 611139313Sjeff def __init__(self, thread, cpu, timestamp, prio, bythread): 612139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 613139313Sjeff self.prio = prio 614139313Sjeff self.linked = bythread 615139313Sjeff self.textadd(("prio:", self.prio, 0)) 616139313Sjeff self.textadd(("by thread:", self.linked.name, 1)) 617139313Sjeff 618139313Sjeffconfigtypes.append(KsegrpRunq) 619139313Sjeff 620139313Sjeffclass Runq(StateEvent): 621139313Sjeff name = "Runq" 622139313Sjeff color = "yellow" 623139313Sjeff enabled = 1 624139313Sjeff def __init__(self, thread, cpu, timestamp, prio, bythread): 625139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 626139313Sjeff self.prio = prio 627139313Sjeff self.linked = bythread 628139313Sjeff self.textadd(("prio:", self.prio, 0)) 629139313Sjeff self.textadd(("by thread:", self.linked.name, 1)) 630139313Sjeff 631139313Sjeffconfigtypes.append(Runq) 632139313Sjeff 633139313Sjeffclass Sched_exit(StateEvent): 634139313Sjeff name = "exit" 635139313Sjeff color = "grey" 636139313Sjeff enabled = 0 637139313Sjeff def __init__(self, thread, cpu, timestamp, prio): 638139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 639139313Sjeff self.name = "sched_exit" 640139313Sjeff self.prio = prio 641139313Sjeff self.textadd(("prio:", self.prio, 0)) 642139313Sjeff 643139313Sjeffconfigtypes.append(Sched_exit) 644139313Sjeff 645139313Sjeffclass Padevent(StateEvent): 646139313Sjeff def __init__(self, thread, cpu, timestamp, last=0): 647139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp, last) 648139313Sjeff self.name = "pad" 649139313Sjeff self.real = 0 650139313Sjeff 651139313Sjeff def draw(self, canvas, xpos, ypos): 652139313Sjeff next = self.next() 653139313Sjeff if (next == None): 654139313Sjeff return (xpos) 655139313Sjeff self.duration = next.timestamp - self.timestamp 656139313Sjeff delta = self.duration / canvas.ratio 657139313Sjeff return (xpos + delta) 658139313Sjeff 659139313Sjeffclass Tick(PointEvent): 660139313Sjeff name = "tick" 661139313Sjeff color = "black" 662139313Sjeff enabled = 0 663139313Sjeff def __init__(self, thread, cpu, timestamp, prio, stathz): 664139313Sjeff PointEvent.__init__(self, thread, cpu, timestamp) 665139313Sjeff self.prio = prio 666139313Sjeff self.textadd(("prio:", self.prio, 0)) 667139313Sjeff 668139313Sjeffconfigtypes.append(Tick) 669139313Sjeff 670139313Sjeffclass Prio(PointEvent): 671139313Sjeff name = "prio" 672139313Sjeff color = "black" 673139313Sjeff enabled = 0 674139313Sjeff def __init__(self, thread, cpu, timestamp, prio, newprio, bythread): 675139313Sjeff PointEvent.__init__(self, thread, cpu, timestamp) 676139313Sjeff self.prio = prio 677139313Sjeff self.newprio = newprio 678139313Sjeff self.linked = bythread 679139313Sjeff self.textadd(("new prio:", self.newprio, 0)) 680139313Sjeff self.textadd(("prio:", self.prio, 0)) 681139313Sjeff if (self.linked != self.source): 682139313Sjeff self.textadd(("by thread:", self.linked.name, 1)) 683139313Sjeff else: 684139313Sjeff self.textadd(("by thread:", self.linked.name, 0)) 685139313Sjeff 686139313Sjeffconfigtypes.append(Prio) 687139313Sjeff 688139313Sjeffclass Lend(PointEvent): 689139313Sjeff name = "lend" 690139313Sjeff color = "black" 691139313Sjeff enabled = 0 692139313Sjeff def __init__(self, thread, cpu, timestamp, prio, tothread): 693139313Sjeff PointEvent.__init__(self, thread, cpu, timestamp) 694139313Sjeff self.prio = prio 695139313Sjeff self.linked = tothread 696139313Sjeff self.textadd(("prio:", self.prio, 0)) 697139313Sjeff self.textadd(("to thread:", self.linked.name, 1)) 698139313Sjeff 699139313Sjeffconfigtypes.append(Lend) 700139313Sjeff 701139313Sjeffclass Wokeup(PointEvent): 702139313Sjeff name = "wokeup" 703139313Sjeff color = "black" 704139313Sjeff enabled = 0 705139313Sjeff def __init__(self, thread, cpu, timestamp, ranthread): 706139313Sjeff PointEvent.__init__(self, thread, cpu, timestamp) 707139313Sjeff self.linked = ranthread 708139313Sjeff self.textadd(("ran thread:", self.linked.name, 1)) 709139313Sjeff 710139313Sjeffconfigtypes.append(Wokeup) 711139313Sjeff 712139313Sjeffclass EventSource: 713139313Sjeff def __init__(self, name): 714139313Sjeff self.name = name 715139313Sjeff self.events = [] 716139313Sjeff self.cpu = 0 717139313Sjeff self.cpux = 0 718139313Sjeff 719139313Sjeff def fixup(self): 720139313Sjeff pass 721139313Sjeff 722139313Sjeff def event(self, event): 723139313Sjeff self.events.insert(0, event) 724139313Sjeff 725139313Sjeff def remove(self, event): 726139313Sjeff self.events.remove(event) 727139313Sjeff 728139313Sjeff def lastevent(self, event): 729139313Sjeff self.events.append(event) 730139313Sjeff 731139313Sjeff def draw(self, canvas, ypos): 732139313Sjeff xpos = 10 733139313Sjeff self.cpux = 10 734139313Sjeff self.cpu = self.events[1].cpu 735139313Sjeff for i in range(0, len(self.events)): 736139313Sjeff self.events[i].idx = i 737139313Sjeff for event in self.events: 738139313Sjeff if (event.cpu != self.cpu and event.cpu != -1): 739139313Sjeff self.drawcpu(canvas, xpos, ypos) 740139313Sjeff self.cpux = xpos 741139313Sjeff self.cpu = event.cpu 742139313Sjeff xpos = event.draw(canvas, xpos, ypos) 743139313Sjeff self.drawcpu(canvas, xpos, ypos) 744139313Sjeff 745139313Sjeff def drawname(self, canvas, ypos): 746139313Sjeff ypos = ypos - (self.ysize() / 2) 747139313Sjeff canvas.create_text(10, ypos, anchor="w", text=self.name) 748139313Sjeff 749139313Sjeff def drawcpu(self, canvas, xpos, ypos): 750139313Sjeff cpu = int(self.cpu) 751139313Sjeff if (cpu == 0): 752139313Sjeff color = 'light grey' 753139313Sjeff elif (cpu == 1): 754139313Sjeff color = 'dark grey' 755139313Sjeff elif (cpu == 2): 756139313Sjeff color = 'light blue' 757139313Sjeff elif (cpu == 3): 758152131Srwatson color = 'light green' 759165824Sjeff elif (cpu == 4): 760165824Sjeff color = 'blanched almond' 761165824Sjeff elif (cpu == 5): 762165824Sjeff color = 'slate grey' 763165824Sjeff elif (cpu == 6): 764165824Sjeff color = 'light slate blue' 765165824Sjeff elif (cpu == 7): 766165824Sjeff color = 'thistle' 767139313Sjeff else: 768152131Srwatson color = "white" 769139313Sjeff l = canvas.create_rectangle(self.cpux, 770139313Sjeff ypos - self.ysize() - canvas.bdheight, 771139313Sjeff xpos, ypos + canvas.bdheight, fill=color, width=0, 772139313Sjeff tags=("all", "cpuinfo")) 773139313Sjeff 774139313Sjeff def ysize(self): 775139313Sjeff return (None) 776139313Sjeff 777139313Sjeff def eventat(self, i): 778139313Sjeff if (i >= len(self.events)): 779139313Sjeff return (None) 780139313Sjeff event = self.events[i] 781139313Sjeff return (event) 782139313Sjeff 783139313Sjeff def findevent(self, timestamp): 784139313Sjeff for event in self.events: 785139313Sjeff if (event.timestamp >= timestamp and event.real): 786139313Sjeff return (event) 787139313Sjeff return (None) 788139313Sjeff 789139313Sjeffclass Thread(EventSource): 790139313Sjeff names = {} 791139313Sjeff def __init__(self, td, pcomm): 792139313Sjeff EventSource.__init__(self, pcomm) 793139313Sjeff self.str = td 794139313Sjeff try: 795139313Sjeff cnt = Thread.names[pcomm] 796139313Sjeff except: 797139313Sjeff Thread.names[pcomm] = 0 798139313Sjeff return 799139313Sjeff Thread.names[pcomm] = cnt + 1 800139313Sjeff 801139313Sjeff def fixup(self): 802139313Sjeff cnt = Thread.names[self.name] 803139313Sjeff if (cnt == 0): 804139313Sjeff return 805139313Sjeff cnt -= 1 806139313Sjeff Thread.names[self.name] = cnt 807139313Sjeff self.name += " td" + str(cnt) 808139313Sjeff 809139313Sjeff def ysize(self): 810139313Sjeff return (10) 811139313Sjeff 812139313Sjeffclass Counter(EventSource): 813139313Sjeff max = 0 814139313Sjeff def __init__(self, name): 815139313Sjeff EventSource.__init__(self, name) 816139313Sjeff 817139313Sjeff def event(self, event): 818139313Sjeff EventSource.event(self, event) 819139313Sjeff try: 820139313Sjeff count = event.count 821139313Sjeff except: 822139313Sjeff return 823139313Sjeff count = int(count) 824139313Sjeff if (count > Counter.max): 825139313Sjeff Counter.max = count 826139313Sjeff 827139313Sjeff def ysize(self): 828139313Sjeff return (80) 829139313Sjeff 830139313Sjeff def yscale(self): 831139313Sjeff return (self.ysize() / Counter.max) 832139313Sjeff 833139313Sjeff 834139313Sjeffclass KTRFile: 835139313Sjeff def __init__(self, file): 836166209Sjeff self.timestamp_first = {} 837166209Sjeff self.timestamp_last = {} 838166209Sjeff self.timestamp_adjust = {} 839166209Sjeff self.timestamp_f = None 840166209Sjeff self.timestamp_l = None 841139313Sjeff self.lineno = -1 842139313Sjeff self.threads = [] 843139313Sjeff self.sources = [] 844139313Sjeff self.ticks = {} 845139313Sjeff self.load = {} 846152663Sscottl self.crit = {} 847166209Sjeff self.stathz = 0 848139313Sjeff 849139313Sjeff self.parse(file) 850139313Sjeff self.fixup() 851139313Sjeff global ticksps 852166209Sjeff print "first", self.timestamp_f, "last", self.timestamp_l 853166209Sjeff print "time span", self.timespan() 854166209Sjeff print "stathz", self.stathz 855139313Sjeff ticksps = self.ticksps() 856166209Sjeff print "Ticks per second", ticksps 857139313Sjeff 858139313Sjeff def parse(self, file): 859139313Sjeff try: 860139313Sjeff ifp = open(file) 861139313Sjeff except: 862139313Sjeff print "Can't open", file 863139313Sjeff sys.exit(1) 864139313Sjeff 865173568Sjeff ktrhdr = "\s*\d+\s+(\d+)\s+(\d+)\s+" 866139313Sjeff tdname = "(\S+)\(([^)]*)\)" 867152663Sscottl crittdname = "(\S+)\s+\(\d+,\s+([^)]*)\)" 868139313Sjeff 869139313Sjeff ktrstr = "mi_switch: " + tdname 870139313Sjeff ktrstr += " prio (\d+) inhibit (\d+) wmesg (\S+) lock (\S+)" 871139313Sjeff switchout_re = re.compile(ktrhdr + ktrstr) 872139313Sjeff 873139313Sjeff ktrstr = "mi_switch: " + tdname + " prio (\d+) idle" 874139313Sjeff idled_re = re.compile(ktrhdr + ktrstr) 875139313Sjeff 876139313Sjeff ktrstr = "mi_switch: " + tdname + " prio (\d+) preempted by " 877139313Sjeff ktrstr += tdname 878139313Sjeff preempted_re = re.compile(ktrhdr + ktrstr) 879139313Sjeff 880139313Sjeff ktrstr = "mi_switch: running " + tdname + " prio (\d+)" 881139313Sjeff switchin_re = re.compile(ktrhdr + ktrstr) 882139313Sjeff 883139313Sjeff ktrstr = "sched_add: " + tdname + " prio (\d+) by " + tdname 884139313Sjeff sched_add_re = re.compile(ktrhdr + ktrstr) 885139313Sjeff 886139313Sjeff ktrstr = "setrunqueue: " + tdname + " prio (\d+) by " + tdname 887139313Sjeff setrunqueue_re = re.compile(ktrhdr + ktrstr) 888139313Sjeff 889139313Sjeff ktrstr = "sched_rem: " + tdname + " prio (\d+) by " + tdname 890139313Sjeff sched_rem_re = re.compile(ktrhdr + ktrstr) 891139313Sjeff 892139313Sjeff ktrstr = "sched_exit_thread: " + tdname + " prio (\d+)" 893139313Sjeff sched_exit_re = re.compile(ktrhdr + ktrstr) 894139313Sjeff 895139313Sjeff ktrstr = "statclock: " + tdname + " prio (\d+)" 896139313Sjeff ktrstr += " stathz (\d+)" 897139313Sjeff sched_clock_re = re.compile(ktrhdr + ktrstr) 898139313Sjeff 899139313Sjeff ktrstr = "sched_prio: " + tdname + " prio (\d+)" 900139313Sjeff ktrstr += " newprio (\d+) by " + tdname 901139313Sjeff sched_prio_re = re.compile(ktrhdr + ktrstr) 902139313Sjeff 903139319Sjeff cpuload_re = re.compile(ktrhdr + "load: (\d+)") 904173568Sjeff cpuload2_re = re.compile(ktrhdr + "cpu (\d+) load: (\d+)") 905139319Sjeff loadglobal_re = re.compile(ktrhdr + "global load: (\d+)") 906139313Sjeff 907152663Sscottl ktrstr = "critical_\S+ by thread " + crittdname + " to (\d+)" 908152663Sscottl critsec_re = re.compile(ktrhdr + ktrstr) 909152663Sscottl 910139313Sjeff parsers = [[cpuload_re, self.cpuload], 911173568Sjeff [cpuload2_re, self.cpuload2], 912139313Sjeff [loadglobal_re, self.loadglobal], 913139313Sjeff [switchin_re, self.switchin], 914139313Sjeff [switchout_re, self.switchout], 915139313Sjeff [sched_add_re, self.sched_add], 916139313Sjeff [setrunqueue_re, self.sched_rem], 917139313Sjeff [sched_prio_re, self.sched_prio], 918139313Sjeff [preempted_re, self.preempted], 919139313Sjeff [sched_rem_re, self.sched_rem], 920139313Sjeff [sched_exit_re, self.sched_exit], 921139313Sjeff [sched_clock_re, self.sched_clock], 922152663Sscottl [critsec_re, self.critsec], 923139313Sjeff [idled_re, self.idled]] 924139313Sjeff 925166209Sjeff lines = ifp.readlines() 926166209Sjeff self.synchstamp(lines) 927166209Sjeff for line in lines: 928139313Sjeff self.lineno += 1 929139313Sjeff if ((self.lineno % 1024) == 0): 930139313Sjeff status.startup("Parsing line " + 931139313Sjeff str(self.lineno)) 932139313Sjeff for p in parsers: 933139313Sjeff m = p[0].match(line) 934139313Sjeff if (m != None): 935139313Sjeff p[1](*m.groups()) 936139313Sjeff break 937173568Sjeff if (m == None): 938173568Sjeff print line, 939139313Sjeff 940166209Sjeff def synchstamp(self, lines): 941166209Sjeff status.startup("Rationalizing Timestamps") 942166209Sjeff tstamp_re = re.compile("\s+\d+\s+(\d+)\s+(\d+)\s+.*") 943166209Sjeff for line in lines: 944166209Sjeff m = tstamp_re.match(line) 945166209Sjeff if (m != None): 946166209Sjeff self.addstamp(*m.groups()) 947166209Sjeff self.pickstamp() 948166209Sjeff self.monostamp(lines) 949166209Sjeff 950166209Sjeff 951166209Sjeff def monostamp(self, lines): 952166209Sjeff laststamp = None 953166209Sjeff tstamp_re = re.compile("\s+\d+\s+(\d+)\s+(\d+)\s+.*") 954166209Sjeff for line in lines: 955166209Sjeff m = tstamp_re.match(line) 956166209Sjeff if (m == None): 957166209Sjeff continue 958166209Sjeff (cpu, timestamp) = m.groups() 959166209Sjeff timestamp = int(timestamp) 960166209Sjeff cpu = int(cpu) 961166209Sjeff timestamp -= self.timestamp_adjust[cpu] 962166209Sjeff if (laststamp != None and timestamp > laststamp): 963166209Sjeff self.timestamp_adjust[cpu] += timestamp - laststamp 964166209Sjeff laststamp = timestamp 965166209Sjeff 966166209Sjeff def addstamp(self, cpu, timestamp): 967139313Sjeff timestamp = int(timestamp) 968166209Sjeff cpu = int(cpu) 969166209Sjeff try: 970166209Sjeff if (timestamp > self.timestamp_first[cpu]): 971166209Sjeff return 972166209Sjeff except: 973166209Sjeff self.timestamp_first[cpu] = timestamp 974166209Sjeff self.timestamp_last[cpu] = timestamp 975166209Sjeff 976166209Sjeff def pickstamp(self): 977166209Sjeff base = self.timestamp_last[0] 978166209Sjeff for i in range(0, len(self.timestamp_last)): 979166209Sjeff if (self.timestamp_last[i] < base): 980166209Sjeff base = self.timestamp_last[i] 981166209Sjeff 982166209Sjeff print "Adjusting to base stamp", base 983166209Sjeff for i in range(0, len(self.timestamp_last)): 984166209Sjeff self.timestamp_adjust[i] = self.timestamp_last[i] - base; 985166209Sjeff print "CPU ", i, "adjust by ", self.timestamp_adjust[i] 986166209Sjeff 987166209Sjeff self.timestamp_f = 0 988166209Sjeff for i in range(0, len(self.timestamp_first)): 989166209Sjeff first = self.timestamp_first[i] - self.timestamp_adjust[i] 990166209Sjeff if (first > self.timestamp_f): 991166209Sjeff self.timestamp_f = first 992166209Sjeff 993166209Sjeff self.timestamp_l = 0 994166209Sjeff for i in range(0, len(self.timestamp_last)): 995166209Sjeff last = self.timestamp_last[i] - self.timestamp_adjust[i] 996166209Sjeff if (last > self.timestamp_l): 997166209Sjeff self.timestamp_l = last 998166209Sjeff 999166209Sjeff 1000166209Sjeff def checkstamp(self, cpu, timestamp): 1001166209Sjeff cpu = int(cpu) 1002166209Sjeff timestamp = int(timestamp) 1003166209Sjeff if (timestamp > self.timestamp_first[cpu]): 1004139313Sjeff print "Bad timestamp on line ", self.lineno 1005139313Sjeff return (0) 1006166209Sjeff timestamp -= self.timestamp_adjust[cpu] 1007166209Sjeff return (timestamp) 1008139313Sjeff 1009139313Sjeff def timespan(self): 1010166209Sjeff return (self.timestamp_f - self.timestamp_l); 1011139313Sjeff 1012139313Sjeff def ticksps(self): 1013139313Sjeff return (self.timespan() / self.ticks[0]) * int(self.stathz) 1014139313Sjeff 1015139313Sjeff def switchout(self, cpu, timestamp, td, pcomm, prio, inhibit, wmesg, lock): 1016139313Sjeff TDI_SUSPENDED = 0x0001 1017139313Sjeff TDI_SLEEPING = 0x0002 1018139313Sjeff TDI_SWAPPED = 0x0004 1019139313Sjeff TDI_LOCK = 0x0008 1020139313Sjeff TDI_IWAIT = 0x0010 1021139313Sjeff 1022166209Sjeff timestamp = self.checkstamp(cpu, timestamp) 1023166209Sjeff if (timestamp == 0): 1024139313Sjeff return 1025139313Sjeff inhibit = int(inhibit) 1026139313Sjeff thread = self.findtd(td, pcomm) 1027139313Sjeff if (inhibit & TDI_SWAPPED): 1028139313Sjeff Swapped(thread, cpu, timestamp, prio) 1029139313Sjeff elif (inhibit & TDI_SLEEPING): 1030139313Sjeff Sleep(thread, cpu, timestamp, prio, wmesg) 1031139313Sjeff elif (inhibit & TDI_LOCK): 1032139313Sjeff Blocked(thread, cpu, timestamp, prio, lock) 1033139313Sjeff elif (inhibit & TDI_IWAIT): 1034139313Sjeff Iwait(thread, cpu, timestamp, prio) 1035139313Sjeff elif (inhibit & TDI_SUSPENDED): 1036139313Sjeff Suspended(thread, cpu, timestamp, prio) 1037139313Sjeff elif (inhibit == 0): 1038139313Sjeff Yielding(thread, cpu, timestamp, prio) 1039139313Sjeff else: 1040139313Sjeff print "Unknown event", inhibit 1041139313Sjeff sys.exit(1) 1042139313Sjeff 1043139313Sjeff def idled(self, cpu, timestamp, td, pcomm, prio): 1044166209Sjeff timestamp = self.checkstamp(cpu, timestamp) 1045166209Sjeff if (timestamp == 0): 1046139313Sjeff return 1047139313Sjeff thread = self.findtd(td, pcomm) 1048139313Sjeff Idle(thread, cpu, timestamp, prio) 1049139313Sjeff 1050139313Sjeff def preempted(self, cpu, timestamp, td, pcomm, prio, bytd, bypcomm): 1051166209Sjeff timestamp = self.checkstamp(cpu, timestamp) 1052166209Sjeff if (timestamp == 0): 1053139313Sjeff return 1054139313Sjeff thread = self.findtd(td, pcomm) 1055139313Sjeff Preempted(thread, cpu, timestamp, prio, 1056139313Sjeff self.findtd(bytd, bypcomm)) 1057139313Sjeff 1058139313Sjeff def switchin(self, cpu, timestamp, td, pcomm, prio): 1059166209Sjeff timestamp = self.checkstamp(cpu, timestamp) 1060166209Sjeff if (timestamp == 0): 1061139313Sjeff return 1062139313Sjeff thread = self.findtd(td, pcomm) 1063139313Sjeff Running(thread, cpu, timestamp, prio) 1064139313Sjeff 1065139313Sjeff def sched_add(self, cpu, timestamp, td, pcomm, prio, bytd, bypcomm): 1066166209Sjeff timestamp = self.checkstamp(cpu, timestamp) 1067166209Sjeff if (timestamp == 0): 1068139313Sjeff return 1069139313Sjeff thread = self.findtd(td, pcomm) 1070139313Sjeff bythread = self.findtd(bytd, bypcomm) 1071139313Sjeff Runq(thread, cpu, timestamp, prio, bythread) 1072139313Sjeff Wokeup(bythread, cpu, timestamp, thread) 1073139313Sjeff 1074139313Sjeff def sched_rem(self, cpu, timestamp, td, pcomm, prio, bytd, bypcomm): 1075166209Sjeff timestamp = self.checkstamp(cpu, timestamp) 1076166209Sjeff if (timestamp == 0): 1077139313Sjeff return 1078139313Sjeff thread = self.findtd(td, pcomm) 1079139313Sjeff KsegrpRunq(thread, cpu, timestamp, prio, 1080139313Sjeff self.findtd(bytd, bypcomm)) 1081139313Sjeff 1082139313Sjeff def sched_exit(self, cpu, timestamp, td, pcomm, prio): 1083166209Sjeff timestamp = self.checkstamp(cpu, timestamp) 1084166209Sjeff if (timestamp == 0): 1085139313Sjeff return 1086139313Sjeff thread = self.findtd(td, pcomm) 1087139313Sjeff Sched_exit(thread, cpu, timestamp, prio) 1088139313Sjeff 1089139313Sjeff def sched_clock(self, cpu, timestamp, td, pcomm, prio, stathz): 1090166209Sjeff timestamp = self.checkstamp(cpu, timestamp) 1091166209Sjeff if (timestamp == 0): 1092139313Sjeff return 1093139313Sjeff self.stathz = stathz 1094139313Sjeff cpu = int(cpu) 1095139313Sjeff try: 1096139313Sjeff ticks = self.ticks[cpu] 1097139313Sjeff except: 1098139313Sjeff self.ticks[cpu] = 0 1099139313Sjeff self.ticks[cpu] += 1 1100139313Sjeff thread = self.findtd(td, pcomm) 1101139313Sjeff Tick(thread, cpu, timestamp, prio, stathz) 1102139313Sjeff 1103139313Sjeff def sched_prio(self, cpu, timestamp, td, pcomm, prio, newprio, bytd, bypcomm): 1104139313Sjeff if (prio == newprio): 1105139313Sjeff return 1106166209Sjeff timestamp = self.checkstamp(cpu, timestamp) 1107166209Sjeff if (timestamp == 0): 1108139313Sjeff return 1109139313Sjeff thread = self.findtd(td, pcomm) 1110139313Sjeff bythread = self.findtd(bytd, bypcomm) 1111139313Sjeff Prio(thread, cpu, timestamp, prio, newprio, bythread) 1112139313Sjeff Lend(bythread, cpu, timestamp, newprio, thread) 1113139313Sjeff 1114139313Sjeff def cpuload(self, cpu, timestamp, count): 1115166209Sjeff timestamp = self.checkstamp(cpu, timestamp) 1116166209Sjeff if (timestamp == 0): 1117139320Sjeff return 1118139313Sjeff cpu = int(cpu) 1119139313Sjeff try: 1120139313Sjeff load = self.load[cpu] 1121139313Sjeff except: 1122139313Sjeff load = Counter("cpu" + str(cpu) + " load") 1123139313Sjeff self.load[cpu] = load 1124139313Sjeff self.sources.insert(0, load) 1125139313Sjeff Count(load, cpu, timestamp, count) 1126139313Sjeff 1127173568Sjeff def cpuload2(self, cpu, timestamp, ncpu, count): 1128173568Sjeff timestamp = self.checkstamp(cpu, timestamp) 1129173568Sjeff if (timestamp == 0): 1130173568Sjeff return 1131173568Sjeff cpu = int(ncpu) 1132173568Sjeff try: 1133173568Sjeff load = self.load[cpu] 1134173568Sjeff except: 1135173568Sjeff load = Counter("cpu" + str(cpu) + " load") 1136173568Sjeff self.load[cpu] = load 1137173568Sjeff self.sources.insert(0, load) 1138173568Sjeff Count(load, cpu, timestamp, count) 1139173568Sjeff 1140139313Sjeff def loadglobal(self, cpu, timestamp, count): 1141166209Sjeff timestamp = self.checkstamp(cpu, timestamp) 1142166209Sjeff if (timestamp == 0): 1143139320Sjeff return 1144139313Sjeff cpu = 0 1145139313Sjeff try: 1146139313Sjeff load = self.load[cpu] 1147139313Sjeff except: 1148139313Sjeff load = Counter("CPU load") 1149139313Sjeff self.load[cpu] = load 1150139313Sjeff self.sources.insert(0, load) 1151139313Sjeff Count(load, cpu, timestamp, count) 1152139313Sjeff 1153152663Sscottl def critsec(self, cpu, timestamp, td, pcomm, to): 1154166209Sjeff timestamp = self.checkstamp(cpu, timestamp) 1155166209Sjeff if (timestamp == 0): 1156152663Sscottl return 1157152663Sscottl cpu = int(cpu) 1158152663Sscottl try: 1159152663Sscottl crit = self.crit[cpu] 1160152663Sscottl except: 1161152663Sscottl crit = Counter("Critical Section") 1162152663Sscottl self.crit[cpu] = crit 1163152663Sscottl self.sources.insert(0, crit) 1164152663Sscottl Count(crit, cpu, timestamp, to) 1165152663Sscottl 1166139313Sjeff def findtd(self, td, pcomm): 1167139313Sjeff for thread in self.threads: 1168139313Sjeff if (thread.str == td and thread.name == pcomm): 1169139313Sjeff return thread 1170139313Sjeff thread = Thread(td, pcomm) 1171139313Sjeff self.threads.append(thread) 1172139313Sjeff self.sources.append(thread) 1173139313Sjeff return (thread) 1174139313Sjeff 1175139313Sjeff def fixup(self): 1176139313Sjeff for source in self.sources: 1177166209Sjeff Padevent(source, -1, self.timestamp_l) 1178166209Sjeff Padevent(source, -1, self.timestamp_f, last=1) 1179139313Sjeff source.fixup() 1180139313Sjeff 1181139313Sjeffclass SchedDisplay(Canvas): 1182139313Sjeff def __init__(self, master): 1183139313Sjeff self.ratio = 1 1184139313Sjeff self.ktrfile = None 1185139313Sjeff self.sources = None 1186139313Sjeff self.bdheight = 10 1187139313Sjeff self.events = {} 1188139313Sjeff 1189139313Sjeff Canvas.__init__(self, master, width=800, height=500, bg='grey', 1190139313Sjeff scrollregion=(0, 0, 800, 500)) 1191139313Sjeff 1192139313Sjeff def setfile(self, ktrfile): 1193139313Sjeff self.ktrfile = ktrfile 1194139313Sjeff self.sources = ktrfile.sources 1195139313Sjeff 1196139313Sjeff def draw(self): 1197139313Sjeff ypos = 0 1198139313Sjeff xsize = self.xsize() 1199139313Sjeff for source in self.sources: 1200139313Sjeff status.startup("Drawing " + source.name) 1201139313Sjeff self.create_line(0, ypos, xsize, ypos, 1202139313Sjeff width=1, fill="black", tags=("all",)) 1203139313Sjeff ypos += self.bdheight 1204139313Sjeff ypos += source.ysize() 1205139313Sjeff source.draw(self, ypos) 1206139313Sjeff ypos += self.bdheight 1207139313Sjeff try: 1208139313Sjeff self.tag_raise("point", "state") 1209139313Sjeff self.tag_lower("cpuinfo", "all") 1210139313Sjeff except: 1211139313Sjeff pass 1212139313Sjeff self.create_line(0, ypos, xsize, ypos, 1213139313Sjeff width=1, fill="black", tags=("all",)) 1214139313Sjeff self.tag_bind("event", "<Enter>", self.mouseenter) 1215139313Sjeff self.tag_bind("event", "<Leave>", self.mouseexit) 1216139313Sjeff self.tag_bind("event", "<Button-1>", self.mousepress) 1217139313Sjeff 1218139313Sjeff def mouseenter(self, event): 1219139313Sjeff item, = self.find_withtag(CURRENT) 1220139313Sjeff event = self.events[item] 1221139313Sjeff event.mouseenter(self, item) 1222139313Sjeff 1223139313Sjeff def mouseexit(self, event): 1224139313Sjeff item, = self.find_withtag(CURRENT) 1225139313Sjeff event = self.events[item] 1226139313Sjeff event.mouseexit(self, item) 1227139313Sjeff 1228139313Sjeff def mousepress(self, event): 1229139313Sjeff item, = self.find_withtag(CURRENT) 1230139313Sjeff event = self.events[item] 1231139313Sjeff event.mousepress(self, item) 1232139313Sjeff 1233139313Sjeff def drawnames(self, canvas): 1234139313Sjeff status.startup("Drawing names") 1235139313Sjeff ypos = 0 1236139313Sjeff canvas.configure(scrollregion=(0, 0, 1237139313Sjeff canvas["width"], self.ysize())) 1238139313Sjeff for source in self.sources: 1239139313Sjeff canvas.create_line(0, ypos, canvas["width"], ypos, 1240139313Sjeff width=1, fill="black", tags=("all",)) 1241139313Sjeff ypos += self.bdheight 1242139313Sjeff ypos += source.ysize() 1243139313Sjeff source.drawname(canvas, ypos) 1244139313Sjeff ypos += self.bdheight 1245139313Sjeff canvas.create_line(0, ypos, canvas["width"], ypos, 1246139313Sjeff width=1, fill="black", tags=("all",)) 1247139313Sjeff 1248139313Sjeff def xsize(self): 1249139313Sjeff return ((self.ktrfile.timespan() / self.ratio) + 20) 1250139313Sjeff 1251139313Sjeff def ysize(self): 1252139313Sjeff ysize = 0 1253139313Sjeff for source in self.sources: 1254139313Sjeff ysize += source.ysize() + (self.bdheight * 2) 1255139313Sjeff return (ysize) 1256139313Sjeff 1257139313Sjeff def scaleset(self, ratio): 1258139313Sjeff if (self.ktrfile == None): 1259139313Sjeff return 1260139313Sjeff oldratio = self.ratio 1261139313Sjeff xstart, ystart = self.xview() 1262139313Sjeff length = (float(self["width"]) / self.xsize()) 1263139313Sjeff middle = xstart + (length / 2) 1264139313Sjeff 1265139313Sjeff self.ratio = ratio 1266139313Sjeff self.configure(scrollregion=(0, 0, self.xsize(), self.ysize())) 1267139313Sjeff self.scale("all", 0, 0, float(oldratio) / ratio, 1) 1268139313Sjeff 1269139313Sjeff length = (float(self["width"]) / self.xsize()) 1270139313Sjeff xstart = middle - (length / 2) 1271139313Sjeff self.xview_moveto(xstart) 1272139313Sjeff 1273139313Sjeff def scaleget(self): 1274139313Sjeff return self.ratio 1275139313Sjeff 1276139313Sjeff def setcolor(self, tag, color): 1277139313Sjeff self.itemconfigure(tag, state="normal", fill=color) 1278139313Sjeff 1279139313Sjeff def hide(self, tag): 1280139313Sjeff self.itemconfigure(tag, state="hidden") 1281139313Sjeff 1282139313Sjeffclass GraphMenu(Frame): 1283139313Sjeff def __init__(self, master): 1284139313Sjeff Frame.__init__(self, master, bd=2, relief=RAISED) 1285139313Sjeff self.view = Menubutton(self, text="Configure") 1286139313Sjeff self.viewmenu = Menu(self.view, tearoff=0) 1287139313Sjeff self.viewmenu.add_command(label="Events", 1288139313Sjeff command=self.econf) 1289139313Sjeff self.view["menu"] = self.viewmenu 1290139313Sjeff self.view.pack(side=LEFT) 1291139313Sjeff 1292139313Sjeff def econf(self): 1293139313Sjeff EventConfigure() 1294139313Sjeff 1295139313Sjeff 1296139313Sjeffclass SchedGraph(Frame): 1297139313Sjeff def __init__(self, master): 1298139313Sjeff Frame.__init__(self, master) 1299139313Sjeff self.menu = None 1300139313Sjeff self.names = None 1301139313Sjeff self.display = None 1302139313Sjeff self.scale = None 1303139313Sjeff self.status = None 1304139313Sjeff self.pack(expand=1, fill="both") 1305139313Sjeff self.buildwidgets() 1306139313Sjeff self.layout() 1307139313Sjeff self.draw(sys.argv[1]) 1308139313Sjeff 1309139313Sjeff def buildwidgets(self): 1310139313Sjeff global status 1311139313Sjeff self.menu = GraphMenu(self) 1312139313Sjeff self.display = SchedDisplay(self) 1313139313Sjeff self.names = Canvas(self, 1314139313Sjeff width=100, height=self.display["height"], 1315139313Sjeff bg='grey', scrollregion=(0, 0, 50, 100)) 1316139313Sjeff self.scale = Scaler(self, self.display) 1317139313Sjeff status = self.status = Status(self) 1318139313Sjeff self.scrollY = Scrollbar(self, orient="vertical", 1319139313Sjeff command=self.display_yview) 1320139313Sjeff self.display.scrollX = Scrollbar(self, orient="horizontal", 1321139313Sjeff command=self.display.xview) 1322139313Sjeff self.display["xscrollcommand"] = self.display.scrollX.set 1323139313Sjeff self.display["yscrollcommand"] = self.scrollY.set 1324139313Sjeff self.names["yscrollcommand"] = self.scrollY.set 1325139313Sjeff 1326139313Sjeff def layout(self): 1327139313Sjeff self.columnconfigure(1, weight=1) 1328139313Sjeff self.rowconfigure(1, weight=1) 1329139313Sjeff self.menu.grid(row=0, column=0, columnspan=3, sticky=E+W) 1330139313Sjeff self.names.grid(row=1, column=0, sticky=N+S) 1331139313Sjeff self.display.grid(row=1, column=1, sticky=W+E+N+S) 1332139313Sjeff self.scrollY.grid(row=1, column=2, sticky=N+S) 1333139313Sjeff self.display.scrollX.grid(row=2, column=0, columnspan=2, 1334139313Sjeff sticky=E+W) 1335139313Sjeff self.scale.grid(row=3, column=0, columnspan=3, sticky=E+W) 1336139313Sjeff self.status.grid(row=4, column=0, columnspan=3, sticky=E+W) 1337139313Sjeff 1338139313Sjeff def draw(self, file): 1339139313Sjeff self.master.update() 1340139313Sjeff ktrfile = KTRFile(file) 1341139313Sjeff self.display.setfile(ktrfile) 1342139313Sjeff self.display.drawnames(self.names) 1343139313Sjeff self.display.draw() 1344139313Sjeff self.scale.set(250000) 1345139313Sjeff self.display.xview_moveto(0) 1346139313Sjeff 1347139313Sjeff def display_yview(self, *args): 1348139313Sjeff self.names.yview(*args) 1349139313Sjeff self.display.yview(*args) 1350139313Sjeff 1351139313Sjeff def setcolor(self, tag, color): 1352139313Sjeff self.display.setcolor(tag, color) 1353139313Sjeff 1354139313Sjeff def hide(self, tag): 1355139313Sjeff self.display.hide(tag) 1356139313Sjeff 1357139313Sjeffif (len(sys.argv) != 2): 1358139313Sjeff print "usage:", sys.argv[0], "<ktr file>" 1359139313Sjeff sys.exit(1) 1360139313Sjeff 1361139313Sjeffroot = Tk() 1362139313Sjeffroot.title("Scheduler Graph") 1363139313Sjeffgraph = SchedGraph(root) 1364139313Sjeffroot.mainloop() 1365