diff options
Diffstat (limited to 'tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
3 files changed, 391 insertions, 0 deletions
| diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py new file mode 100644 index 000000000000..de7211e4fa47 --- /dev/null +++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py @@ -0,0 +1,121 @@ +# Core.py - Python extension for perf script, core functions +# +# Copyright (C) 2010 by Tom Zanussi <tzanussi@gmail.com> +# +# This software may be distributed under the terms of the GNU General +# Public License ("GPL") version 2 as published by the Free Software +# Foundation. + +from collections import defaultdict + +def autodict(): +    return defaultdict(autodict) + +flag_fields = autodict() +symbolic_fields = autodict() + +def define_flag_field(event_name, field_name, delim): +    flag_fields[event_name][field_name]['delim'] = delim + +def define_flag_value(event_name, field_name, value, field_str): +    flag_fields[event_name][field_name]['values'][value] = field_str + +def define_symbolic_field(event_name, field_name): +    # nothing to do, really +    pass + +def define_symbolic_value(event_name, field_name, value, field_str): +    symbolic_fields[event_name][field_name]['values'][value] = field_str + +def flag_str(event_name, field_name, value): +    string = "" + +    if flag_fields[event_name][field_name]: +	print_delim = 0 +        keys = flag_fields[event_name][field_name]['values'].keys() +        keys.sort() +        for idx in keys: +            if not value and not idx: +                string += flag_fields[event_name][field_name]['values'][idx] +                break +            if idx and (value & idx) == idx: +                if print_delim and flag_fields[event_name][field_name]['delim']: +                    string += " " + flag_fields[event_name][field_name]['delim'] + " " +                string += flag_fields[event_name][field_name]['values'][idx] +                print_delim = 1 +                value &= ~idx + +    return string + +def symbol_str(event_name, field_name, value): +    string = "" + +    if symbolic_fields[event_name][field_name]: +        keys = symbolic_fields[event_name][field_name]['values'].keys() +        keys.sort() +        for idx in keys: +            if not value and not idx: +		string = symbolic_fields[event_name][field_name]['values'][idx] +                break +	    if (value == idx): +		string = symbolic_fields[event_name][field_name]['values'][idx] +                break + +    return string + +trace_flags = { 0x00: "NONE", \ +                    0x01: "IRQS_OFF", \ +                    0x02: "IRQS_NOSUPPORT", \ +                    0x04: "NEED_RESCHED", \ +                    0x08: "HARDIRQ", \ +                    0x10: "SOFTIRQ" } + +def trace_flag_str(value): +    string = "" +    print_delim = 0 + +    keys = trace_flags.keys() + +    for idx in keys: +	if not value and not idx: +	    string += "NONE" +	    break + +	if idx and (value & idx) == idx: +	    if print_delim: +		string += " | "; +	    string += trace_flags[idx] +	    print_delim = 1 +	    value &= ~idx + +    return string + + +def taskState(state): +	states = { +		0 : "R", +		1 : "S", +		2 : "D", +		64: "DEAD" +	} + +	if state not in states: +		return "Unknown" + +	return states[state] + + +class EventHeaders: +	def __init__(self, common_cpu, common_secs, common_nsecs, +		     common_pid, common_comm): +		self.cpu = common_cpu +		self.secs = common_secs +		self.nsecs = common_nsecs +		self.pid = common_pid +		self.comm = common_comm + +	def ts(self): +		return (self.secs * (10 ** 9)) + self.nsecs + +	def ts_format(self): +		return "%d.%d" % (self.secs, int(self.nsecs / 1000)) diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py new file mode 100644 index 000000000000..fdd92f699055 --- /dev/null +++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py @@ -0,0 +1,184 @@ +# SchedGui.py - Python extension for perf script, basic GUI code for +#		traces drawing and overview. +# +# Copyright (C) 2010 by Frederic Weisbecker <fweisbec@gmail.com> +# +# This software is distributed under the terms of the GNU General +# Public License ("GPL") version 2 as published by the Free Software +# Foundation. + + +try: +	import wx +except ImportError: +	raise ImportError, "You need to install the wxpython lib for this script" + + +class RootFrame(wx.Frame): +	Y_OFFSET = 100 +	RECT_HEIGHT = 100 +	RECT_SPACE = 50 +	EVENT_MARKING_WIDTH = 5 + +	def __init__(self, sched_tracer, title, parent = None, id = -1): +		wx.Frame.__init__(self, parent, id, title) + +		(self.screen_width, self.screen_height) = wx.GetDisplaySize() +		self.screen_width -= 10 +		self.screen_height -= 10 +		self.zoom = 0.5 +		self.scroll_scale = 20 +		self.sched_tracer = sched_tracer +		self.sched_tracer.set_root_win(self) +		(self.ts_start, self.ts_end) = sched_tracer.interval() +		self.update_width_virtual() +		self.nr_rects = sched_tracer.nr_rectangles() + 1 +		self.height_virtual = RootFrame.Y_OFFSET + (self.nr_rects * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)) + +		# whole window panel +		self.panel = wx.Panel(self, size=(self.screen_width, self.screen_height)) + +		# scrollable container +		self.scroll = wx.ScrolledWindow(self.panel) +		self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, self.height_virtual / self.scroll_scale) +		self.scroll.EnableScrolling(True, True) +		self.scroll.SetFocus() + +		# scrollable drawing area +		self.scroll_panel = wx.Panel(self.scroll, size=(self.screen_width - 15, self.screen_height / 2)) +		self.scroll_panel.Bind(wx.EVT_PAINT, self.on_paint) +		self.scroll_panel.Bind(wx.EVT_KEY_DOWN, self.on_key_press) +		self.scroll_panel.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down) +		self.scroll.Bind(wx.EVT_PAINT, self.on_paint) +		self.scroll.Bind(wx.EVT_KEY_DOWN, self.on_key_press) +		self.scroll.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down) + +		self.scroll.Fit() +		self.Fit() + +		self.scroll_panel.SetDimensions(-1, -1, self.width_virtual, self.height_virtual, wx.SIZE_USE_EXISTING) + +		self.txt = None + +		self.Show(True) + +	def us_to_px(self, val): +		return val / (10 ** 3) * self.zoom + +	def px_to_us(self, val): +		return (val / self.zoom) * (10 ** 3) + +	def scroll_start(self): +		(x, y) = self.scroll.GetViewStart() +		return (x * self.scroll_scale, y * self.scroll_scale) + +	def scroll_start_us(self): +		(x, y) = self.scroll_start() +		return self.px_to_us(x) + +	def paint_rectangle_zone(self, nr, color, top_color, start, end): +		offset_px = self.us_to_px(start - self.ts_start) +		width_px = self.us_to_px(end - self.ts_start) + +		offset_py = RootFrame.Y_OFFSET + (nr * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)) +		width_py = RootFrame.RECT_HEIGHT + +		dc = self.dc + +		if top_color is not None: +			(r, g, b) = top_color +			top_color = wx.Colour(r, g, b) +			brush = wx.Brush(top_color, wx.SOLID) +			dc.SetBrush(brush) +			dc.DrawRectangle(offset_px, offset_py, width_px, RootFrame.EVENT_MARKING_WIDTH) +			width_py -= RootFrame.EVENT_MARKING_WIDTH +			offset_py += RootFrame.EVENT_MARKING_WIDTH + +		(r ,g, b) = color +		color = wx.Colour(r, g, b) +		brush = wx.Brush(color, wx.SOLID) +		dc.SetBrush(brush) +		dc.DrawRectangle(offset_px, offset_py, width_px, width_py) + +	def update_rectangles(self, dc, start, end): +		start += self.ts_start +		end += self.ts_start +		self.sched_tracer.fill_zone(start, end) + +	def on_paint(self, event): +		dc = wx.PaintDC(self.scroll_panel) +		self.dc = dc + +		width = min(self.width_virtual, self.screen_width) +		(x, y) = self.scroll_start() +		start = self.px_to_us(x) +		end = self.px_to_us(x + width) +		self.update_rectangles(dc, start, end) + +	def rect_from_ypixel(self, y): +		y -= RootFrame.Y_OFFSET +		rect = y / (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE) +		height = y % (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE) + +		if rect < 0 or rect > self.nr_rects - 1 or height > RootFrame.RECT_HEIGHT: +			return -1 + +		return rect + +	def update_summary(self, txt): +		if self.txt: +			self.txt.Destroy() +		self.txt = wx.StaticText(self.panel, -1, txt, (0, (self.screen_height / 2) + 50)) + + +	def on_mouse_down(self, event): +		(x, y) = event.GetPositionTuple() +		rect = self.rect_from_ypixel(y) +		if rect == -1: +			return + +		t = self.px_to_us(x) + self.ts_start + +		self.sched_tracer.mouse_down(rect, t) + + +	def update_width_virtual(self): +		self.width_virtual = self.us_to_px(self.ts_end - self.ts_start) + +	def __zoom(self, x): +		self.update_width_virtual() +		(xpos, ypos) = self.scroll.GetViewStart() +		xpos = self.us_to_px(x) / self.scroll_scale +		self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, self.height_virtual / self.scroll_scale, xpos, ypos) +		self.Refresh() + +	def zoom_in(self): +		x = self.scroll_start_us() +		self.zoom *= 2 +		self.__zoom(x) + +	def zoom_out(self): +		x = self.scroll_start_us() +		self.zoom /= 2 +		self.__zoom(x) + + +	def on_key_press(self, event): +		key = event.GetRawKeyCode() +		if key == ord("+"): +			self.zoom_in() +			return +		if key == ord("-"): +			self.zoom_out() +			return + +		key = event.GetKeyCode() +		(x, y) = self.scroll.GetViewStart() +		if key == wx.WXK_RIGHT: +			self.scroll.Scroll(x + 1, y) +		elif key == wx.WXK_LEFT: +			self.scroll.Scroll(x - 1, y) +		elif key == wx.WXK_DOWN: +			self.scroll.Scroll(x, y + 1) +		elif key == wx.WXK_UP: +			self.scroll.Scroll(x, y - 1) diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py new file mode 100644 index 000000000000..15c8400240fd --- /dev/null +++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py @@ -0,0 +1,86 @@ +# Util.py - Python extension for perf script, miscellaneous utility code +# +# Copyright (C) 2010 by Tom Zanussi <tzanussi@gmail.com> +# +# This software may be distributed under the terms of the GNU General +# Public License ("GPL") version 2 as published by the Free Software +# Foundation. + +import errno, os + +FUTEX_WAIT = 0 +FUTEX_WAKE = 1 +FUTEX_PRIVATE_FLAG = 128 +FUTEX_CLOCK_REALTIME = 256 +FUTEX_CMD_MASK = ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME) + +NSECS_PER_SEC    = 1000000000 + +def avg(total, n): +    return total / n + +def nsecs(secs, nsecs): +    return secs * NSECS_PER_SEC + nsecs + +def nsecs_secs(nsecs): +    return nsecs / NSECS_PER_SEC + +def nsecs_nsecs(nsecs): +    return nsecs % NSECS_PER_SEC + +def nsecs_str(nsecs): +    str = "%5u.%09u" % (nsecs_secs(nsecs), nsecs_nsecs(nsecs)), +    return str + +def add_stats(dict, key, value): +	if not dict.has_key(key): +		dict[key] = (value, value, value, 1) +	else: +		min, max, avg, count = dict[key] +		if value < min: +			min = value +		if value > max: +			max = value +		avg = (avg + value) / 2 +		dict[key] = (min, max, avg, count + 1) + +def clear_term(): +    print("\x1b[H\x1b[2J") + +audit_package_warned = False + +try: +	import audit +	machine_to_id = { +		'x86_64': audit.MACH_86_64, +		'alpha'	: audit.MACH_ALPHA, +		'ia64'	: audit.MACH_IA64, +		'ppc'	: audit.MACH_PPC, +		'ppc64'	: audit.MACH_PPC64, +		's390'	: audit.MACH_S390, +		's390x'	: audit.MACH_S390X, +		'i386'	: audit.MACH_X86, +		'i586'	: audit.MACH_X86, +		'i686'	: audit.MACH_X86, +	} +	try: +		machine_to_id['armeb'] = audit.MACH_ARMEB +	except: +		pass +	machine_id = machine_to_id[os.uname()[4]] +except: +	if not audit_package_warned: +		audit_package_warned = True +		print "Install the audit-libs-python package to get syscall names" + +def syscall_name(id): +	try: +		return audit.audit_syscall_to_name(id, machine_id) +	except: +		return str(id) + +def strerror(nr): +	try: +		return errno.errorcode[abs(nr)] +	except: +		return "Unknown %d errno" % nr | 
