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