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