1880d22f2SFrederic Weisbecker#!/usr/bin/python
2880d22f2SFrederic Weisbecker#
3880d22f2SFrederic Weisbecker# Cpu task migration overview toy
4880d22f2SFrederic Weisbecker#
5880d22f2SFrederic Weisbecker# Copyright (C) 2010 Frederic Weisbecker <[email protected]>
6880d22f2SFrederic Weisbecker#
7880d22f2SFrederic Weisbecker# perf trace event handlers have been generated by perf trace -g python
8880d22f2SFrederic Weisbecker#
9880d22f2SFrederic Weisbecker# The whole is licensed under the terms of the GNU GPL License version 2
10880d22f2SFrederic Weisbecker
11880d22f2SFrederic Weisbecker
12880d22f2SFrederic Weisbeckertry:
13880d22f2SFrederic Weisbecker	import wx
14880d22f2SFrederic Weisbeckerexcept ImportError:
15880d22f2SFrederic Weisbecker	raise ImportError, "You need to install the wxpython lib for this script"
16880d22f2SFrederic Weisbecker
17880d22f2SFrederic Weisbeckerimport os
18880d22f2SFrederic Weisbeckerimport sys
19880d22f2SFrederic Weisbecker
20880d22f2SFrederic Weisbeckerfrom collections import defaultdict
21880d22f2SFrederic Weisbeckerfrom UserList import UserList
22880d22f2SFrederic Weisbecker
23880d22f2SFrederic Weisbeckersys.path.append(os.environ['PERF_EXEC_PATH'] + \
24880d22f2SFrederic Weisbecker	'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
25880d22f2SFrederic Weisbecker
26880d22f2SFrederic Weisbeckerfrom perf_trace_context import *
27880d22f2SFrederic Weisbeckerfrom Core import *
28880d22f2SFrederic Weisbecker
29880d22f2SFrederic Weisbeckerclass RootFrame(wx.Frame):
30880d22f2SFrederic Weisbecker	def __init__(self, timeslices, parent = None, id = -1, title = "Migration"):
31880d22f2SFrederic Weisbecker		wx.Frame.__init__(self, parent, id, title)
32880d22f2SFrederic Weisbecker
33880d22f2SFrederic Weisbecker		(self.screen_width, self.screen_height) = wx.GetDisplaySize()
34880d22f2SFrederic Weisbecker		self.screen_width -= 10
35880d22f2SFrederic Weisbecker		self.screen_height -= 10
36880d22f2SFrederic Weisbecker		self.zoom = 0.5
37880d22f2SFrederic Weisbecker		self.scroll_scale = 20
38880d22f2SFrederic Weisbecker		self.timeslices = timeslices
39880d22f2SFrederic Weisbecker		(self.ts_start, self.ts_end) = timeslices.interval()
40880d22f2SFrederic Weisbecker		self.update_width_virtual()
41880d22f2SFrederic Weisbecker
42880d22f2SFrederic Weisbecker		# whole window panel
43880d22f2SFrederic Weisbecker		self.panel = wx.Panel(self, size=(self.screen_width, self.screen_height))
44880d22f2SFrederic Weisbecker
45880d22f2SFrederic Weisbecker		# scrollable container
46880d22f2SFrederic Weisbecker		self.scroll = wx.ScrolledWindow(self.panel)
47880d22f2SFrederic Weisbecker		self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, 100 / 10)
48880d22f2SFrederic Weisbecker		self.scroll.EnableScrolling(True, True)
49880d22f2SFrederic Weisbecker		self.scroll.SetFocus()
50880d22f2SFrederic Weisbecker
51880d22f2SFrederic Weisbecker		# scrollable drawing area
52880d22f2SFrederic Weisbecker		self.scroll_panel = wx.Panel(self.scroll, size=(self.screen_width, self.screen_height / 2))
53880d22f2SFrederic Weisbecker		self.scroll_panel.Bind(wx.EVT_PAINT, self.on_paint)
54880d22f2SFrederic Weisbecker		self.scroll_panel.Bind(wx.EVT_KEY_DOWN, self.on_key_press)
55880d22f2SFrederic Weisbecker		self.scroll_panel.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down)
56880d22f2SFrederic Weisbecker		self.scroll.Bind(wx.EVT_PAINT, self.on_paint)
57880d22f2SFrederic Weisbecker
58880d22f2SFrederic Weisbecker		self.scroll.Fit()
59880d22f2SFrederic Weisbecker		self.Fit()
60880d22f2SFrederic Weisbecker
61880d22f2SFrederic Weisbecker		self.scroll_panel.SetDimensions(-1, -1, self.width_virtual, -1, wx.SIZE_USE_EXISTING)
62880d22f2SFrederic Weisbecker
63880d22f2SFrederic Weisbecker		self.max_cpu = -1
64880d22f2SFrederic Weisbecker		self.txt = None
65880d22f2SFrederic Weisbecker
66880d22f2SFrederic Weisbecker		self.Show(True)
67880d22f2SFrederic Weisbecker
68880d22f2SFrederic Weisbecker	def us_to_px(self, val):
69880d22f2SFrederic Weisbecker		return val / (10 ** 3) * self.zoom
70880d22f2SFrederic Weisbecker
71880d22f2SFrederic Weisbecker	def px_to_us(self, val):
72880d22f2SFrederic Weisbecker		return (val / self.zoom) * (10 ** 3)
73880d22f2SFrederic Weisbecker
74880d22f2SFrederic Weisbecker	def scroll_start(self):
75880d22f2SFrederic Weisbecker		(x, y) = self.scroll.GetViewStart()
76880d22f2SFrederic Weisbecker		return (x * self.scroll_scale, y * self.scroll_scale)
77880d22f2SFrederic Weisbecker
78880d22f2SFrederic Weisbecker	def scroll_start_us(self):
79880d22f2SFrederic Weisbecker		(x, y) = self.scroll_start()
80880d22f2SFrederic Weisbecker		return self.px_to_us(x)
81880d22f2SFrederic Weisbecker
82880d22f2SFrederic Weisbecker	def update_rectangle_cpu(self, dc, slice, cpu, offset_time):
83880d22f2SFrederic Weisbecker		rq = slice.rqs[cpu]
84880d22f2SFrederic Weisbecker
85880d22f2SFrederic Weisbecker		if slice.total_load != 0:
86880d22f2SFrederic Weisbecker			load_rate = rq.load() / float(slice.total_load)
87880d22f2SFrederic Weisbecker		else:
88880d22f2SFrederic Weisbecker			load_rate = 0
89880d22f2SFrederic Weisbecker
90880d22f2SFrederic Weisbecker
91880d22f2SFrederic Weisbecker		offset_px = self.us_to_px(slice.start - offset_time)
92880d22f2SFrederic Weisbecker		width_px = self.us_to_px(slice.end - slice.start)
93880d22f2SFrederic Weisbecker		(x, y) = self.scroll_start()
94880d22f2SFrederic Weisbecker
95880d22f2SFrederic Weisbecker		if width_px == 0:
96880d22f2SFrederic Weisbecker			return
97880d22f2SFrederic Weisbecker
98880d22f2SFrederic Weisbecker		offset_py = 100 + (cpu * 150)
99880d22f2SFrederic Weisbecker		width_py = 100
100880d22f2SFrederic Weisbecker
101880d22f2SFrederic Weisbecker		if cpu in slice.event_cpus:
102880d22f2SFrederic Weisbecker			rgb = rq.event.color()
103880d22f2SFrederic Weisbecker			if rgb is not None:
104880d22f2SFrederic Weisbecker				(r, g, b) = rgb
105880d22f2SFrederic Weisbecker				color = wx.Colour(r, g, b)
106880d22f2SFrederic Weisbecker				brush = wx.Brush(color, wx.SOLID)
107880d22f2SFrederic Weisbecker				dc.SetBrush(brush)
108880d22f2SFrederic Weisbecker				dc.DrawRectangle(offset_px, offset_py, width_px, 5)
109880d22f2SFrederic Weisbecker				width_py -= 5
110880d22f2SFrederic Weisbecker				offset_py += 5
111880d22f2SFrederic Weisbecker
112880d22f2SFrederic Weisbecker		red_power = int(0xff - (0xff * load_rate))
113880d22f2SFrederic Weisbecker		color = wx.Colour(0xff, red_power, red_power)
114880d22f2SFrederic Weisbecker		brush = wx.Brush(color, wx.SOLID)
115880d22f2SFrederic Weisbecker		dc.SetBrush(brush)
116880d22f2SFrederic Weisbecker		dc.DrawRectangle(offset_px, offset_py, width_px, width_py)
117880d22f2SFrederic Weisbecker
118880d22f2SFrederic Weisbecker	def update_rectangles(self, dc, start, end):
119880d22f2SFrederic Weisbecker		if len(self.timeslices) == 0:
120880d22f2SFrederic Weisbecker			return
121880d22f2SFrederic Weisbecker		start += self.timeslices[0].start
122880d22f2SFrederic Weisbecker		end += self.timeslices[0].start
123880d22f2SFrederic Weisbecker
124880d22f2SFrederic Weisbecker		color = wx.Colour(0, 0, 0)
125880d22f2SFrederic Weisbecker		brush = wx.Brush(color, wx.SOLID)
126880d22f2SFrederic Weisbecker		dc.SetBrush(brush)
127880d22f2SFrederic Weisbecker
128880d22f2SFrederic Weisbecker		i = self.timeslices.find_time_slice(start)
129880d22f2SFrederic Weisbecker		if i == -1:
130880d22f2SFrederic Weisbecker			return
131880d22f2SFrederic Weisbecker
132880d22f2SFrederic Weisbecker		for i in xrange(i, len(self.timeslices)):
133880d22f2SFrederic Weisbecker			timeslice = self.timeslices[i]
134880d22f2SFrederic Weisbecker			if timeslice.start > end:
135880d22f2SFrederic Weisbecker				return
136880d22f2SFrederic Weisbecker
137880d22f2SFrederic Weisbecker			for cpu in timeslice.rqs:
138880d22f2SFrederic Weisbecker				self.update_rectangle_cpu(dc, timeslice, cpu, self.timeslices[0].start)
139880d22f2SFrederic Weisbecker				if cpu > self.max_cpu:
140880d22f2SFrederic Weisbecker					self.max_cpu = cpu
141880d22f2SFrederic Weisbecker
142880d22f2SFrederic Weisbecker	def on_paint(self, event):
143880d22f2SFrederic Weisbecker		color = wx.Colour(0xff, 0xff, 0xff)
144880d22f2SFrederic Weisbecker		brush = wx.Brush(color, wx.SOLID)
145880d22f2SFrederic Weisbecker		dc = wx.PaintDC(self.scroll_panel)
146880d22f2SFrederic Weisbecker		dc.SetBrush(brush)
147880d22f2SFrederic Weisbecker
148880d22f2SFrederic Weisbecker		width = min(self.width_virtual, self.screen_width)
149880d22f2SFrederic Weisbecker		(x, y) = self.scroll_start()
150880d22f2SFrederic Weisbecker		start = self.px_to_us(x)
151880d22f2SFrederic Weisbecker		end = self.px_to_us(x + width)
152880d22f2SFrederic Weisbecker		self.update_rectangles(dc, start, end)
153880d22f2SFrederic Weisbecker
154880d22f2SFrederic Weisbecker	def cpu_from_ypixel(self, y):
155880d22f2SFrederic Weisbecker		y -= 100
156880d22f2SFrederic Weisbecker		cpu = y / 150
157880d22f2SFrederic Weisbecker		height = y % 150
158880d22f2SFrederic Weisbecker
159880d22f2SFrederic Weisbecker		if cpu < 0 or cpu > self.max_cpu or height > 100:
160880d22f2SFrederic Weisbecker			return -1
161880d22f2SFrederic Weisbecker
162880d22f2SFrederic Weisbecker		return cpu
163880d22f2SFrederic Weisbecker
164880d22f2SFrederic Weisbecker	def update_summary(self, cpu, t):
165880d22f2SFrederic Weisbecker		idx = self.timeslices.find_time_slice(t)
166880d22f2SFrederic Weisbecker		if idx == -1:
167880d22f2SFrederic Weisbecker			return
168880d22f2SFrederic Weisbecker
169880d22f2SFrederic Weisbecker		ts = self.timeslices[idx]
170880d22f2SFrederic Weisbecker		rq = ts.rqs[cpu]
171880d22f2SFrederic Weisbecker		raw = "CPU: %d\n" % cpu
172880d22f2SFrederic Weisbecker		raw += "Last event : %s\n" % rq.event.__repr__()
173880d22f2SFrederic Weisbecker		raw += "Timestamp : %d.%06d\n" % (ts.start / (10 ** 9), (ts.start % (10 ** 9)) / 1000)
174880d22f2SFrederic Weisbecker		raw += "Duration : %6d us\n" % ((ts.end - ts.start) / (10 ** 6))
175880d22f2SFrederic Weisbecker		raw += "Load = %d\n" % rq.load()
176880d22f2SFrederic Weisbecker		for t in rq.tasks:
177880d22f2SFrederic Weisbecker			raw += "%s \n" % thread_name(t)
178880d22f2SFrederic Weisbecker
179880d22f2SFrederic Weisbecker		if self.txt:
180880d22f2SFrederic Weisbecker			self.txt.Destroy()
181880d22f2SFrederic Weisbecker		self.txt = wx.StaticText(self.panel, -1, raw, (0, (self.screen_height / 2) + 50))
182880d22f2SFrederic Weisbecker
183880d22f2SFrederic Weisbecker
184880d22f2SFrederic Weisbecker	def on_mouse_down(self, event):
185880d22f2SFrederic Weisbecker		(x, y) = event.GetPositionTuple()
186880d22f2SFrederic Weisbecker		cpu = self.cpu_from_ypixel(y)
187880d22f2SFrederic Weisbecker		if cpu == -1:
188880d22f2SFrederic Weisbecker			return
189880d22f2SFrederic Weisbecker
190880d22f2SFrederic Weisbecker		t = self.px_to_us(x) + self.timeslices[0].start
191880d22f2SFrederic Weisbecker
192880d22f2SFrederic Weisbecker		self.update_summary(cpu, t)
193880d22f2SFrederic Weisbecker
194880d22f2SFrederic Weisbecker
195880d22f2SFrederic Weisbecker	def update_width_virtual(self):
196880d22f2SFrederic Weisbecker		self.width_virtual = self.us_to_px(self.ts_end - self.ts_start)
197880d22f2SFrederic Weisbecker
198880d22f2SFrederic Weisbecker	def __zoom(self, x):
199880d22f2SFrederic Weisbecker		self.update_width_virtual()
200880d22f2SFrederic Weisbecker		(xpos, ypos) = self.scroll.GetViewStart()
201880d22f2SFrederic Weisbecker		xpos = self.us_to_px(x) / self.scroll_scale
202880d22f2SFrederic Weisbecker		self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, 100 / 10, xpos, ypos)
203880d22f2SFrederic Weisbecker		self.Refresh()
204880d22f2SFrederic Weisbecker
205880d22f2SFrederic Weisbecker	def zoom_in(self):
206880d22f2SFrederic Weisbecker		x = self.scroll_start_us()
207880d22f2SFrederic Weisbecker		self.zoom *= 2
208880d22f2SFrederic Weisbecker		self.__zoom(x)
209880d22f2SFrederic Weisbecker
210880d22f2SFrederic Weisbecker	def zoom_out(self):
211880d22f2SFrederic Weisbecker		x = self.scroll_start_us()
212880d22f2SFrederic Weisbecker		self.zoom /= 2
213880d22f2SFrederic Weisbecker		self.__zoom(x)
214880d22f2SFrederic Weisbecker
215880d22f2SFrederic Weisbecker
216880d22f2SFrederic Weisbecker	def on_key_press(self, event):
217880d22f2SFrederic Weisbecker		key = event.GetRawKeyCode()
218880d22f2SFrederic Weisbecker		if key == ord("+"):
219880d22f2SFrederic Weisbecker			self.zoom_in()
220880d22f2SFrederic Weisbecker			return
221880d22f2SFrederic Weisbecker		if key == ord("-"):
222880d22f2SFrederic Weisbecker			self.zoom_out()
223880d22f2SFrederic Weisbecker			return
224880d22f2SFrederic Weisbecker
225880d22f2SFrederic Weisbecker		key = event.GetKeyCode()
226880d22f2SFrederic Weisbecker		(x, y) = self.scroll.GetViewStart()
227880d22f2SFrederic Weisbecker		if key == wx.WXK_RIGHT:
228880d22f2SFrederic Weisbecker			self.scroll.Scroll(x + 1, y)
229880d22f2SFrederic Weisbecker		elif key == wx.WXK_LEFT:
230880d22f2SFrederic Weisbecker			self.scroll.Scroll(x -1, y)
231880d22f2SFrederic Weisbecker
232880d22f2SFrederic Weisbecker
233880d22f2SFrederic Weisbeckerthreads = { 0 : "idle"}
234880d22f2SFrederic Weisbecker
235880d22f2SFrederic Weisbeckerdef thread_name(pid):
236880d22f2SFrederic Weisbecker	return "%s:%d" % (threads[pid], pid)
237880d22f2SFrederic Weisbecker
238880d22f2SFrederic Weisbeckerclass EventHeaders:
239880d22f2SFrederic Weisbecker	def __init__(self, common_cpu, common_secs, common_nsecs,
240880d22f2SFrederic Weisbecker		     common_pid, common_comm):
241880d22f2SFrederic Weisbecker		self.cpu = common_cpu
242880d22f2SFrederic Weisbecker		self.secs = common_secs
243880d22f2SFrederic Weisbecker		self.nsecs = common_nsecs
244880d22f2SFrederic Weisbecker		self.pid = common_pid
245880d22f2SFrederic Weisbecker		self.comm = common_comm
246880d22f2SFrederic Weisbecker
247880d22f2SFrederic Weisbecker	def ts(self):
248880d22f2SFrederic Weisbecker		return (self.secs * (10 ** 9)) + self.nsecs
249880d22f2SFrederic Weisbecker
250880d22f2SFrederic Weisbecker	def ts_format(self):
251880d22f2SFrederic Weisbecker		return "%d.%d" % (self.secs, int(self.nsecs / 1000))
252880d22f2SFrederic Weisbecker
253880d22f2SFrederic Weisbecker
254880d22f2SFrederic Weisbeckerdef taskState(state):
255880d22f2SFrederic Weisbecker	states = {
256880d22f2SFrederic Weisbecker		0 : "R",
257880d22f2SFrederic Weisbecker		1 : "S",
258880d22f2SFrederic Weisbecker		2 : "D",
259880d22f2SFrederic Weisbecker		64: "DEAD"
260880d22f2SFrederic Weisbecker	}
261880d22f2SFrederic Weisbecker
262880d22f2SFrederic Weisbecker	if state not in states:
263*207f90fcSFrederic Weisbecker		return "Unknown"
264880d22f2SFrederic Weisbecker
265880d22f2SFrederic Weisbecker	return states[state]
266880d22f2SFrederic Weisbecker
267880d22f2SFrederic Weisbecker
268880d22f2SFrederic Weisbeckerclass RunqueueEventUnknown:
269880d22f2SFrederic Weisbecker	@staticmethod
270880d22f2SFrederic Weisbecker	def color():
271880d22f2SFrederic Weisbecker		return None
272880d22f2SFrederic Weisbecker
273880d22f2SFrederic Weisbecker	def __repr__(self):
274880d22f2SFrederic Weisbecker		return "unknown"
275880d22f2SFrederic Weisbecker
276880d22f2SFrederic Weisbeckerclass RunqueueEventSleep:
277880d22f2SFrederic Weisbecker	@staticmethod
278880d22f2SFrederic Weisbecker	def color():
279880d22f2SFrederic Weisbecker		return (0, 0, 0xff)
280880d22f2SFrederic Weisbecker
281880d22f2SFrederic Weisbecker	def __init__(self, sleeper):
282880d22f2SFrederic Weisbecker		self.sleeper = sleeper
283880d22f2SFrederic Weisbecker
284880d22f2SFrederic Weisbecker	def __repr__(self):
285880d22f2SFrederic Weisbecker		return "%s gone to sleep" % thread_name(self.sleeper)
286880d22f2SFrederic Weisbecker
287880d22f2SFrederic Weisbeckerclass RunqueueEventWakeup:
288880d22f2SFrederic Weisbecker	@staticmethod
289880d22f2SFrederic Weisbecker	def color():
290880d22f2SFrederic Weisbecker		return (0xff, 0xff, 0)
291880d22f2SFrederic Weisbecker
292880d22f2SFrederic Weisbecker	def __init__(self, wakee):
293880d22f2SFrederic Weisbecker		self.wakee = wakee
294880d22f2SFrederic Weisbecker
295880d22f2SFrederic Weisbecker	def __repr__(self):
296880d22f2SFrederic Weisbecker		return "%s woke up" % thread_name(self.wakee)
297880d22f2SFrederic Weisbecker
298880d22f2SFrederic Weisbeckerclass RunqueueEventFork:
299880d22f2SFrederic Weisbecker	@staticmethod
300880d22f2SFrederic Weisbecker	def color():
301880d22f2SFrederic Weisbecker		return (0, 0xff, 0)
302880d22f2SFrederic Weisbecker
303880d22f2SFrederic Weisbecker	def __init__(self, child):
304880d22f2SFrederic Weisbecker		self.child = child
305880d22f2SFrederic Weisbecker
306880d22f2SFrederic Weisbecker	def __repr__(self):
307880d22f2SFrederic Weisbecker		return "new forked task %s" % thread_name(self.child)
308880d22f2SFrederic Weisbecker
309880d22f2SFrederic Weisbeckerclass RunqueueMigrateIn:
310880d22f2SFrederic Weisbecker	@staticmethod
311880d22f2SFrederic Weisbecker	def color():
312880d22f2SFrederic Weisbecker		return (0, 0xf0, 0xff)
313880d22f2SFrederic Weisbecker
314880d22f2SFrederic Weisbecker	def __init__(self, new):
315880d22f2SFrederic Weisbecker		self.new = new
316880d22f2SFrederic Weisbecker
317880d22f2SFrederic Weisbecker	def __repr__(self):
318880d22f2SFrederic Weisbecker		return "task migrated in %s" % thread_name(self.new)
319880d22f2SFrederic Weisbecker
320880d22f2SFrederic Weisbeckerclass RunqueueMigrateOut:
321880d22f2SFrederic Weisbecker	@staticmethod
322880d22f2SFrederic Weisbecker	def color():
323880d22f2SFrederic Weisbecker		return (0xff, 0, 0xff)
324880d22f2SFrederic Weisbecker
325880d22f2SFrederic Weisbecker	def __init__(self, old):
326880d22f2SFrederic Weisbecker		self.old = old
327880d22f2SFrederic Weisbecker
328880d22f2SFrederic Weisbecker	def __repr__(self):
329880d22f2SFrederic Weisbecker		return "task migrated out %s" % thread_name(self.old)
330880d22f2SFrederic Weisbecker
331880d22f2SFrederic Weisbeckerclass RunqueueSnapshot:
332880d22f2SFrederic Weisbecker	def __init__(self, tasks = [0], event = RunqueueEventUnknown()):
333880d22f2SFrederic Weisbecker		self.tasks = tuple(tasks)
334880d22f2SFrederic Weisbecker		self.event = event
335880d22f2SFrederic Weisbecker
336880d22f2SFrederic Weisbecker	def sched_switch(self, prev, prev_state, next):
337880d22f2SFrederic Weisbecker		event = RunqueueEventUnknown()
338880d22f2SFrederic Weisbecker
339880d22f2SFrederic Weisbecker		if taskState(prev_state) == "R" and next in self.tasks \
340880d22f2SFrederic Weisbecker			and prev in self.tasks:
341880d22f2SFrederic Weisbecker			return self
342880d22f2SFrederic Weisbecker
343880d22f2SFrederic Weisbecker		if taskState(prev_state) != "R":
344880d22f2SFrederic Weisbecker			event = RunqueueEventSleep(prev)
345880d22f2SFrederic Weisbecker
346880d22f2SFrederic Weisbecker		next_tasks = list(self.tasks[:])
347880d22f2SFrederic Weisbecker		if prev in self.tasks:
348880d22f2SFrederic Weisbecker			if taskState(prev_state) != "R":
349880d22f2SFrederic Weisbecker				next_tasks.remove(prev)
350880d22f2SFrederic Weisbecker		elif taskState(prev_state) == "R":
351880d22f2SFrederic Weisbecker			next_tasks.append(prev)
352880d22f2SFrederic Weisbecker
353880d22f2SFrederic Weisbecker		if next not in next_tasks:
354880d22f2SFrederic Weisbecker			next_tasks.append(next)
355880d22f2SFrederic Weisbecker
356880d22f2SFrederic Weisbecker		return RunqueueSnapshot(next_tasks, event)
357880d22f2SFrederic Weisbecker
358880d22f2SFrederic Weisbecker	def migrate_out(self, old):
359880d22f2SFrederic Weisbecker		if old not in self.tasks:
360880d22f2SFrederic Weisbecker			return self
361880d22f2SFrederic Weisbecker		next_tasks = [task for task in self.tasks if task != old]
362880d22f2SFrederic Weisbecker
363880d22f2SFrederic Weisbecker		return RunqueueSnapshot(next_tasks, RunqueueMigrateOut(old))
364880d22f2SFrederic Weisbecker
365880d22f2SFrederic Weisbecker	def __migrate_in(self, new, event):
366880d22f2SFrederic Weisbecker		if new in self.tasks:
367880d22f2SFrederic Weisbecker			self.event = event
368880d22f2SFrederic Weisbecker			return self
369880d22f2SFrederic Weisbecker		next_tasks = self.tasks[:] + tuple([new])
370880d22f2SFrederic Weisbecker
371880d22f2SFrederic Weisbecker		return RunqueueSnapshot(next_tasks, event)
372880d22f2SFrederic Weisbecker
373880d22f2SFrederic Weisbecker	def migrate_in(self, new):
374880d22f2SFrederic Weisbecker		return self.__migrate_in(new, RunqueueMigrateIn(new))
375880d22f2SFrederic Weisbecker
376880d22f2SFrederic Weisbecker	def wake_up(self, new):
377880d22f2SFrederic Weisbecker		return self.__migrate_in(new, RunqueueEventWakeup(new))
378880d22f2SFrederic Weisbecker
379880d22f2SFrederic Weisbecker	def wake_up_new(self, new):
380880d22f2SFrederic Weisbecker		return self.__migrate_in(new, RunqueueEventFork(new))
381880d22f2SFrederic Weisbecker
382880d22f2SFrederic Weisbecker	def load(self):
383880d22f2SFrederic Weisbecker		""" Provide the number of tasks on the runqueue.
384880d22f2SFrederic Weisbecker		    Don't count idle"""
385880d22f2SFrederic Weisbecker		return len(self.tasks) - 1
386880d22f2SFrederic Weisbecker
387880d22f2SFrederic Weisbecker	def __repr__(self):
388880d22f2SFrederic Weisbecker		ret = self.tasks.__repr__()
389880d22f2SFrederic Weisbecker		ret += self.origin_tostring()
390880d22f2SFrederic Weisbecker
391880d22f2SFrederic Weisbecker		return ret
392880d22f2SFrederic Weisbecker
393880d22f2SFrederic Weisbeckerclass TimeSlice:
394880d22f2SFrederic Weisbecker	def __init__(self, start, prev):
395880d22f2SFrederic Weisbecker		self.start = start
396880d22f2SFrederic Weisbecker		self.prev = prev
397880d22f2SFrederic Weisbecker		self.end = start
398880d22f2SFrederic Weisbecker		# cpus that triggered the event
399880d22f2SFrederic Weisbecker		self.event_cpus = []
400880d22f2SFrederic Weisbecker		if prev is not None:
401880d22f2SFrederic Weisbecker			self.total_load = prev.total_load
402880d22f2SFrederic Weisbecker			self.rqs = prev.rqs.copy()
403880d22f2SFrederic Weisbecker		else:
404880d22f2SFrederic Weisbecker			self.rqs = defaultdict(RunqueueSnapshot)
405880d22f2SFrederic Weisbecker			self.total_load = 0
406880d22f2SFrederic Weisbecker
407880d22f2SFrederic Weisbecker	def __update_total_load(self, old_rq, new_rq):
408880d22f2SFrederic Weisbecker		diff = new_rq.load() - old_rq.load()
409880d22f2SFrederic Weisbecker		self.total_load += diff
410880d22f2SFrederic Weisbecker
411880d22f2SFrederic Weisbecker	def sched_switch(self, ts_list, prev, prev_state, next, cpu):
412880d22f2SFrederic Weisbecker		old_rq = self.prev.rqs[cpu]
413880d22f2SFrederic Weisbecker		new_rq = old_rq.sched_switch(prev, prev_state, next)
414880d22f2SFrederic Weisbecker
415880d22f2SFrederic Weisbecker		if old_rq is new_rq:
416880d22f2SFrederic Weisbecker			return
417880d22f2SFrederic Weisbecker
418880d22f2SFrederic Weisbecker		self.rqs[cpu] = new_rq
419880d22f2SFrederic Weisbecker		self.__update_total_load(old_rq, new_rq)
420880d22f2SFrederic Weisbecker		ts_list.append(self)
421880d22f2SFrederic Weisbecker		self.event_cpus = [cpu]
422880d22f2SFrederic Weisbecker
423880d22f2SFrederic Weisbecker	def migrate(self, ts_list, new, old_cpu, new_cpu):
424880d22f2SFrederic Weisbecker		if old_cpu == new_cpu:
425880d22f2SFrederic Weisbecker			return
426880d22f2SFrederic Weisbecker		old_rq = self.prev.rqs[old_cpu]
427880d22f2SFrederic Weisbecker		out_rq = old_rq.migrate_out(new)
428880d22f2SFrederic Weisbecker		self.rqs[old_cpu] = out_rq
429880d22f2SFrederic Weisbecker		self.__update_total_load(old_rq, out_rq)
430880d22f2SFrederic Weisbecker
431880d22f2SFrederic Weisbecker		new_rq = self.prev.rqs[new_cpu]
432880d22f2SFrederic Weisbecker		in_rq = new_rq.migrate_in(new)
433880d22f2SFrederic Weisbecker		self.rqs[new_cpu] = in_rq
434880d22f2SFrederic Weisbecker		self.__update_total_load(new_rq, in_rq)
435880d22f2SFrederic Weisbecker
436880d22f2SFrederic Weisbecker		ts_list.append(self)
437749e5074SFrederic Weisbecker
438749e5074SFrederic Weisbecker		if old_rq is not out_rq:
439749e5074SFrederic Weisbecker			self.event_cpus.append(old_cpu)
440749e5074SFrederic Weisbecker		self.event_cpus.append(new_cpu)
441880d22f2SFrederic Weisbecker
442880d22f2SFrederic Weisbecker	def wake_up(self, ts_list, pid, cpu, fork):
443880d22f2SFrederic Weisbecker		old_rq = self.prev.rqs[cpu]
444880d22f2SFrederic Weisbecker		if fork:
445880d22f2SFrederic Weisbecker			new_rq = old_rq.wake_up_new(pid)
446880d22f2SFrederic Weisbecker		else:
447880d22f2SFrederic Weisbecker			new_rq = old_rq.wake_up(pid)
448880d22f2SFrederic Weisbecker
449880d22f2SFrederic Weisbecker		if new_rq is old_rq:
450880d22f2SFrederic Weisbecker			return
451880d22f2SFrederic Weisbecker		self.rqs[cpu] = new_rq
452880d22f2SFrederic Weisbecker		self.__update_total_load(old_rq, new_rq)
453880d22f2SFrederic Weisbecker		ts_list.append(self)
454880d22f2SFrederic Weisbecker		self.event_cpus = [cpu]
455880d22f2SFrederic Weisbecker
456880d22f2SFrederic Weisbecker	def next(self, t):
457880d22f2SFrederic Weisbecker		self.end = t
458880d22f2SFrederic Weisbecker		return TimeSlice(t, self)
459880d22f2SFrederic Weisbecker
460880d22f2SFrederic Weisbeckerclass TimeSliceList(UserList):
461880d22f2SFrederic Weisbecker	def __init__(self, arg = []):
462880d22f2SFrederic Weisbecker		self.data = arg
463880d22f2SFrederic Weisbecker
464880d22f2SFrederic Weisbecker	def get_time_slice(self, ts):
465880d22f2SFrederic Weisbecker		if len(self.data) == 0:
466880d22f2SFrederic Weisbecker			slice = TimeSlice(ts, TimeSlice(-1, None))
467880d22f2SFrederic Weisbecker		else:
468880d22f2SFrederic Weisbecker			slice = self.data[-1].next(ts)
469880d22f2SFrederic Weisbecker		return slice
470880d22f2SFrederic Weisbecker
471880d22f2SFrederic Weisbecker	def find_time_slice(self, ts):
472880d22f2SFrederic Weisbecker		start = 0
473880d22f2SFrederic Weisbecker		end = len(self.data)
474880d22f2SFrederic Weisbecker		found = -1
475880d22f2SFrederic Weisbecker		searching = True
476880d22f2SFrederic Weisbecker		while searching:
477880d22f2SFrederic Weisbecker			if start == end or start == end - 1:
478880d22f2SFrederic Weisbecker				searching = False
479880d22f2SFrederic Weisbecker
480880d22f2SFrederic Weisbecker			i = (end + start) / 2
481880d22f2SFrederic Weisbecker			if self.data[i].start <= ts and self.data[i].end >= ts:
482880d22f2SFrederic Weisbecker				found = i
483880d22f2SFrederic Weisbecker				end = i
484880d22f2SFrederic Weisbecker				continue
485880d22f2SFrederic Weisbecker
486880d22f2SFrederic Weisbecker			if self.data[i].end < ts:
487880d22f2SFrederic Weisbecker				start = i
488880d22f2SFrederic Weisbecker
489880d22f2SFrederic Weisbecker			elif self.data[i].start > ts:
490880d22f2SFrederic Weisbecker				end = i
491880d22f2SFrederic Weisbecker
492880d22f2SFrederic Weisbecker		return found
493880d22f2SFrederic Weisbecker
494880d22f2SFrederic Weisbecker	def interval(self):
495880d22f2SFrederic Weisbecker		if len(self.data) == 0:
496880d22f2SFrederic Weisbecker			return (0, 0)
497880d22f2SFrederic Weisbecker
498880d22f2SFrederic Weisbecker		return (self.data[0].start, self.data[-1].end)
499880d22f2SFrederic Weisbecker
500880d22f2SFrederic Weisbecker
501880d22f2SFrederic Weisbeckerclass SchedEventProxy:
502880d22f2SFrederic Weisbecker	def __init__(self):
503880d22f2SFrederic Weisbecker		self.current_tsk = defaultdict(lambda : -1)
504880d22f2SFrederic Weisbecker		self.timeslices = TimeSliceList()
505880d22f2SFrederic Weisbecker
506880d22f2SFrederic Weisbecker	def sched_switch(self, headers, prev_comm, prev_pid, prev_prio, prev_state,
507880d22f2SFrederic Weisbecker			 next_comm, next_pid, next_prio):
508880d22f2SFrederic Weisbecker		""" Ensure the task we sched out this cpu is really the one
509880d22f2SFrederic Weisbecker		    we logged. Otherwise we may have missed traces """
510880d22f2SFrederic Weisbecker
511880d22f2SFrederic Weisbecker		on_cpu_task = self.current_tsk[headers.cpu]
512880d22f2SFrederic Weisbecker
513880d22f2SFrederic Weisbecker		if on_cpu_task != -1 and on_cpu_task != prev_pid:
514880d22f2SFrederic Weisbecker			print "Sched switch event rejected ts: %s cpu: %d prev: %s(%d) next: %s(%d)" % \
515880d22f2SFrederic Weisbecker				(headers.ts_format(), headers.cpu, prev_comm, prev_pid, next_comm, next_pid)
516880d22f2SFrederic Weisbecker
517880d22f2SFrederic Weisbecker		threads[prev_pid] = prev_comm
518880d22f2SFrederic Weisbecker		threads[next_pid] = next_comm
519880d22f2SFrederic Weisbecker		self.current_tsk[headers.cpu] = next_pid
520880d22f2SFrederic Weisbecker
521880d22f2SFrederic Weisbecker		ts = self.timeslices.get_time_slice(headers.ts())
522880d22f2SFrederic Weisbecker		ts.sched_switch(self.timeslices, prev_pid, prev_state, next_pid, headers.cpu)
523880d22f2SFrederic Weisbecker
524880d22f2SFrederic Weisbecker	def migrate(self, headers, pid, prio, orig_cpu, dest_cpu):
525880d22f2SFrederic Weisbecker		ts = self.timeslices.get_time_slice(headers.ts())
526880d22f2SFrederic Weisbecker		ts.migrate(self.timeslices, pid, orig_cpu, dest_cpu)
527880d22f2SFrederic Weisbecker
528880d22f2SFrederic Weisbecker	def wake_up(self, headers, comm, pid, success, target_cpu, fork):
529880d22f2SFrederic Weisbecker		if success == 0:
530880d22f2SFrederic Weisbecker			return
531880d22f2SFrederic Weisbecker		ts = self.timeslices.get_time_slice(headers.ts())
532880d22f2SFrederic Weisbecker		ts.wake_up(self.timeslices, pid, target_cpu, fork)
533880d22f2SFrederic Weisbecker
534880d22f2SFrederic Weisbecker
535880d22f2SFrederic Weisbeckerdef trace_begin():
536880d22f2SFrederic Weisbecker	global parser
537880d22f2SFrederic Weisbecker	parser = SchedEventProxy()
538880d22f2SFrederic Weisbecker
539880d22f2SFrederic Weisbeckerdef trace_end():
540880d22f2SFrederic Weisbecker	app = wx.App(False)
541880d22f2SFrederic Weisbecker	timeslices = parser.timeslices
542880d22f2SFrederic Weisbecker	frame = RootFrame(timeslices)
543880d22f2SFrederic Weisbecker	app.MainLoop()
544880d22f2SFrederic Weisbecker
545880d22f2SFrederic Weisbeckerdef sched__sched_stat_runtime(event_name, context, common_cpu,
546880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
547880d22f2SFrederic Weisbecker	comm, pid, runtime, vruntime):
548880d22f2SFrederic Weisbecker	pass
549880d22f2SFrederic Weisbecker
550880d22f2SFrederic Weisbeckerdef sched__sched_stat_iowait(event_name, context, common_cpu,
551880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
552880d22f2SFrederic Weisbecker	comm, pid, delay):
553880d22f2SFrederic Weisbecker	pass
554880d22f2SFrederic Weisbecker
555880d22f2SFrederic Weisbeckerdef sched__sched_stat_sleep(event_name, context, common_cpu,
556880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
557880d22f2SFrederic Weisbecker	comm, pid, delay):
558880d22f2SFrederic Weisbecker	pass
559880d22f2SFrederic Weisbecker
560880d22f2SFrederic Weisbeckerdef sched__sched_stat_wait(event_name, context, common_cpu,
561880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
562880d22f2SFrederic Weisbecker	comm, pid, delay):
563880d22f2SFrederic Weisbecker	pass
564880d22f2SFrederic Weisbecker
565880d22f2SFrederic Weisbeckerdef sched__sched_process_fork(event_name, context, common_cpu,
566880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
567880d22f2SFrederic Weisbecker	parent_comm, parent_pid, child_comm, child_pid):
568880d22f2SFrederic Weisbecker	pass
569880d22f2SFrederic Weisbecker
570880d22f2SFrederic Weisbeckerdef sched__sched_process_wait(event_name, context, common_cpu,
571880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
572880d22f2SFrederic Weisbecker	comm, pid, prio):
573880d22f2SFrederic Weisbecker	pass
574880d22f2SFrederic Weisbecker
575880d22f2SFrederic Weisbeckerdef sched__sched_process_exit(event_name, context, common_cpu,
576880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
577880d22f2SFrederic Weisbecker	comm, pid, prio):
578880d22f2SFrederic Weisbecker	pass
579880d22f2SFrederic Weisbecker
580880d22f2SFrederic Weisbeckerdef sched__sched_process_free(event_name, context, common_cpu,
581880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
582880d22f2SFrederic Weisbecker	comm, pid, prio):
583880d22f2SFrederic Weisbecker	pass
584880d22f2SFrederic Weisbecker
585880d22f2SFrederic Weisbeckerdef sched__sched_migrate_task(event_name, context, common_cpu,
586880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
587880d22f2SFrederic Weisbecker	comm, pid, prio, orig_cpu,
588880d22f2SFrederic Weisbecker	dest_cpu):
589880d22f2SFrederic Weisbecker	headers = EventHeaders(common_cpu, common_secs, common_nsecs,
590880d22f2SFrederic Weisbecker				common_pid, common_comm)
591880d22f2SFrederic Weisbecker	parser.migrate(headers, pid, prio, orig_cpu, dest_cpu)
592880d22f2SFrederic Weisbecker
593880d22f2SFrederic Weisbeckerdef sched__sched_switch(event_name, context, common_cpu,
594880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
595880d22f2SFrederic Weisbecker	prev_comm, prev_pid, prev_prio, prev_state,
596880d22f2SFrederic Weisbecker	next_comm, next_pid, next_prio):
597880d22f2SFrederic Weisbecker
598880d22f2SFrederic Weisbecker	headers = EventHeaders(common_cpu, common_secs, common_nsecs,
599880d22f2SFrederic Weisbecker				common_pid, common_comm)
600880d22f2SFrederic Weisbecker	parser.sched_switch(headers, prev_comm, prev_pid, prev_prio, prev_state,
601880d22f2SFrederic Weisbecker			 next_comm, next_pid, next_prio)
602880d22f2SFrederic Weisbecker
603880d22f2SFrederic Weisbeckerdef sched__sched_wakeup_new(event_name, context, common_cpu,
604880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
605880d22f2SFrederic Weisbecker	comm, pid, prio, success,
606880d22f2SFrederic Weisbecker	target_cpu):
607880d22f2SFrederic Weisbecker	headers = EventHeaders(common_cpu, common_secs, common_nsecs,
608880d22f2SFrederic Weisbecker				common_pid, common_comm)
609880d22f2SFrederic Weisbecker	parser.wake_up(headers, comm, pid, success, target_cpu, 1)
610880d22f2SFrederic Weisbecker
611880d22f2SFrederic Weisbeckerdef sched__sched_wakeup(event_name, context, common_cpu,
612880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
613880d22f2SFrederic Weisbecker	comm, pid, prio, success,
614880d22f2SFrederic Weisbecker	target_cpu):
615880d22f2SFrederic Weisbecker	headers = EventHeaders(common_cpu, common_secs, common_nsecs,
616880d22f2SFrederic Weisbecker				common_pid, common_comm)
617880d22f2SFrederic Weisbecker	parser.wake_up(headers, comm, pid, success, target_cpu, 0)
618880d22f2SFrederic Weisbecker
619880d22f2SFrederic Weisbeckerdef sched__sched_wait_task(event_name, context, common_cpu,
620880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
621880d22f2SFrederic Weisbecker	comm, pid, prio):
622880d22f2SFrederic Weisbecker	pass
623880d22f2SFrederic Weisbecker
624880d22f2SFrederic Weisbeckerdef sched__sched_kthread_stop_ret(event_name, context, common_cpu,
625880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
626880d22f2SFrederic Weisbecker	ret):
627880d22f2SFrederic Weisbecker	pass
628880d22f2SFrederic Weisbecker
629880d22f2SFrederic Weisbeckerdef sched__sched_kthread_stop(event_name, context, common_cpu,
630880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
631880d22f2SFrederic Weisbecker	comm, pid):
632880d22f2SFrederic Weisbecker	pass
633880d22f2SFrederic Weisbecker
634880d22f2SFrederic Weisbeckerdef trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs,
635880d22f2SFrederic Weisbecker		common_pid, common_comm):
636880d22f2SFrederic Weisbecker	pass
637