schedgraph.py revision 152131
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 152131 2005-11-06 17:43:25Z rwatson $ 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. 38139366Sarr# - Rebuild kernel with proper changes to KERNCONF. 39139366Sarr# - Dump the trace to a file: 'ktrdump -ct > ktr.out' 40139366Sarr# - Run the python script: 'python schedgraph.py ktr.out' 41139366Sarr# 42139366Sarr# To do: 43139313Sjeff# 1) Add a per-thread summary display 44139313Sjeff# 2) Add bounding box style zoom. 45139313Sjeff# 3) Click to center. 46139313Sjeff# 4) Implement some sorting mechanism. 47139313Sjeff 48139313Sjeffticksps = None 49139313Sjeffstatus = None 50139313Sjeffconfigtypes = [] 51139313Sjeff 52139313Sjeffdef ticks2sec(ticks): 53139313Sjeff ns = ticksps / 1000000000 54139313Sjeff ticks /= ns 55139313Sjeff if (ticks < 1000): 56139313Sjeff return (str(ticks) + "ns") 57139313Sjeff ticks /= 1000 58139313Sjeff if (ticks < 1000): 59139313Sjeff return (str(ticks) + "us") 60139313Sjeff ticks /= 1000 61139313Sjeff if (ticks < 1000): 62139313Sjeff return (str(ticks) + "ms") 63139313Sjeff ticks /= 1000 64139313Sjeff return (str(ticks) + "s") 65139313Sjeff 66139313Sjeffclass Scaler(Frame): 67139313Sjeff def __init__(self, master, target): 68139313Sjeff Frame.__init__(self, master) 69139313Sjeff self.scale = Scale(self, command=self.scaleset, 70139313Sjeff from_=1000, to_=1000000, orient=HORIZONTAL, resolution=1000) 71139313Sjeff self.label = Label(self, text="Ticks per pixel") 72139313Sjeff self.label.pack(side=LEFT) 73139313Sjeff self.scale.pack(fill="both", expand=1) 74139313Sjeff self.target = target 75139313Sjeff self.scale.set(target.scaleget()) 76139313Sjeff self.initialized = 1 77139313Sjeff 78139313Sjeff def scaleset(self, value): 79139313Sjeff self.target.scaleset(int(value)) 80139313Sjeff 81139313Sjeff def set(self, value): 82139313Sjeff self.scale.set(value) 83139313Sjeff 84139313Sjeffclass Status(Frame): 85139313Sjeff def __init__(self, master): 86139313Sjeff Frame.__init__(self, master) 87139313Sjeff self.label = Label(self, bd=1, relief=SUNKEN, anchor=W) 88139313Sjeff self.label.pack(fill="both", expand=1) 89139313Sjeff self.clear() 90139313Sjeff 91139313Sjeff def set(self, str): 92139313Sjeff self.label.config(text=str) 93139313Sjeff 94139313Sjeff def clear(self): 95139313Sjeff self.label.config(text="") 96139313Sjeff 97139313Sjeff def startup(self, str): 98139313Sjeff self.set(str) 99139313Sjeff root.update() 100139313Sjeff 101139313Sjeffclass EventConf(Frame): 102139313Sjeff def __init__(self, master, name, color, enabled): 103139313Sjeff Frame.__init__(self, master) 104139313Sjeff self.name = name 105139313Sjeff self.color = StringVar() 106139313Sjeff self.color_default = color 107139313Sjeff self.color_current = color 108139313Sjeff self.color.set(color) 109139313Sjeff self.enabled = IntVar() 110139313Sjeff self.enabled_default = enabled 111139313Sjeff self.enabled_current = enabled 112139313Sjeff self.enabled.set(enabled) 113139313Sjeff self.draw() 114139313Sjeff 115139313Sjeff def draw(self): 116139313Sjeff self.label = Label(self, text=self.name, anchor=W) 117139313Sjeff self.sample = Canvas(self, width=24, height=24, 118139313Sjeff bg='grey') 119139313Sjeff self.rect = self.sample.create_rectangle(0, 0, 24, 24, 120139313Sjeff fill=self.color.get()) 121139313Sjeff self.list = OptionMenu(self, self.color, 122139313Sjeff "dark red", "red", "pink", 123139313Sjeff "dark orange", "orange", 124139313Sjeff "yellow", "light yellow", 125139313Sjeff "dark green", "green", "light green", 126139313Sjeff "dark blue", "blue", "light blue", 127139313Sjeff "dark violet", "violet", "purple", 128139313Sjeff "dark grey", "light grey", 129139313Sjeff "white", "black", 130139313Sjeff command=self.setcolor) 131139313Sjeff self.checkbox = Checkbutton(self, text="enabled", 132139313Sjeff variable=self.enabled) 133139313Sjeff self.label.grid(row=0, column=0, sticky=E+W) 134139313Sjeff self.sample.grid(row=0, column=1) 135139313Sjeff self.list.grid(row=0, column=2, sticky=E+W) 136139313Sjeff self.checkbox.grid(row=0, column=3) 137139313Sjeff self.columnconfigure(0, weight=1) 138139313Sjeff self.columnconfigure(2, minsize=110) 139139313Sjeff 140139313Sjeff def setcolor(self, color): 141139313Sjeff self.color.set(color) 142139313Sjeff self.sample.itemconfigure(self.rect, fill=color) 143139313Sjeff 144139313Sjeff def apply(self): 145139313Sjeff cchange = 0 146139313Sjeff echange = 0 147139313Sjeff if (self.color_current != self.color.get()): 148139313Sjeff cchange = 1 149139313Sjeff if (self.enabled_current != self.enabled.get()): 150139313Sjeff echange = 1 151139313Sjeff self.color_current = self.color.get() 152139313Sjeff self.enabled_current = self.enabled.get() 153139313Sjeff if (echange != 0): 154139313Sjeff if (self.enabled_current): 155139313Sjeff graph.setcolor(self.name, self.color_current) 156139313Sjeff else: 157139313Sjeff graph.hide(self.name) 158139313Sjeff return 159139313Sjeff if (cchange != 0): 160139313Sjeff graph.setcolor(self.name, self.color_current) 161139313Sjeff 162139313Sjeff def revert(self): 163139313Sjeff self.setcolor(self.color_current) 164139313Sjeff self.enabled.set(self.enabled_current) 165139313Sjeff 166139313Sjeff def default(self): 167139313Sjeff self.setcolor(self.color_default) 168139313Sjeff self.enabled.set(self.enabled_default) 169139313Sjeff 170139313Sjeffclass EventConfigure(Toplevel): 171139313Sjeff def __init__(self): 172139313Sjeff Toplevel.__init__(self) 173139313Sjeff self.resizable(0, 0) 174139313Sjeff self.title("Event Configuration") 175139313Sjeff self.items = LabelFrame(self, text="Event Type") 176139313Sjeff self.buttons = Frame(self) 177139313Sjeff self.drawbuttons() 178139313Sjeff self.items.grid(row=0, column=0, sticky=E+W) 179139313Sjeff self.columnconfigure(0, weight=1) 180139313Sjeff self.buttons.grid(row=1, column=0, sticky=E+W) 181139313Sjeff self.types = [] 182139313Sjeff self.irow = 0 183139313Sjeff for type in configtypes: 184139313Sjeff self.additem(type.name, type.color, type.enabled) 185139313Sjeff 186139313Sjeff def additem(self, name, color, enabled=1): 187139313Sjeff item = EventConf(self.items, name, color, enabled) 188139313Sjeff self.types.append(item) 189139313Sjeff item.grid(row=self.irow, column=0, sticky=E+W) 190139313Sjeff self.irow += 1 191139313Sjeff 192139313Sjeff def drawbuttons(self): 193139313Sjeff self.apply = Button(self.buttons, text="Apply", 194139313Sjeff command=self.apress) 195139313Sjeff self.revert = Button(self.buttons, text="Revert", 196139313Sjeff command=self.rpress) 197139313Sjeff self.default = Button(self.buttons, text="Default", 198139313Sjeff command=self.dpress) 199139313Sjeff self.apply.grid(row=0, column=0, sticky=E+W) 200139313Sjeff self.revert.grid(row=0, column=1, sticky=E+W) 201139313Sjeff self.default.grid(row=0, column=2, sticky=E+W) 202139313Sjeff self.buttons.columnconfigure(0, weight=1) 203139313Sjeff self.buttons.columnconfigure(1, weight=1) 204139313Sjeff self.buttons.columnconfigure(2, weight=1) 205139313Sjeff 206139313Sjeff def apress(self): 207139313Sjeff for item in self.types: 208139313Sjeff item.apply() 209139313Sjeff 210139313Sjeff def rpress(self): 211139313Sjeff for item in self.types: 212139313Sjeff item.revert() 213139313Sjeff 214139313Sjeff def dpress(self): 215139313Sjeff for item in self.types: 216139313Sjeff item.default() 217139313Sjeff 218139313Sjeffclass EventView(Toplevel): 219139313Sjeff def __init__(self, event, canvas): 220139313Sjeff Toplevel.__init__(self) 221139313Sjeff self.resizable(0, 0) 222139313Sjeff self.title("Event") 223139313Sjeff self.event = event 224139313Sjeff self.frame = Frame(self) 225139313Sjeff self.frame.grid(row=0, column=0, sticky=N+S+E+W) 226139313Sjeff self.buttons = Frame(self) 227139313Sjeff self.buttons.grid(row=1, column=0, sticky=E+W) 228139313Sjeff self.canvas = canvas 229139313Sjeff self.drawlabels() 230139313Sjeff self.drawbuttons() 231139313Sjeff event.displayref(canvas) 232139313Sjeff self.bind("<Destroy>", self.destroycb) 233139313Sjeff 234139313Sjeff def destroycb(self, event): 235139313Sjeff self.unbind("<Destroy>") 236139313Sjeff if (self.event != None): 237139313Sjeff self.event.displayunref(self.canvas) 238139313Sjeff self.event = None 239139313Sjeff self.destroy() 240139313Sjeff 241139313Sjeff def clearlabels(self): 242139313Sjeff for label in self.frame.grid_slaves(): 243139313Sjeff label.grid_remove() 244139313Sjeff 245139313Sjeff def drawlabels(self): 246139313Sjeff ypos = 0 247139313Sjeff labels = self.event.labels() 248139313Sjeff while (len(labels) < 7): 249139313Sjeff labels.append(("", "", 0)) 250139313Sjeff for label in labels: 251139313Sjeff name, value, linked = label 252139313Sjeff l = Label(self.frame, text=name, bd=1, width=15, 253139313Sjeff relief=SUNKEN, anchor=W) 254139313Sjeff if (linked): 255139313Sjeff fgcolor = "blue" 256139313Sjeff else: 257139313Sjeff fgcolor = "black" 258139313Sjeff r = Label(self.frame, text=value, bd=1, 259139313Sjeff relief=SUNKEN, anchor=W, fg=fgcolor) 260139313Sjeff l.grid(row=ypos, column=0, sticky=E+W) 261139313Sjeff r.grid(row=ypos, column=1, sticky=E+W) 262139313Sjeff if (linked): 263139313Sjeff r.bind("<Button-1>", self.linkpress) 264139313Sjeff ypos += 1 265139313Sjeff self.frame.columnconfigure(1, minsize=80) 266139313Sjeff 267139313Sjeff def drawbuttons(self): 268139313Sjeff self.back = Button(self.buttons, text="<", command=self.bpress) 269139313Sjeff self.forw = Button(self.buttons, text=">", command=self.fpress) 270139313Sjeff self.new = Button(self.buttons, text="new", command=self.npress) 271139313Sjeff self.back.grid(row=0, column=0, sticky=E+W) 272139313Sjeff self.forw.grid(row=0, column=1, sticky=E+W) 273139313Sjeff self.new.grid(row=0, column=2, sticky=E+W) 274139313Sjeff self.buttons.columnconfigure(2, weight=1) 275139313Sjeff 276139313Sjeff def newevent(self, event): 277139313Sjeff self.event.displayunref(self.canvas) 278139313Sjeff self.clearlabels() 279139313Sjeff self.event = event 280139313Sjeff self.event.displayref(self.canvas) 281139313Sjeff self.drawlabels() 282139313Sjeff 283139313Sjeff def npress(self): 284139313Sjeff EventView(self.event, self.canvas) 285139313Sjeff 286139313Sjeff def bpress(self): 287139313Sjeff prev = self.event.prev() 288139313Sjeff if (prev == None): 289139313Sjeff return 290139313Sjeff while (prev.real == 0): 291139313Sjeff prev = prev.prev() 292139313Sjeff if (prev == None): 293139313Sjeff return 294139313Sjeff self.newevent(prev) 295139313Sjeff 296139313Sjeff def fpress(self): 297139313Sjeff next = self.event.next() 298139313Sjeff if (next == None): 299139313Sjeff return 300139313Sjeff while (next.real == 0): 301139313Sjeff next = next.next() 302139313Sjeff if (next == None): 303139313Sjeff return 304139313Sjeff self.newevent(next) 305139313Sjeff 306139313Sjeff def linkpress(self, wevent): 307139313Sjeff event = self.event.getlinked() 308139313Sjeff if (event != None): 309139313Sjeff self.newevent(event) 310139313Sjeff 311139313Sjeffclass Event: 312139313Sjeff name = "none" 313139313Sjeff color = "grey" 314139313Sjeff def __init__(self, source, cpu, timestamp, last=0): 315139313Sjeff self.source = source 316139313Sjeff self.cpu = cpu 317139313Sjeff self.timestamp = int(timestamp) 318139313Sjeff self.entries = [] 319139313Sjeff self.real = 1 320139313Sjeff self.idx = None 321139313Sjeff self.state = 0 322139313Sjeff self.item = None 323139313Sjeff self.dispcnt = 0 324139313Sjeff self.linked = None 325139313Sjeff if (last): 326139313Sjeff source.lastevent(self) 327139313Sjeff else: 328139313Sjeff source.event(self) 329139313Sjeff 330139313Sjeff def status(self): 331139313Sjeff statstr = self.name + " " + self.source.name 332139313Sjeff statstr += " on: cpu" + str(self.cpu) 333139313Sjeff statstr += " at: " + str(self.timestamp) 334139313Sjeff statstr += self.stattxt() 335139313Sjeff status.set(statstr) 336139313Sjeff 337139313Sjeff def stattxt(self): 338139313Sjeff return "" 339139313Sjeff 340139313Sjeff def textadd(self, tuple): 341139313Sjeff pass 342139313Sjeff self.entries.append(tuple) 343139313Sjeff 344139313Sjeff def labels(self): 345139313Sjeff return [("Source:", self.source.name, 0), 346139313Sjeff ("Event:", self.name, 0), 347139313Sjeff ("CPU:", self.cpu, 0), 348139313Sjeff ("Timestamp:", self.timestamp, 0)] + self.entries 349139313Sjeff def mouseenter(self, canvas, item): 350139313Sjeff self.displayref(canvas) 351139313Sjeff self.status() 352139313Sjeff 353139313Sjeff def mouseexit(self, canvas, item): 354139313Sjeff self.displayunref(canvas) 355139313Sjeff status.clear() 356139313Sjeff 357139313Sjeff def mousepress(self, canvas, item): 358139313Sjeff EventView(self, canvas) 359139313Sjeff 360139313Sjeff def next(self): 361139313Sjeff return self.source.eventat(self.idx + 1) 362139313Sjeff 363139313Sjeff def prev(self): 364139313Sjeff return self.source.eventat(self.idx - 1) 365139313Sjeff 366139313Sjeff def displayref(self, canvas): 367139313Sjeff if (self.dispcnt == 0): 368139313Sjeff canvas.itemconfigure(self.item, width=2) 369139313Sjeff self.dispcnt += 1 370139313Sjeff 371139313Sjeff def displayunref(self, canvas): 372139313Sjeff self.dispcnt -= 1 373139313Sjeff if (self.dispcnt == 0): 374139313Sjeff canvas.itemconfigure(self.item, width=0) 375139313Sjeff canvas.tag_raise("point", "state") 376139313Sjeff 377139313Sjeff def getlinked(self): 378139313Sjeff return self.linked.findevent(self.timestamp) 379139313Sjeff 380139313Sjeffclass PointEvent(Event): 381139313Sjeff def __init__(self, thread, cpu, timestamp, last=0): 382139313Sjeff Event.__init__(self, thread, cpu, timestamp, last) 383139313Sjeff 384139313Sjeff def draw(self, canvas, xpos, ypos): 385139313Sjeff l = canvas.create_oval(xpos - 6, ypos + 1, xpos + 6, ypos - 11, 386139313Sjeff fill=self.color, tags=("all", "point", "event") 387139313Sjeff + (self.name,), width=0) 388139313Sjeff canvas.events[l] = self 389139313Sjeff self.item = l 390139313Sjeff if (self.enabled == 0): 391139313Sjeff canvas.itemconfigure(l, state="hidden") 392139313Sjeff 393139313Sjeff return (xpos) 394139313Sjeff 395139313Sjeffclass StateEvent(Event): 396139313Sjeff def __init__(self, thread, cpu, timestamp, last=0): 397139313Sjeff Event.__init__(self, thread, cpu, timestamp, last) 398139313Sjeff self.duration = 0 399139313Sjeff self.skipnext = 0 400139313Sjeff self.skipself = 0 401139313Sjeff self.state = 1 402139313Sjeff 403139313Sjeff def draw(self, canvas, xpos, ypos): 404139313Sjeff next = self.nextstate() 405139313Sjeff if (self.skipself == 1 or next == None): 406139313Sjeff return (xpos) 407139321Sjeff while (self.skipnext): 408139313Sjeff skipped = next 409139313Sjeff next.skipself = 1 410139313Sjeff next.real = 0 411139313Sjeff next = next.nextstate() 412139313Sjeff if (next == None): 413139313Sjeff next = skipped 414139321Sjeff self.skipnext -= 1 415139313Sjeff self.duration = next.timestamp - self.timestamp 416139313Sjeff delta = self.duration / canvas.ratio 417139313Sjeff l = canvas.create_rectangle(xpos, ypos, 418139313Sjeff xpos + delta, ypos - 10, fill=self.color, width=0, 419139313Sjeff tags=("all", "state", "event") + (self.name,)) 420139313Sjeff canvas.events[l] = self 421139313Sjeff self.item = l 422139313Sjeff if (self.enabled == 0): 423139313Sjeff canvas.itemconfigure(l, state="hidden") 424139313Sjeff 425139313Sjeff return (xpos + delta) 426139313Sjeff 427139313Sjeff def stattxt(self): 428139313Sjeff return " duration: " + ticks2sec(self.duration) 429139313Sjeff 430139313Sjeff def nextstate(self): 431139313Sjeff next = self.next() 432139313Sjeff while (next != None and next.state == 0): 433139313Sjeff next = next.next() 434139313Sjeff return (next) 435139313Sjeff 436139313Sjeff def labels(self): 437139313Sjeff return [("Source:", self.source.name, 0), 438139313Sjeff ("Event:", self.name, 0), 439139313Sjeff ("Timestamp:", self.timestamp, 0), 440139313Sjeff ("CPU:", self.cpu, 0), 441139313Sjeff ("Duration:", ticks2sec(self.duration), 0)] \ 442139313Sjeff + self.entries 443139313Sjeff 444139313Sjeffclass Count(Event): 445139313Sjeff name = "Count" 446139313Sjeff color = "red" 447139313Sjeff enabled = 1 448139313Sjeff def __init__(self, source, cpu, timestamp, count): 449139313Sjeff self.count = int(count) 450139313Sjeff Event.__init__(self, source, cpu, timestamp) 451139313Sjeff self.duration = 0 452139313Sjeff self.textadd(("count:", self.count, 0)) 453139313Sjeff 454139313Sjeff def draw(self, canvas, xpos, ypos): 455139313Sjeff next = self.next() 456139313Sjeff self.duration = next.timestamp - self.timestamp 457139313Sjeff delta = self.duration / canvas.ratio 458139313Sjeff yhight = self.source.yscale() * self.count 459139313Sjeff l = canvas.create_rectangle(xpos, ypos - yhight, 460139313Sjeff xpos + delta, ypos, fill=self.color, width=0, 461139313Sjeff tags=("all", "count", "event") + (self.name,)) 462139313Sjeff canvas.events[l] = self 463139313Sjeff self.item = l 464139313Sjeff if (self.enabled == 0): 465139313Sjeff canvas.itemconfigure(l, state="hidden") 466139313Sjeff return (xpos + delta) 467139313Sjeff 468139313Sjeff def stattxt(self): 469139313Sjeff return " count: " + str(self.count) 470139313Sjeff 471139313Sjeffconfigtypes.append(Count) 472139313Sjeff 473139313Sjeffclass Running(StateEvent): 474139313Sjeff name = "running" 475139313Sjeff color = "green" 476139313Sjeff enabled = 1 477139313Sjeff def __init__(self, thread, cpu, timestamp, prio): 478139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 479139313Sjeff self.prio = prio 480139313Sjeff self.textadd(("prio:", self.prio, 0)) 481139313Sjeff 482139313Sjeffconfigtypes.append(Running) 483139313Sjeff 484139313Sjeffclass Idle(StateEvent): 485139313Sjeff name = "idle" 486139313Sjeff color = "grey" 487139313Sjeff enabled = 0 488139313Sjeff def __init__(self, thread, cpu, timestamp, prio): 489139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 490139313Sjeff self.prio = prio 491139313Sjeff self.textadd(("prio:", self.prio, 0)) 492139313Sjeff 493139313Sjeffconfigtypes.append(Idle) 494139313Sjeff 495139313Sjeffclass Yielding(StateEvent): 496139313Sjeff name = "yielding" 497139313Sjeff color = "yellow" 498139313Sjeff enabled = 1 499139313Sjeff def __init__(self, thread, cpu, timestamp, prio): 500139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 501139321Sjeff self.skipnext = 2 502139313Sjeff self.prio = prio 503139313Sjeff self.textadd(("prio:", self.prio, 0)) 504139313Sjeff 505139313Sjeffconfigtypes.append(Yielding) 506139313Sjeff 507139313Sjeffclass Swapped(StateEvent): 508139313Sjeff name = "swapped" 509139313Sjeff color = "violet" 510139313Sjeff enabled = 1 511139313Sjeff def __init__(self, thread, cpu, timestamp, prio): 512139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 513139313Sjeff self.prio = prio 514139313Sjeff self.textadd(("prio:", self.prio, 0)) 515139313Sjeff 516139313Sjeffconfigtypes.append(Swapped) 517139313Sjeff 518139313Sjeffclass Suspended(StateEvent): 519139313Sjeff name = "suspended" 520139313Sjeff color = "purple" 521139313Sjeff enabled = 1 522139313Sjeff def __init__(self, thread, cpu, timestamp, prio): 523139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 524139313Sjeff self.prio = prio 525139313Sjeff self.textadd(("prio:", self.prio, 0)) 526139313Sjeff 527139313Sjeffconfigtypes.append(Suspended) 528139313Sjeff 529139313Sjeffclass Iwait(StateEvent): 530139313Sjeff name = "iwait" 531139313Sjeff color = "grey" 532139313Sjeff enabled = 0 533139313Sjeff def __init__(self, thread, cpu, timestamp, prio): 534139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 535139313Sjeff self.prio = prio 536139313Sjeff self.textadd(("prio:", self.prio, 0)) 537139313Sjeff 538139313Sjeffconfigtypes.append(Iwait) 539139313Sjeff 540139313Sjeffclass Preempted(StateEvent): 541139313Sjeff name = "preempted" 542139313Sjeff color = "red" 543139313Sjeff enabled = 1 544139313Sjeff def __init__(self, thread, cpu, timestamp, prio, bythread): 545139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 546139321Sjeff self.skipnext = 2 547139313Sjeff self.prio = prio 548139313Sjeff self.linked = bythread 549139313Sjeff self.textadd(("prio:", self.prio, 0)) 550139313Sjeff self.textadd(("by thread:", self.linked.name, 1)) 551139313Sjeff 552139313Sjeffconfigtypes.append(Preempted) 553139313Sjeff 554139313Sjeffclass Sleep(StateEvent): 555139313Sjeff name = "sleep" 556139313Sjeff color = "blue" 557139313Sjeff enabled = 1 558139313Sjeff def __init__(self, thread, cpu, timestamp, prio, wmesg): 559139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 560139313Sjeff self.prio = prio 561139313Sjeff self.wmesg = wmesg 562139313Sjeff self.textadd(("prio:", self.prio, 0)) 563139313Sjeff self.textadd(("wmesg:", self.wmesg, 0)) 564139313Sjeff 565139313Sjeff def stattxt(self): 566139313Sjeff statstr = StateEvent.stattxt(self) 567139313Sjeff statstr += " sleeping on: " + self.wmesg 568139313Sjeff return (statstr) 569139313Sjeff 570139313Sjeffconfigtypes.append(Sleep) 571139313Sjeff 572139313Sjeffclass Blocked(StateEvent): 573139313Sjeff name = "blocked" 574139313Sjeff color = "dark red" 575139313Sjeff enabled = 1 576139313Sjeff def __init__(self, thread, cpu, timestamp, prio, lock): 577139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 578139313Sjeff self.prio = prio 579139313Sjeff self.lock = lock 580139313Sjeff self.textadd(("prio:", self.prio, 0)) 581139313Sjeff self.textadd(("lock:", self.lock, 0)) 582139313Sjeff 583139313Sjeff def stattxt(self): 584139313Sjeff statstr = StateEvent.stattxt(self) 585139313Sjeff statstr += " blocked on: " + self.lock 586139313Sjeff return (statstr) 587139313Sjeff 588139313Sjeffconfigtypes.append(Blocked) 589139313Sjeff 590139313Sjeffclass KsegrpRunq(StateEvent): 591139313Sjeff name = "KsegrpRunq" 592139313Sjeff color = "orange" 593139313Sjeff enabled = 1 594139313Sjeff def __init__(self, thread, cpu, timestamp, prio, bythread): 595139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 596139313Sjeff self.prio = prio 597139313Sjeff self.linked = bythread 598139313Sjeff self.textadd(("prio:", self.prio, 0)) 599139313Sjeff self.textadd(("by thread:", self.linked.name, 1)) 600139313Sjeff 601139313Sjeffconfigtypes.append(KsegrpRunq) 602139313Sjeff 603139313Sjeffclass Runq(StateEvent): 604139313Sjeff name = "Runq" 605139313Sjeff color = "yellow" 606139313Sjeff enabled = 1 607139313Sjeff def __init__(self, thread, cpu, timestamp, prio, bythread): 608139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 609139313Sjeff self.prio = prio 610139313Sjeff self.linked = bythread 611139313Sjeff self.textadd(("prio:", self.prio, 0)) 612139313Sjeff self.textadd(("by thread:", self.linked.name, 1)) 613139313Sjeff 614139313Sjeffconfigtypes.append(Runq) 615139313Sjeff 616139313Sjeffclass Sched_exit(StateEvent): 617139313Sjeff name = "exit" 618139313Sjeff color = "grey" 619139313Sjeff enabled = 0 620139313Sjeff def __init__(self, thread, cpu, timestamp, prio): 621139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp) 622139313Sjeff self.name = "sched_exit" 623139313Sjeff self.prio = prio 624139313Sjeff self.textadd(("prio:", self.prio, 0)) 625139313Sjeff 626139313Sjeffconfigtypes.append(Sched_exit) 627139313Sjeff 628139313Sjeffclass Padevent(StateEvent): 629139313Sjeff def __init__(self, thread, cpu, timestamp, last=0): 630139313Sjeff StateEvent.__init__(self, thread, cpu, timestamp, last) 631139313Sjeff self.name = "pad" 632139313Sjeff self.real = 0 633139313Sjeff 634139313Sjeff def draw(self, canvas, xpos, ypos): 635139313Sjeff next = self.next() 636139313Sjeff if (next == None): 637139313Sjeff return (xpos) 638139313Sjeff self.duration = next.timestamp - self.timestamp 639139313Sjeff delta = self.duration / canvas.ratio 640139313Sjeff return (xpos + delta) 641139313Sjeff 642139313Sjeffclass Tick(PointEvent): 643139313Sjeff name = "tick" 644139313Sjeff color = "black" 645139313Sjeff enabled = 0 646139313Sjeff def __init__(self, thread, cpu, timestamp, prio, stathz): 647139313Sjeff PointEvent.__init__(self, thread, cpu, timestamp) 648139313Sjeff self.prio = prio 649139313Sjeff self.textadd(("prio:", self.prio, 0)) 650139313Sjeff 651139313Sjeffconfigtypes.append(Tick) 652139313Sjeff 653139313Sjeffclass Prio(PointEvent): 654139313Sjeff name = "prio" 655139313Sjeff color = "black" 656139313Sjeff enabled = 0 657139313Sjeff def __init__(self, thread, cpu, timestamp, prio, newprio, bythread): 658139313Sjeff PointEvent.__init__(self, thread, cpu, timestamp) 659139313Sjeff self.prio = prio 660139313Sjeff self.newprio = newprio 661139313Sjeff self.linked = bythread 662139313Sjeff self.textadd(("new prio:", self.newprio, 0)) 663139313Sjeff self.textadd(("prio:", self.prio, 0)) 664139313Sjeff if (self.linked != self.source): 665139313Sjeff self.textadd(("by thread:", self.linked.name, 1)) 666139313Sjeff else: 667139313Sjeff self.textadd(("by thread:", self.linked.name, 0)) 668139313Sjeff 669139313Sjeffconfigtypes.append(Prio) 670139313Sjeff 671139313Sjeffclass Lend(PointEvent): 672139313Sjeff name = "lend" 673139313Sjeff color = "black" 674139313Sjeff enabled = 0 675139313Sjeff def __init__(self, thread, cpu, timestamp, prio, tothread): 676139313Sjeff PointEvent.__init__(self, thread, cpu, timestamp) 677139313Sjeff self.prio = prio 678139313Sjeff self.linked = tothread 679139313Sjeff self.textadd(("prio:", self.prio, 0)) 680139313Sjeff self.textadd(("to thread:", self.linked.name, 1)) 681139313Sjeff 682139313Sjeffconfigtypes.append(Lend) 683139313Sjeff 684139313Sjeffclass Wokeup(PointEvent): 685139313Sjeff name = "wokeup" 686139313Sjeff color = "black" 687139313Sjeff enabled = 0 688139313Sjeff def __init__(self, thread, cpu, timestamp, ranthread): 689139313Sjeff PointEvent.__init__(self, thread, cpu, timestamp) 690139313Sjeff self.linked = ranthread 691139313Sjeff self.textadd(("ran thread:", self.linked.name, 1)) 692139313Sjeff 693139313Sjeffconfigtypes.append(Wokeup) 694139313Sjeff 695139313Sjeffclass EventSource: 696139313Sjeff def __init__(self, name): 697139313Sjeff self.name = name 698139313Sjeff self.events = [] 699139313Sjeff self.cpu = 0 700139313Sjeff self.cpux = 0 701139313Sjeff 702139313Sjeff def fixup(self): 703139313Sjeff pass 704139313Sjeff 705139313Sjeff def event(self, event): 706139313Sjeff self.events.insert(0, event) 707139313Sjeff 708139313Sjeff def remove(self, event): 709139313Sjeff self.events.remove(event) 710139313Sjeff 711139313Sjeff def lastevent(self, event): 712139313Sjeff self.events.append(event) 713139313Sjeff 714139313Sjeff def draw(self, canvas, ypos): 715139313Sjeff xpos = 10 716139313Sjeff self.cpux = 10 717139313Sjeff self.cpu = self.events[1].cpu 718139313Sjeff for i in range(0, len(self.events)): 719139313Sjeff self.events[i].idx = i 720139313Sjeff for event in self.events: 721139313Sjeff if (event.cpu != self.cpu and event.cpu != -1): 722139313Sjeff self.drawcpu(canvas, xpos, ypos) 723139313Sjeff self.cpux = xpos 724139313Sjeff self.cpu = event.cpu 725139313Sjeff xpos = event.draw(canvas, xpos, ypos) 726139313Sjeff self.drawcpu(canvas, xpos, ypos) 727139313Sjeff 728139313Sjeff def drawname(self, canvas, ypos): 729139313Sjeff ypos = ypos - (self.ysize() / 2) 730139313Sjeff canvas.create_text(10, ypos, anchor="w", text=self.name) 731139313Sjeff 732139313Sjeff def drawcpu(self, canvas, xpos, ypos): 733139313Sjeff cpu = int(self.cpu) 734139313Sjeff if (cpu == 0): 735139313Sjeff color = 'light grey' 736139313Sjeff elif (cpu == 1): 737139313Sjeff color = 'dark grey' 738139313Sjeff elif (cpu == 2): 739139313Sjeff color = 'light blue' 740139313Sjeff elif (cpu == 3): 741152131Srwatson color = 'light green' 742139313Sjeff else: 743152131Srwatson color = "white" 744139313Sjeff l = canvas.create_rectangle(self.cpux, 745139313Sjeff ypos - self.ysize() - canvas.bdheight, 746139313Sjeff xpos, ypos + canvas.bdheight, fill=color, width=0, 747139313Sjeff tags=("all", "cpuinfo")) 748139313Sjeff 749139313Sjeff def ysize(self): 750139313Sjeff return (None) 751139313Sjeff 752139313Sjeff def eventat(self, i): 753139313Sjeff if (i >= len(self.events)): 754139313Sjeff return (None) 755139313Sjeff event = self.events[i] 756139313Sjeff return (event) 757139313Sjeff 758139313Sjeff def findevent(self, timestamp): 759139313Sjeff for event in self.events: 760139313Sjeff if (event.timestamp >= timestamp and event.real): 761139313Sjeff return (event) 762139313Sjeff return (None) 763139313Sjeff 764139313Sjeffclass Thread(EventSource): 765139313Sjeff names = {} 766139313Sjeff def __init__(self, td, pcomm): 767139313Sjeff EventSource.__init__(self, pcomm) 768139313Sjeff self.str = td 769139313Sjeff try: 770139313Sjeff cnt = Thread.names[pcomm] 771139313Sjeff except: 772139313Sjeff Thread.names[pcomm] = 0 773139313Sjeff return 774139313Sjeff Thread.names[pcomm] = cnt + 1 775139313Sjeff 776139313Sjeff def fixup(self): 777139313Sjeff cnt = Thread.names[self.name] 778139313Sjeff if (cnt == 0): 779139313Sjeff return 780139313Sjeff cnt -= 1 781139313Sjeff Thread.names[self.name] = cnt 782139313Sjeff self.name += " td" + str(cnt) 783139313Sjeff 784139313Sjeff def ysize(self): 785139313Sjeff return (10) 786139313Sjeff 787139313Sjeffclass Counter(EventSource): 788139313Sjeff max = 0 789139313Sjeff def __init__(self, name): 790139313Sjeff EventSource.__init__(self, name) 791139313Sjeff 792139313Sjeff def event(self, event): 793139313Sjeff EventSource.event(self, event) 794139313Sjeff try: 795139313Sjeff count = event.count 796139313Sjeff except: 797139313Sjeff return 798139313Sjeff count = int(count) 799139313Sjeff if (count > Counter.max): 800139313Sjeff Counter.max = count 801139313Sjeff 802139313Sjeff def ysize(self): 803139313Sjeff return (80) 804139313Sjeff 805139313Sjeff def yscale(self): 806139313Sjeff return (self.ysize() / Counter.max) 807139313Sjeff 808139313Sjeff 809139313Sjeffclass KTRFile: 810139313Sjeff def __init__(self, file): 811139313Sjeff self.timestamp_first = None 812139313Sjeff self.timestamp_last = None 813139313Sjeff self.lineno = -1 814139313Sjeff self.threads = [] 815139313Sjeff self.sources = [] 816139313Sjeff self.ticks = {} 817139313Sjeff self.load = {} 818139313Sjeff 819139313Sjeff self.parse(file) 820139313Sjeff self.fixup() 821139313Sjeff global ticksps 822139313Sjeff ticksps = self.ticksps() 823139313Sjeff 824139313Sjeff def parse(self, file): 825139313Sjeff try: 826139313Sjeff ifp = open(file) 827139313Sjeff except: 828139313Sjeff print "Can't open", file 829139313Sjeff sys.exit(1) 830139313Sjeff 831139313Sjeff ktrhdr = "\s+\d+\s+(\d+)\s+(\d+)\s+" 832139313Sjeff tdname = "(\S+)\(([^)]*)\)" 833139313Sjeff 834139313Sjeff ktrstr = "mi_switch: " + tdname 835139313Sjeff ktrstr += " prio (\d+) inhibit (\d+) wmesg (\S+) lock (\S+)" 836139313Sjeff switchout_re = re.compile(ktrhdr + ktrstr) 837139313Sjeff 838139313Sjeff ktrstr = "mi_switch: " + tdname + " prio (\d+) idle" 839139313Sjeff idled_re = re.compile(ktrhdr + ktrstr) 840139313Sjeff 841139313Sjeff ktrstr = "mi_switch: " + tdname + " prio (\d+) preempted by " 842139313Sjeff ktrstr += tdname 843139313Sjeff preempted_re = re.compile(ktrhdr + ktrstr) 844139313Sjeff 845139313Sjeff ktrstr = "mi_switch: running " + tdname + " prio (\d+)" 846139313Sjeff switchin_re = re.compile(ktrhdr + ktrstr) 847139313Sjeff 848139313Sjeff ktrstr = "sched_add: " + tdname + " prio (\d+) by " + tdname 849139313Sjeff sched_add_re = re.compile(ktrhdr + ktrstr) 850139313Sjeff 851139313Sjeff ktrstr = "setrunqueue: " + tdname + " prio (\d+) by " + tdname 852139313Sjeff setrunqueue_re = re.compile(ktrhdr + ktrstr) 853139313Sjeff 854139313Sjeff ktrstr = "sched_rem: " + tdname + " prio (\d+) by " + tdname 855139313Sjeff sched_rem_re = re.compile(ktrhdr + ktrstr) 856139313Sjeff 857139313Sjeff ktrstr = "sched_exit_thread: " + tdname + " prio (\d+)" 858139313Sjeff sched_exit_re = re.compile(ktrhdr + ktrstr) 859139313Sjeff 860139313Sjeff ktrstr = "statclock: " + tdname + " prio (\d+)" 861139313Sjeff ktrstr += " stathz (\d+)" 862139313Sjeff sched_clock_re = re.compile(ktrhdr + ktrstr) 863139313Sjeff 864139313Sjeff ktrstr = "sched_prio: " + tdname + " prio (\d+)" 865139313Sjeff ktrstr += " newprio (\d+) by " + tdname 866139313Sjeff sched_prio_re = re.compile(ktrhdr + ktrstr) 867139313Sjeff 868139319Sjeff cpuload_re = re.compile(ktrhdr + "load: (\d+)") 869139319Sjeff loadglobal_re = re.compile(ktrhdr + "global load: (\d+)") 870139313Sjeff 871139313Sjeff parsers = [[cpuload_re, self.cpuload], 872139313Sjeff [loadglobal_re, self.loadglobal], 873139313Sjeff [switchin_re, self.switchin], 874139313Sjeff [switchout_re, self.switchout], 875139313Sjeff [sched_add_re, self.sched_add], 876139313Sjeff [setrunqueue_re, self.sched_rem], 877139313Sjeff [sched_prio_re, self.sched_prio], 878139313Sjeff [preempted_re, self.preempted], 879139313Sjeff [sched_rem_re, self.sched_rem], 880139313Sjeff [sched_exit_re, self.sched_exit], 881139313Sjeff [sched_clock_re, self.sched_clock], 882139313Sjeff [idled_re, self.idled]] 883139313Sjeff 884139313Sjeff for line in ifp.readlines(): 885139313Sjeff self.lineno += 1 886139313Sjeff if ((self.lineno % 1024) == 0): 887139313Sjeff status.startup("Parsing line " + 888139313Sjeff str(self.lineno)) 889139313Sjeff for p in parsers: 890139313Sjeff m = p[0].match(line) 891139313Sjeff if (m != None): 892139313Sjeff p[1](*m.groups()) 893139313Sjeff break 894139313Sjeff # if (m == None): 895139313Sjeff # print line, 896139313Sjeff 897139313Sjeff def checkstamp(self, timestamp): 898139313Sjeff timestamp = int(timestamp) 899139313Sjeff if (self.timestamp_first == None): 900139313Sjeff self.timestamp_first = timestamp 901139313Sjeff if (timestamp > self.timestamp_first): 902139313Sjeff print "Bad timestamp on line ", self.lineno 903139313Sjeff return (0) 904139313Sjeff self.timestamp_last = timestamp 905139313Sjeff return (1) 906139313Sjeff 907139313Sjeff def timespan(self): 908139313Sjeff return (self.timestamp_first - self.timestamp_last); 909139313Sjeff 910139313Sjeff def ticksps(self): 911139313Sjeff return (self.timespan() / self.ticks[0]) * int(self.stathz) 912139313Sjeff 913139313Sjeff def switchout(self, cpu, timestamp, td, pcomm, prio, inhibit, wmesg, lock): 914139313Sjeff TDI_SUSPENDED = 0x0001 915139313Sjeff TDI_SLEEPING = 0x0002 916139313Sjeff TDI_SWAPPED = 0x0004 917139313Sjeff TDI_LOCK = 0x0008 918139313Sjeff TDI_IWAIT = 0x0010 919139313Sjeff 920139313Sjeff if (self.checkstamp(timestamp) == 0): 921139313Sjeff return 922139313Sjeff inhibit = int(inhibit) 923139313Sjeff thread = self.findtd(td, pcomm) 924139313Sjeff if (inhibit & TDI_SWAPPED): 925139313Sjeff Swapped(thread, cpu, timestamp, prio) 926139313Sjeff elif (inhibit & TDI_SLEEPING): 927139313Sjeff Sleep(thread, cpu, timestamp, prio, wmesg) 928139313Sjeff elif (inhibit & TDI_LOCK): 929139313Sjeff Blocked(thread, cpu, timestamp, prio, lock) 930139313Sjeff elif (inhibit & TDI_IWAIT): 931139313Sjeff Iwait(thread, cpu, timestamp, prio) 932139313Sjeff elif (inhibit & TDI_SUSPENDED): 933139313Sjeff Suspended(thread, cpu, timestamp, prio) 934139313Sjeff elif (inhibit == 0): 935139313Sjeff Yielding(thread, cpu, timestamp, prio) 936139313Sjeff else: 937139313Sjeff print "Unknown event", inhibit 938139313Sjeff sys.exit(1) 939139313Sjeff 940139313Sjeff def idled(self, cpu, timestamp, td, pcomm, prio): 941139313Sjeff if (self.checkstamp(timestamp) == 0): 942139313Sjeff return 943139313Sjeff thread = self.findtd(td, pcomm) 944139313Sjeff Idle(thread, cpu, timestamp, prio) 945139313Sjeff 946139313Sjeff def preempted(self, cpu, timestamp, td, pcomm, prio, bytd, bypcomm): 947139313Sjeff if (self.checkstamp(timestamp) == 0): 948139313Sjeff return 949139313Sjeff thread = self.findtd(td, pcomm) 950139313Sjeff Preempted(thread, cpu, timestamp, prio, 951139313Sjeff self.findtd(bytd, bypcomm)) 952139313Sjeff 953139313Sjeff def switchin(self, cpu, timestamp, td, pcomm, prio): 954139313Sjeff if (self.checkstamp(timestamp) == 0): 955139313Sjeff return 956139313Sjeff thread = self.findtd(td, pcomm) 957139313Sjeff Running(thread, cpu, timestamp, prio) 958139313Sjeff 959139313Sjeff def sched_add(self, cpu, timestamp, td, pcomm, prio, bytd, bypcomm): 960139313Sjeff if (self.checkstamp(timestamp) == 0): 961139313Sjeff return 962139313Sjeff thread = self.findtd(td, pcomm) 963139313Sjeff bythread = self.findtd(bytd, bypcomm) 964139313Sjeff Runq(thread, cpu, timestamp, prio, bythread) 965139313Sjeff Wokeup(bythread, cpu, timestamp, thread) 966139313Sjeff 967139313Sjeff def sched_rem(self, cpu, timestamp, td, pcomm, prio, bytd, bypcomm): 968139313Sjeff if (self.checkstamp(timestamp) == 0): 969139313Sjeff return 970139313Sjeff thread = self.findtd(td, pcomm) 971139313Sjeff KsegrpRunq(thread, cpu, timestamp, prio, 972139313Sjeff self.findtd(bytd, bypcomm)) 973139313Sjeff 974139313Sjeff def sched_exit(self, cpu, timestamp, td, pcomm, prio): 975139313Sjeff if (self.checkstamp(timestamp) == 0): 976139313Sjeff return 977139313Sjeff thread = self.findtd(td, pcomm) 978139313Sjeff Sched_exit(thread, cpu, timestamp, prio) 979139313Sjeff 980139313Sjeff def sched_clock(self, cpu, timestamp, td, pcomm, prio, stathz): 981139313Sjeff if (self.checkstamp(timestamp) == 0): 982139313Sjeff return 983139313Sjeff self.stathz = stathz 984139313Sjeff cpu = int(cpu) 985139313Sjeff try: 986139313Sjeff ticks = self.ticks[cpu] 987139313Sjeff except: 988139313Sjeff self.ticks[cpu] = 0 989139313Sjeff self.ticks[cpu] += 1 990139313Sjeff thread = self.findtd(td, pcomm) 991139313Sjeff Tick(thread, cpu, timestamp, prio, stathz) 992139313Sjeff 993139313Sjeff def sched_prio(self, cpu, timestamp, td, pcomm, prio, newprio, bytd, bypcomm): 994139313Sjeff if (prio == newprio): 995139313Sjeff return 996139313Sjeff if (self.checkstamp(timestamp) == 0): 997139313Sjeff return 998139313Sjeff thread = self.findtd(td, pcomm) 999139313Sjeff bythread = self.findtd(bytd, bypcomm) 1000139313Sjeff Prio(thread, cpu, timestamp, prio, newprio, bythread) 1001139313Sjeff Lend(bythread, cpu, timestamp, newprio, thread) 1002139313Sjeff 1003139313Sjeff def cpuload(self, cpu, timestamp, count): 1004139320Sjeff if (self.checkstamp(timestamp) == 0): 1005139320Sjeff return 1006139313Sjeff cpu = int(cpu) 1007139313Sjeff try: 1008139313Sjeff load = self.load[cpu] 1009139313Sjeff except: 1010139313Sjeff load = Counter("cpu" + str(cpu) + " load") 1011139313Sjeff self.load[cpu] = load 1012139313Sjeff self.sources.insert(0, load) 1013139313Sjeff Count(load, cpu, timestamp, count) 1014139313Sjeff 1015139313Sjeff def loadglobal(self, cpu, timestamp, count): 1016139320Sjeff if (self.checkstamp(timestamp) == 0): 1017139320Sjeff return 1018139313Sjeff cpu = 0 1019139313Sjeff try: 1020139313Sjeff load = self.load[cpu] 1021139313Sjeff except: 1022139313Sjeff load = Counter("CPU load") 1023139313Sjeff self.load[cpu] = load 1024139313Sjeff self.sources.insert(0, load) 1025139313Sjeff Count(load, cpu, timestamp, count) 1026139313Sjeff 1027139313Sjeff def findtd(self, td, pcomm): 1028139313Sjeff for thread in self.threads: 1029139313Sjeff if (thread.str == td and thread.name == pcomm): 1030139313Sjeff return thread 1031139313Sjeff thread = Thread(td, pcomm) 1032139313Sjeff self.threads.append(thread) 1033139313Sjeff self.sources.append(thread) 1034139313Sjeff return (thread) 1035139313Sjeff 1036139313Sjeff def fixup(self): 1037139313Sjeff for source in self.sources: 1038139313Sjeff Padevent(source, -1, self.timestamp_last) 1039139313Sjeff Padevent(source, -1, self.timestamp_first, last=1) 1040139313Sjeff source.fixup() 1041139313Sjeff 1042139313Sjeffclass SchedDisplay(Canvas): 1043139313Sjeff def __init__(self, master): 1044139313Sjeff self.ratio = 1 1045139313Sjeff self.ktrfile = None 1046139313Sjeff self.sources = None 1047139313Sjeff self.bdheight = 10 1048139313Sjeff self.events = {} 1049139313Sjeff 1050139313Sjeff Canvas.__init__(self, master, width=800, height=500, bg='grey', 1051139313Sjeff scrollregion=(0, 0, 800, 500)) 1052139313Sjeff 1053139313Sjeff def setfile(self, ktrfile): 1054139313Sjeff self.ktrfile = ktrfile 1055139313Sjeff self.sources = ktrfile.sources 1056139313Sjeff 1057139313Sjeff def draw(self): 1058139313Sjeff ypos = 0 1059139313Sjeff xsize = self.xsize() 1060139313Sjeff for source in self.sources: 1061139313Sjeff status.startup("Drawing " + source.name) 1062139313Sjeff self.create_line(0, ypos, xsize, ypos, 1063139313Sjeff width=1, fill="black", tags=("all",)) 1064139313Sjeff ypos += self.bdheight 1065139313Sjeff ypos += source.ysize() 1066139313Sjeff source.draw(self, ypos) 1067139313Sjeff ypos += self.bdheight 1068139313Sjeff try: 1069139313Sjeff self.tag_raise("point", "state") 1070139313Sjeff self.tag_lower("cpuinfo", "all") 1071139313Sjeff except: 1072139313Sjeff pass 1073139313Sjeff self.create_line(0, ypos, xsize, ypos, 1074139313Sjeff width=1, fill="black", tags=("all",)) 1075139313Sjeff self.tag_bind("event", "<Enter>", self.mouseenter) 1076139313Sjeff self.tag_bind("event", "<Leave>", self.mouseexit) 1077139313Sjeff self.tag_bind("event", "<Button-1>", self.mousepress) 1078139313Sjeff 1079139313Sjeff def mouseenter(self, event): 1080139313Sjeff item, = self.find_withtag(CURRENT) 1081139313Sjeff event = self.events[item] 1082139313Sjeff event.mouseenter(self, item) 1083139313Sjeff 1084139313Sjeff def mouseexit(self, event): 1085139313Sjeff item, = self.find_withtag(CURRENT) 1086139313Sjeff event = self.events[item] 1087139313Sjeff event.mouseexit(self, item) 1088139313Sjeff 1089139313Sjeff def mousepress(self, event): 1090139313Sjeff item, = self.find_withtag(CURRENT) 1091139313Sjeff event = self.events[item] 1092139313Sjeff event.mousepress(self, item) 1093139313Sjeff 1094139313Sjeff def drawnames(self, canvas): 1095139313Sjeff status.startup("Drawing names") 1096139313Sjeff ypos = 0 1097139313Sjeff canvas.configure(scrollregion=(0, 0, 1098139313Sjeff canvas["width"], self.ysize())) 1099139313Sjeff for source in self.sources: 1100139313Sjeff canvas.create_line(0, ypos, canvas["width"], ypos, 1101139313Sjeff width=1, fill="black", tags=("all",)) 1102139313Sjeff ypos += self.bdheight 1103139313Sjeff ypos += source.ysize() 1104139313Sjeff source.drawname(canvas, ypos) 1105139313Sjeff ypos += self.bdheight 1106139313Sjeff canvas.create_line(0, ypos, canvas["width"], ypos, 1107139313Sjeff width=1, fill="black", tags=("all",)) 1108139313Sjeff 1109139313Sjeff def xsize(self): 1110139313Sjeff return ((self.ktrfile.timespan() / self.ratio) + 20) 1111139313Sjeff 1112139313Sjeff def ysize(self): 1113139313Sjeff ysize = 0 1114139313Sjeff for source in self.sources: 1115139313Sjeff ysize += source.ysize() + (self.bdheight * 2) 1116139313Sjeff return (ysize) 1117139313Sjeff 1118139313Sjeff def scaleset(self, ratio): 1119139313Sjeff if (self.ktrfile == None): 1120139313Sjeff return 1121139313Sjeff oldratio = self.ratio 1122139313Sjeff xstart, ystart = self.xview() 1123139313Sjeff length = (float(self["width"]) / self.xsize()) 1124139313Sjeff middle = xstart + (length / 2) 1125139313Sjeff 1126139313Sjeff self.ratio = ratio 1127139313Sjeff self.configure(scrollregion=(0, 0, self.xsize(), self.ysize())) 1128139313Sjeff self.scale("all", 0, 0, float(oldratio) / ratio, 1) 1129139313Sjeff 1130139313Sjeff length = (float(self["width"]) / self.xsize()) 1131139313Sjeff xstart = middle - (length / 2) 1132139313Sjeff self.xview_moveto(xstart) 1133139313Sjeff 1134139313Sjeff def scaleget(self): 1135139313Sjeff return self.ratio 1136139313Sjeff 1137139313Sjeff def setcolor(self, tag, color): 1138139313Sjeff self.itemconfigure(tag, state="normal", fill=color) 1139139313Sjeff 1140139313Sjeff def hide(self, tag): 1141139313Sjeff self.itemconfigure(tag, state="hidden") 1142139313Sjeff 1143139313Sjeffclass GraphMenu(Frame): 1144139313Sjeff def __init__(self, master): 1145139313Sjeff Frame.__init__(self, master, bd=2, relief=RAISED) 1146139313Sjeff self.view = Menubutton(self, text="Configure") 1147139313Sjeff self.viewmenu = Menu(self.view, tearoff=0) 1148139313Sjeff self.viewmenu.add_command(label="Events", 1149139313Sjeff command=self.econf) 1150139313Sjeff self.view["menu"] = self.viewmenu 1151139313Sjeff self.view.pack(side=LEFT) 1152139313Sjeff 1153139313Sjeff def econf(self): 1154139313Sjeff EventConfigure() 1155139313Sjeff 1156139313Sjeff 1157139313Sjeffclass SchedGraph(Frame): 1158139313Sjeff def __init__(self, master): 1159139313Sjeff Frame.__init__(self, master) 1160139313Sjeff self.menu = None 1161139313Sjeff self.names = None 1162139313Sjeff self.display = None 1163139313Sjeff self.scale = None 1164139313Sjeff self.status = None 1165139313Sjeff self.pack(expand=1, fill="both") 1166139313Sjeff self.buildwidgets() 1167139313Sjeff self.layout() 1168139313Sjeff self.draw(sys.argv[1]) 1169139313Sjeff 1170139313Sjeff def buildwidgets(self): 1171139313Sjeff global status 1172139313Sjeff self.menu = GraphMenu(self) 1173139313Sjeff self.display = SchedDisplay(self) 1174139313Sjeff self.names = Canvas(self, 1175139313Sjeff width=100, height=self.display["height"], 1176139313Sjeff bg='grey', scrollregion=(0, 0, 50, 100)) 1177139313Sjeff self.scale = Scaler(self, self.display) 1178139313Sjeff status = self.status = Status(self) 1179139313Sjeff self.scrollY = Scrollbar(self, orient="vertical", 1180139313Sjeff command=self.display_yview) 1181139313Sjeff self.display.scrollX = Scrollbar(self, orient="horizontal", 1182139313Sjeff command=self.display.xview) 1183139313Sjeff self.display["xscrollcommand"] = self.display.scrollX.set 1184139313Sjeff self.display["yscrollcommand"] = self.scrollY.set 1185139313Sjeff self.names["yscrollcommand"] = self.scrollY.set 1186139313Sjeff 1187139313Sjeff def layout(self): 1188139313Sjeff self.columnconfigure(1, weight=1) 1189139313Sjeff self.rowconfigure(1, weight=1) 1190139313Sjeff self.menu.grid(row=0, column=0, columnspan=3, sticky=E+W) 1191139313Sjeff self.names.grid(row=1, column=0, sticky=N+S) 1192139313Sjeff self.display.grid(row=1, column=1, sticky=W+E+N+S) 1193139313Sjeff self.scrollY.grid(row=1, column=2, sticky=N+S) 1194139313Sjeff self.display.scrollX.grid(row=2, column=0, columnspan=2, 1195139313Sjeff sticky=E+W) 1196139313Sjeff self.scale.grid(row=3, column=0, columnspan=3, sticky=E+W) 1197139313Sjeff self.status.grid(row=4, column=0, columnspan=3, sticky=E+W) 1198139313Sjeff 1199139313Sjeff def draw(self, file): 1200139313Sjeff self.master.update() 1201139313Sjeff ktrfile = KTRFile(file) 1202139313Sjeff self.display.setfile(ktrfile) 1203139313Sjeff self.display.drawnames(self.names) 1204139313Sjeff self.display.draw() 1205139313Sjeff self.scale.set(250000) 1206139313Sjeff self.display.xview_moveto(0) 1207139313Sjeff 1208139313Sjeff def display_yview(self, *args): 1209139313Sjeff self.names.yview(*args) 1210139313Sjeff self.display.yview(*args) 1211139313Sjeff 1212139313Sjeff def setcolor(self, tag, color): 1213139313Sjeff self.display.setcolor(tag, color) 1214139313Sjeff 1215139313Sjeff def hide(self, tag): 1216139313Sjeff self.display.hide(tag) 1217139313Sjeff 1218139313Sjeffif (len(sys.argv) != 2): 1219139313Sjeff print "usage:", sys.argv[0], "<ktr file>" 1220139313Sjeff sys.exit(1) 1221139313Sjeff 1222139313Sjeffroot = Tk() 1223139313Sjeffroot.title("Scheduler Graph") 1224139313Sjeffgraph = SchedGraph(root) 1225139313Sjeffroot.mainloop() 1226