xref: /freebsd/tools/sched/schedgraph.py (revision 0482a607bcd156e327e0bad22a1cb008e5e74878)
1dcee3bd3SJeff Roberson#!/usr/local/bin/python
2dcee3bd3SJeff Roberson
3dcee3bd3SJeff Roberson# Copyright (c) 2002-2003, Jeffrey Roberson <jeff@freebsd.org>
4dcee3bd3SJeff Roberson# All rights reserved.
5dcee3bd3SJeff Roberson#
6dcee3bd3SJeff Roberson# Redistribution and use in source and binary forms, with or without
7dcee3bd3SJeff Roberson# modification, are permitted provided that the following conditions
8dcee3bd3SJeff Roberson# are met:
9dcee3bd3SJeff Roberson# 1. Redistributions of source code must retain the above copyright
10dcee3bd3SJeff Roberson#    notice unmodified, this list of conditions, and the following
11dcee3bd3SJeff Roberson#    disclaimer.
12dcee3bd3SJeff Roberson# 2. Redistributions in binary form must reproduce the above copyright
13dcee3bd3SJeff Roberson#    notice, this list of conditions and the following disclaimer in the
14dcee3bd3SJeff Roberson#     documentation and/or other materials provided with the distribution.
15dcee3bd3SJeff Roberson#
16dcee3bd3SJeff Roberson# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17dcee3bd3SJeff Roberson# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18dcee3bd3SJeff Roberson# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19dcee3bd3SJeff Roberson# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20dcee3bd3SJeff Roberson# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21dcee3bd3SJeff Roberson# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22dcee3bd3SJeff Roberson# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23dcee3bd3SJeff Roberson# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24dcee3bd3SJeff Roberson# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25dcee3bd3SJeff Roberson# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26dcee3bd3SJeff Roberson#
27dcee3bd3SJeff Roberson# $FreeBSD$
28dcee3bd3SJeff Roberson
29dcee3bd3SJeff Robersonimport sys
30dcee3bd3SJeff Robersonimport re
31dcee3bd3SJeff Robersonfrom Tkinter import *
32dcee3bd3SJeff Roberson
33698e6141SAndrew R. Reiter# To use:
34698e6141SAndrew R. Reiter# - Install the ports/x11-toolkits/py-tkinter package.
35698e6141SAndrew R. Reiter# - Add KTR_SCHED to KTR_COMPILE and KTR_MASK in your KERNCONF
36698e6141SAndrew R. Reiter# - It is encouraged to increase KTR_ENTRIES size to 32768 to gather
37698e6141SAndrew R. Reiter#    enough information for analysis.
38698e6141SAndrew R. Reiter# - Rebuild kernel with proper changes to KERNCONF.
39698e6141SAndrew R. Reiter# - Dump the trace to a file: 'ktrdump -ct > ktr.out'
40698e6141SAndrew R. Reiter# - Run the python script: 'python schedgraph.py ktr.out'
41698e6141SAndrew R. Reiter#
42698e6141SAndrew R. Reiter# To do:
43dcee3bd3SJeff Roberson# 1)  Add a per-thread summary display
44dcee3bd3SJeff Roberson# 2)  Add bounding box style zoom.
45dcee3bd3SJeff Roberson# 3)  Click to center.
46dcee3bd3SJeff Roberson# 4)  Implement some sorting mechanism.
47dcee3bd3SJeff Roberson
48dcee3bd3SJeff Robersonticksps = None
49dcee3bd3SJeff Robersonstatus = None
50dcee3bd3SJeff Robersonconfigtypes = []
51dcee3bd3SJeff Roberson
52dcee3bd3SJeff Robersondef ticks2sec(ticks):
534a2e6a08SJeff Roberson	us = ticksps / 1000000
544a2e6a08SJeff Roberson	ticks /= us
55dcee3bd3SJeff Roberson	if (ticks < 1000):
56dcee3bd3SJeff Roberson		return (str(ticks) + "us")
57dcee3bd3SJeff Roberson	ticks /= 1000
58dcee3bd3SJeff Roberson	if (ticks < 1000):
59dcee3bd3SJeff Roberson		return (str(ticks) + "ms")
60dcee3bd3SJeff Roberson	ticks /= 1000
61dcee3bd3SJeff Roberson	return (str(ticks) + "s")
62dcee3bd3SJeff Roberson
63dcee3bd3SJeff Robersonclass Scaler(Frame):
64dcee3bd3SJeff Roberson	def __init__(self, master, target):
65dcee3bd3SJeff Roberson		Frame.__init__(self, master)
66dcee3bd3SJeff Roberson		self.scale = Scale(self, command=self.scaleset,
670482a607SJeff Roberson		    from_=1000, to_=10000000, orient=HORIZONTAL,
680482a607SJeff Roberson		    resolution=1000)
69dcee3bd3SJeff Roberson		self.label = Label(self, text="Ticks per pixel")
70dcee3bd3SJeff Roberson		self.label.pack(side=LEFT)
71dcee3bd3SJeff Roberson		self.scale.pack(fill="both", expand=1)
72dcee3bd3SJeff Roberson		self.target = target
73dcee3bd3SJeff Roberson		self.scale.set(target.scaleget())
74dcee3bd3SJeff Roberson		self.initialized = 1
75dcee3bd3SJeff Roberson
76dcee3bd3SJeff Roberson	def scaleset(self, value):
77dcee3bd3SJeff Roberson		self.target.scaleset(int(value))
78dcee3bd3SJeff Roberson
79dcee3bd3SJeff Roberson	def set(self, value):
80dcee3bd3SJeff Roberson		self.scale.set(value)
81dcee3bd3SJeff Roberson
82dcee3bd3SJeff Robersonclass Status(Frame):
83dcee3bd3SJeff Roberson	def __init__(self, master):
84dcee3bd3SJeff Roberson		Frame.__init__(self, master)
85dcee3bd3SJeff Roberson		self.label = Label(self, bd=1, relief=SUNKEN, anchor=W)
86dcee3bd3SJeff Roberson		self.label.pack(fill="both", expand=1)
87dcee3bd3SJeff Roberson		self.clear()
88dcee3bd3SJeff Roberson
89dcee3bd3SJeff Roberson	def set(self, str):
90dcee3bd3SJeff Roberson		self.label.config(text=str)
91dcee3bd3SJeff Roberson
92dcee3bd3SJeff Roberson	def clear(self):
93dcee3bd3SJeff Roberson		self.label.config(text="")
94dcee3bd3SJeff Roberson
95dcee3bd3SJeff Roberson	def startup(self, str):
96dcee3bd3SJeff Roberson		self.set(str)
97dcee3bd3SJeff Roberson		root.update()
98dcee3bd3SJeff Roberson
99dcee3bd3SJeff Robersonclass EventConf(Frame):
100dcee3bd3SJeff Roberson	def __init__(self, master, name, color, enabled):
101dcee3bd3SJeff Roberson		Frame.__init__(self, master)
102dcee3bd3SJeff Roberson		self.name = name
103dcee3bd3SJeff Roberson		self.color = StringVar()
104dcee3bd3SJeff Roberson		self.color_default = color
105dcee3bd3SJeff Roberson		self.color_current = color
106dcee3bd3SJeff Roberson		self.color.set(color)
107dcee3bd3SJeff Roberson		self.enabled = IntVar()
108dcee3bd3SJeff Roberson		self.enabled_default = enabled
109dcee3bd3SJeff Roberson		self.enabled_current = enabled
110dcee3bd3SJeff Roberson		self.enabled.set(enabled)
111dcee3bd3SJeff Roberson		self.draw()
112dcee3bd3SJeff Roberson
113dcee3bd3SJeff Roberson	def draw(self):
114dcee3bd3SJeff Roberson		self.label = Label(self, text=self.name, anchor=W)
115dcee3bd3SJeff Roberson		self.sample = Canvas(self, width=24, height=24,
116dcee3bd3SJeff Roberson		    bg='grey')
117dcee3bd3SJeff Roberson		self.rect = self.sample.create_rectangle(0, 0, 24, 24,
118dcee3bd3SJeff Roberson		    fill=self.color.get())
119dcee3bd3SJeff Roberson		self.list = OptionMenu(self, self.color,
120dcee3bd3SJeff Roberson		    "dark red", "red", "pink",
121dcee3bd3SJeff Roberson		    "dark orange", "orange",
122dcee3bd3SJeff Roberson		    "yellow", "light yellow",
123dcee3bd3SJeff Roberson		    "dark green", "green", "light green",
124dcee3bd3SJeff Roberson		    "dark blue", "blue", "light blue",
125dcee3bd3SJeff Roberson		    "dark violet", "violet", "purple",
126dcee3bd3SJeff Roberson		    "dark grey", "light grey",
127dcee3bd3SJeff Roberson		    "white", "black",
128dcee3bd3SJeff Roberson		    command=self.setcolor)
129dcee3bd3SJeff Roberson		self.checkbox = Checkbutton(self, text="enabled",
130dcee3bd3SJeff Roberson		    variable=self.enabled)
131dcee3bd3SJeff Roberson		self.label.grid(row=0, column=0, sticky=E+W)
132dcee3bd3SJeff Roberson		self.sample.grid(row=0, column=1)
133dcee3bd3SJeff Roberson		self.list.grid(row=0, column=2, sticky=E+W)
134dcee3bd3SJeff Roberson		self.checkbox.grid(row=0, column=3)
135dcee3bd3SJeff Roberson		self.columnconfigure(0, weight=1)
136dcee3bd3SJeff Roberson		self.columnconfigure(2, minsize=110)
137dcee3bd3SJeff Roberson
138dcee3bd3SJeff Roberson	def setcolor(self, color):
139dcee3bd3SJeff Roberson		self.color.set(color)
140dcee3bd3SJeff Roberson		self.sample.itemconfigure(self.rect, fill=color)
141dcee3bd3SJeff Roberson
142dcee3bd3SJeff Roberson	def apply(self):
143dcee3bd3SJeff Roberson		cchange = 0
144dcee3bd3SJeff Roberson		echange = 0
145dcee3bd3SJeff Roberson		if (self.color_current != self.color.get()):
146dcee3bd3SJeff Roberson			cchange = 1
147dcee3bd3SJeff Roberson		if (self.enabled_current != self.enabled.get()):
148dcee3bd3SJeff Roberson			echange = 1
149dcee3bd3SJeff Roberson		self.color_current = self.color.get()
150dcee3bd3SJeff Roberson		self.enabled_current = self.enabled.get()
151dcee3bd3SJeff Roberson		if (echange != 0):
152dcee3bd3SJeff Roberson			if (self.enabled_current):
153dcee3bd3SJeff Roberson				graph.setcolor(self.name, self.color_current)
154dcee3bd3SJeff Roberson			else:
155dcee3bd3SJeff Roberson				graph.hide(self.name)
156dcee3bd3SJeff Roberson			return
157dcee3bd3SJeff Roberson		if (cchange != 0):
158dcee3bd3SJeff Roberson			graph.setcolor(self.name, self.color_current)
159dcee3bd3SJeff Roberson
160dcee3bd3SJeff Roberson	def revert(self):
161dcee3bd3SJeff Roberson		self.setcolor(self.color_current)
162dcee3bd3SJeff Roberson		self.enabled.set(self.enabled_current)
163dcee3bd3SJeff Roberson
164dcee3bd3SJeff Roberson	def default(self):
165dcee3bd3SJeff Roberson		self.setcolor(self.color_default)
166dcee3bd3SJeff Roberson		self.enabled.set(self.enabled_default)
167dcee3bd3SJeff Roberson
168dcee3bd3SJeff Robersonclass EventConfigure(Toplevel):
169dcee3bd3SJeff Roberson	def __init__(self):
170dcee3bd3SJeff Roberson		Toplevel.__init__(self)
171dcee3bd3SJeff Roberson		self.resizable(0, 0)
172dcee3bd3SJeff Roberson		self.title("Event Configuration")
173dcee3bd3SJeff Roberson		self.items = LabelFrame(self, text="Event Type")
174dcee3bd3SJeff Roberson		self.buttons = Frame(self)
175dcee3bd3SJeff Roberson		self.drawbuttons()
176dcee3bd3SJeff Roberson		self.items.grid(row=0, column=0, sticky=E+W)
177dcee3bd3SJeff Roberson		self.columnconfigure(0, weight=1)
178dcee3bd3SJeff Roberson		self.buttons.grid(row=1, column=0, sticky=E+W)
179dcee3bd3SJeff Roberson		self.types = []
180dcee3bd3SJeff Roberson		self.irow = 0
181dcee3bd3SJeff Roberson		for type in configtypes:
182dcee3bd3SJeff Roberson			self.additem(type.name, type.color, type.enabled)
183dcee3bd3SJeff Roberson
184dcee3bd3SJeff Roberson	def additem(self, name, color, enabled=1):
185dcee3bd3SJeff Roberson		item = EventConf(self.items, name, color, enabled)
186dcee3bd3SJeff Roberson		self.types.append(item)
187dcee3bd3SJeff Roberson		item.grid(row=self.irow, column=0, sticky=E+W)
188dcee3bd3SJeff Roberson		self.irow += 1
189dcee3bd3SJeff Roberson
190dcee3bd3SJeff Roberson	def drawbuttons(self):
191dcee3bd3SJeff Roberson		self.apply = Button(self.buttons, text="Apply",
192dcee3bd3SJeff Roberson		    command=self.apress)
193dcee3bd3SJeff Roberson		self.revert = Button(self.buttons, text="Revert",
194dcee3bd3SJeff Roberson		    command=self.rpress)
195dcee3bd3SJeff Roberson		self.default = Button(self.buttons, text="Default",
196dcee3bd3SJeff Roberson		    command=self.dpress)
197dcee3bd3SJeff Roberson		self.apply.grid(row=0, column=0, sticky=E+W)
198dcee3bd3SJeff Roberson		self.revert.grid(row=0, column=1, sticky=E+W)
199dcee3bd3SJeff Roberson		self.default.grid(row=0, column=2, sticky=E+W)
200dcee3bd3SJeff Roberson		self.buttons.columnconfigure(0, weight=1)
201dcee3bd3SJeff Roberson		self.buttons.columnconfigure(1, weight=1)
202dcee3bd3SJeff Roberson		self.buttons.columnconfigure(2, weight=1)
203dcee3bd3SJeff Roberson
204dcee3bd3SJeff Roberson	def apress(self):
205dcee3bd3SJeff Roberson		for item in self.types:
206dcee3bd3SJeff Roberson			item.apply()
207dcee3bd3SJeff Roberson
208dcee3bd3SJeff Roberson	def rpress(self):
209dcee3bd3SJeff Roberson		for item in self.types:
210dcee3bd3SJeff Roberson			item.revert()
211dcee3bd3SJeff Roberson
212dcee3bd3SJeff Roberson	def dpress(self):
213dcee3bd3SJeff Roberson		for item in self.types:
214dcee3bd3SJeff Roberson			item.default()
215dcee3bd3SJeff Roberson
216dcee3bd3SJeff Robersonclass EventView(Toplevel):
217dcee3bd3SJeff Roberson	def __init__(self, event, canvas):
218dcee3bd3SJeff Roberson		Toplevel.__init__(self)
219dcee3bd3SJeff Roberson		self.resizable(0, 0)
220dcee3bd3SJeff Roberson		self.title("Event")
221dcee3bd3SJeff Roberson		self.event = event
222dcee3bd3SJeff Roberson		self.frame = Frame(self)
223dcee3bd3SJeff Roberson		self.frame.grid(row=0, column=0, sticky=N+S+E+W)
224dcee3bd3SJeff Roberson		self.buttons = Frame(self)
225dcee3bd3SJeff Roberson		self.buttons.grid(row=1, column=0, sticky=E+W)
226dcee3bd3SJeff Roberson		self.canvas = canvas
227dcee3bd3SJeff Roberson		self.drawlabels()
228dcee3bd3SJeff Roberson		self.drawbuttons()
229dcee3bd3SJeff Roberson		event.displayref(canvas)
230dcee3bd3SJeff Roberson		self.bind("<Destroy>", self.destroycb)
231dcee3bd3SJeff Roberson
232dcee3bd3SJeff Roberson	def destroycb(self, event):
233dcee3bd3SJeff Roberson		self.unbind("<Destroy>")
234dcee3bd3SJeff Roberson		if (self.event != None):
235dcee3bd3SJeff Roberson			self.event.displayunref(self.canvas)
236dcee3bd3SJeff Roberson			self.event = None
237dcee3bd3SJeff Roberson		self.destroy()
238dcee3bd3SJeff Roberson
239dcee3bd3SJeff Roberson	def clearlabels(self):
240dcee3bd3SJeff Roberson		for label in self.frame.grid_slaves():
241dcee3bd3SJeff Roberson			label.grid_remove()
242dcee3bd3SJeff Roberson
243dcee3bd3SJeff Roberson	def drawlabels(self):
244dcee3bd3SJeff Roberson		ypos = 0
245dcee3bd3SJeff Roberson		labels = self.event.labels()
246dcee3bd3SJeff Roberson		while (len(labels) < 7):
247dcee3bd3SJeff Roberson			labels.append(("", "", 0))
248dcee3bd3SJeff Roberson		for label in labels:
249dcee3bd3SJeff Roberson			name, value, linked = label
250dcee3bd3SJeff Roberson			l = Label(self.frame, text=name, bd=1, width=15,
251dcee3bd3SJeff Roberson			    relief=SUNKEN, anchor=W)
252dcee3bd3SJeff Roberson			if (linked):
253dcee3bd3SJeff Roberson				fgcolor = "blue"
254dcee3bd3SJeff Roberson			else:
255dcee3bd3SJeff Roberson				fgcolor = "black"
256dcee3bd3SJeff Roberson			r = Label(self.frame, text=value, bd=1,
257dcee3bd3SJeff Roberson			    relief=SUNKEN, anchor=W, fg=fgcolor)
258dcee3bd3SJeff Roberson			l.grid(row=ypos, column=0, sticky=E+W)
259dcee3bd3SJeff Roberson			r.grid(row=ypos, column=1, sticky=E+W)
260dcee3bd3SJeff Roberson			if (linked):
261dcee3bd3SJeff Roberson				r.bind("<Button-1>", self.linkpress)
262dcee3bd3SJeff Roberson			ypos += 1
263dcee3bd3SJeff Roberson		self.frame.columnconfigure(1, minsize=80)
264dcee3bd3SJeff Roberson
265dcee3bd3SJeff Roberson	def drawbuttons(self):
266dcee3bd3SJeff Roberson		self.back = Button(self.buttons, text="<", command=self.bpress)
267dcee3bd3SJeff Roberson		self.forw = Button(self.buttons, text=">", command=self.fpress)
268dcee3bd3SJeff Roberson		self.new = Button(self.buttons, text="new", command=self.npress)
269dcee3bd3SJeff Roberson		self.back.grid(row=0, column=0, sticky=E+W)
270dcee3bd3SJeff Roberson		self.forw.grid(row=0, column=1, sticky=E+W)
271dcee3bd3SJeff Roberson		self.new.grid(row=0, column=2, sticky=E+W)
272dcee3bd3SJeff Roberson		self.buttons.columnconfigure(2, weight=1)
273dcee3bd3SJeff Roberson
274dcee3bd3SJeff Roberson	def newevent(self, event):
275dcee3bd3SJeff Roberson		self.event.displayunref(self.canvas)
276dcee3bd3SJeff Roberson		self.clearlabels()
277dcee3bd3SJeff Roberson		self.event = event
278dcee3bd3SJeff Roberson		self.event.displayref(self.canvas)
279dcee3bd3SJeff Roberson		self.drawlabels()
280dcee3bd3SJeff Roberson
281dcee3bd3SJeff Roberson	def npress(self):
282dcee3bd3SJeff Roberson		EventView(self.event, self.canvas)
283dcee3bd3SJeff Roberson
284dcee3bd3SJeff Roberson	def bpress(self):
285dcee3bd3SJeff Roberson		prev = self.event.prev()
286dcee3bd3SJeff Roberson		if (prev == None):
287dcee3bd3SJeff Roberson			return
288dcee3bd3SJeff Roberson		while (prev.real == 0):
289dcee3bd3SJeff Roberson			prev = prev.prev()
290dcee3bd3SJeff Roberson			if (prev == None):
291dcee3bd3SJeff Roberson				return
292dcee3bd3SJeff Roberson		self.newevent(prev)
293dcee3bd3SJeff Roberson
294dcee3bd3SJeff Roberson	def fpress(self):
295dcee3bd3SJeff Roberson		next = self.event.next()
296dcee3bd3SJeff Roberson		if (next == None):
297dcee3bd3SJeff Roberson			return
298dcee3bd3SJeff Roberson		while (next.real == 0):
299dcee3bd3SJeff Roberson			next = next.next()
300dcee3bd3SJeff Roberson			if (next == None):
301dcee3bd3SJeff Roberson				return
302dcee3bd3SJeff Roberson		self.newevent(next)
303dcee3bd3SJeff Roberson
304dcee3bd3SJeff Roberson	def linkpress(self, wevent):
305dcee3bd3SJeff Roberson		event = self.event.getlinked()
306dcee3bd3SJeff Roberson		if (event != None):
307dcee3bd3SJeff Roberson			self.newevent(event)
308dcee3bd3SJeff Roberson
309dcee3bd3SJeff Robersonclass Event:
310dcee3bd3SJeff Roberson	name = "none"
311dcee3bd3SJeff Roberson	color = "grey"
312dcee3bd3SJeff Roberson	def __init__(self, source, cpu, timestamp, last=0):
313dcee3bd3SJeff Roberson		self.source = source
314dcee3bd3SJeff Roberson		self.cpu = cpu
315dcee3bd3SJeff Roberson		self.timestamp = int(timestamp)
316dcee3bd3SJeff Roberson		self.entries = []
317dcee3bd3SJeff Roberson		self.real = 1
318dcee3bd3SJeff Roberson		self.idx = None
319dcee3bd3SJeff Roberson		self.state = 0
320dcee3bd3SJeff Roberson		self.item = None
321dcee3bd3SJeff Roberson		self.dispcnt = 0
322dcee3bd3SJeff Roberson		self.linked = None
323dcee3bd3SJeff Roberson		if (last):
324dcee3bd3SJeff Roberson			source.lastevent(self)
325dcee3bd3SJeff Roberson		else:
326dcee3bd3SJeff Roberson			source.event(self)
327dcee3bd3SJeff Roberson
328dcee3bd3SJeff Roberson	def status(self):
329dcee3bd3SJeff Roberson		statstr = self.name + " " + self.source.name
330dcee3bd3SJeff Roberson		statstr += " on: cpu" + str(self.cpu)
331dcee3bd3SJeff Roberson		statstr += " at: " + str(self.timestamp)
332dcee3bd3SJeff Roberson		statstr += self.stattxt()
333dcee3bd3SJeff Roberson		status.set(statstr)
334dcee3bd3SJeff Roberson
335dcee3bd3SJeff Roberson	def stattxt(self):
336dcee3bd3SJeff Roberson		return ""
337dcee3bd3SJeff Roberson
338dcee3bd3SJeff Roberson	def textadd(self, tuple):
339dcee3bd3SJeff Roberson		pass
340dcee3bd3SJeff Roberson		self.entries.append(tuple)
341dcee3bd3SJeff Roberson
342dcee3bd3SJeff Roberson	def labels(self):
343dcee3bd3SJeff Roberson		return [("Source:", self.source.name, 0),
344dcee3bd3SJeff Roberson				("Event:", self.name, 0),
345dcee3bd3SJeff Roberson				("CPU:", self.cpu, 0),
346dcee3bd3SJeff Roberson				("Timestamp:", self.timestamp, 0)] + self.entries
347dcee3bd3SJeff Roberson	def mouseenter(self, canvas, item):
348dcee3bd3SJeff Roberson		self.displayref(canvas)
349dcee3bd3SJeff Roberson		self.status()
350dcee3bd3SJeff Roberson
351dcee3bd3SJeff Roberson	def mouseexit(self, canvas, item):
352dcee3bd3SJeff Roberson		self.displayunref(canvas)
353dcee3bd3SJeff Roberson		status.clear()
354dcee3bd3SJeff Roberson
355dcee3bd3SJeff Roberson	def mousepress(self, canvas, item):
356dcee3bd3SJeff Roberson		EventView(self, canvas)
357dcee3bd3SJeff Roberson
358dcee3bd3SJeff Roberson	def next(self):
359dcee3bd3SJeff Roberson		return self.source.eventat(self.idx + 1)
360dcee3bd3SJeff Roberson
361dcee3bd3SJeff Roberson	def prev(self):
362dcee3bd3SJeff Roberson		return self.source.eventat(self.idx - 1)
363dcee3bd3SJeff Roberson
364dcee3bd3SJeff Roberson	def displayref(self, canvas):
365dcee3bd3SJeff Roberson		if (self.dispcnt == 0):
366dcee3bd3SJeff Roberson			canvas.itemconfigure(self.item, width=2)
367dcee3bd3SJeff Roberson		self.dispcnt += 1
368dcee3bd3SJeff Roberson
369dcee3bd3SJeff Roberson	def displayunref(self, canvas):
370dcee3bd3SJeff Roberson		self.dispcnt -= 1
371dcee3bd3SJeff Roberson		if (self.dispcnt == 0):
372dcee3bd3SJeff Roberson			canvas.itemconfigure(self.item, width=0)
373dcee3bd3SJeff Roberson			canvas.tag_raise("point", "state")
374dcee3bd3SJeff Roberson
375dcee3bd3SJeff Roberson	def getlinked(self):
376dcee3bd3SJeff Roberson		return self.linked.findevent(self.timestamp)
377dcee3bd3SJeff Roberson
378dcee3bd3SJeff Robersonclass PointEvent(Event):
379dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, last=0):
380dcee3bd3SJeff Roberson		Event.__init__(self, thread, cpu, timestamp, last)
381dcee3bd3SJeff Roberson
382dcee3bd3SJeff Roberson	def draw(self, canvas, xpos, ypos):
383dcee3bd3SJeff Roberson		l = canvas.create_oval(xpos - 6, ypos + 1, xpos + 6, ypos - 11,
384dcee3bd3SJeff Roberson		    fill=self.color, tags=("all", "point", "event")
385dcee3bd3SJeff Roberson		    + (self.name,), width=0)
386dcee3bd3SJeff Roberson		canvas.events[l] = self
387dcee3bd3SJeff Roberson		self.item = l
388dcee3bd3SJeff Roberson		if (self.enabled == 0):
389dcee3bd3SJeff Roberson			canvas.itemconfigure(l, state="hidden")
390dcee3bd3SJeff Roberson
391dcee3bd3SJeff Roberson		return (xpos)
392dcee3bd3SJeff Roberson
393dcee3bd3SJeff Robersonclass StateEvent(Event):
394dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, last=0):
395dcee3bd3SJeff Roberson		Event.__init__(self, thread, cpu, timestamp, last)
396dcee3bd3SJeff Roberson		self.duration = 0
397dcee3bd3SJeff Roberson		self.skipnext = 0
398dcee3bd3SJeff Roberson		self.skipself = 0
399dcee3bd3SJeff Roberson		self.state = 1
400dcee3bd3SJeff Roberson
401dcee3bd3SJeff Roberson	def draw(self, canvas, xpos, ypos):
402dcee3bd3SJeff Roberson		next = self.nextstate()
403dcee3bd3SJeff Roberson		if (self.skipself == 1 or next == None):
404dcee3bd3SJeff Roberson			return (xpos)
4059a5c9d55SJeff Roberson		while (self.skipnext):
406dcee3bd3SJeff Roberson			skipped = next
407dcee3bd3SJeff Roberson			next.skipself = 1
408dcee3bd3SJeff Roberson			next.real = 0
409dcee3bd3SJeff Roberson			next = next.nextstate()
410dcee3bd3SJeff Roberson			if (next == None):
411dcee3bd3SJeff Roberson				next = skipped
4129a5c9d55SJeff Roberson			self.skipnext -= 1
413dcee3bd3SJeff Roberson		self.duration = next.timestamp - self.timestamp
4140482a607SJeff Roberson		if (self.duration < 0):
4150482a607SJeff Roberson			self.duration = 0
4160482a607SJeff Roberson			print "Unsynchronized timestamp"
4170482a607SJeff Roberson			print self.cpu, self.timestamp
4180482a607SJeff Roberson			print next.cpu, next.timestamp
419dcee3bd3SJeff Roberson		delta = self.duration / canvas.ratio
420dcee3bd3SJeff Roberson		l = canvas.create_rectangle(xpos, ypos,
421dcee3bd3SJeff Roberson		    xpos + delta, ypos - 10, fill=self.color, width=0,
422dcee3bd3SJeff Roberson		    tags=("all", "state", "event") + (self.name,))
423dcee3bd3SJeff Roberson		canvas.events[l] = self
424dcee3bd3SJeff Roberson		self.item = l
425dcee3bd3SJeff Roberson		if (self.enabled == 0):
426dcee3bd3SJeff Roberson			canvas.itemconfigure(l, state="hidden")
427dcee3bd3SJeff Roberson
428dcee3bd3SJeff Roberson		return (xpos + delta)
429dcee3bd3SJeff Roberson
430dcee3bd3SJeff Roberson	def stattxt(self):
431dcee3bd3SJeff Roberson		return " duration: " + ticks2sec(self.duration)
432dcee3bd3SJeff Roberson
433dcee3bd3SJeff Roberson	def nextstate(self):
434dcee3bd3SJeff Roberson		next = self.next()
435dcee3bd3SJeff Roberson		while (next != None and next.state == 0):
436dcee3bd3SJeff Roberson			next = next.next()
437dcee3bd3SJeff Roberson		return (next)
438dcee3bd3SJeff Roberson
439dcee3bd3SJeff Roberson	def labels(self):
440dcee3bd3SJeff Roberson		return [("Source:", self.source.name, 0),
441dcee3bd3SJeff Roberson				("Event:", self.name, 0),
442dcee3bd3SJeff Roberson				("Timestamp:", self.timestamp, 0),
443dcee3bd3SJeff Roberson				("CPU:", self.cpu, 0),
444dcee3bd3SJeff Roberson				("Duration:", ticks2sec(self.duration), 0)] \
445dcee3bd3SJeff Roberson				 + self.entries
446dcee3bd3SJeff Roberson
447dcee3bd3SJeff Robersonclass Count(Event):
448dcee3bd3SJeff Roberson	name = "Count"
449dcee3bd3SJeff Roberson	color = "red"
450dcee3bd3SJeff Roberson	enabled = 1
451dcee3bd3SJeff Roberson	def __init__(self, source, cpu, timestamp, count):
452dcee3bd3SJeff Roberson		self.count = int(count)
453dcee3bd3SJeff Roberson		Event.__init__(self, source, cpu, timestamp)
454dcee3bd3SJeff Roberson		self.duration = 0
455dcee3bd3SJeff Roberson		self.textadd(("count:", self.count, 0))
456dcee3bd3SJeff Roberson
457dcee3bd3SJeff Roberson	def draw(self, canvas, xpos, ypos):
458dcee3bd3SJeff Roberson		next = self.next()
459dcee3bd3SJeff Roberson		self.duration = next.timestamp - self.timestamp
460dcee3bd3SJeff Roberson		delta = self.duration / canvas.ratio
461dcee3bd3SJeff Roberson		yhight = self.source.yscale() * self.count
462dcee3bd3SJeff Roberson		l = canvas.create_rectangle(xpos, ypos - yhight,
463dcee3bd3SJeff Roberson		    xpos + delta, ypos, fill=self.color, width=0,
464dcee3bd3SJeff Roberson		    tags=("all", "count", "event") + (self.name,))
465dcee3bd3SJeff Roberson		canvas.events[l] = self
466dcee3bd3SJeff Roberson		self.item = l
467dcee3bd3SJeff Roberson		if (self.enabled == 0):
468dcee3bd3SJeff Roberson			canvas.itemconfigure(l, state="hidden")
469dcee3bd3SJeff Roberson		return (xpos + delta)
470dcee3bd3SJeff Roberson
471dcee3bd3SJeff Roberson	def stattxt(self):
472dcee3bd3SJeff Roberson		return " count: " + str(self.count)
473dcee3bd3SJeff Roberson
474dcee3bd3SJeff Robersonconfigtypes.append(Count)
475dcee3bd3SJeff Roberson
476dcee3bd3SJeff Robersonclass Running(StateEvent):
477dcee3bd3SJeff Roberson	name = "running"
478dcee3bd3SJeff Roberson	color = "green"
479dcee3bd3SJeff Roberson	enabled = 1
480dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, prio):
481dcee3bd3SJeff Roberson		StateEvent.__init__(self, thread, cpu, timestamp)
482dcee3bd3SJeff Roberson		self.prio = prio
483dcee3bd3SJeff Roberson		self.textadd(("prio:", self.prio, 0))
484dcee3bd3SJeff Roberson
485dcee3bd3SJeff Robersonconfigtypes.append(Running)
486dcee3bd3SJeff Roberson
487dcee3bd3SJeff Robersonclass Idle(StateEvent):
488dcee3bd3SJeff Roberson	name = "idle"
489dcee3bd3SJeff Roberson	color = "grey"
490dcee3bd3SJeff Roberson	enabled = 0
491dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, prio):
492dcee3bd3SJeff Roberson		StateEvent.__init__(self, thread, cpu, timestamp)
493dcee3bd3SJeff Roberson		self.prio = prio
494dcee3bd3SJeff Roberson		self.textadd(("prio:", self.prio, 0))
495dcee3bd3SJeff Roberson
496dcee3bd3SJeff Robersonconfigtypes.append(Idle)
497dcee3bd3SJeff Roberson
498dcee3bd3SJeff Robersonclass Yielding(StateEvent):
499dcee3bd3SJeff Roberson	name = "yielding"
500dcee3bd3SJeff Roberson	color = "yellow"
501dcee3bd3SJeff Roberson	enabled = 1
502dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, prio):
503dcee3bd3SJeff Roberson		StateEvent.__init__(self, thread, cpu, timestamp)
5044a2e6a08SJeff Roberson		self.skipnext = 1
505dcee3bd3SJeff Roberson		self.prio = prio
506dcee3bd3SJeff Roberson		self.textadd(("prio:", self.prio, 0))
507dcee3bd3SJeff Roberson
508dcee3bd3SJeff Robersonconfigtypes.append(Yielding)
509dcee3bd3SJeff Roberson
510dcee3bd3SJeff Robersonclass Swapped(StateEvent):
511dcee3bd3SJeff Roberson	name = "swapped"
512dcee3bd3SJeff Roberson	color = "violet"
513dcee3bd3SJeff Roberson	enabled = 1
514dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, prio):
515dcee3bd3SJeff Roberson		StateEvent.__init__(self, thread, cpu, timestamp)
516dcee3bd3SJeff Roberson		self.prio = prio
517dcee3bd3SJeff Roberson		self.textadd(("prio:", self.prio, 0))
518dcee3bd3SJeff Roberson
519dcee3bd3SJeff Robersonconfigtypes.append(Swapped)
520dcee3bd3SJeff Roberson
521dcee3bd3SJeff Robersonclass Suspended(StateEvent):
522dcee3bd3SJeff Roberson	name = "suspended"
523dcee3bd3SJeff Roberson	color = "purple"
524dcee3bd3SJeff Roberson	enabled = 1
525dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, prio):
526dcee3bd3SJeff Roberson		StateEvent.__init__(self, thread, cpu, timestamp)
527dcee3bd3SJeff Roberson		self.prio = prio
528dcee3bd3SJeff Roberson		self.textadd(("prio:", self.prio, 0))
529dcee3bd3SJeff Roberson
530dcee3bd3SJeff Robersonconfigtypes.append(Suspended)
531dcee3bd3SJeff Roberson
532dcee3bd3SJeff Robersonclass Iwait(StateEvent):
533dcee3bd3SJeff Roberson	name = "iwait"
534dcee3bd3SJeff Roberson	color = "grey"
535dcee3bd3SJeff Roberson	enabled = 0
536dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, prio):
537dcee3bd3SJeff Roberson		StateEvent.__init__(self, thread, cpu, timestamp)
538dcee3bd3SJeff Roberson		self.prio = prio
539dcee3bd3SJeff Roberson		self.textadd(("prio:", self.prio, 0))
540dcee3bd3SJeff Roberson
541dcee3bd3SJeff Robersonconfigtypes.append(Iwait)
542dcee3bd3SJeff Roberson
543dcee3bd3SJeff Robersonclass Preempted(StateEvent):
544dcee3bd3SJeff Roberson	name = "preempted"
545dcee3bd3SJeff Roberson	color = "red"
546dcee3bd3SJeff Roberson	enabled = 1
547dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, prio, bythread):
548dcee3bd3SJeff Roberson		StateEvent.__init__(self, thread, cpu, timestamp)
5494a2e6a08SJeff Roberson		self.skipnext = 1
550dcee3bd3SJeff Roberson		self.prio = prio
551dcee3bd3SJeff Roberson		self.linked = bythread
552dcee3bd3SJeff Roberson		self.textadd(("prio:", self.prio, 0))
553dcee3bd3SJeff Roberson		self.textadd(("by thread:", self.linked.name, 1))
554dcee3bd3SJeff Roberson
555dcee3bd3SJeff Robersonconfigtypes.append(Preempted)
556dcee3bd3SJeff Roberson
557dcee3bd3SJeff Robersonclass Sleep(StateEvent):
558dcee3bd3SJeff Roberson	name = "sleep"
559dcee3bd3SJeff Roberson	color = "blue"
560dcee3bd3SJeff Roberson	enabled = 1
561dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, prio, wmesg):
562dcee3bd3SJeff Roberson		StateEvent.__init__(self, thread, cpu, timestamp)
563dcee3bd3SJeff Roberson		self.prio = prio
564dcee3bd3SJeff Roberson		self.wmesg = wmesg
565dcee3bd3SJeff Roberson		self.textadd(("prio:", self.prio, 0))
566dcee3bd3SJeff Roberson		self.textadd(("wmesg:", self.wmesg, 0))
567dcee3bd3SJeff Roberson
568dcee3bd3SJeff Roberson	def stattxt(self):
569dcee3bd3SJeff Roberson		statstr = StateEvent.stattxt(self)
570dcee3bd3SJeff Roberson		statstr += " sleeping on: " + self.wmesg
571dcee3bd3SJeff Roberson		return (statstr)
572dcee3bd3SJeff Roberson
573dcee3bd3SJeff Robersonconfigtypes.append(Sleep)
574dcee3bd3SJeff Roberson
575dcee3bd3SJeff Robersonclass Blocked(StateEvent):
576dcee3bd3SJeff Roberson	name = "blocked"
577dcee3bd3SJeff Roberson	color = "dark red"
578dcee3bd3SJeff Roberson	enabled = 1
579dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, prio, lock):
580dcee3bd3SJeff Roberson		StateEvent.__init__(self, thread, cpu, timestamp)
581dcee3bd3SJeff Roberson		self.prio = prio
582dcee3bd3SJeff Roberson		self.lock = lock
583dcee3bd3SJeff Roberson		self.textadd(("prio:", self.prio, 0))
584dcee3bd3SJeff Roberson		self.textadd(("lock:", self.lock, 0))
585dcee3bd3SJeff Roberson
586dcee3bd3SJeff Roberson	def stattxt(self):
587dcee3bd3SJeff Roberson		statstr = StateEvent.stattxt(self)
588dcee3bd3SJeff Roberson		statstr += " blocked on: " + self.lock
589dcee3bd3SJeff Roberson		return (statstr)
590dcee3bd3SJeff Roberson
591dcee3bd3SJeff Robersonconfigtypes.append(Blocked)
592dcee3bd3SJeff Roberson
593dcee3bd3SJeff Robersonclass KsegrpRunq(StateEvent):
594dcee3bd3SJeff Roberson	name = "KsegrpRunq"
595dcee3bd3SJeff Roberson	color = "orange"
596dcee3bd3SJeff Roberson	enabled = 1
597dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, prio, bythread):
598dcee3bd3SJeff Roberson		StateEvent.__init__(self, thread, cpu, timestamp)
599dcee3bd3SJeff Roberson		self.prio = prio
600dcee3bd3SJeff Roberson		self.linked = bythread
601dcee3bd3SJeff Roberson		self.textadd(("prio:", self.prio, 0))
602dcee3bd3SJeff Roberson		self.textadd(("by thread:", self.linked.name, 1))
603dcee3bd3SJeff Roberson
604dcee3bd3SJeff Robersonconfigtypes.append(KsegrpRunq)
605dcee3bd3SJeff Roberson
606dcee3bd3SJeff Robersonclass Runq(StateEvent):
607dcee3bd3SJeff Roberson	name = "Runq"
608dcee3bd3SJeff Roberson	color = "yellow"
609dcee3bd3SJeff Roberson	enabled = 1
610dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, prio, bythread):
611dcee3bd3SJeff Roberson		StateEvent.__init__(self, thread, cpu, timestamp)
612dcee3bd3SJeff Roberson		self.prio = prio
613dcee3bd3SJeff Roberson		self.linked = bythread
614dcee3bd3SJeff Roberson		self.textadd(("prio:", self.prio, 0))
615dcee3bd3SJeff Roberson		self.textadd(("by thread:", self.linked.name, 1))
616dcee3bd3SJeff Roberson
617dcee3bd3SJeff Robersonconfigtypes.append(Runq)
618dcee3bd3SJeff Roberson
619dcee3bd3SJeff Robersonclass Sched_exit(StateEvent):
620dcee3bd3SJeff Roberson	name = "exit"
621dcee3bd3SJeff Roberson	color = "grey"
622dcee3bd3SJeff Roberson	enabled = 0
623dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, prio):
624dcee3bd3SJeff Roberson		StateEvent.__init__(self, thread, cpu, timestamp)
625dcee3bd3SJeff Roberson		self.name = "sched_exit"
626dcee3bd3SJeff Roberson		self.prio = prio
627dcee3bd3SJeff Roberson		self.textadd(("prio:", self.prio, 0))
628dcee3bd3SJeff Roberson
629dcee3bd3SJeff Robersonconfigtypes.append(Sched_exit)
630dcee3bd3SJeff Roberson
631dcee3bd3SJeff Robersonclass Padevent(StateEvent):
632dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, last=0):
633dcee3bd3SJeff Roberson		StateEvent.__init__(self, thread, cpu, timestamp, last)
634dcee3bd3SJeff Roberson		self.name = "pad"
635dcee3bd3SJeff Roberson		self.real = 0
636dcee3bd3SJeff Roberson
637dcee3bd3SJeff Roberson	def draw(self, canvas, xpos, ypos):
638dcee3bd3SJeff Roberson		next = self.next()
639dcee3bd3SJeff Roberson		if (next == None):
640dcee3bd3SJeff Roberson			return (xpos)
641dcee3bd3SJeff Roberson		self.duration = next.timestamp - self.timestamp
642dcee3bd3SJeff Roberson		delta = self.duration / canvas.ratio
643dcee3bd3SJeff Roberson		return (xpos + delta)
644dcee3bd3SJeff Roberson
645dcee3bd3SJeff Robersonclass Tick(PointEvent):
646dcee3bd3SJeff Roberson	name = "tick"
647dcee3bd3SJeff Roberson	color = "black"
648dcee3bd3SJeff Roberson	enabled = 0
649dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, prio, stathz):
650dcee3bd3SJeff Roberson		PointEvent.__init__(self, thread, cpu, timestamp)
651dcee3bd3SJeff Roberson		self.prio = prio
652dcee3bd3SJeff Roberson		self.textadd(("prio:", self.prio, 0))
653dcee3bd3SJeff Roberson
654dcee3bd3SJeff Robersonconfigtypes.append(Tick)
655dcee3bd3SJeff Roberson
656dcee3bd3SJeff Robersonclass Prio(PointEvent):
657dcee3bd3SJeff Roberson	name = "prio"
658dcee3bd3SJeff Roberson	color = "black"
659dcee3bd3SJeff Roberson	enabled = 0
660dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, prio, newprio, bythread):
661dcee3bd3SJeff Roberson		PointEvent.__init__(self, thread, cpu, timestamp)
662dcee3bd3SJeff Roberson		self.prio = prio
663dcee3bd3SJeff Roberson		self.newprio = newprio
664dcee3bd3SJeff Roberson		self.linked = bythread
665dcee3bd3SJeff Roberson		self.textadd(("new prio:", self.newprio, 0))
666dcee3bd3SJeff Roberson		self.textadd(("prio:", self.prio, 0))
667dcee3bd3SJeff Roberson		if (self.linked != self.source):
668dcee3bd3SJeff Roberson			self.textadd(("by thread:", self.linked.name, 1))
669dcee3bd3SJeff Roberson		else:
670dcee3bd3SJeff Roberson			self.textadd(("by thread:", self.linked.name, 0))
671dcee3bd3SJeff Roberson
672dcee3bd3SJeff Robersonconfigtypes.append(Prio)
673dcee3bd3SJeff Roberson
674dcee3bd3SJeff Robersonclass Lend(PointEvent):
675dcee3bd3SJeff Roberson	name = "lend"
676dcee3bd3SJeff Roberson	color = "black"
677dcee3bd3SJeff Roberson	enabled = 0
678dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, prio, tothread):
679dcee3bd3SJeff Roberson		PointEvent.__init__(self, thread, cpu, timestamp)
680dcee3bd3SJeff Roberson		self.prio = prio
681dcee3bd3SJeff Roberson		self.linked = tothread
682dcee3bd3SJeff Roberson		self.textadd(("prio:", self.prio, 0))
683dcee3bd3SJeff Roberson		self.textadd(("to thread:", self.linked.name, 1))
684dcee3bd3SJeff Roberson
685dcee3bd3SJeff Robersonconfigtypes.append(Lend)
686dcee3bd3SJeff Roberson
687dcee3bd3SJeff Robersonclass Wokeup(PointEvent):
688dcee3bd3SJeff Roberson	name = "wokeup"
689dcee3bd3SJeff Roberson	color = "black"
690dcee3bd3SJeff Roberson	enabled = 0
691dcee3bd3SJeff Roberson	def __init__(self, thread, cpu, timestamp, ranthread):
692dcee3bd3SJeff Roberson		PointEvent.__init__(self, thread, cpu, timestamp)
693dcee3bd3SJeff Roberson		self.linked = ranthread
694dcee3bd3SJeff Roberson		self.textadd(("ran thread:", self.linked.name, 1))
695dcee3bd3SJeff Roberson
696dcee3bd3SJeff Robersonconfigtypes.append(Wokeup)
697dcee3bd3SJeff Roberson
698dcee3bd3SJeff Robersonclass EventSource:
699dcee3bd3SJeff Roberson	def __init__(self, name):
700dcee3bd3SJeff Roberson		self.name = name
701dcee3bd3SJeff Roberson		self.events = []
702dcee3bd3SJeff Roberson		self.cpu = 0
703dcee3bd3SJeff Roberson		self.cpux = 0
704dcee3bd3SJeff Roberson
705dcee3bd3SJeff Roberson	def fixup(self):
706dcee3bd3SJeff Roberson		pass
707dcee3bd3SJeff Roberson
708dcee3bd3SJeff Roberson	def event(self, event):
709dcee3bd3SJeff Roberson		self.events.insert(0, event)
710dcee3bd3SJeff Roberson
711dcee3bd3SJeff Roberson	def remove(self, event):
712dcee3bd3SJeff Roberson		self.events.remove(event)
713dcee3bd3SJeff Roberson
714dcee3bd3SJeff Roberson	def lastevent(self, event):
715dcee3bd3SJeff Roberson		self.events.append(event)
716dcee3bd3SJeff Roberson
717dcee3bd3SJeff Roberson	def draw(self, canvas, ypos):
718dcee3bd3SJeff Roberson		xpos = 10
719dcee3bd3SJeff Roberson		self.cpux = 10
720dcee3bd3SJeff Roberson		self.cpu = self.events[1].cpu
721dcee3bd3SJeff Roberson		for i in range(0, len(self.events)):
722dcee3bd3SJeff Roberson			self.events[i].idx = i
723dcee3bd3SJeff Roberson		for event in self.events:
724dcee3bd3SJeff Roberson			if (event.cpu != self.cpu and event.cpu != -1):
725dcee3bd3SJeff Roberson				self.drawcpu(canvas, xpos, ypos)
726dcee3bd3SJeff Roberson				self.cpux = xpos
727dcee3bd3SJeff Roberson				self.cpu = event.cpu
728dcee3bd3SJeff Roberson			xpos = event.draw(canvas, xpos, ypos)
729dcee3bd3SJeff Roberson		self.drawcpu(canvas, xpos, ypos)
730dcee3bd3SJeff Roberson
731dcee3bd3SJeff Roberson	def drawname(self, canvas, ypos):
732dcee3bd3SJeff Roberson		ypos = ypos - (self.ysize() / 2)
733dcee3bd3SJeff Roberson		canvas.create_text(10, ypos, anchor="w", text=self.name)
734dcee3bd3SJeff Roberson
735dcee3bd3SJeff Roberson	def drawcpu(self, canvas, xpos, ypos):
736dcee3bd3SJeff Roberson		cpu = int(self.cpu)
737dcee3bd3SJeff Roberson		if (cpu == 0):
738dcee3bd3SJeff Roberson			color = 'light grey'
739dcee3bd3SJeff Roberson		elif (cpu == 1):
740dcee3bd3SJeff Roberson			color = 'dark grey'
741dcee3bd3SJeff Roberson		elif (cpu == 2):
742dcee3bd3SJeff Roberson			color = 'light blue'
743dcee3bd3SJeff Roberson		elif (cpu == 3):
7446030f133SRobert Watson			color = 'light green'
74593fb9479SJeff Roberson		elif (cpu == 4):
74693fb9479SJeff Roberson			color = 'blanched almond'
74793fb9479SJeff Roberson		elif (cpu == 5):
74893fb9479SJeff Roberson			color = 'slate grey'
74993fb9479SJeff Roberson		elif (cpu == 6):
75093fb9479SJeff Roberson			color = 'light slate blue'
75193fb9479SJeff Roberson		elif (cpu == 7):
75293fb9479SJeff Roberson			color = 'thistle'
753dcee3bd3SJeff Roberson		else:
7546030f133SRobert Watson			color = "white"
755dcee3bd3SJeff Roberson		l = canvas.create_rectangle(self.cpux,
756dcee3bd3SJeff Roberson		    ypos - self.ysize() - canvas.bdheight,
757dcee3bd3SJeff Roberson		    xpos, ypos + canvas.bdheight, fill=color, width=0,
758dcee3bd3SJeff Roberson		    tags=("all", "cpuinfo"))
759dcee3bd3SJeff Roberson
760dcee3bd3SJeff Roberson	def ysize(self):
761dcee3bd3SJeff Roberson		return (None)
762dcee3bd3SJeff Roberson
763dcee3bd3SJeff Roberson	def eventat(self, i):
764dcee3bd3SJeff Roberson		if (i >= len(self.events)):
765dcee3bd3SJeff Roberson			return (None)
766dcee3bd3SJeff Roberson		event = self.events[i]
767dcee3bd3SJeff Roberson		return (event)
768dcee3bd3SJeff Roberson
769dcee3bd3SJeff Roberson	def findevent(self, timestamp):
770dcee3bd3SJeff Roberson		for event in self.events:
771dcee3bd3SJeff Roberson			if (event.timestamp >= timestamp and event.real):
772dcee3bd3SJeff Roberson				return (event)
773dcee3bd3SJeff Roberson		return (None)
774dcee3bd3SJeff Roberson
775dcee3bd3SJeff Robersonclass Thread(EventSource):
776dcee3bd3SJeff Roberson	names = {}
777dcee3bd3SJeff Roberson	def __init__(self, td, pcomm):
778dcee3bd3SJeff Roberson		EventSource.__init__(self, pcomm)
779dcee3bd3SJeff Roberson		self.str = td
780dcee3bd3SJeff Roberson		try:
781dcee3bd3SJeff Roberson			cnt = Thread.names[pcomm]
782dcee3bd3SJeff Roberson		except:
783dcee3bd3SJeff Roberson			Thread.names[pcomm] = 0
784dcee3bd3SJeff Roberson			return
785dcee3bd3SJeff Roberson		Thread.names[pcomm] = cnt + 1
786dcee3bd3SJeff Roberson
787dcee3bd3SJeff Roberson	def fixup(self):
788dcee3bd3SJeff Roberson		cnt = Thread.names[self.name]
789dcee3bd3SJeff Roberson		if (cnt == 0):
790dcee3bd3SJeff Roberson			return
791dcee3bd3SJeff Roberson		cnt -= 1
792dcee3bd3SJeff Roberson		Thread.names[self.name] = cnt
793dcee3bd3SJeff Roberson		self.name += " td" + str(cnt)
794dcee3bd3SJeff Roberson
795dcee3bd3SJeff Roberson	def ysize(self):
796dcee3bd3SJeff Roberson		return (10)
797dcee3bd3SJeff Roberson
798dcee3bd3SJeff Robersonclass Counter(EventSource):
799dcee3bd3SJeff Roberson	max = 0
800dcee3bd3SJeff Roberson	def __init__(self, name):
801dcee3bd3SJeff Roberson		EventSource.__init__(self, name)
802dcee3bd3SJeff Roberson
803dcee3bd3SJeff Roberson	def event(self, event):
804dcee3bd3SJeff Roberson		EventSource.event(self, event)
805dcee3bd3SJeff Roberson		try:
806dcee3bd3SJeff Roberson			count = event.count
807dcee3bd3SJeff Roberson		except:
808dcee3bd3SJeff Roberson			return
809dcee3bd3SJeff Roberson		count = int(count)
810dcee3bd3SJeff Roberson		if (count > Counter.max):
811dcee3bd3SJeff Roberson			Counter.max = count
812dcee3bd3SJeff Roberson
813dcee3bd3SJeff Roberson	def ysize(self):
814dcee3bd3SJeff Roberson		return (80)
815dcee3bd3SJeff Roberson
816dcee3bd3SJeff Roberson	def yscale(self):
817dcee3bd3SJeff Roberson		return (self.ysize() / Counter.max)
818dcee3bd3SJeff Roberson
819dcee3bd3SJeff Roberson
820dcee3bd3SJeff Robersonclass KTRFile:
821dcee3bd3SJeff Roberson	def __init__(self, file):
8220482a607SJeff Roberson		self.timestamp_first = {}
8230482a607SJeff Roberson		self.timestamp_last = {}
8240482a607SJeff Roberson		self.timestamp_adjust = {}
8250482a607SJeff Roberson		self.timestamp_f = None
8260482a607SJeff Roberson		self.timestamp_l = None
827dcee3bd3SJeff Roberson		self.lineno = -1
828dcee3bd3SJeff Roberson		self.threads = []
829dcee3bd3SJeff Roberson		self.sources = []
830dcee3bd3SJeff Roberson		self.ticks = {}
831dcee3bd3SJeff Roberson		self.load = {}
83201e7fb47SScott Long		self.crit = {}
8330482a607SJeff Roberson		self.stathz = 0
834dcee3bd3SJeff Roberson
835dcee3bd3SJeff Roberson		self.parse(file)
836dcee3bd3SJeff Roberson		self.fixup()
837dcee3bd3SJeff Roberson		global ticksps
8380482a607SJeff Roberson		print "first", self.timestamp_f, "last", self.timestamp_l
8390482a607SJeff Roberson		print "time span", self.timespan()
8404a2e6a08SJeff Roberson		print "stathz", self.stathz
8410482a607SJeff Roberson		ticksps = self.ticksps()
8420482a607SJeff Roberson		print "Ticks per second", ticksps
843dcee3bd3SJeff Roberson
844dcee3bd3SJeff Roberson	def parse(self, file):
845dcee3bd3SJeff Roberson		try:
846dcee3bd3SJeff Roberson			ifp = open(file)
847dcee3bd3SJeff Roberson		except:
848dcee3bd3SJeff Roberson			print "Can't open", file
849dcee3bd3SJeff Roberson			sys.exit(1)
850dcee3bd3SJeff Roberson
851dcee3bd3SJeff Roberson		ktrhdr = "\s+\d+\s+(\d+)\s+(\d+)\s+"
852dcee3bd3SJeff Roberson		tdname = "(\S+)\(([^)]*)\)"
85301e7fb47SScott Long		crittdname = "(\S+)\s+\(\d+,\s+([^)]*)\)"
854dcee3bd3SJeff Roberson
855dcee3bd3SJeff Roberson		ktrstr = "mi_switch: " + tdname
856dcee3bd3SJeff Roberson		ktrstr += " prio (\d+) inhibit (\d+) wmesg (\S+) lock (\S+)"
857dcee3bd3SJeff Roberson		switchout_re = re.compile(ktrhdr + ktrstr)
858dcee3bd3SJeff Roberson
859dcee3bd3SJeff Roberson		ktrstr = "mi_switch: " + tdname + " prio (\d+) idle"
860dcee3bd3SJeff Roberson		idled_re = re.compile(ktrhdr + ktrstr)
861dcee3bd3SJeff Roberson
862dcee3bd3SJeff Roberson		ktrstr = "mi_switch: " + tdname + " prio (\d+) preempted by "
863dcee3bd3SJeff Roberson		ktrstr += tdname
864dcee3bd3SJeff Roberson		preempted_re = re.compile(ktrhdr + ktrstr)
865dcee3bd3SJeff Roberson
866dcee3bd3SJeff Roberson		ktrstr = "mi_switch: running " + tdname + " prio (\d+)"
867dcee3bd3SJeff Roberson		switchin_re = re.compile(ktrhdr + ktrstr)
868dcee3bd3SJeff Roberson
869dcee3bd3SJeff Roberson		ktrstr = "sched_add: " + tdname + " prio (\d+) by " + tdname
870dcee3bd3SJeff Roberson		sched_add_re = re.compile(ktrhdr + ktrstr)
871dcee3bd3SJeff Roberson
872dcee3bd3SJeff Roberson		ktrstr = "setrunqueue: " + tdname + " prio (\d+) by " + tdname
873dcee3bd3SJeff Roberson		setrunqueue_re = re.compile(ktrhdr + ktrstr)
874dcee3bd3SJeff Roberson
875dcee3bd3SJeff Roberson		ktrstr = "sched_rem: " + tdname + " prio (\d+) by " + tdname
876dcee3bd3SJeff Roberson		sched_rem_re = re.compile(ktrhdr + ktrstr)
877dcee3bd3SJeff Roberson
878dcee3bd3SJeff Roberson		ktrstr = "sched_exit_thread: " + tdname + " prio (\d+)"
879dcee3bd3SJeff Roberson		sched_exit_re = re.compile(ktrhdr + ktrstr)
880dcee3bd3SJeff Roberson
881dcee3bd3SJeff Roberson		ktrstr = "statclock: " + tdname + " prio (\d+)"
882dcee3bd3SJeff Roberson		ktrstr += " stathz (\d+)"
883dcee3bd3SJeff Roberson		sched_clock_re = re.compile(ktrhdr + ktrstr)
884dcee3bd3SJeff Roberson
885dcee3bd3SJeff Roberson		ktrstr = "sched_prio: " + tdname + " prio (\d+)"
886dcee3bd3SJeff Roberson		ktrstr += " newprio (\d+) by " + tdname
887dcee3bd3SJeff Roberson		sched_prio_re = re.compile(ktrhdr + ktrstr)
888dcee3bd3SJeff Roberson
8893e16b3e0SJeff Roberson		cpuload_re = re.compile(ktrhdr + "load: (\d+)")
8903e16b3e0SJeff Roberson		loadglobal_re = re.compile(ktrhdr + "global load: (\d+)")
891dcee3bd3SJeff Roberson
89201e7fb47SScott Long		ktrstr = "critical_\S+ by thread " + crittdname + " to (\d+)"
89301e7fb47SScott Long		critsec_re = re.compile(ktrhdr + ktrstr)
89401e7fb47SScott Long
895dcee3bd3SJeff Roberson		parsers = [[cpuload_re, self.cpuload],
896dcee3bd3SJeff Roberson			   [loadglobal_re, self.loadglobal],
897dcee3bd3SJeff Roberson			   [switchin_re, self.switchin],
898dcee3bd3SJeff Roberson			   [switchout_re, self.switchout],
899dcee3bd3SJeff Roberson			   [sched_add_re, self.sched_add],
900dcee3bd3SJeff Roberson			   [setrunqueue_re, self.sched_rem],
901dcee3bd3SJeff Roberson			   [sched_prio_re, self.sched_prio],
902dcee3bd3SJeff Roberson			   [preempted_re, self.preempted],
903dcee3bd3SJeff Roberson			   [sched_rem_re, self.sched_rem],
904dcee3bd3SJeff Roberson			   [sched_exit_re, self.sched_exit],
905dcee3bd3SJeff Roberson			   [sched_clock_re, self.sched_clock],
90601e7fb47SScott Long			   [critsec_re, self.critsec],
907dcee3bd3SJeff Roberson			   [idled_re, self.idled]]
908dcee3bd3SJeff Roberson
9090482a607SJeff Roberson		lines = ifp.readlines()
9100482a607SJeff Roberson		self.synchstamp(lines)
9110482a607SJeff Roberson		for line in lines:
912dcee3bd3SJeff Roberson			self.lineno += 1
913dcee3bd3SJeff Roberson			if ((self.lineno % 1024) == 0):
914dcee3bd3SJeff Roberson				status.startup("Parsing line " +
915dcee3bd3SJeff Roberson				    str(self.lineno))
916dcee3bd3SJeff Roberson			for p in parsers:
917dcee3bd3SJeff Roberson				m = p[0].match(line)
918dcee3bd3SJeff Roberson				if (m != None):
919dcee3bd3SJeff Roberson					p[1](*m.groups())
920dcee3bd3SJeff Roberson					break
921dcee3bd3SJeff Roberson			# if (m == None):
922dcee3bd3SJeff Roberson			# 	print line,
923dcee3bd3SJeff Roberson
9240482a607SJeff Roberson	def synchstamp(self, lines):
9250482a607SJeff Roberson		status.startup("Rationalizing Timestamps")
9260482a607SJeff Roberson		tstamp_re = re.compile("\s+\d+\s+(\d+)\s+(\d+)\s+.*")
9270482a607SJeff Roberson		for line in lines:
9280482a607SJeff Roberson			m = tstamp_re.match(line)
9290482a607SJeff Roberson			if (m != None):
9300482a607SJeff Roberson				self.addstamp(*m.groups())
9310482a607SJeff Roberson		self.pickstamp()
9320482a607SJeff Roberson		self.monostamp(lines)
9330482a607SJeff Roberson
9340482a607SJeff Roberson
9350482a607SJeff Roberson	def monostamp(self, lines):
9360482a607SJeff Roberson		laststamp = None
9370482a607SJeff Roberson		tstamp_re = re.compile("\s+\d+\s+(\d+)\s+(\d+)\s+.*")
9380482a607SJeff Roberson		for line in lines:
9390482a607SJeff Roberson			m = tstamp_re.match(line)
9400482a607SJeff Roberson			if (m == None):
9410482a607SJeff Roberson				continue
9420482a607SJeff Roberson			(cpu, timestamp) = m.groups()
943dcee3bd3SJeff Roberson			timestamp = int(timestamp)
9440482a607SJeff Roberson			cpu = int(cpu)
9450482a607SJeff Roberson			timestamp -= self.timestamp_adjust[cpu]
9460482a607SJeff Roberson			if (laststamp != None and timestamp > laststamp):
9470482a607SJeff Roberson				self.timestamp_adjust[cpu] += timestamp - laststamp
9480482a607SJeff Roberson			laststamp = timestamp
9490482a607SJeff Roberson
9500482a607SJeff Roberson	def addstamp(self, cpu, timestamp):
9510482a607SJeff Roberson		timestamp = int(timestamp)
9520482a607SJeff Roberson		cpu = int(cpu)
9530482a607SJeff Roberson		try:
9540482a607SJeff Roberson			if (timestamp > self.timestamp_first[cpu]):
9550482a607SJeff Roberson				return
9560482a607SJeff Roberson		except:
9570482a607SJeff Roberson			self.timestamp_first[cpu] = timestamp
9580482a607SJeff Roberson		self.timestamp_last[cpu] = timestamp
9590482a607SJeff Roberson
9600482a607SJeff Roberson	def pickstamp(self):
9610482a607SJeff Roberson		base = self.timestamp_last[0]
9620482a607SJeff Roberson		for i in range(0, len(self.timestamp_last)):
9630482a607SJeff Roberson			if (self.timestamp_last[i] < base):
9640482a607SJeff Roberson				base = self.timestamp_last[i]
9650482a607SJeff Roberson
9660482a607SJeff Roberson		print "Adjusting to base stamp", base
9670482a607SJeff Roberson		for i in range(0, len(self.timestamp_last)):
9680482a607SJeff Roberson			self.timestamp_adjust[i] = self.timestamp_last[i] - base;
9690482a607SJeff Roberson			print "CPU ", i, "adjust by ", self.timestamp_adjust[i]
9700482a607SJeff Roberson
9710482a607SJeff Roberson		self.timestamp_f = 0
9720482a607SJeff Roberson		for i in range(0, len(self.timestamp_first)):
9730482a607SJeff Roberson			first = self.timestamp_first[i] - self.timestamp_adjust[i]
9740482a607SJeff Roberson			if (first > self.timestamp_f):
9750482a607SJeff Roberson				self.timestamp_f = first
9760482a607SJeff Roberson
9770482a607SJeff Roberson		self.timestamp_l = 0
9780482a607SJeff Roberson		for i in range(0, len(self.timestamp_last)):
9790482a607SJeff Roberson			last = self.timestamp_last[i] - self.timestamp_adjust[i]
9800482a607SJeff Roberson			if (last > self.timestamp_l):
9810482a607SJeff Roberson				self.timestamp_l = last
9820482a607SJeff Roberson
9830482a607SJeff Roberson
9840482a607SJeff Roberson	def checkstamp(self, cpu, timestamp):
9850482a607SJeff Roberson		cpu = int(cpu)
9860482a607SJeff Roberson		timestamp = int(timestamp)
9870482a607SJeff Roberson		if (timestamp > self.timestamp_first[cpu]):
988dcee3bd3SJeff Roberson			print "Bad timestamp on line ", self.lineno
989dcee3bd3SJeff Roberson			return (0)
9900482a607SJeff Roberson		timestamp -= self.timestamp_adjust[cpu]
9910482a607SJeff Roberson		return (timestamp)
992dcee3bd3SJeff Roberson
993dcee3bd3SJeff Roberson	def timespan(self):
9940482a607SJeff Roberson		return (self.timestamp_f - self.timestamp_l);
995dcee3bd3SJeff Roberson
996dcee3bd3SJeff Roberson	def ticksps(self):
997dcee3bd3SJeff Roberson		return (self.timespan() / self.ticks[0]) * int(self.stathz)
998dcee3bd3SJeff Roberson
999dcee3bd3SJeff Roberson	def switchout(self, cpu, timestamp, td, pcomm, prio, inhibit, wmesg, lock):
1000dcee3bd3SJeff Roberson		TDI_SUSPENDED = 0x0001
1001dcee3bd3SJeff Roberson		TDI_SLEEPING = 0x0002
1002dcee3bd3SJeff Roberson		TDI_SWAPPED = 0x0004
1003dcee3bd3SJeff Roberson		TDI_LOCK = 0x0008
1004dcee3bd3SJeff Roberson		TDI_IWAIT = 0x0010
1005dcee3bd3SJeff Roberson
10060482a607SJeff Roberson		timestamp = self.checkstamp(cpu, timestamp)
10070482a607SJeff Roberson		if (timestamp == 0):
1008dcee3bd3SJeff Roberson			return
1009dcee3bd3SJeff Roberson		inhibit = int(inhibit)
1010dcee3bd3SJeff Roberson		thread = self.findtd(td, pcomm)
1011dcee3bd3SJeff Roberson		if (inhibit & TDI_SWAPPED):
1012dcee3bd3SJeff Roberson			Swapped(thread, cpu, timestamp, prio)
1013dcee3bd3SJeff Roberson		elif (inhibit & TDI_SLEEPING):
1014dcee3bd3SJeff Roberson			Sleep(thread, cpu, timestamp, prio, wmesg)
1015dcee3bd3SJeff Roberson		elif (inhibit & TDI_LOCK):
1016dcee3bd3SJeff Roberson			Blocked(thread, cpu, timestamp, prio, lock)
1017dcee3bd3SJeff Roberson		elif (inhibit & TDI_IWAIT):
1018dcee3bd3SJeff Roberson			Iwait(thread, cpu, timestamp, prio)
1019dcee3bd3SJeff Roberson		elif (inhibit & TDI_SUSPENDED):
1020dcee3bd3SJeff Roberson			Suspended(thread, cpu, timestamp, prio)
1021dcee3bd3SJeff Roberson		elif (inhibit == 0):
1022dcee3bd3SJeff Roberson			Yielding(thread, cpu, timestamp, prio)
1023dcee3bd3SJeff Roberson		else:
1024dcee3bd3SJeff Roberson			print "Unknown event", inhibit
1025dcee3bd3SJeff Roberson			sys.exit(1)
1026dcee3bd3SJeff Roberson
1027dcee3bd3SJeff Roberson	def idled(self, cpu, timestamp, td, pcomm, prio):
10280482a607SJeff Roberson		timestamp = self.checkstamp(cpu, timestamp)
10290482a607SJeff Roberson		if (timestamp == 0):
1030dcee3bd3SJeff Roberson			return
1031dcee3bd3SJeff Roberson		thread = self.findtd(td, pcomm)
1032dcee3bd3SJeff Roberson		Idle(thread, cpu, timestamp, prio)
1033dcee3bd3SJeff Roberson
1034dcee3bd3SJeff Roberson	def preempted(self, cpu, timestamp, td, pcomm, prio, bytd, bypcomm):
10350482a607SJeff Roberson		timestamp = self.checkstamp(cpu, timestamp)
10360482a607SJeff Roberson		if (timestamp == 0):
1037dcee3bd3SJeff Roberson			return
1038dcee3bd3SJeff Roberson		thread = self.findtd(td, pcomm)
1039dcee3bd3SJeff Roberson		Preempted(thread, cpu, timestamp, prio,
1040dcee3bd3SJeff Roberson		    self.findtd(bytd, bypcomm))
1041dcee3bd3SJeff Roberson
1042dcee3bd3SJeff Roberson	def switchin(self, cpu, timestamp, td, pcomm, prio):
10430482a607SJeff Roberson		timestamp = self.checkstamp(cpu, timestamp)
10440482a607SJeff Roberson		if (timestamp == 0):
1045dcee3bd3SJeff Roberson			return
1046dcee3bd3SJeff Roberson		thread = self.findtd(td, pcomm)
1047dcee3bd3SJeff Roberson		Running(thread, cpu, timestamp, prio)
1048dcee3bd3SJeff Roberson
1049dcee3bd3SJeff Roberson	def sched_add(self, cpu, timestamp, td, pcomm, prio, bytd, bypcomm):
10500482a607SJeff Roberson		timestamp = self.checkstamp(cpu, timestamp)
10510482a607SJeff Roberson		if (timestamp == 0):
1052dcee3bd3SJeff Roberson			return
1053dcee3bd3SJeff Roberson		thread = self.findtd(td, pcomm)
1054dcee3bd3SJeff Roberson		bythread = self.findtd(bytd, bypcomm)
1055dcee3bd3SJeff Roberson		Runq(thread, cpu, timestamp, prio, bythread)
1056dcee3bd3SJeff Roberson		Wokeup(bythread, cpu, timestamp, thread)
1057dcee3bd3SJeff Roberson
1058dcee3bd3SJeff Roberson	def sched_rem(self, cpu, timestamp, td, pcomm, prio, bytd, bypcomm):
10590482a607SJeff Roberson		timestamp = self.checkstamp(cpu, timestamp)
10600482a607SJeff Roberson		if (timestamp == 0):
1061dcee3bd3SJeff Roberson			return
1062dcee3bd3SJeff Roberson		thread = self.findtd(td, pcomm)
1063dcee3bd3SJeff Roberson		KsegrpRunq(thread, cpu, timestamp, prio,
1064dcee3bd3SJeff Roberson		    self.findtd(bytd, bypcomm))
1065dcee3bd3SJeff Roberson
1066dcee3bd3SJeff Roberson	def sched_exit(self, cpu, timestamp, td, pcomm, prio):
10670482a607SJeff Roberson		timestamp = self.checkstamp(cpu, timestamp)
10680482a607SJeff Roberson		if (timestamp == 0):
1069dcee3bd3SJeff Roberson			return
1070dcee3bd3SJeff Roberson		thread = self.findtd(td, pcomm)
1071dcee3bd3SJeff Roberson		Sched_exit(thread, cpu, timestamp, prio)
1072dcee3bd3SJeff Roberson
1073dcee3bd3SJeff Roberson	def sched_clock(self, cpu, timestamp, td, pcomm, prio, stathz):
10740482a607SJeff Roberson		timestamp = self.checkstamp(cpu, timestamp)
10750482a607SJeff Roberson		if (timestamp == 0):
1076dcee3bd3SJeff Roberson			return
1077dcee3bd3SJeff Roberson		self.stathz = stathz
1078dcee3bd3SJeff Roberson		cpu = int(cpu)
1079dcee3bd3SJeff Roberson		try:
1080dcee3bd3SJeff Roberson			ticks = self.ticks[cpu]
1081dcee3bd3SJeff Roberson		except:
1082dcee3bd3SJeff Roberson			self.ticks[cpu] = 0
1083dcee3bd3SJeff Roberson		self.ticks[cpu] += 1
1084dcee3bd3SJeff Roberson		thread = self.findtd(td, pcomm)
1085dcee3bd3SJeff Roberson		Tick(thread, cpu, timestamp, prio, stathz)
1086dcee3bd3SJeff Roberson
1087dcee3bd3SJeff Roberson	def sched_prio(self, cpu, timestamp, td, pcomm, prio, newprio, bytd, bypcomm):
1088dcee3bd3SJeff Roberson		if (prio == newprio):
1089dcee3bd3SJeff Roberson			return
10900482a607SJeff Roberson		timestamp = self.checkstamp(cpu, timestamp)
10910482a607SJeff Roberson		if (timestamp == 0):
1092dcee3bd3SJeff Roberson			return
1093dcee3bd3SJeff Roberson		thread = self.findtd(td, pcomm)
1094dcee3bd3SJeff Roberson		bythread = self.findtd(bytd, bypcomm)
1095dcee3bd3SJeff Roberson		Prio(thread, cpu, timestamp, prio, newprio, bythread)
1096dcee3bd3SJeff Roberson		Lend(bythread, cpu, timestamp, newprio, thread)
1097dcee3bd3SJeff Roberson
1098dcee3bd3SJeff Roberson	def cpuload(self, cpu, timestamp, count):
10990482a607SJeff Roberson		timestamp = self.checkstamp(cpu, timestamp)
11000482a607SJeff Roberson		if (timestamp == 0):
1101b0e48518SJeff Roberson			return
1102dcee3bd3SJeff Roberson		cpu = int(cpu)
1103dcee3bd3SJeff Roberson		try:
1104dcee3bd3SJeff Roberson			load = self.load[cpu]
1105dcee3bd3SJeff Roberson		except:
1106dcee3bd3SJeff Roberson			load = Counter("cpu" + str(cpu) + " load")
1107dcee3bd3SJeff Roberson			self.load[cpu] = load
1108dcee3bd3SJeff Roberson			self.sources.insert(0, load)
1109dcee3bd3SJeff Roberson		Count(load, cpu, timestamp, count)
1110dcee3bd3SJeff Roberson
1111dcee3bd3SJeff Roberson	def loadglobal(self, cpu, timestamp, count):
11120482a607SJeff Roberson		timestamp = self.checkstamp(cpu, timestamp)
11130482a607SJeff Roberson		if (timestamp == 0):
1114b0e48518SJeff Roberson			return
1115dcee3bd3SJeff Roberson		cpu = 0
1116dcee3bd3SJeff Roberson		try:
1117dcee3bd3SJeff Roberson			load = self.load[cpu]
1118dcee3bd3SJeff Roberson		except:
1119dcee3bd3SJeff Roberson			load = Counter("CPU load")
1120dcee3bd3SJeff Roberson			self.load[cpu] = load
1121dcee3bd3SJeff Roberson			self.sources.insert(0, load)
1122dcee3bd3SJeff Roberson		Count(load, cpu, timestamp, count)
1123dcee3bd3SJeff Roberson
112401e7fb47SScott Long	def critsec(self, cpu, timestamp, td, pcomm, to):
11250482a607SJeff Roberson		timestamp = self.checkstamp(cpu, timestamp)
11260482a607SJeff Roberson		if (timestamp == 0):
112701e7fb47SScott Long			return
112801e7fb47SScott Long		cpu = int(cpu)
112901e7fb47SScott Long		try:
113001e7fb47SScott Long			crit = self.crit[cpu]
113101e7fb47SScott Long		except:
113201e7fb47SScott Long			crit = Counter("Critical Section")
113301e7fb47SScott Long			self.crit[cpu] = crit
113401e7fb47SScott Long			self.sources.insert(0, crit)
113501e7fb47SScott Long		Count(crit, cpu, timestamp, to)
113601e7fb47SScott Long
1137dcee3bd3SJeff Roberson	def findtd(self, td, pcomm):
1138dcee3bd3SJeff Roberson		for thread in self.threads:
1139dcee3bd3SJeff Roberson			if (thread.str == td and thread.name == pcomm):
1140dcee3bd3SJeff Roberson				return thread
1141dcee3bd3SJeff Roberson		thread = Thread(td, pcomm)
1142dcee3bd3SJeff Roberson		self.threads.append(thread)
1143dcee3bd3SJeff Roberson		self.sources.append(thread)
1144dcee3bd3SJeff Roberson		return (thread)
1145dcee3bd3SJeff Roberson
1146dcee3bd3SJeff Roberson	def fixup(self):
1147dcee3bd3SJeff Roberson		for source in self.sources:
11480482a607SJeff Roberson			Padevent(source, -1, self.timestamp_l)
11490482a607SJeff Roberson			Padevent(source, -1, self.timestamp_f, last=1)
1150dcee3bd3SJeff Roberson			source.fixup()
1151dcee3bd3SJeff Roberson
1152dcee3bd3SJeff Robersonclass SchedDisplay(Canvas):
1153dcee3bd3SJeff Roberson	def __init__(self, master):
1154dcee3bd3SJeff Roberson		self.ratio = 1
1155dcee3bd3SJeff Roberson		self.ktrfile = None
1156dcee3bd3SJeff Roberson		self.sources = None
1157dcee3bd3SJeff Roberson		self.bdheight = 10
1158dcee3bd3SJeff Roberson		self.events = {}
1159dcee3bd3SJeff Roberson
1160dcee3bd3SJeff Roberson		Canvas.__init__(self, master, width=800, height=500, bg='grey',
1161dcee3bd3SJeff Roberson		     scrollregion=(0, 0, 800, 500))
1162dcee3bd3SJeff Roberson
1163dcee3bd3SJeff Roberson	def setfile(self, ktrfile):
1164dcee3bd3SJeff Roberson		self.ktrfile = ktrfile
1165dcee3bd3SJeff Roberson		self.sources = ktrfile.sources
1166dcee3bd3SJeff Roberson
1167dcee3bd3SJeff Roberson	def draw(self):
1168dcee3bd3SJeff Roberson		ypos = 0
1169dcee3bd3SJeff Roberson		xsize = self.xsize()
1170dcee3bd3SJeff Roberson		for source in self.sources:
1171dcee3bd3SJeff Roberson			status.startup("Drawing " + source.name)
1172dcee3bd3SJeff Roberson			self.create_line(0, ypos, xsize, ypos,
1173dcee3bd3SJeff Roberson			    width=1, fill="black", tags=("all",))
1174dcee3bd3SJeff Roberson			ypos += self.bdheight
1175dcee3bd3SJeff Roberson			ypos += source.ysize()
1176dcee3bd3SJeff Roberson			source.draw(self, ypos)
1177dcee3bd3SJeff Roberson			ypos += self.bdheight
1178dcee3bd3SJeff Roberson			try:
1179dcee3bd3SJeff Roberson				self.tag_raise("point", "state")
1180dcee3bd3SJeff Roberson				self.tag_lower("cpuinfo", "all")
1181dcee3bd3SJeff Roberson			except:
1182dcee3bd3SJeff Roberson				pass
1183dcee3bd3SJeff Roberson		self.create_line(0, ypos, xsize, ypos,
1184dcee3bd3SJeff Roberson		    width=1, fill="black", tags=("all",))
1185dcee3bd3SJeff Roberson		self.tag_bind("event", "<Enter>", self.mouseenter)
1186dcee3bd3SJeff Roberson		self.tag_bind("event", "<Leave>", self.mouseexit)
1187dcee3bd3SJeff Roberson		self.tag_bind("event", "<Button-1>", self.mousepress)
1188dcee3bd3SJeff Roberson
1189dcee3bd3SJeff Roberson	def mouseenter(self, event):
1190dcee3bd3SJeff Roberson		item, = self.find_withtag(CURRENT)
1191dcee3bd3SJeff Roberson		event = self.events[item]
1192dcee3bd3SJeff Roberson		event.mouseenter(self, item)
1193dcee3bd3SJeff Roberson
1194dcee3bd3SJeff Roberson	def mouseexit(self, event):
1195dcee3bd3SJeff Roberson		item, = self.find_withtag(CURRENT)
1196dcee3bd3SJeff Roberson		event = self.events[item]
1197dcee3bd3SJeff Roberson		event.mouseexit(self, item)
1198dcee3bd3SJeff Roberson
1199dcee3bd3SJeff Roberson	def mousepress(self, event):
1200dcee3bd3SJeff Roberson		item, = self.find_withtag(CURRENT)
1201dcee3bd3SJeff Roberson		event = self.events[item]
1202dcee3bd3SJeff Roberson		event.mousepress(self, item)
1203dcee3bd3SJeff Roberson
1204dcee3bd3SJeff Roberson	def drawnames(self, canvas):
1205dcee3bd3SJeff Roberson		status.startup("Drawing names")
1206dcee3bd3SJeff Roberson		ypos = 0
1207dcee3bd3SJeff Roberson		canvas.configure(scrollregion=(0, 0,
1208dcee3bd3SJeff Roberson		    canvas["width"], self.ysize()))
1209dcee3bd3SJeff Roberson		for source in self.sources:
1210dcee3bd3SJeff Roberson			canvas.create_line(0, ypos, canvas["width"], ypos,
1211dcee3bd3SJeff Roberson			    width=1, fill="black", tags=("all",))
1212dcee3bd3SJeff Roberson			ypos += self.bdheight
1213dcee3bd3SJeff Roberson			ypos += source.ysize()
1214dcee3bd3SJeff Roberson			source.drawname(canvas, ypos)
1215dcee3bd3SJeff Roberson			ypos += self.bdheight
1216dcee3bd3SJeff Roberson		canvas.create_line(0, ypos, canvas["width"], ypos,
1217dcee3bd3SJeff Roberson		    width=1, fill="black", tags=("all",))
1218dcee3bd3SJeff Roberson
1219dcee3bd3SJeff Roberson	def xsize(self):
1220dcee3bd3SJeff Roberson		return ((self.ktrfile.timespan() / self.ratio) + 20)
1221dcee3bd3SJeff Roberson
1222dcee3bd3SJeff Roberson	def ysize(self):
1223dcee3bd3SJeff Roberson		ysize = 0
1224dcee3bd3SJeff Roberson		for source in self.sources:
1225dcee3bd3SJeff Roberson			ysize += source.ysize() + (self.bdheight * 2)
1226dcee3bd3SJeff Roberson		return (ysize)
1227dcee3bd3SJeff Roberson
1228dcee3bd3SJeff Roberson	def scaleset(self, ratio):
1229dcee3bd3SJeff Roberson		if (self.ktrfile == None):
1230dcee3bd3SJeff Roberson			return
1231dcee3bd3SJeff Roberson		oldratio = self.ratio
1232dcee3bd3SJeff Roberson		xstart, ystart = self.xview()
1233dcee3bd3SJeff Roberson		length = (float(self["width"]) / self.xsize())
1234dcee3bd3SJeff Roberson		middle = xstart + (length / 2)
1235dcee3bd3SJeff Roberson
1236dcee3bd3SJeff Roberson		self.ratio = ratio
1237dcee3bd3SJeff Roberson		self.configure(scrollregion=(0, 0, self.xsize(), self.ysize()))
1238dcee3bd3SJeff Roberson		self.scale("all", 0, 0, float(oldratio) / ratio, 1)
1239dcee3bd3SJeff Roberson
1240dcee3bd3SJeff Roberson		length = (float(self["width"]) / self.xsize())
1241dcee3bd3SJeff Roberson		xstart = middle - (length / 2)
1242dcee3bd3SJeff Roberson		self.xview_moveto(xstart)
1243dcee3bd3SJeff Roberson
1244dcee3bd3SJeff Roberson	def scaleget(self):
1245dcee3bd3SJeff Roberson		return self.ratio
1246dcee3bd3SJeff Roberson
1247dcee3bd3SJeff Roberson	def setcolor(self, tag, color):
1248dcee3bd3SJeff Roberson		self.itemconfigure(tag, state="normal", fill=color)
1249dcee3bd3SJeff Roberson
1250dcee3bd3SJeff Roberson	def hide(self, tag):
1251dcee3bd3SJeff Roberson		self.itemconfigure(tag, state="hidden")
1252dcee3bd3SJeff Roberson
1253dcee3bd3SJeff Robersonclass GraphMenu(Frame):
1254dcee3bd3SJeff Roberson	def __init__(self, master):
1255dcee3bd3SJeff Roberson		Frame.__init__(self, master, bd=2, relief=RAISED)
1256dcee3bd3SJeff Roberson		self.view = Menubutton(self, text="Configure")
1257dcee3bd3SJeff Roberson		self.viewmenu = Menu(self.view, tearoff=0)
1258dcee3bd3SJeff Roberson		self.viewmenu.add_command(label="Events",
1259dcee3bd3SJeff Roberson		    command=self.econf)
1260dcee3bd3SJeff Roberson		self.view["menu"] = self.viewmenu
1261dcee3bd3SJeff Roberson		self.view.pack(side=LEFT)
1262dcee3bd3SJeff Roberson
1263dcee3bd3SJeff Roberson	def econf(self):
1264dcee3bd3SJeff Roberson		EventConfigure()
1265dcee3bd3SJeff Roberson
1266dcee3bd3SJeff Roberson
1267dcee3bd3SJeff Robersonclass SchedGraph(Frame):
1268dcee3bd3SJeff Roberson	def __init__(self, master):
1269dcee3bd3SJeff Roberson		Frame.__init__(self, master)
1270dcee3bd3SJeff Roberson		self.menu = None
1271dcee3bd3SJeff Roberson		self.names = None
1272dcee3bd3SJeff Roberson		self.display = None
1273dcee3bd3SJeff Roberson		self.scale = None
1274dcee3bd3SJeff Roberson		self.status = None
1275dcee3bd3SJeff Roberson		self.pack(expand=1, fill="both")
1276dcee3bd3SJeff Roberson		self.buildwidgets()
1277dcee3bd3SJeff Roberson		self.layout()
1278dcee3bd3SJeff Roberson		self.draw(sys.argv[1])
1279dcee3bd3SJeff Roberson
1280dcee3bd3SJeff Roberson	def buildwidgets(self):
1281dcee3bd3SJeff Roberson		global status
1282dcee3bd3SJeff Roberson		self.menu = GraphMenu(self)
1283dcee3bd3SJeff Roberson		self.display = SchedDisplay(self)
1284dcee3bd3SJeff Roberson		self.names = Canvas(self,
1285dcee3bd3SJeff Roberson		    width=100, height=self.display["height"],
1286dcee3bd3SJeff Roberson		    bg='grey', scrollregion=(0, 0, 50, 100))
1287dcee3bd3SJeff Roberson		self.scale = Scaler(self, self.display)
1288dcee3bd3SJeff Roberson		status = self.status = Status(self)
1289dcee3bd3SJeff Roberson		self.scrollY = Scrollbar(self, orient="vertical",
1290dcee3bd3SJeff Roberson		    command=self.display_yview)
1291dcee3bd3SJeff Roberson		self.display.scrollX = Scrollbar(self, orient="horizontal",
1292dcee3bd3SJeff Roberson		    command=self.display.xview)
1293dcee3bd3SJeff Roberson		self.display["xscrollcommand"] = self.display.scrollX.set
1294dcee3bd3SJeff Roberson		self.display["yscrollcommand"] = self.scrollY.set
1295dcee3bd3SJeff Roberson		self.names["yscrollcommand"] = self.scrollY.set
1296dcee3bd3SJeff Roberson
1297dcee3bd3SJeff Roberson	def layout(self):
1298dcee3bd3SJeff Roberson		self.columnconfigure(1, weight=1)
1299dcee3bd3SJeff Roberson		self.rowconfigure(1, weight=1)
1300dcee3bd3SJeff Roberson		self.menu.grid(row=0, column=0, columnspan=3, sticky=E+W)
1301dcee3bd3SJeff Roberson		self.names.grid(row=1, column=0, sticky=N+S)
1302dcee3bd3SJeff Roberson		self.display.grid(row=1, column=1, sticky=W+E+N+S)
1303dcee3bd3SJeff Roberson		self.scrollY.grid(row=1, column=2, sticky=N+S)
1304dcee3bd3SJeff Roberson		self.display.scrollX.grid(row=2, column=0, columnspan=2,
1305dcee3bd3SJeff Roberson		    sticky=E+W)
1306dcee3bd3SJeff Roberson		self.scale.grid(row=3, column=0, columnspan=3, sticky=E+W)
1307dcee3bd3SJeff Roberson		self.status.grid(row=4, column=0, columnspan=3, sticky=E+W)
1308dcee3bd3SJeff Roberson
1309dcee3bd3SJeff Roberson	def draw(self, file):
1310dcee3bd3SJeff Roberson		self.master.update()
1311dcee3bd3SJeff Roberson		ktrfile = KTRFile(file)
1312dcee3bd3SJeff Roberson		self.display.setfile(ktrfile)
1313dcee3bd3SJeff Roberson		self.display.drawnames(self.names)
1314dcee3bd3SJeff Roberson		self.display.draw()
1315dcee3bd3SJeff Roberson		self.scale.set(250000)
1316dcee3bd3SJeff Roberson		self.display.xview_moveto(0)
1317dcee3bd3SJeff Roberson
1318dcee3bd3SJeff Roberson	def display_yview(self, *args):
1319dcee3bd3SJeff Roberson		self.names.yview(*args)
1320dcee3bd3SJeff Roberson		self.display.yview(*args)
1321dcee3bd3SJeff Roberson
1322dcee3bd3SJeff Roberson	def setcolor(self, tag, color):
1323dcee3bd3SJeff Roberson		self.display.setcolor(tag, color)
1324dcee3bd3SJeff Roberson
1325dcee3bd3SJeff Roberson	def hide(self, tag):
1326dcee3bd3SJeff Roberson		self.display.hide(tag)
1327dcee3bd3SJeff Roberson
1328dcee3bd3SJeff Robersonif (len(sys.argv) != 2):
1329dcee3bd3SJeff Roberson	print "usage:", sys.argv[0], "<ktr file>"
1330dcee3bd3SJeff Roberson	sys.exit(1)
1331dcee3bd3SJeff Roberson
1332dcee3bd3SJeff Robersonroot = Tk()
1333dcee3bd3SJeff Robersonroot.title("Scheduler Graph")
1334dcee3bd3SJeff Robersongraph = SchedGraph(root)
1335dcee3bd3SJeff Robersonroot.mainloop()
1336