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