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):
300cddf56aSNikhil Rao	Y_OFFSET = 100
31*699b6d92SFrederic Weisbecker	RECT_HEIGHT = 100
32*699b6d92SFrederic Weisbecker	RECT_SPACE = 50
330cddf56aSNikhil Rao	EVENT_MARKING_WIDTH = 5
340cddf56aSNikhil Rao
35*699b6d92SFrederic Weisbecker	def __init__(self, sched_tracer, title, parent = None, id = -1):
36880d22f2SFrederic Weisbecker		wx.Frame.__init__(self, parent, id, title)
37880d22f2SFrederic Weisbecker
38880d22f2SFrederic Weisbecker		(self.screen_width, self.screen_height) = wx.GetDisplaySize()
39880d22f2SFrederic Weisbecker		self.screen_width -= 10
40880d22f2SFrederic Weisbecker		self.screen_height -= 10
41880d22f2SFrederic Weisbecker		self.zoom = 0.5
42880d22f2SFrederic Weisbecker		self.scroll_scale = 20
43*699b6d92SFrederic Weisbecker		self.sched_tracer = sched_tracer
44*699b6d92SFrederic Weisbecker		self.sched_tracer.set_root_win(self)
45*699b6d92SFrederic Weisbecker		(self.ts_start, self.ts_end) = sched_tracer.interval()
46880d22f2SFrederic Weisbecker		self.update_width_virtual()
47*699b6d92SFrederic Weisbecker		self.nr_rects = sched_tracer.nr_rectangles() + 1
48*699b6d92SFrederic Weisbecker		self.height_virtual = RootFrame.Y_OFFSET + (self.nr_rects * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE))
49880d22f2SFrederic Weisbecker
50880d22f2SFrederic Weisbecker		# whole window panel
51880d22f2SFrederic Weisbecker		self.panel = wx.Panel(self, size=(self.screen_width, self.screen_height))
52880d22f2SFrederic Weisbecker
53880d22f2SFrederic Weisbecker		# scrollable container
54880d22f2SFrederic Weisbecker		self.scroll = wx.ScrolledWindow(self.panel)
5570d815a3SFrederic Weisbecker		self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, self.height_virtual / self.scroll_scale)
56880d22f2SFrederic Weisbecker		self.scroll.EnableScrolling(True, True)
57880d22f2SFrederic Weisbecker		self.scroll.SetFocus()
58880d22f2SFrederic Weisbecker
59880d22f2SFrederic Weisbecker		# scrollable drawing area
6070d815a3SFrederic Weisbecker		self.scroll_panel = wx.Panel(self.scroll, size=(self.screen_width - 15, self.screen_height / 2))
61880d22f2SFrederic Weisbecker		self.scroll_panel.Bind(wx.EVT_PAINT, self.on_paint)
62880d22f2SFrederic Weisbecker		self.scroll_panel.Bind(wx.EVT_KEY_DOWN, self.on_key_press)
63880d22f2SFrederic Weisbecker		self.scroll_panel.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down)
64880d22f2SFrederic Weisbecker		self.scroll.Bind(wx.EVT_PAINT, self.on_paint)
65be6d9476SNikhil Rao		self.scroll.Bind(wx.EVT_KEY_DOWN, self.on_key_press)
66be6d9476SNikhil Rao		self.scroll.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down)
67880d22f2SFrederic Weisbecker
68880d22f2SFrederic Weisbecker		self.scroll.Fit()
69880d22f2SFrederic Weisbecker		self.Fit()
70880d22f2SFrederic Weisbecker
7170d815a3SFrederic Weisbecker		self.scroll_panel.SetDimensions(-1, -1, self.width_virtual, self.height_virtual, wx.SIZE_USE_EXISTING)
72880d22f2SFrederic Weisbecker
73880d22f2SFrederic Weisbecker		self.txt = None
74880d22f2SFrederic Weisbecker
75880d22f2SFrederic Weisbecker		self.Show(True)
76880d22f2SFrederic Weisbecker
77880d22f2SFrederic Weisbecker	def us_to_px(self, val):
78880d22f2SFrederic Weisbecker		return val / (10 ** 3) * self.zoom
79880d22f2SFrederic Weisbecker
80880d22f2SFrederic Weisbecker	def px_to_us(self, val):
81880d22f2SFrederic Weisbecker		return (val / self.zoom) * (10 ** 3)
82880d22f2SFrederic Weisbecker
83880d22f2SFrederic Weisbecker	def scroll_start(self):
84880d22f2SFrederic Weisbecker		(x, y) = self.scroll.GetViewStart()
85880d22f2SFrederic Weisbecker		return (x * self.scroll_scale, y * self.scroll_scale)
86880d22f2SFrederic Weisbecker
87880d22f2SFrederic Weisbecker	def scroll_start_us(self):
88880d22f2SFrederic Weisbecker		(x, y) = self.scroll_start()
89880d22f2SFrederic Weisbecker		return self.px_to_us(x)
90880d22f2SFrederic Weisbecker
91*699b6d92SFrederic Weisbecker	def paint_rectangle_zone(self, nr, color, top_color, start, end):
92*699b6d92SFrederic Weisbecker		offset_px = self.us_to_px(start - self.ts_start)
93*699b6d92SFrederic Weisbecker		width_px = self.us_to_px(end - self.ts_start)
94880d22f2SFrederic Weisbecker
95*699b6d92SFrederic Weisbecker		offset_py = RootFrame.Y_OFFSET + (nr * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE))
96*699b6d92SFrederic Weisbecker		width_py = RootFrame.RECT_HEIGHT
97880d22f2SFrederic Weisbecker
98*699b6d92SFrederic Weisbecker		dc = self.dc
99880d22f2SFrederic Weisbecker
100*699b6d92SFrederic Weisbecker		if top_color is not None:
101*699b6d92SFrederic Weisbecker			(r, g, b) = top_color
102*699b6d92SFrederic Weisbecker			top_color = wx.Colour(r, g, b)
103*699b6d92SFrederic Weisbecker			brush = wx.Brush(top_color, wx.SOLID)
104880d22f2SFrederic Weisbecker			dc.SetBrush(brush)
1050cddf56aSNikhil Rao			dc.DrawRectangle(offset_px, offset_py, width_px, RootFrame.EVENT_MARKING_WIDTH)
1060cddf56aSNikhil Rao			width_py -= RootFrame.EVENT_MARKING_WIDTH
1070cddf56aSNikhil Rao			offset_py += RootFrame.EVENT_MARKING_WIDTH
108880d22f2SFrederic Weisbecker
109*699b6d92SFrederic Weisbecker		(r ,g, b) = color
110*699b6d92SFrederic Weisbecker		color = wx.Colour(r, g, b)
111880d22f2SFrederic Weisbecker		brush = wx.Brush(color, wx.SOLID)
112880d22f2SFrederic Weisbecker		dc.SetBrush(brush)
113880d22f2SFrederic Weisbecker		dc.DrawRectangle(offset_px, offset_py, width_px, width_py)
114880d22f2SFrederic Weisbecker
115880d22f2SFrederic Weisbecker	def update_rectangles(self, dc, start, end):
116*699b6d92SFrederic Weisbecker		start += self.ts_start
117*699b6d92SFrederic Weisbecker		end += self.ts_start
118*699b6d92SFrederic Weisbecker		self.sched_tracer.fill_zone(start, end)
119880d22f2SFrederic Weisbecker
120880d22f2SFrederic Weisbecker	def on_paint(self, event):
121880d22f2SFrederic Weisbecker		dc = wx.PaintDC(self.scroll_panel)
122*699b6d92SFrederic Weisbecker		self.dc = dc
123880d22f2SFrederic Weisbecker
124880d22f2SFrederic Weisbecker		width = min(self.width_virtual, self.screen_width)
125880d22f2SFrederic Weisbecker		(x, y) = self.scroll_start()
126880d22f2SFrederic Weisbecker		start = self.px_to_us(x)
127880d22f2SFrederic Weisbecker		end = self.px_to_us(x + width)
128880d22f2SFrederic Weisbecker		self.update_rectangles(dc, start, end)
129880d22f2SFrederic Weisbecker
130*699b6d92SFrederic Weisbecker	def rect_from_ypixel(self, y):
1310cddf56aSNikhil Rao		y -= RootFrame.Y_OFFSET
132*699b6d92SFrederic Weisbecker		rect = y / (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)
133*699b6d92SFrederic Weisbecker		height = y % (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)
134880d22f2SFrederic Weisbecker
135*699b6d92SFrederic Weisbecker		if rect < 0 or rect > self.nr_rects - 1 or height > RootFrame.RECT_HEIGHT:
136880d22f2SFrederic Weisbecker			return -1
137880d22f2SFrederic Weisbecker
138*699b6d92SFrederic Weisbecker		return rect
139880d22f2SFrederic Weisbecker
140*699b6d92SFrederic Weisbecker	def update_summary(self, txt):
141880d22f2SFrederic Weisbecker		if self.txt:
142880d22f2SFrederic Weisbecker			self.txt.Destroy()
143*699b6d92SFrederic Weisbecker		self.txt = wx.StaticText(self.panel, -1, txt, (0, (self.screen_height / 2) + 50))
144880d22f2SFrederic Weisbecker
145880d22f2SFrederic Weisbecker
146880d22f2SFrederic Weisbecker	def on_mouse_down(self, event):
147880d22f2SFrederic Weisbecker		(x, y) = event.GetPositionTuple()
148*699b6d92SFrederic Weisbecker		rect = self.rect_from_ypixel(y)
149*699b6d92SFrederic Weisbecker		if rect == -1:
150880d22f2SFrederic Weisbecker			return
151880d22f2SFrederic Weisbecker
152*699b6d92SFrederic Weisbecker		t = self.px_to_us(x) + self.ts_start
153880d22f2SFrederic Weisbecker
154*699b6d92SFrederic Weisbecker		self.sched_tracer.mouse_down(rect, t)
155880d22f2SFrederic Weisbecker
156880d22f2SFrederic Weisbecker
157880d22f2SFrederic Weisbecker	def update_width_virtual(self):
158880d22f2SFrederic Weisbecker		self.width_virtual = self.us_to_px(self.ts_end - self.ts_start)
159880d22f2SFrederic Weisbecker
160880d22f2SFrederic Weisbecker	def __zoom(self, x):
161880d22f2SFrederic Weisbecker		self.update_width_virtual()
162880d22f2SFrederic Weisbecker		(xpos, ypos) = self.scroll.GetViewStart()
163880d22f2SFrederic Weisbecker		xpos = self.us_to_px(x) / self.scroll_scale
16470d815a3SFrederic Weisbecker		self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, self.height_virtual / self.scroll_scale, xpos, ypos)
165880d22f2SFrederic Weisbecker		self.Refresh()
166880d22f2SFrederic Weisbecker
167880d22f2SFrederic Weisbecker	def zoom_in(self):
168880d22f2SFrederic Weisbecker		x = self.scroll_start_us()
169880d22f2SFrederic Weisbecker		self.zoom *= 2
170880d22f2SFrederic Weisbecker		self.__zoom(x)
171880d22f2SFrederic Weisbecker
172880d22f2SFrederic Weisbecker	def zoom_out(self):
173880d22f2SFrederic Weisbecker		x = self.scroll_start_us()
174880d22f2SFrederic Weisbecker		self.zoom /= 2
175880d22f2SFrederic Weisbecker		self.__zoom(x)
176880d22f2SFrederic Weisbecker
177880d22f2SFrederic Weisbecker
178880d22f2SFrederic Weisbecker	def on_key_press(self, event):
179880d22f2SFrederic Weisbecker		key = event.GetRawKeyCode()
180880d22f2SFrederic Weisbecker		if key == ord("+"):
181880d22f2SFrederic Weisbecker			self.zoom_in()
182880d22f2SFrederic Weisbecker			return
183880d22f2SFrederic Weisbecker		if key == ord("-"):
184880d22f2SFrederic Weisbecker			self.zoom_out()
185880d22f2SFrederic Weisbecker			return
186880d22f2SFrederic Weisbecker
187880d22f2SFrederic Weisbecker		key = event.GetKeyCode()
188880d22f2SFrederic Weisbecker		(x, y) = self.scroll.GetViewStart()
189880d22f2SFrederic Weisbecker		if key == wx.WXK_RIGHT:
190880d22f2SFrederic Weisbecker			self.scroll.Scroll(x + 1, y)
191880d22f2SFrederic Weisbecker		elif key == wx.WXK_LEFT:
192880d22f2SFrederic Weisbecker			self.scroll.Scroll(x - 1, y)
19370d815a3SFrederic Weisbecker		elif key == wx.WXK_DOWN:
19470d815a3SFrederic Weisbecker			self.scroll.Scroll(x, y + 1)
19570d815a3SFrederic Weisbecker		elif key == wx.WXK_UP:
19670d815a3SFrederic Weisbecker			self.scroll.Scroll(x, y - 1)
197880d22f2SFrederic Weisbecker
198880d22f2SFrederic Weisbecker
199880d22f2SFrederic Weisbeckerthreads = { 0 : "idle"}
200880d22f2SFrederic Weisbecker
201880d22f2SFrederic Weisbeckerdef thread_name(pid):
202880d22f2SFrederic Weisbecker	return "%s:%d" % (threads[pid], pid)
203880d22f2SFrederic Weisbecker
204880d22f2SFrederic Weisbeckerclass EventHeaders:
205880d22f2SFrederic Weisbecker	def __init__(self, common_cpu, common_secs, common_nsecs,
206880d22f2SFrederic Weisbecker		     common_pid, common_comm):
207880d22f2SFrederic Weisbecker		self.cpu = common_cpu
208880d22f2SFrederic Weisbecker		self.secs = common_secs
209880d22f2SFrederic Weisbecker		self.nsecs = common_nsecs
210880d22f2SFrederic Weisbecker		self.pid = common_pid
211880d22f2SFrederic Weisbecker		self.comm = common_comm
212880d22f2SFrederic Weisbecker
213880d22f2SFrederic Weisbecker	def ts(self):
214880d22f2SFrederic Weisbecker		return (self.secs * (10 ** 9)) + self.nsecs
215880d22f2SFrederic Weisbecker
216880d22f2SFrederic Weisbecker	def ts_format(self):
217880d22f2SFrederic Weisbecker		return "%d.%d" % (self.secs, int(self.nsecs / 1000))
218880d22f2SFrederic Weisbecker
219880d22f2SFrederic Weisbecker
220880d22f2SFrederic Weisbeckerdef taskState(state):
221880d22f2SFrederic Weisbecker	states = {
222880d22f2SFrederic Weisbecker		0 : "R",
223880d22f2SFrederic Weisbecker		1 : "S",
224880d22f2SFrederic Weisbecker		2 : "D",
225880d22f2SFrederic Weisbecker		64: "DEAD"
226880d22f2SFrederic Weisbecker	}
227880d22f2SFrederic Weisbecker
228880d22f2SFrederic Weisbecker	if state not in states:
229207f90fcSFrederic Weisbecker		return "Unknown"
230880d22f2SFrederic Weisbecker
231880d22f2SFrederic Weisbecker	return states[state]
232880d22f2SFrederic Weisbecker
233880d22f2SFrederic Weisbecker
234880d22f2SFrederic Weisbeckerclass RunqueueEventUnknown:
235880d22f2SFrederic Weisbecker	@staticmethod
236880d22f2SFrederic Weisbecker	def color():
237880d22f2SFrederic Weisbecker		return None
238880d22f2SFrederic Weisbecker
239880d22f2SFrederic Weisbecker	def __repr__(self):
240880d22f2SFrederic Weisbecker		return "unknown"
241880d22f2SFrederic Weisbecker
242880d22f2SFrederic Weisbeckerclass RunqueueEventSleep:
243880d22f2SFrederic Weisbecker	@staticmethod
244880d22f2SFrederic Weisbecker	def color():
245880d22f2SFrederic Weisbecker		return (0, 0, 0xff)
246880d22f2SFrederic Weisbecker
247880d22f2SFrederic Weisbecker	def __init__(self, sleeper):
248880d22f2SFrederic Weisbecker		self.sleeper = sleeper
249880d22f2SFrederic Weisbecker
250880d22f2SFrederic Weisbecker	def __repr__(self):
251880d22f2SFrederic Weisbecker		return "%s gone to sleep" % thread_name(self.sleeper)
252880d22f2SFrederic Weisbecker
253880d22f2SFrederic Weisbeckerclass RunqueueEventWakeup:
254880d22f2SFrederic Weisbecker	@staticmethod
255880d22f2SFrederic Weisbecker	def color():
256880d22f2SFrederic Weisbecker		return (0xff, 0xff, 0)
257880d22f2SFrederic Weisbecker
258880d22f2SFrederic Weisbecker	def __init__(self, wakee):
259880d22f2SFrederic Weisbecker		self.wakee = wakee
260880d22f2SFrederic Weisbecker
261880d22f2SFrederic Weisbecker	def __repr__(self):
262880d22f2SFrederic Weisbecker		return "%s woke up" % thread_name(self.wakee)
263880d22f2SFrederic Weisbecker
264880d22f2SFrederic Weisbeckerclass RunqueueEventFork:
265880d22f2SFrederic Weisbecker	@staticmethod
266880d22f2SFrederic Weisbecker	def color():
267880d22f2SFrederic Weisbecker		return (0, 0xff, 0)
268880d22f2SFrederic Weisbecker
269880d22f2SFrederic Weisbecker	def __init__(self, child):
270880d22f2SFrederic Weisbecker		self.child = child
271880d22f2SFrederic Weisbecker
272880d22f2SFrederic Weisbecker	def __repr__(self):
273880d22f2SFrederic Weisbecker		return "new forked task %s" % thread_name(self.child)
274880d22f2SFrederic Weisbecker
275880d22f2SFrederic Weisbeckerclass RunqueueMigrateIn:
276880d22f2SFrederic Weisbecker	@staticmethod
277880d22f2SFrederic Weisbecker	def color():
278880d22f2SFrederic Weisbecker		return (0, 0xf0, 0xff)
279880d22f2SFrederic Weisbecker
280880d22f2SFrederic Weisbecker	def __init__(self, new):
281880d22f2SFrederic Weisbecker		self.new = new
282880d22f2SFrederic Weisbecker
283880d22f2SFrederic Weisbecker	def __repr__(self):
284880d22f2SFrederic Weisbecker		return "task migrated in %s" % thread_name(self.new)
285880d22f2SFrederic Weisbecker
286880d22f2SFrederic Weisbeckerclass RunqueueMigrateOut:
287880d22f2SFrederic Weisbecker	@staticmethod
288880d22f2SFrederic Weisbecker	def color():
289880d22f2SFrederic Weisbecker		return (0xff, 0, 0xff)
290880d22f2SFrederic Weisbecker
291880d22f2SFrederic Weisbecker	def __init__(self, old):
292880d22f2SFrederic Weisbecker		self.old = old
293880d22f2SFrederic Weisbecker
294880d22f2SFrederic Weisbecker	def __repr__(self):
295880d22f2SFrederic Weisbecker		return "task migrated out %s" % thread_name(self.old)
296880d22f2SFrederic Weisbecker
297880d22f2SFrederic Weisbeckerclass RunqueueSnapshot:
298880d22f2SFrederic Weisbecker	def __init__(self, tasks = [0], event = RunqueueEventUnknown()):
299880d22f2SFrederic Weisbecker		self.tasks = tuple(tasks)
300880d22f2SFrederic Weisbecker		self.event = event
301880d22f2SFrederic Weisbecker
302880d22f2SFrederic Weisbecker	def sched_switch(self, prev, prev_state, next):
303880d22f2SFrederic Weisbecker		event = RunqueueEventUnknown()
304880d22f2SFrederic Weisbecker
305880d22f2SFrederic Weisbecker		if taskState(prev_state) == "R" and next in self.tasks \
306880d22f2SFrederic Weisbecker			and prev in self.tasks:
307880d22f2SFrederic Weisbecker			return self
308880d22f2SFrederic Weisbecker
309880d22f2SFrederic Weisbecker		if taskState(prev_state) != "R":
310880d22f2SFrederic Weisbecker			event = RunqueueEventSleep(prev)
311880d22f2SFrederic Weisbecker
312880d22f2SFrederic Weisbecker		next_tasks = list(self.tasks[:])
313880d22f2SFrederic Weisbecker		if prev in self.tasks:
314880d22f2SFrederic Weisbecker			if taskState(prev_state) != "R":
315880d22f2SFrederic Weisbecker				next_tasks.remove(prev)
316880d22f2SFrederic Weisbecker		elif taskState(prev_state) == "R":
317880d22f2SFrederic Weisbecker			next_tasks.append(prev)
318880d22f2SFrederic Weisbecker
319880d22f2SFrederic Weisbecker		if next not in next_tasks:
320880d22f2SFrederic Weisbecker			next_tasks.append(next)
321880d22f2SFrederic Weisbecker
322880d22f2SFrederic Weisbecker		return RunqueueSnapshot(next_tasks, event)
323880d22f2SFrederic Weisbecker
324880d22f2SFrederic Weisbecker	def migrate_out(self, old):
325880d22f2SFrederic Weisbecker		if old not in self.tasks:
326880d22f2SFrederic Weisbecker			return self
327880d22f2SFrederic Weisbecker		next_tasks = [task for task in self.tasks if task != old]
328880d22f2SFrederic Weisbecker
329880d22f2SFrederic Weisbecker		return RunqueueSnapshot(next_tasks, RunqueueMigrateOut(old))
330880d22f2SFrederic Weisbecker
331880d22f2SFrederic Weisbecker	def __migrate_in(self, new, event):
332880d22f2SFrederic Weisbecker		if new in self.tasks:
333880d22f2SFrederic Weisbecker			self.event = event
334880d22f2SFrederic Weisbecker			return self
335880d22f2SFrederic Weisbecker		next_tasks = self.tasks[:] + tuple([new])
336880d22f2SFrederic Weisbecker
337880d22f2SFrederic Weisbecker		return RunqueueSnapshot(next_tasks, event)
338880d22f2SFrederic Weisbecker
339880d22f2SFrederic Weisbecker	def migrate_in(self, new):
340880d22f2SFrederic Weisbecker		return self.__migrate_in(new, RunqueueMigrateIn(new))
341880d22f2SFrederic Weisbecker
342880d22f2SFrederic Weisbecker	def wake_up(self, new):
343880d22f2SFrederic Weisbecker		return self.__migrate_in(new, RunqueueEventWakeup(new))
344880d22f2SFrederic Weisbecker
345880d22f2SFrederic Weisbecker	def wake_up_new(self, new):
346880d22f2SFrederic Weisbecker		return self.__migrate_in(new, RunqueueEventFork(new))
347880d22f2SFrederic Weisbecker
348880d22f2SFrederic Weisbecker	def load(self):
349880d22f2SFrederic Weisbecker		""" Provide the number of tasks on the runqueue.
350880d22f2SFrederic Weisbecker		    Don't count idle"""
351880d22f2SFrederic Weisbecker		return len(self.tasks) - 1
352880d22f2SFrederic Weisbecker
353880d22f2SFrederic Weisbecker	def __repr__(self):
354880d22f2SFrederic Weisbecker		ret = self.tasks.__repr__()
355880d22f2SFrederic Weisbecker		ret += self.origin_tostring()
356880d22f2SFrederic Weisbecker
357880d22f2SFrederic Weisbecker		return ret
358880d22f2SFrederic Weisbecker
359880d22f2SFrederic Weisbeckerclass TimeSlice:
360880d22f2SFrederic Weisbecker	def __init__(self, start, prev):
361880d22f2SFrederic Weisbecker		self.start = start
362880d22f2SFrederic Weisbecker		self.prev = prev
363880d22f2SFrederic Weisbecker		self.end = start
364880d22f2SFrederic Weisbecker		# cpus that triggered the event
365880d22f2SFrederic Weisbecker		self.event_cpus = []
366880d22f2SFrederic Weisbecker		if prev is not None:
367880d22f2SFrederic Weisbecker			self.total_load = prev.total_load
368880d22f2SFrederic Weisbecker			self.rqs = prev.rqs.copy()
369880d22f2SFrederic Weisbecker		else:
370880d22f2SFrederic Weisbecker			self.rqs = defaultdict(RunqueueSnapshot)
371880d22f2SFrederic Weisbecker			self.total_load = 0
372880d22f2SFrederic Weisbecker
373880d22f2SFrederic Weisbecker	def __update_total_load(self, old_rq, new_rq):
374880d22f2SFrederic Weisbecker		diff = new_rq.load() - old_rq.load()
375880d22f2SFrederic Weisbecker		self.total_load += diff
376880d22f2SFrederic Weisbecker
377880d22f2SFrederic Weisbecker	def sched_switch(self, ts_list, prev, prev_state, next, cpu):
378880d22f2SFrederic Weisbecker		old_rq = self.prev.rqs[cpu]
379880d22f2SFrederic Weisbecker		new_rq = old_rq.sched_switch(prev, prev_state, next)
380880d22f2SFrederic Weisbecker
381880d22f2SFrederic Weisbecker		if old_rq is new_rq:
382880d22f2SFrederic Weisbecker			return
383880d22f2SFrederic Weisbecker
384880d22f2SFrederic Weisbecker		self.rqs[cpu] = new_rq
385880d22f2SFrederic Weisbecker		self.__update_total_load(old_rq, new_rq)
386880d22f2SFrederic Weisbecker		ts_list.append(self)
387880d22f2SFrederic Weisbecker		self.event_cpus = [cpu]
388880d22f2SFrederic Weisbecker
389880d22f2SFrederic Weisbecker	def migrate(self, ts_list, new, old_cpu, new_cpu):
390880d22f2SFrederic Weisbecker		if old_cpu == new_cpu:
391880d22f2SFrederic Weisbecker			return
392880d22f2SFrederic Weisbecker		old_rq = self.prev.rqs[old_cpu]
393880d22f2SFrederic Weisbecker		out_rq = old_rq.migrate_out(new)
394880d22f2SFrederic Weisbecker		self.rqs[old_cpu] = out_rq
395880d22f2SFrederic Weisbecker		self.__update_total_load(old_rq, out_rq)
396880d22f2SFrederic Weisbecker
397880d22f2SFrederic Weisbecker		new_rq = self.prev.rqs[new_cpu]
398880d22f2SFrederic Weisbecker		in_rq = new_rq.migrate_in(new)
399880d22f2SFrederic Weisbecker		self.rqs[new_cpu] = in_rq
400880d22f2SFrederic Weisbecker		self.__update_total_load(new_rq, in_rq)
401880d22f2SFrederic Weisbecker
402880d22f2SFrederic Weisbecker		ts_list.append(self)
403749e5074SFrederic Weisbecker
404749e5074SFrederic Weisbecker		if old_rq is not out_rq:
405749e5074SFrederic Weisbecker			self.event_cpus.append(old_cpu)
406749e5074SFrederic Weisbecker		self.event_cpus.append(new_cpu)
407880d22f2SFrederic Weisbecker
408880d22f2SFrederic Weisbecker	def wake_up(self, ts_list, pid, cpu, fork):
409880d22f2SFrederic Weisbecker		old_rq = self.prev.rqs[cpu]
410880d22f2SFrederic Weisbecker		if fork:
411880d22f2SFrederic Weisbecker			new_rq = old_rq.wake_up_new(pid)
412880d22f2SFrederic Weisbecker		else:
413880d22f2SFrederic Weisbecker			new_rq = old_rq.wake_up(pid)
414880d22f2SFrederic Weisbecker
415880d22f2SFrederic Weisbecker		if new_rq is old_rq:
416880d22f2SFrederic Weisbecker			return
417880d22f2SFrederic Weisbecker		self.rqs[cpu] = new_rq
418880d22f2SFrederic Weisbecker		self.__update_total_load(old_rq, new_rq)
419880d22f2SFrederic Weisbecker		ts_list.append(self)
420880d22f2SFrederic Weisbecker		self.event_cpus = [cpu]
421880d22f2SFrederic Weisbecker
422880d22f2SFrederic Weisbecker	def next(self, t):
423880d22f2SFrederic Weisbecker		self.end = t
424880d22f2SFrederic Weisbecker		return TimeSlice(t, self)
425880d22f2SFrederic Weisbecker
426880d22f2SFrederic Weisbeckerclass TimeSliceList(UserList):
427880d22f2SFrederic Weisbecker	def __init__(self, arg = []):
428880d22f2SFrederic Weisbecker		self.data = arg
429880d22f2SFrederic Weisbecker
430880d22f2SFrederic Weisbecker	def get_time_slice(self, ts):
431880d22f2SFrederic Weisbecker		if len(self.data) == 0:
432880d22f2SFrederic Weisbecker			slice = TimeSlice(ts, TimeSlice(-1, None))
433880d22f2SFrederic Weisbecker		else:
434880d22f2SFrederic Weisbecker			slice = self.data[-1].next(ts)
435880d22f2SFrederic Weisbecker		return slice
436880d22f2SFrederic Weisbecker
437880d22f2SFrederic Weisbecker	def find_time_slice(self, ts):
438880d22f2SFrederic Weisbecker		start = 0
439880d22f2SFrederic Weisbecker		end = len(self.data)
440880d22f2SFrederic Weisbecker		found = -1
441880d22f2SFrederic Weisbecker		searching = True
442880d22f2SFrederic Weisbecker		while searching:
443880d22f2SFrederic Weisbecker			if start == end or start == end - 1:
444880d22f2SFrederic Weisbecker				searching = False
445880d22f2SFrederic Weisbecker
446880d22f2SFrederic Weisbecker			i = (end + start) / 2
447880d22f2SFrederic Weisbecker			if self.data[i].start <= ts and self.data[i].end >= ts:
448880d22f2SFrederic Weisbecker				found = i
449880d22f2SFrederic Weisbecker				end = i
450880d22f2SFrederic Weisbecker				continue
451880d22f2SFrederic Weisbecker
452880d22f2SFrederic Weisbecker			if self.data[i].end < ts:
453880d22f2SFrederic Weisbecker				start = i
454880d22f2SFrederic Weisbecker
455880d22f2SFrederic Weisbecker			elif self.data[i].start > ts:
456880d22f2SFrederic Weisbecker				end = i
457880d22f2SFrederic Weisbecker
458880d22f2SFrederic Weisbecker		return found
459880d22f2SFrederic Weisbecker
460*699b6d92SFrederic Weisbecker	def set_root_win(self, win):
461*699b6d92SFrederic Weisbecker		self.root_win = win
462*699b6d92SFrederic Weisbecker
463*699b6d92SFrederic Weisbecker	def mouse_down(self, cpu, t):
464*699b6d92SFrederic Weisbecker		idx = self.find_time_slice(t)
465*699b6d92SFrederic Weisbecker		if idx == -1:
466*699b6d92SFrederic Weisbecker			return
467*699b6d92SFrederic Weisbecker
468*699b6d92SFrederic Weisbecker		ts = self[idx]
469*699b6d92SFrederic Weisbecker		rq = ts.rqs[cpu]
470*699b6d92SFrederic Weisbecker		raw = "CPU: %d\n" % cpu
471*699b6d92SFrederic Weisbecker		raw += "Last event : %s\n" % rq.event.__repr__()
472*699b6d92SFrederic Weisbecker		raw += "Timestamp : %d.%06d\n" % (ts.start / (10 ** 9), (ts.start % (10 ** 9)) / 1000)
473*699b6d92SFrederic Weisbecker		raw += "Duration : %6d us\n" % ((ts.end - ts.start) / (10 ** 6))
474*699b6d92SFrederic Weisbecker		raw += "Load = %d\n" % rq.load()
475*699b6d92SFrederic Weisbecker		for t in rq.tasks:
476*699b6d92SFrederic Weisbecker			raw += "%s \n" % thread_name(t)
477*699b6d92SFrederic Weisbecker
478*699b6d92SFrederic Weisbecker		self.root_win.update_summary(raw)
479*699b6d92SFrederic Weisbecker
480*699b6d92SFrederic Weisbecker	def update_rectangle_cpu(self, slice, cpu):
481*699b6d92SFrederic Weisbecker		rq = slice.rqs[cpu]
482*699b6d92SFrederic Weisbecker
483*699b6d92SFrederic Weisbecker		if slice.total_load != 0:
484*699b6d92SFrederic Weisbecker			load_rate = rq.load() / float(slice.total_load)
485*699b6d92SFrederic Weisbecker		else:
486*699b6d92SFrederic Weisbecker			load_rate = 0
487*699b6d92SFrederic Weisbecker
488*699b6d92SFrederic Weisbecker		red_power = int(0xff - (0xff * load_rate))
489*699b6d92SFrederic Weisbecker		color = (0xff, red_power, red_power)
490*699b6d92SFrederic Weisbecker
491*699b6d92SFrederic Weisbecker		top_color = None
492*699b6d92SFrederic Weisbecker
493*699b6d92SFrederic Weisbecker		if cpu in slice.event_cpus:
494*699b6d92SFrederic Weisbecker			top_color = rq.event.color()
495*699b6d92SFrederic Weisbecker
496*699b6d92SFrederic Weisbecker		self.root_win.paint_rectangle_zone(cpu, color, top_color, slice.start, slice.end)
497*699b6d92SFrederic Weisbecker
498*699b6d92SFrederic Weisbecker	def fill_zone(self, start, end):
499*699b6d92SFrederic Weisbecker		i = self.find_time_slice(start)
500*699b6d92SFrederic Weisbecker		if i == -1:
501*699b6d92SFrederic Weisbecker			return
502*699b6d92SFrederic Weisbecker
503*699b6d92SFrederic Weisbecker		for i in xrange(i, len(self.data)):
504*699b6d92SFrederic Weisbecker			timeslice = self.data[i]
505*699b6d92SFrederic Weisbecker			if timeslice.start > end:
506*699b6d92SFrederic Weisbecker				return
507*699b6d92SFrederic Weisbecker
508*699b6d92SFrederic Weisbecker			for cpu in timeslice.rqs:
509*699b6d92SFrederic Weisbecker				self.update_rectangle_cpu(timeslice, cpu)
510*699b6d92SFrederic Weisbecker
511880d22f2SFrederic Weisbecker	def interval(self):
512880d22f2SFrederic Weisbecker		if len(self.data) == 0:
513880d22f2SFrederic Weisbecker			return (0, 0)
514880d22f2SFrederic Weisbecker
515880d22f2SFrederic Weisbecker		return (self.data[0].start, self.data[-1].end)
516880d22f2SFrederic Weisbecker
517*699b6d92SFrederic Weisbecker	def nr_rectangles(self):
51870d815a3SFrederic Weisbecker		last_ts = self.data[-1]
51970d815a3SFrederic Weisbecker		max_cpu = 0
52070d815a3SFrederic Weisbecker		for cpu in last_ts.rqs:
52170d815a3SFrederic Weisbecker			if cpu > max_cpu:
52270d815a3SFrederic Weisbecker				max_cpu = cpu
52370d815a3SFrederic Weisbecker		return max_cpu
52470d815a3SFrederic Weisbecker
525880d22f2SFrederic Weisbecker
526880d22f2SFrederic Weisbeckerclass SchedEventProxy:
527880d22f2SFrederic Weisbecker	def __init__(self):
528880d22f2SFrederic Weisbecker		self.current_tsk = defaultdict(lambda : -1)
529880d22f2SFrederic Weisbecker		self.timeslices = TimeSliceList()
530880d22f2SFrederic Weisbecker
531880d22f2SFrederic Weisbecker	def sched_switch(self, headers, prev_comm, prev_pid, prev_prio, prev_state,
532880d22f2SFrederic Weisbecker			 next_comm, next_pid, next_prio):
533880d22f2SFrederic Weisbecker		""" Ensure the task we sched out this cpu is really the one
534880d22f2SFrederic Weisbecker		    we logged. Otherwise we may have missed traces """
535880d22f2SFrederic Weisbecker
536880d22f2SFrederic Weisbecker		on_cpu_task = self.current_tsk[headers.cpu]
537880d22f2SFrederic Weisbecker
538880d22f2SFrederic Weisbecker		if on_cpu_task != -1 and on_cpu_task != prev_pid:
539880d22f2SFrederic Weisbecker			print "Sched switch event rejected ts: %s cpu: %d prev: %s(%d) next: %s(%d)" % \
540880d22f2SFrederic Weisbecker				(headers.ts_format(), headers.cpu, prev_comm, prev_pid, next_comm, next_pid)
541880d22f2SFrederic Weisbecker
542880d22f2SFrederic Weisbecker		threads[prev_pid] = prev_comm
543880d22f2SFrederic Weisbecker		threads[next_pid] = next_comm
544880d22f2SFrederic Weisbecker		self.current_tsk[headers.cpu] = next_pid
545880d22f2SFrederic Weisbecker
546880d22f2SFrederic Weisbecker		ts = self.timeslices.get_time_slice(headers.ts())
547880d22f2SFrederic Weisbecker		ts.sched_switch(self.timeslices, prev_pid, prev_state, next_pid, headers.cpu)
548880d22f2SFrederic Weisbecker
549880d22f2SFrederic Weisbecker	def migrate(self, headers, pid, prio, orig_cpu, dest_cpu):
550880d22f2SFrederic Weisbecker		ts = self.timeslices.get_time_slice(headers.ts())
551880d22f2SFrederic Weisbecker		ts.migrate(self.timeslices, pid, orig_cpu, dest_cpu)
552880d22f2SFrederic Weisbecker
553880d22f2SFrederic Weisbecker	def wake_up(self, headers, comm, pid, success, target_cpu, fork):
554880d22f2SFrederic Weisbecker		if success == 0:
555880d22f2SFrederic Weisbecker			return
556880d22f2SFrederic Weisbecker		ts = self.timeslices.get_time_slice(headers.ts())
557880d22f2SFrederic Weisbecker		ts.wake_up(self.timeslices, pid, target_cpu, fork)
558880d22f2SFrederic Weisbecker
559880d22f2SFrederic Weisbecker
560880d22f2SFrederic Weisbeckerdef trace_begin():
561880d22f2SFrederic Weisbecker	global parser
562880d22f2SFrederic Weisbecker	parser = SchedEventProxy()
563880d22f2SFrederic Weisbecker
564880d22f2SFrederic Weisbeckerdef trace_end():
565880d22f2SFrederic Weisbecker	app = wx.App(False)
566880d22f2SFrederic Weisbecker	timeslices = parser.timeslices
567*699b6d92SFrederic Weisbecker	frame = RootFrame(timeslices, "Migration")
568880d22f2SFrederic Weisbecker	app.MainLoop()
569880d22f2SFrederic Weisbecker
570880d22f2SFrederic Weisbeckerdef sched__sched_stat_runtime(event_name, context, common_cpu,
571880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
572880d22f2SFrederic Weisbecker	comm, pid, runtime, vruntime):
573880d22f2SFrederic Weisbecker	pass
574880d22f2SFrederic Weisbecker
575880d22f2SFrederic Weisbeckerdef sched__sched_stat_iowait(event_name, context, common_cpu,
576880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
577880d22f2SFrederic Weisbecker	comm, pid, delay):
578880d22f2SFrederic Weisbecker	pass
579880d22f2SFrederic Weisbecker
580880d22f2SFrederic Weisbeckerdef sched__sched_stat_sleep(event_name, context, common_cpu,
581880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
582880d22f2SFrederic Weisbecker	comm, pid, delay):
583880d22f2SFrederic Weisbecker	pass
584880d22f2SFrederic Weisbecker
585880d22f2SFrederic Weisbeckerdef sched__sched_stat_wait(event_name, context, common_cpu,
586880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
587880d22f2SFrederic Weisbecker	comm, pid, delay):
588880d22f2SFrederic Weisbecker	pass
589880d22f2SFrederic Weisbecker
590880d22f2SFrederic Weisbeckerdef sched__sched_process_fork(event_name, context, common_cpu,
591880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
592880d22f2SFrederic Weisbecker	parent_comm, parent_pid, child_comm, child_pid):
593880d22f2SFrederic Weisbecker	pass
594880d22f2SFrederic Weisbecker
595880d22f2SFrederic Weisbeckerdef sched__sched_process_wait(event_name, context, common_cpu,
596880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
597880d22f2SFrederic Weisbecker	comm, pid, prio):
598880d22f2SFrederic Weisbecker	pass
599880d22f2SFrederic Weisbecker
600880d22f2SFrederic Weisbeckerdef sched__sched_process_exit(event_name, context, common_cpu,
601880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
602880d22f2SFrederic Weisbecker	comm, pid, prio):
603880d22f2SFrederic Weisbecker	pass
604880d22f2SFrederic Weisbecker
605880d22f2SFrederic Weisbeckerdef sched__sched_process_free(event_name, context, common_cpu,
606880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
607880d22f2SFrederic Weisbecker	comm, pid, prio):
608880d22f2SFrederic Weisbecker	pass
609880d22f2SFrederic Weisbecker
610880d22f2SFrederic Weisbeckerdef sched__sched_migrate_task(event_name, context, common_cpu,
611880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
612880d22f2SFrederic Weisbecker	comm, pid, prio, orig_cpu,
613880d22f2SFrederic Weisbecker	dest_cpu):
614880d22f2SFrederic Weisbecker	headers = EventHeaders(common_cpu, common_secs, common_nsecs,
615880d22f2SFrederic Weisbecker				common_pid, common_comm)
616880d22f2SFrederic Weisbecker	parser.migrate(headers, pid, prio, orig_cpu, dest_cpu)
617880d22f2SFrederic Weisbecker
618880d22f2SFrederic Weisbeckerdef sched__sched_switch(event_name, context, common_cpu,
619880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
620880d22f2SFrederic Weisbecker	prev_comm, prev_pid, prev_prio, prev_state,
621880d22f2SFrederic Weisbecker	next_comm, next_pid, next_prio):
622880d22f2SFrederic Weisbecker
623880d22f2SFrederic Weisbecker	headers = EventHeaders(common_cpu, common_secs, common_nsecs,
624880d22f2SFrederic Weisbecker				common_pid, common_comm)
625880d22f2SFrederic Weisbecker	parser.sched_switch(headers, prev_comm, prev_pid, prev_prio, prev_state,
626880d22f2SFrederic Weisbecker			 next_comm, next_pid, next_prio)
627880d22f2SFrederic Weisbecker
628880d22f2SFrederic Weisbeckerdef sched__sched_wakeup_new(event_name, context, common_cpu,
629880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
630880d22f2SFrederic Weisbecker	comm, pid, prio, success,
631880d22f2SFrederic Weisbecker	target_cpu):
632880d22f2SFrederic Weisbecker	headers = EventHeaders(common_cpu, common_secs, common_nsecs,
633880d22f2SFrederic Weisbecker				common_pid, common_comm)
634880d22f2SFrederic Weisbecker	parser.wake_up(headers, comm, pid, success, target_cpu, 1)
635880d22f2SFrederic Weisbecker
636880d22f2SFrederic Weisbeckerdef sched__sched_wakeup(event_name, context, common_cpu,
637880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
638880d22f2SFrederic Weisbecker	comm, pid, prio, success,
639880d22f2SFrederic Weisbecker	target_cpu):
640880d22f2SFrederic Weisbecker	headers = EventHeaders(common_cpu, common_secs, common_nsecs,
641880d22f2SFrederic Weisbecker				common_pid, common_comm)
642880d22f2SFrederic Weisbecker	parser.wake_up(headers, comm, pid, success, target_cpu, 0)
643880d22f2SFrederic Weisbecker
644880d22f2SFrederic Weisbeckerdef sched__sched_wait_task(event_name, context, common_cpu,
645880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
646880d22f2SFrederic Weisbecker	comm, pid, prio):
647880d22f2SFrederic Weisbecker	pass
648880d22f2SFrederic Weisbecker
649880d22f2SFrederic Weisbeckerdef sched__sched_kthread_stop_ret(event_name, context, common_cpu,
650880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
651880d22f2SFrederic Weisbecker	ret):
652880d22f2SFrederic Weisbecker	pass
653880d22f2SFrederic Weisbecker
654880d22f2SFrederic Weisbeckerdef sched__sched_kthread_stop(event_name, context, common_cpu,
655880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
656880d22f2SFrederic Weisbecker	comm, pid):
657880d22f2SFrederic Weisbecker	pass
658880d22f2SFrederic Weisbecker
659880d22f2SFrederic Weisbeckerdef trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs,
660880d22f2SFrederic Weisbecker		common_pid, common_comm):
661880d22f2SFrederic Weisbecker	pass
662