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:
263880d22f2SFrederic Weisbecker		print "Unhandled task state %d" % state
264880d22f2SFrederic Weisbecker		return ""
265880d22f2SFrederic Weisbecker
266880d22f2SFrederic Weisbecker	return states[state]
267880d22f2SFrederic Weisbecker
268880d22f2SFrederic Weisbecker
269880d22f2SFrederic Weisbeckerclass RunqueueEventUnknown:
270880d22f2SFrederic Weisbecker	@staticmethod
271880d22f2SFrederic Weisbecker	def color():
272880d22f2SFrederic Weisbecker		return None
273880d22f2SFrederic Weisbecker
274880d22f2SFrederic Weisbecker	def __repr__(self):
275880d22f2SFrederic Weisbecker		return "unknown"
276880d22f2SFrederic Weisbecker
277880d22f2SFrederic Weisbeckerclass RunqueueEventSleep:
278880d22f2SFrederic Weisbecker	@staticmethod
279880d22f2SFrederic Weisbecker	def color():
280880d22f2SFrederic Weisbecker		return (0, 0, 0xff)
281880d22f2SFrederic Weisbecker
282880d22f2SFrederic Weisbecker	def __init__(self, sleeper):
283880d22f2SFrederic Weisbecker		self.sleeper = sleeper
284880d22f2SFrederic Weisbecker
285880d22f2SFrederic Weisbecker	def __repr__(self):
286880d22f2SFrederic Weisbecker		return "%s gone to sleep" % thread_name(self.sleeper)
287880d22f2SFrederic Weisbecker
288880d22f2SFrederic Weisbeckerclass RunqueueEventWakeup:
289880d22f2SFrederic Weisbecker	@staticmethod
290880d22f2SFrederic Weisbecker	def color():
291880d22f2SFrederic Weisbecker		return (0xff, 0xff, 0)
292880d22f2SFrederic Weisbecker
293880d22f2SFrederic Weisbecker	def __init__(self, wakee):
294880d22f2SFrederic Weisbecker		self.wakee = wakee
295880d22f2SFrederic Weisbecker
296880d22f2SFrederic Weisbecker	def __repr__(self):
297880d22f2SFrederic Weisbecker		return "%s woke up" % thread_name(self.wakee)
298880d22f2SFrederic Weisbecker
299880d22f2SFrederic Weisbeckerclass RunqueueEventFork:
300880d22f2SFrederic Weisbecker	@staticmethod
301880d22f2SFrederic Weisbecker	def color():
302880d22f2SFrederic Weisbecker		return (0, 0xff, 0)
303880d22f2SFrederic Weisbecker
304880d22f2SFrederic Weisbecker	def __init__(self, child):
305880d22f2SFrederic Weisbecker		self.child = child
306880d22f2SFrederic Weisbecker
307880d22f2SFrederic Weisbecker	def __repr__(self):
308880d22f2SFrederic Weisbecker		return "new forked task %s" % thread_name(self.child)
309880d22f2SFrederic Weisbecker
310880d22f2SFrederic Weisbeckerclass RunqueueMigrateIn:
311880d22f2SFrederic Weisbecker	@staticmethod
312880d22f2SFrederic Weisbecker	def color():
313880d22f2SFrederic Weisbecker		return (0, 0xf0, 0xff)
314880d22f2SFrederic Weisbecker
315880d22f2SFrederic Weisbecker	def __init__(self, new):
316880d22f2SFrederic Weisbecker		self.new = new
317880d22f2SFrederic Weisbecker
318880d22f2SFrederic Weisbecker	def __repr__(self):
319880d22f2SFrederic Weisbecker		return "task migrated in %s" % thread_name(self.new)
320880d22f2SFrederic Weisbecker
321880d22f2SFrederic Weisbeckerclass RunqueueMigrateOut:
322880d22f2SFrederic Weisbecker	@staticmethod
323880d22f2SFrederic Weisbecker	def color():
324880d22f2SFrederic Weisbecker		return (0xff, 0, 0xff)
325880d22f2SFrederic Weisbecker
326880d22f2SFrederic Weisbecker	def __init__(self, old):
327880d22f2SFrederic Weisbecker		self.old = old
328880d22f2SFrederic Weisbecker
329880d22f2SFrederic Weisbecker	def __repr__(self):
330880d22f2SFrederic Weisbecker		return "task migrated out %s" % thread_name(self.old)
331880d22f2SFrederic Weisbecker
332880d22f2SFrederic Weisbeckerclass RunqueueSnapshot:
333880d22f2SFrederic Weisbecker	def __init__(self, tasks = [0], event = RunqueueEventUnknown()):
334880d22f2SFrederic Weisbecker		self.tasks = tuple(tasks)
335880d22f2SFrederic Weisbecker		self.event = event
336880d22f2SFrederic Weisbecker
337880d22f2SFrederic Weisbecker	def sched_switch(self, prev, prev_state, next):
338880d22f2SFrederic Weisbecker		event = RunqueueEventUnknown()
339880d22f2SFrederic Weisbecker
340880d22f2SFrederic Weisbecker		if taskState(prev_state) == "R" and next in self.tasks \
341880d22f2SFrederic Weisbecker			and prev in self.tasks:
342880d22f2SFrederic Weisbecker			return self
343880d22f2SFrederic Weisbecker
344880d22f2SFrederic Weisbecker		if taskState(prev_state) != "R":
345880d22f2SFrederic Weisbecker			event = RunqueueEventSleep(prev)
346880d22f2SFrederic Weisbecker
347880d22f2SFrederic Weisbecker		next_tasks = list(self.tasks[:])
348880d22f2SFrederic Weisbecker		if prev in self.tasks:
349880d22f2SFrederic Weisbecker			if taskState(prev_state) != "R":
350880d22f2SFrederic Weisbecker				next_tasks.remove(prev)
351880d22f2SFrederic Weisbecker		elif taskState(prev_state) == "R":
352880d22f2SFrederic Weisbecker			next_tasks.append(prev)
353880d22f2SFrederic Weisbecker
354880d22f2SFrederic Weisbecker		if next not in next_tasks:
355880d22f2SFrederic Weisbecker			next_tasks.append(next)
356880d22f2SFrederic Weisbecker
357880d22f2SFrederic Weisbecker		return RunqueueSnapshot(next_tasks, event)
358880d22f2SFrederic Weisbecker
359880d22f2SFrederic Weisbecker	def migrate_out(self, old):
360880d22f2SFrederic Weisbecker		if old not in self.tasks:
361880d22f2SFrederic Weisbecker			return self
362880d22f2SFrederic Weisbecker		next_tasks = [task for task in self.tasks if task != old]
363880d22f2SFrederic Weisbecker
364880d22f2SFrederic Weisbecker		return RunqueueSnapshot(next_tasks, RunqueueMigrateOut(old))
365880d22f2SFrederic Weisbecker
366880d22f2SFrederic Weisbecker	def __migrate_in(self, new, event):
367880d22f2SFrederic Weisbecker		if new in self.tasks:
368880d22f2SFrederic Weisbecker			self.event = event
369880d22f2SFrederic Weisbecker			return self
370880d22f2SFrederic Weisbecker		next_tasks = self.tasks[:] + tuple([new])
371880d22f2SFrederic Weisbecker
372880d22f2SFrederic Weisbecker		return RunqueueSnapshot(next_tasks, event)
373880d22f2SFrederic Weisbecker
374880d22f2SFrederic Weisbecker	def migrate_in(self, new):
375880d22f2SFrederic Weisbecker		return self.__migrate_in(new, RunqueueMigrateIn(new))
376880d22f2SFrederic Weisbecker
377880d22f2SFrederic Weisbecker	def wake_up(self, new):
378880d22f2SFrederic Weisbecker		return self.__migrate_in(new, RunqueueEventWakeup(new))
379880d22f2SFrederic Weisbecker
380880d22f2SFrederic Weisbecker	def wake_up_new(self, new):
381880d22f2SFrederic Weisbecker		return self.__migrate_in(new, RunqueueEventFork(new))
382880d22f2SFrederic Weisbecker
383880d22f2SFrederic Weisbecker	def load(self):
384880d22f2SFrederic Weisbecker		""" Provide the number of tasks on the runqueue.
385880d22f2SFrederic Weisbecker		    Don't count idle"""
386880d22f2SFrederic Weisbecker		return len(self.tasks) - 1
387880d22f2SFrederic Weisbecker
388880d22f2SFrederic Weisbecker	def __repr__(self):
389880d22f2SFrederic Weisbecker		ret = self.tasks.__repr__()
390880d22f2SFrederic Weisbecker		ret += self.origin_tostring()
391880d22f2SFrederic Weisbecker
392880d22f2SFrederic Weisbecker		return ret
393880d22f2SFrederic Weisbecker
394880d22f2SFrederic Weisbeckerclass TimeSlice:
395880d22f2SFrederic Weisbecker	def __init__(self, start, prev):
396880d22f2SFrederic Weisbecker		self.start = start
397880d22f2SFrederic Weisbecker		self.prev = prev
398880d22f2SFrederic Weisbecker		self.end = start
399880d22f2SFrederic Weisbecker		# cpus that triggered the event
400880d22f2SFrederic Weisbecker		self.event_cpus = []
401880d22f2SFrederic Weisbecker		if prev is not None:
402880d22f2SFrederic Weisbecker			self.total_load = prev.total_load
403880d22f2SFrederic Weisbecker			self.rqs = prev.rqs.copy()
404880d22f2SFrederic Weisbecker		else:
405880d22f2SFrederic Weisbecker			self.rqs = defaultdict(RunqueueSnapshot)
406880d22f2SFrederic Weisbecker			self.total_load = 0
407880d22f2SFrederic Weisbecker
408880d22f2SFrederic Weisbecker	def __update_total_load(self, old_rq, new_rq):
409880d22f2SFrederic Weisbecker		diff = new_rq.load() - old_rq.load()
410880d22f2SFrederic Weisbecker		self.total_load += diff
411880d22f2SFrederic Weisbecker
412880d22f2SFrederic Weisbecker	def sched_switch(self, ts_list, prev, prev_state, next, cpu):
413880d22f2SFrederic Weisbecker		old_rq = self.prev.rqs[cpu]
414880d22f2SFrederic Weisbecker		new_rq = old_rq.sched_switch(prev, prev_state, next)
415880d22f2SFrederic Weisbecker
416880d22f2SFrederic Weisbecker		if old_rq is new_rq:
417880d22f2SFrederic Weisbecker			return
418880d22f2SFrederic Weisbecker
419880d22f2SFrederic Weisbecker		self.rqs[cpu] = new_rq
420880d22f2SFrederic Weisbecker		self.__update_total_load(old_rq, new_rq)
421880d22f2SFrederic Weisbecker		ts_list.append(self)
422880d22f2SFrederic Weisbecker		self.event_cpus = [cpu]
423880d22f2SFrederic Weisbecker
424880d22f2SFrederic Weisbecker	def migrate(self, ts_list, new, old_cpu, new_cpu):
425880d22f2SFrederic Weisbecker		if old_cpu == new_cpu:
426880d22f2SFrederic Weisbecker			return
427880d22f2SFrederic Weisbecker		old_rq = self.prev.rqs[old_cpu]
428880d22f2SFrederic Weisbecker		out_rq = old_rq.migrate_out(new)
429880d22f2SFrederic Weisbecker		self.rqs[old_cpu] = out_rq
430880d22f2SFrederic Weisbecker		self.__update_total_load(old_rq, out_rq)
431880d22f2SFrederic Weisbecker
432880d22f2SFrederic Weisbecker		new_rq = self.prev.rqs[new_cpu]
433880d22f2SFrederic Weisbecker		in_rq = new_rq.migrate_in(new)
434880d22f2SFrederic Weisbecker		self.rqs[new_cpu] = in_rq
435880d22f2SFrederic Weisbecker		self.__update_total_load(new_rq, in_rq)
436880d22f2SFrederic Weisbecker
437880d22f2SFrederic Weisbecker		ts_list.append(self)
438*749e5074SFrederic Weisbecker
439*749e5074SFrederic Weisbecker		if old_rq is not out_rq:
440*749e5074SFrederic Weisbecker			self.event_cpus.append(old_cpu)
441*749e5074SFrederic Weisbecker		self.event_cpus.append(new_cpu)
442880d22f2SFrederic Weisbecker
443880d22f2SFrederic Weisbecker	def wake_up(self, ts_list, pid, cpu, fork):
444880d22f2SFrederic Weisbecker		old_rq = self.prev.rqs[cpu]
445880d22f2SFrederic Weisbecker		if fork:
446880d22f2SFrederic Weisbecker			new_rq = old_rq.wake_up_new(pid)
447880d22f2SFrederic Weisbecker		else:
448880d22f2SFrederic Weisbecker			new_rq = old_rq.wake_up(pid)
449880d22f2SFrederic Weisbecker
450880d22f2SFrederic Weisbecker		if new_rq is old_rq:
451880d22f2SFrederic Weisbecker			return
452880d22f2SFrederic Weisbecker		self.rqs[cpu] = new_rq
453880d22f2SFrederic Weisbecker		self.__update_total_load(old_rq, new_rq)
454880d22f2SFrederic Weisbecker		ts_list.append(self)
455880d22f2SFrederic Weisbecker		self.event_cpus = [cpu]
456880d22f2SFrederic Weisbecker
457880d22f2SFrederic Weisbecker	def next(self, t):
458880d22f2SFrederic Weisbecker		self.end = t
459880d22f2SFrederic Weisbecker		return TimeSlice(t, self)
460880d22f2SFrederic Weisbecker
461880d22f2SFrederic Weisbeckerclass TimeSliceList(UserList):
462880d22f2SFrederic Weisbecker	def __init__(self, arg = []):
463880d22f2SFrederic Weisbecker		self.data = arg
464880d22f2SFrederic Weisbecker
465880d22f2SFrederic Weisbecker	def get_time_slice(self, ts):
466880d22f2SFrederic Weisbecker		if len(self.data) == 0:
467880d22f2SFrederic Weisbecker			slice = TimeSlice(ts, TimeSlice(-1, None))
468880d22f2SFrederic Weisbecker		else:
469880d22f2SFrederic Weisbecker			slice = self.data[-1].next(ts)
470880d22f2SFrederic Weisbecker		return slice
471880d22f2SFrederic Weisbecker
472880d22f2SFrederic Weisbecker	def find_time_slice(self, ts):
473880d22f2SFrederic Weisbecker		start = 0
474880d22f2SFrederic Weisbecker		end = len(self.data)
475880d22f2SFrederic Weisbecker		found = -1
476880d22f2SFrederic Weisbecker		searching = True
477880d22f2SFrederic Weisbecker		while searching:
478880d22f2SFrederic Weisbecker			if start == end or start == end - 1:
479880d22f2SFrederic Weisbecker				searching = False
480880d22f2SFrederic Weisbecker
481880d22f2SFrederic Weisbecker			i = (end + start) / 2
482880d22f2SFrederic Weisbecker			if self.data[i].start <= ts and self.data[i].end >= ts:
483880d22f2SFrederic Weisbecker				found = i
484880d22f2SFrederic Weisbecker				end = i
485880d22f2SFrederic Weisbecker				continue
486880d22f2SFrederic Weisbecker
487880d22f2SFrederic Weisbecker			if self.data[i].end < ts:
488880d22f2SFrederic Weisbecker				start = i
489880d22f2SFrederic Weisbecker
490880d22f2SFrederic Weisbecker			elif self.data[i].start > ts:
491880d22f2SFrederic Weisbecker				end = i
492880d22f2SFrederic Weisbecker
493880d22f2SFrederic Weisbecker		return found
494880d22f2SFrederic Weisbecker
495880d22f2SFrederic Weisbecker	def interval(self):
496880d22f2SFrederic Weisbecker		if len(self.data) == 0:
497880d22f2SFrederic Weisbecker			return (0, 0)
498880d22f2SFrederic Weisbecker
499880d22f2SFrederic Weisbecker		return (self.data[0].start, self.data[-1].end)
500880d22f2SFrederic Weisbecker
501880d22f2SFrederic Weisbecker
502880d22f2SFrederic Weisbeckerclass SchedEventProxy:
503880d22f2SFrederic Weisbecker	def __init__(self):
504880d22f2SFrederic Weisbecker		self.current_tsk = defaultdict(lambda : -1)
505880d22f2SFrederic Weisbecker		self.timeslices = TimeSliceList()
506880d22f2SFrederic Weisbecker
507880d22f2SFrederic Weisbecker	def sched_switch(self, headers, prev_comm, prev_pid, prev_prio, prev_state,
508880d22f2SFrederic Weisbecker			 next_comm, next_pid, next_prio):
509880d22f2SFrederic Weisbecker		""" Ensure the task we sched out this cpu is really the one
510880d22f2SFrederic Weisbecker		    we logged. Otherwise we may have missed traces """
511880d22f2SFrederic Weisbecker
512880d22f2SFrederic Weisbecker		on_cpu_task = self.current_tsk[headers.cpu]
513880d22f2SFrederic Weisbecker
514880d22f2SFrederic Weisbecker		if on_cpu_task != -1 and on_cpu_task != prev_pid:
515880d22f2SFrederic Weisbecker			print "Sched switch event rejected ts: %s cpu: %d prev: %s(%d) next: %s(%d)" % \
516880d22f2SFrederic Weisbecker				(headers.ts_format(), headers.cpu, prev_comm, prev_pid, next_comm, next_pid)
517880d22f2SFrederic Weisbecker
518880d22f2SFrederic Weisbecker		threads[prev_pid] = prev_comm
519880d22f2SFrederic Weisbecker		threads[next_pid] = next_comm
520880d22f2SFrederic Weisbecker		self.current_tsk[headers.cpu] = next_pid
521880d22f2SFrederic Weisbecker
522880d22f2SFrederic Weisbecker		ts = self.timeslices.get_time_slice(headers.ts())
523880d22f2SFrederic Weisbecker		ts.sched_switch(self.timeslices, prev_pid, prev_state, next_pid, headers.cpu)
524880d22f2SFrederic Weisbecker
525880d22f2SFrederic Weisbecker	def migrate(self, headers, pid, prio, orig_cpu, dest_cpu):
526880d22f2SFrederic Weisbecker		ts = self.timeslices.get_time_slice(headers.ts())
527880d22f2SFrederic Weisbecker		ts.migrate(self.timeslices, pid, orig_cpu, dest_cpu)
528880d22f2SFrederic Weisbecker
529880d22f2SFrederic Weisbecker	def wake_up(self, headers, comm, pid, success, target_cpu, fork):
530880d22f2SFrederic Weisbecker		if success == 0:
531880d22f2SFrederic Weisbecker			return
532880d22f2SFrederic Weisbecker		ts = self.timeslices.get_time_slice(headers.ts())
533880d22f2SFrederic Weisbecker		ts.wake_up(self.timeslices, pid, target_cpu, fork)
534880d22f2SFrederic Weisbecker
535880d22f2SFrederic Weisbecker
536880d22f2SFrederic Weisbeckerdef trace_begin():
537880d22f2SFrederic Weisbecker	global parser
538880d22f2SFrederic Weisbecker	parser = SchedEventProxy()
539880d22f2SFrederic Weisbecker
540880d22f2SFrederic Weisbeckerdef trace_end():
541880d22f2SFrederic Weisbecker	app = wx.App(False)
542880d22f2SFrederic Weisbecker	timeslices = parser.timeslices
543880d22f2SFrederic Weisbecker	frame = RootFrame(timeslices)
544880d22f2SFrederic Weisbecker	app.MainLoop()
545880d22f2SFrederic Weisbecker
546880d22f2SFrederic Weisbeckerdef sched__sched_stat_runtime(event_name, context, common_cpu,
547880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
548880d22f2SFrederic Weisbecker	comm, pid, runtime, vruntime):
549880d22f2SFrederic Weisbecker	pass
550880d22f2SFrederic Weisbecker
551880d22f2SFrederic Weisbeckerdef sched__sched_stat_iowait(event_name, context, common_cpu,
552880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
553880d22f2SFrederic Weisbecker	comm, pid, delay):
554880d22f2SFrederic Weisbecker	pass
555880d22f2SFrederic Weisbecker
556880d22f2SFrederic Weisbeckerdef sched__sched_stat_sleep(event_name, context, common_cpu,
557880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
558880d22f2SFrederic Weisbecker	comm, pid, delay):
559880d22f2SFrederic Weisbecker	pass
560880d22f2SFrederic Weisbecker
561880d22f2SFrederic Weisbeckerdef sched__sched_stat_wait(event_name, context, common_cpu,
562880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
563880d22f2SFrederic Weisbecker	comm, pid, delay):
564880d22f2SFrederic Weisbecker	pass
565880d22f2SFrederic Weisbecker
566880d22f2SFrederic Weisbeckerdef sched__sched_process_fork(event_name, context, common_cpu,
567880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
568880d22f2SFrederic Weisbecker	parent_comm, parent_pid, child_comm, child_pid):
569880d22f2SFrederic Weisbecker	pass
570880d22f2SFrederic Weisbecker
571880d22f2SFrederic Weisbeckerdef sched__sched_process_wait(event_name, context, common_cpu,
572880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
573880d22f2SFrederic Weisbecker	comm, pid, prio):
574880d22f2SFrederic Weisbecker	pass
575880d22f2SFrederic Weisbecker
576880d22f2SFrederic Weisbeckerdef sched__sched_process_exit(event_name, context, common_cpu,
577880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
578880d22f2SFrederic Weisbecker	comm, pid, prio):
579880d22f2SFrederic Weisbecker	pass
580880d22f2SFrederic Weisbecker
581880d22f2SFrederic Weisbeckerdef sched__sched_process_free(event_name, context, common_cpu,
582880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
583880d22f2SFrederic Weisbecker	comm, pid, prio):
584880d22f2SFrederic Weisbecker	pass
585880d22f2SFrederic Weisbecker
586880d22f2SFrederic Weisbeckerdef sched__sched_migrate_task(event_name, context, common_cpu,
587880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
588880d22f2SFrederic Weisbecker	comm, pid, prio, orig_cpu,
589880d22f2SFrederic Weisbecker	dest_cpu):
590880d22f2SFrederic Weisbecker	headers = EventHeaders(common_cpu, common_secs, common_nsecs,
591880d22f2SFrederic Weisbecker				common_pid, common_comm)
592880d22f2SFrederic Weisbecker	parser.migrate(headers, pid, prio, orig_cpu, dest_cpu)
593880d22f2SFrederic Weisbecker
594880d22f2SFrederic Weisbeckerdef sched__sched_switch(event_name, context, common_cpu,
595880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
596880d22f2SFrederic Weisbecker	prev_comm, prev_pid, prev_prio, prev_state,
597880d22f2SFrederic Weisbecker	next_comm, next_pid, next_prio):
598880d22f2SFrederic Weisbecker
599880d22f2SFrederic Weisbecker	headers = EventHeaders(common_cpu, common_secs, common_nsecs,
600880d22f2SFrederic Weisbecker				common_pid, common_comm)
601880d22f2SFrederic Weisbecker	parser.sched_switch(headers, prev_comm, prev_pid, prev_prio, prev_state,
602880d22f2SFrederic Weisbecker			 next_comm, next_pid, next_prio)
603880d22f2SFrederic Weisbecker
604880d22f2SFrederic Weisbeckerdef sched__sched_wakeup_new(event_name, context, common_cpu,
605880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
606880d22f2SFrederic Weisbecker	comm, pid, prio, success,
607880d22f2SFrederic Weisbecker	target_cpu):
608880d22f2SFrederic Weisbecker	headers = EventHeaders(common_cpu, common_secs, common_nsecs,
609880d22f2SFrederic Weisbecker				common_pid, common_comm)
610880d22f2SFrederic Weisbecker	parser.wake_up(headers, comm, pid, success, target_cpu, 1)
611880d22f2SFrederic Weisbecker
612880d22f2SFrederic Weisbeckerdef sched__sched_wakeup(event_name, context, common_cpu,
613880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
614880d22f2SFrederic Weisbecker	comm, pid, prio, success,
615880d22f2SFrederic Weisbecker	target_cpu):
616880d22f2SFrederic Weisbecker	headers = EventHeaders(common_cpu, common_secs, common_nsecs,
617880d22f2SFrederic Weisbecker				common_pid, common_comm)
618880d22f2SFrederic Weisbecker	parser.wake_up(headers, comm, pid, success, target_cpu, 0)
619880d22f2SFrederic Weisbecker
620880d22f2SFrederic Weisbeckerdef sched__sched_wait_task(event_name, context, common_cpu,
621880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
622880d22f2SFrederic Weisbecker	comm, pid, prio):
623880d22f2SFrederic Weisbecker	pass
624880d22f2SFrederic Weisbecker
625880d22f2SFrederic Weisbeckerdef sched__sched_kthread_stop_ret(event_name, context, common_cpu,
626880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
627880d22f2SFrederic Weisbecker	ret):
628880d22f2SFrederic Weisbecker	pass
629880d22f2SFrederic Weisbecker
630880d22f2SFrederic Weisbeckerdef sched__sched_kthread_stop(event_name, context, common_cpu,
631880d22f2SFrederic Weisbecker	common_secs, common_nsecs, common_pid, common_comm,
632880d22f2SFrederic Weisbecker	comm, pid):
633880d22f2SFrederic Weisbecker	pass
634880d22f2SFrederic Weisbecker
635880d22f2SFrederic Weisbeckerdef trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs,
636880d22f2SFrederic Weisbecker		common_pid, common_comm):
637880d22f2SFrederic Weisbecker	pass
638