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