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