diff options
author | John Kacur <jkacur@redhat.com> | 2018-05-09 11:52:30 +0100 |
---|---|---|
committer | John Kacur <jkacur@redhat.com> | 2018-05-09 11:52:30 +0100 |
commit | 1d955d0911e51faa1970168f95504ea881cec025 (patch) | |
tree | 95cdd188d8b0911b1760fcee88c39d350a618538 | |
parent | b01fefae561406756557a02a734a5de82c49d0ba (diff) | |
download | tuna-1d955d0911e51faa1970168f95504ea881cec025.tar.gz |
tuna: Fix more inconsistent spacing problems in cpuview and oscilloscope
Signed-off-by: John Kacur <jkacur@redhat.com>
-rwxr-xr-x | tuna/gui/cpuview.py | 660 | ||||
-rwxr-xr-x | tuna/oscilloscope.py | 796 |
2 files changed, 728 insertions, 728 deletions
diff --git a/tuna/gui/cpuview.py b/tuna/gui/cpuview.py index 80913bf..7a048fb 100755 --- a/tuna/gui/cpuview.py +++ b/tuna/gui/cpuview.py @@ -9,354 +9,354 @@ import gtk, gobject, math, os, procfs, schedutils from tuna import sysfs, tuna, gui def set_affinity_warning(tid, affinity): - dialog = gtk.MessageDialog(None, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - gtk.MESSAGE_WARNING, - gtk.BUTTONS_OK, - _("Couldn't change the affinity of %(tid)d to %(affinity)s!") % \ - {"tid": tid, "affinity": affinity}) - dialog.run() - dialog.destroy() + dialog = gtk.MessageDialog(None, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + gtk.MESSAGE_WARNING, + gtk.BUTTONS_OK, + _("Couldn't change the affinity of %(tid)d to %(affinity)s!") % \ + {"tid": tid, "affinity": affinity}) + dialog.run() + dialog.destroy() def drop_handler_move_threads_to_cpu(new_affinity, data): - pid_list = [ int(pid) for pid in data.split(",") ] + pid_list = [ int(pid) for pid in data.split(",") ] - return tuna.move_threads_to_cpu(new_affinity, pid_list, - set_affinity_warning) + return tuna.move_threads_to_cpu(new_affinity, pid_list, + set_affinity_warning) def drop_handler_move_irqs_to_cpu(cpus, data): - irq_list = [ int(irq) for irq in data.split(",") ] - new_affinity = [ reduce(lambda a, b: a | b, - [1 << cpu for cpu in cpus]), ] + irq_list = [ int(irq) for irq in data.split(",") ] + new_affinity = [ reduce(lambda a, b: a | b, + [1 << cpu for cpu in cpus]), ] - for irq in irq_list: - tuna.set_irq_affinity(irq, new_affinity) + for irq in irq_list: + tuna.set_irq_affinity(irq, new_affinity) - # FIXME: check if we really changed the affinity, but - # its only an optimization to avoid a needless refresh - # in the irqview, now we always refresh. - return True + # FIXME: check if we really changed the affinity, but + # its only an optimization to avoid a needless refresh + # in the irqview, now we always refresh. + return True class cpu_socket_frame(gtk.Frame): - ( COL_FILTER, COL_CPU, COL_USAGE ) = list(range(3)) - - def __init__(self, socket, cpus, creator): - - if creator.nr_sockets > 1: - gtk.Frame.__init__(self, _("Socket %s") % socket) - else: - gtk.Frame.__init__(self) - - self.socket = socket - self.cpus = cpus - self.nr_cpus = len(cpus) - self.creator = creator - - self.list_store = gtk.ListStore(gobject.TYPE_BOOLEAN, - gobject.TYPE_UINT, - gobject.TYPE_UINT) - - self.treeview = gtk.TreeView(self.list_store) - - # Filter column - renderer = gtk.CellRendererToggle() - renderer.connect('toggled', self.filter_toggled, self.list_store) - column = gtk.TreeViewColumn(_('Filter'), renderer, active = self.COL_FILTER) - self.treeview.append_column(column) - - # CPU# column - column = gtk.TreeViewColumn(_('CPU'), gtk.CellRendererText(), - text = self.COL_CPU) - self.treeview.append_column(column) - - # CPU usage column - try: - column = gtk.TreeViewColumn(_('Usage'), gtk.CellRendererProgress(), - text = self.COL_USAGE, value = self.COL_USAGE) - except: - # CellRendererProgress needs pygtk2 >= 2.6 - column = gtk.TreeViewColumn(_('Usage'), gtk.CellRendererText(), - text = self.COL_USAGE) - self.treeview.append_column(column) - - self.add(self.treeview) - - self.treeview.enable_model_drag_dest(gui.DND_TARGETS, - gtk.gdk.ACTION_DEFAULT) - self.treeview.connect("drag_data_received", - self.on_drag_data_received_data) - self.treeview.connect("button_press_event", - self.on_cpu_socket_frame_button_press_event) - - self.drop_handlers = { "pid": (drop_handler_move_threads_to_cpu, self.creator.procview), - "irq": (drop_handler_move_irqs_to_cpu, self.creator.irqview), } - - self.drag_dest_set(gtk.DEST_DEFAULT_ALL, gui.DND_TARGETS, - gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_MOVE) - self.connect("drag_data_received", - self.on_frame_drag_data_received_data) - - def on_frame_drag_data_received_data(self, w, context, x, y, - selection, info, etime): - # Move to all CPUs in this socket - cpus = [ int(cpu.name[3:]) for cpu in self.cpus ] - # pid list, a irq list, etc - source, data = selection.data.split(":") - - if source in self.drop_handlers: - if self.drop_handlers[source][0](cpus, data): - self.drop_handlers[source][1].refresh() - else: - print("cpu_socket_frame: unhandled drag source '%s'" % source) - - def on_drag_data_received_data(self, treeview, context, x, y, - selection, info, etime): - drop_info = treeview.get_dest_row_at_pos(x, y) - - # pid list, a irq list, etc - source, data = selection.data.split(":") - - if drop_info: - model = treeview.get_model() - path, position = drop_info - iter = model.get_iter(path) - cpus = [ model.get_value(iter, self.COL_CPU), ] - else: - # Move to all CPUs in this socket - cpus = [ int(cpu.name[3:]) for cpu in self.cpus ] - - if source in self.drop_handlers: - if self.drop_handlers[source][0](cpus, data): - self.drop_handlers[source][1].refresh() - else: - print("cpu_socket_frame: unhandled drag source '%s'" % source) - - def refresh(self): - self.list_store.clear() - for i in range(self.nr_cpus): - cpu = self.cpus[i] - cpunr = int(cpu.name[3:]) - usage = self.creator.cpustats[cpunr + 1].usage - - iter = self.list_store.append() - self.list_store.set(iter, - self.COL_FILTER, cpunr not in self.creator.cpus_filtered, - self.COL_CPU, cpunr, - self.COL_USAGE, int(usage)) - self.treeview.show_all() - - def isolate_cpu(self, a): - ret = self.treeview.get_path_at_pos(self.last_x, self.last_y) - if not ret: - return - path, col, xpos, ypos = ret - if not path: - return - row = self.list_store.get_iter(path) - cpu = self.list_store.get_value(row, self.COL_CPU) - - self.creator.isolate_cpus([cpu,]) - - def include_cpu(self, a): - ret = self.treeview.get_path_at_pos(self.last_x, self.last_y) - if not ret: - return - path, col, xpos, ypos = ret - if not path: - return - row = self.list_store.get_iter(path) - cpu = self.list_store.get_value(row, self.COL_CPU) - - self.creator.include_cpus([cpu,]) - - def restore_cpu(self, a): - - self.creator.restore_cpu() - - def isolate_cpu_socket(self, a): - - # Isolate all CPUs in this socket - cpus = [ int(cpu.name[3:]) for cpu in self.cpus ] - self.creator.isolate_cpus(cpus) - - def include_cpu_socket(self, a): - - # Include all CPUs in this socket - cpus = [ int(cpu.name[3:]) for cpu in self.cpus ] - self.creator.include_cpus(cpus) - - def on_cpu_socket_frame_button_press_event(self, treeview, event): - if event.type != gtk.gdk.BUTTON_PRESS or event.button != 3: - return - - self.last_x = int(event.x) - self.last_y = int(event.y) - - menu = gtk.Menu() - - include = gtk.MenuItem(_("I_nclude CPU")) - isolate = gtk.MenuItem(_("_Isolate CPU")) - if self.creator.nr_sockets > 1: - include_socket = gtk.MenuItem(_("I_nclude CPU Socket")) - isolate_socket = gtk.MenuItem(_("_Isolate CPU Socket")) - restore = gtk.MenuItem(_("_Restore CPU")) - - menu.add(include) - menu.add(isolate) - if self.creator.nr_sockets > 1: - menu.add(include_socket) - menu.add(isolate_socket) - menu.add(restore) - - include.connect_object('activate', self.include_cpu, event) - isolate.connect_object('activate', self.isolate_cpu, event) - if self.creator.nr_sockets > 1: - include_socket.connect_object('activate', self.include_cpu_socket, event) - isolate_socket.connect_object('activate', self.isolate_cpu_socket, event) - if not (self.creator.previous_pid_affinities or \ - self.creator.previous_irq_affinities): - restore.set_sensitive(False) - restore.connect_object('activate', self.restore_cpu, event) - - include.show() - isolate.show() - if self.creator.nr_sockets > 1: - include_socket.show() - isolate_socket.show() - restore.show() - - menu.popup(None, None, None, event.button, event.time) - - def filter_toggled(self, cell, path, model): - # get toggled iter - iter = model.get_iter((int(path),)) - enabled = model.get_value(iter, self.COL_FILTER) - cpu = model.get_value(iter, self.COL_CPU) - - enabled = not enabled - self.creator.toggle_mask_cpu(cpu, enabled) - - # set new value - model.set(iter, self.COL_FILTER, enabled) + ( COL_FILTER, COL_CPU, COL_USAGE ) = list(range(3)) + + def __init__(self, socket, cpus, creator): + + if creator.nr_sockets > 1: + gtk.Frame.__init__(self, _("Socket %s") % socket) + else: + gtk.Frame.__init__(self) + + self.socket = socket + self.cpus = cpus + self.nr_cpus = len(cpus) + self.creator = creator + + self.list_store = gtk.ListStore(gobject.TYPE_BOOLEAN, + gobject.TYPE_UINT, + gobject.TYPE_UINT) + + self.treeview = gtk.TreeView(self.list_store) + + # Filter column + renderer = gtk.CellRendererToggle() + renderer.connect('toggled', self.filter_toggled, self.list_store) + column = gtk.TreeViewColumn(_('Filter'), renderer, active = self.COL_FILTER) + self.treeview.append_column(column) + + # CPU# column + column = gtk.TreeViewColumn(_('CPU'), gtk.CellRendererText(), + text = self.COL_CPU) + self.treeview.append_column(column) + + # CPU usage column + try: + column = gtk.TreeViewColumn(_('Usage'), gtk.CellRendererProgress(), + text = self.COL_USAGE, value = self.COL_USAGE) + except: + # CellRendererProgress needs pygtk2 >= 2.6 + column = gtk.TreeViewColumn(_('Usage'), gtk.CellRendererText(), + text = self.COL_USAGE) + self.treeview.append_column(column) + + self.add(self.treeview) + + self.treeview.enable_model_drag_dest(gui.DND_TARGETS, + gtk.gdk.ACTION_DEFAULT) + self.treeview.connect("drag_data_received", + self.on_drag_data_received_data) + self.treeview.connect("button_press_event", + self.on_cpu_socket_frame_button_press_event) + + self.drop_handlers = { "pid": (drop_handler_move_threads_to_cpu, self.creator.procview), + "irq": (drop_handler_move_irqs_to_cpu, self.creator.irqview), } + + self.drag_dest_set(gtk.DEST_DEFAULT_ALL, gui.DND_TARGETS, + gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_MOVE) + self.connect("drag_data_received", + self.on_frame_drag_data_received_data) + + def on_frame_drag_data_received_data(self, w, context, x, y, + selection, info, etime): + # Move to all CPUs in this socket + cpus = [ int(cpu.name[3:]) for cpu in self.cpus ] + # pid list, a irq list, etc + source, data = selection.data.split(":") + + if source in self.drop_handlers: + if self.drop_handlers[source][0](cpus, data): + self.drop_handlers[source][1].refresh() + else: + print("cpu_socket_frame: unhandled drag source '%s'" % source) + + def on_drag_data_received_data(self, treeview, context, x, y, + selection, info, etime): + drop_info = treeview.get_dest_row_at_pos(x, y) + + # pid list, a irq list, etc + source, data = selection.data.split(":") + + if drop_info: + model = treeview.get_model() + path, position = drop_info + iter = model.get_iter(path) + cpus = [ model.get_value(iter, self.COL_CPU), ] + else: + # Move to all CPUs in this socket + cpus = [ int(cpu.name[3:]) for cpu in self.cpus ] + + if source in self.drop_handlers: + if self.drop_handlers[source][0](cpus, data): + self.drop_handlers[source][1].refresh() + else: + print("cpu_socket_frame: unhandled drag source '%s'" % source) + + def refresh(self): + self.list_store.clear() + for i in range(self.nr_cpus): + cpu = self.cpus[i] + cpunr = int(cpu.name[3:]) + usage = self.creator.cpustats[cpunr + 1].usage + + iter = self.list_store.append() + self.list_store.set(iter, + self.COL_FILTER, cpunr not in self.creator.cpus_filtered, + self.COL_CPU, cpunr, + self.COL_USAGE, int(usage)) + self.treeview.show_all() + + def isolate_cpu(self, a): + ret = self.treeview.get_path_at_pos(self.last_x, self.last_y) + if not ret: + return + path, col, xpos, ypos = ret + if not path: + return + row = self.list_store.get_iter(path) + cpu = self.list_store.get_value(row, self.COL_CPU) + + self.creator.isolate_cpus([cpu,]) + + def include_cpu(self, a): + ret = self.treeview.get_path_at_pos(self.last_x, self.last_y) + if not ret: + return + path, col, xpos, ypos = ret + if not path: + return + row = self.list_store.get_iter(path) + cpu = self.list_store.get_value(row, self.COL_CPU) + + self.creator.include_cpus([cpu,]) + + def restore_cpu(self, a): + + self.creator.restore_cpu() + + def isolate_cpu_socket(self, a): + + # Isolate all CPUs in this socket + cpus = [ int(cpu.name[3:]) for cpu in self.cpus ] + self.creator.isolate_cpus(cpus) + + def include_cpu_socket(self, a): + + # Include all CPUs in this socket + cpus = [ int(cpu.name[3:]) for cpu in self.cpus ] + self.creator.include_cpus(cpus) + + def on_cpu_socket_frame_button_press_event(self, treeview, event): + if event.type != gtk.gdk.BUTTON_PRESS or event.button != 3: + return + + self.last_x = int(event.x) + self.last_y = int(event.y) + + menu = gtk.Menu() + + include = gtk.MenuItem(_("I_nclude CPU")) + isolate = gtk.MenuItem(_("_Isolate CPU")) + if self.creator.nr_sockets > 1: + include_socket = gtk.MenuItem(_("I_nclude CPU Socket")) + isolate_socket = gtk.MenuItem(_("_Isolate CPU Socket")) + restore = gtk.MenuItem(_("_Restore CPU")) + + menu.add(include) + menu.add(isolate) + if self.creator.nr_sockets > 1: + menu.add(include_socket) + menu.add(isolate_socket) + menu.add(restore) + + include.connect_object('activate', self.include_cpu, event) + isolate.connect_object('activate', self.isolate_cpu, event) + if self.creator.nr_sockets > 1: + include_socket.connect_object('activate', self.include_cpu_socket, event) + isolate_socket.connect_object('activate', self.isolate_cpu_socket, event) + if not (self.creator.previous_pid_affinities or \ + self.creator.previous_irq_affinities): + restore.set_sensitive(False) + restore.connect_object('activate', self.restore_cpu, event) + + include.show() + isolate.show() + if self.creator.nr_sockets > 1: + include_socket.show() + isolate_socket.show() + restore.show() + + menu.popup(None, None, None, event.button, event.time) + + def filter_toggled(self, cell, path, model): + # get toggled iter + iter = model.get_iter((int(path),)) + enabled = model.get_value(iter, self.COL_FILTER) + cpu = model.get_value(iter, self.COL_CPU) + + enabled = not enabled + self.creator.toggle_mask_cpu(cpu, enabled) + + # set new value + model.set(iter, self.COL_FILTER, enabled) class cpuview: - def __init__(self, vpaned, hpaned, window, procview, irqview, cpus_filtered): - self.cpus = sysfs.cpus() - self.cpustats = procfs.cpusstats() - self.socket_frames = {} + def __init__(self, vpaned, hpaned, window, procview, irqview, cpus_filtered): + self.cpus = sysfs.cpus() + self.cpustats = procfs.cpusstats() + self.socket_frames = {} - self.procview = procview - self.irqview = irqview + self.procview = procview + self.irqview = irqview - vbox = window.get_child().get_child() + vbox = window.get_child().get_child() socket_ids = [] for id in list(self.cpus.sockets.keys()): try: socket_ids.append(int(id)) except TypeError: # Skip over offline cpus - type None continue - socket_ids.sort() - - self.nr_sockets = len(socket_ids) - if self.nr_sockets > 1: - columns = math.ceil(math.sqrt(self.nr_sockets)) - rows = math.ceil(self.nr_sockets / columns) - box = gtk.HBox() - vbox.pack_start(box, True, True) - else: - box = vbox - - column = 1 - for socket_id in socket_ids: - frame = cpu_socket_frame(socket_id, - self.cpus.sockets[str(socket_id)], - self) - box.pack_start(frame, False, False) - self.socket_frames[socket_id] = frame - if self.nr_sockets > 1: - if column == columns: - box = gtk.HBox() - vbox.pack_start(box, True, True) - column = 1 - else: - column += 1 - - window.show_all() - - self.cpus_filtered = cpus_filtered - self.refresh() - - self.previous_pid_affinities = None - self.previous_irq_affinities = None - - req = frame.size_request() - # FIXME: what is the slack we have - # to add to every row and column? - width = req[0] + 16 - height = req[1] + 20 - if self.nr_sockets > 1: - width *= columns - height *= rows - vpaned.set_position(int(height)) - hpaned.set_position(int(width)) - - self.timer = gobject.timeout_add(3000, self.refresh) - - def isolate_cpus(self, cpus): - self.previous_pid_affinities, \ - self.previous_irq_affinities = tuna.isolate_cpus(cpus, self.cpus.nr_cpus) - - if self.previous_pid_affinities: - self.procview.refresh() - - if self.previous_irq_affinities: - self.irqview.refresh() - - def include_cpus(self, cpus): - self.previous_pid_affinities, \ - self.previous_irq_affinities = tuna.include_cpus(cpus, self.cpus.nr_cpus) - - if self.previous_pid_affinities: - self.procview.refresh() - - if self.previous_irq_affinities: - self.irqview.refresh() - - def restore_cpu(self): - if not (self.previous_pid_affinities or \ - self.previous_irq_affinities): - return - affinities = self.previous_pid_affinities - for pid in list(affinities.keys()): - try: - schedutils.set_affinity(pid, affinities[pid]) - except: - pass - - affinities = self.previous_irq_affinities - for irq in list(affinities.keys()): - tuna.set_irq_affinity(int(irq), - procfs.hexbitmask(affinities[irq], - self.cpus.nr_cpus)) - - self.previous_pid_affinities = None - self.previous_irq_affinities = None - - def toggle_mask_cpu(self, cpu, enabled): - if enabled: - if cpu in self.cpus_filtered: - self.cpus_filtered.remove(cpu) - else: - if cpu not in self.cpus_filtered: - self.cpus_filtered.append(cpu) - - self.procview.toggle_mask_cpu(cpu, enabled) - self.irqview.toggle_mask_cpu(cpu, enabled) - - def refresh(self): - self.cpustats.reload() - for frame in list(self.socket_frames.keys()): - self.socket_frames[frame].refresh() - return True + socket_ids.sort() + + self.nr_sockets = len(socket_ids) + if self.nr_sockets > 1: + columns = math.ceil(math.sqrt(self.nr_sockets)) + rows = math.ceil(self.nr_sockets / columns) + box = gtk.HBox() + vbox.pack_start(box, True, True) + else: + box = vbox + + column = 1 + for socket_id in socket_ids: + frame = cpu_socket_frame(socket_id, + self.cpus.sockets[str(socket_id)], + self) + box.pack_start(frame, False, False) + self.socket_frames[socket_id] = frame + if self.nr_sockets > 1: + if column == columns: + box = gtk.HBox() + vbox.pack_start(box, True, True) + column = 1 + else: + column += 1 + + window.show_all() + + self.cpus_filtered = cpus_filtered + self.refresh() + + self.previous_pid_affinities = None + self.previous_irq_affinities = None + + req = frame.size_request() + # FIXME: what is the slack we have + # to add to every row and column? + width = req[0] + 16 + height = req[1] + 20 + if self.nr_sockets > 1: + width *= columns + height *= rows + vpaned.set_position(int(height)) + hpaned.set_position(int(width)) + + self.timer = gobject.timeout_add(3000, self.refresh) + + def isolate_cpus(self, cpus): + self.previous_pid_affinities, \ + self.previous_irq_affinities = tuna.isolate_cpus(cpus, self.cpus.nr_cpus) + + if self.previous_pid_affinities: + self.procview.refresh() + + if self.previous_irq_affinities: + self.irqview.refresh() + + def include_cpus(self, cpus): + self.previous_pid_affinities, \ + self.previous_irq_affinities = tuna.include_cpus(cpus, self.cpus.nr_cpus) + + if self.previous_pid_affinities: + self.procview.refresh() + + if self.previous_irq_affinities: + self.irqview.refresh() + + def restore_cpu(self): + if not (self.previous_pid_affinities or \ + self.previous_irq_affinities): + return + affinities = self.previous_pid_affinities + for pid in list(affinities.keys()): + try: + schedutils.set_affinity(pid, affinities[pid]) + except: + pass + + affinities = self.previous_irq_affinities + for irq in list(affinities.keys()): + tuna.set_irq_affinity(int(irq), + procfs.hexbitmask(affinities[irq], + self.cpus.nr_cpus)) + + self.previous_pid_affinities = None + self.previous_irq_affinities = None + + def toggle_mask_cpu(self, cpu, enabled): + if enabled: + if cpu in self.cpus_filtered: + self.cpus_filtered.remove(cpu) + else: + if cpu not in self.cpus_filtered: + self.cpus_filtered.append(cpu) + + self.procview.toggle_mask_cpu(cpu, enabled) + self.irqview.toggle_mask_cpu(cpu, enabled) + + def refresh(self): + self.cpustats.reload() + for frame in list(self.socket_frames.keys()): + self.socket_frames[frame].refresh() + return True diff --git a/tuna/oscilloscope.py b/tuna/oscilloscope.py index 34f51aa..b26f903 100755 --- a/tuna/oscilloscope.py +++ b/tuna/oscilloscope.py @@ -25,432 +25,432 @@ import gobject, gtk, os, sys from matplotlib.backends.backend_gtkagg import \ - FigureCanvasGTKAgg as figure_canvas + FigureCanvasGTKAgg as figure_canvas import matplotlib.figure, matplotlib.ticker, numpy class histogram_frame(gtk.Frame): - def __init__(self, title = "Statistics", width = 780, height = 100, - max_value = 500, nr_entries = 10, - facecolor = "white"): - gtk.Frame.__init__(self, title) - - self.fraction = int(max_value / nr_entries) - if self.fraction == 0: - self.fraction = max_value - nr_entries = 1 - self.max_value = max_value - self.nr_entries = nr_entries - self.nr_samples = 0 - - table = gtk.Table(3, self.nr_entries + 1, False) - table.set_border_width(5) - table.set_row_spacings(5) - table.set_col_spacings(10) - self.add(table) - self.buckets = [ 0, ] * (nr_entries + 1) - self.buckets_bar = [ None, ] * (nr_entries + 1) - self.buckets_counter = [ None, ] * (nr_entries + 1) - - prefix = "<=" - for bucket in range(self.nr_entries + 1): - bucket_range = (bucket + 1) * self.fraction - if bucket_range > self.max_value: - prefix = ">" - bucket_range = self.max_value - - label = gtk.Label("%s %d" % (prefix, bucket_range)) - label.set_alignment(0, 1) - table.attach(label, 0, 1, bucket, bucket + 1, 0, 0, 0, 0) - - self.buckets_bar[bucket] = gtk.ProgressBar() - table.attach(self.buckets_bar[bucket], 1, 2, bucket, bucket + 1, 0, 0, 0, 0) - - self.buckets_counter[bucket] = gtk.Label("0") - label.set_alignment(0, 1) - table.attach(self.buckets_counter[bucket], 2, 3, bucket, bucket + 1, 0, 0, 0, 0) - - self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(facecolor)) - - def add_sample(self, sample): - if sample > self.max_value: - bucket = self.nr_entries - else: - bucket = int(sample / self.fraction) - self.nr_samples += 1 - self.buckets[bucket] += 1 - - def refresh(self): - for bucket in range(self.nr_entries + 1): - self.buckets_counter[bucket].set_text(str(self.buckets[bucket])) - fraction = float(self.buckets[bucket]) / self.nr_samples - self.buckets_bar[bucket].set_fraction(fraction) - - def reset(self): - self.buckets = [ 0, ] * (self.nr_entries + 1) - self.nr_samples = 0 + def __init__(self, title = "Statistics", width = 780, height = 100, + max_value = 500, nr_entries = 10, + facecolor = "white"): + gtk.Frame.__init__(self, title) + + self.fraction = int(max_value / nr_entries) + if self.fraction == 0: + self.fraction = max_value + nr_entries = 1 + self.max_value = max_value + self.nr_entries = nr_entries + self.nr_samples = 0 + + table = gtk.Table(3, self.nr_entries + 1, False) + table.set_border_width(5) + table.set_row_spacings(5) + table.set_col_spacings(10) + self.add(table) + self.buckets = [ 0, ] * (nr_entries + 1) + self.buckets_bar = [ None, ] * (nr_entries + 1) + self.buckets_counter = [ None, ] * (nr_entries + 1) + + prefix = "<=" + for bucket in range(self.nr_entries + 1): + bucket_range = (bucket + 1) * self.fraction + if bucket_range > self.max_value: + prefix = ">" + bucket_range = self.max_value + + label = gtk.Label("%s %d" % (prefix, bucket_range)) + label.set_alignment(0, 1) + table.attach(label, 0, 1, bucket, bucket + 1, 0, 0, 0, 0) + + self.buckets_bar[bucket] = gtk.ProgressBar() + table.attach(self.buckets_bar[bucket], 1, 2, bucket, bucket + 1, 0, 0, 0, 0) + + self.buckets_counter[bucket] = gtk.Label("0") + label.set_alignment(0, 1) + table.attach(self.buckets_counter[bucket], 2, 3, bucket, bucket + 1, 0, 0, 0, 0) + + self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(facecolor)) + + def add_sample(self, sample): + if sample > self.max_value: + bucket = self.nr_entries + else: + bucket = int(sample / self.fraction) + self.nr_samples += 1 + self.buckets[bucket] += 1 + + def refresh(self): + for bucket in range(self.nr_entries + 1): + self.buckets_counter[bucket].set_text(str(self.buckets[bucket])) + fraction = float(self.buckets[bucket]) / self.nr_samples + self.buckets_bar[bucket].set_fraction(fraction) + + def reset(self): + self.buckets = [ 0, ] * (self.nr_entries + 1) + self.nr_samples = 0 class oscilloscope_frame(gtk.Frame): - def __init__(self, title = "Osciloscope", width = 780, height = 360, - nr_samples_on_screen = 250, graph_type = '-', - max_value = 500, plot_color = "lightgreen", - bg_color = "darkgreen", facecolor = "white", - ylabel = "Latency", picker = None): - - gtk.Frame.__init__(self, title) - - self.font = { 'fontname' : 'Liberation Sans', - 'color' : 'b', - 'fontweight' : 'bold', - 'fontsize' : 10 } - - self.max_value = max_value - self.nr_samples_on_screen = nr_samples_on_screen - self.ind = numpy.arange(nr_samples_on_screen) - self.samples = [ 0.0 ] * nr_samples_on_screen - - figure = matplotlib.figure.Figure(figsize = (10, 4), dpi = 100, - facecolor = facecolor) - ax = figure.add_subplot(111) - self.ax = ax - ax.set_axis_bgcolor(bg_color) - - self.on_screen_samples = ax.plot(self.ind, self.samples, graph_type, - color = plot_color, - picker = picker) - - ax.set_ylim(0, max_value) - ax.set_ylabel(ylabel, self.font) - ax.set_xlabel("%d samples" % nr_samples_on_screen, self.font) - ax.set_xticklabels([]) - ax.grid(True) - - for label in ax.get_yticklabels(): - label.set(fontsize = 8) - - self.canvas = figure_canvas(figure) # a gtk.DrawingArea - self.canvas.set_size_request(width, height) - - self.add(self.canvas) - self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(facecolor)) - self.nr_samples = 0 - - def add_sample(self, sample): - del self.samples[0] - self.samples.append(sample) - self.on_screen_samples[0].set_data(self.ind, self.samples) - self.nr_samples += 1 - if self.nr_samples <= self.nr_samples_on_screen: - self.ax.set_xlabel("%d samples" % self.nr_samples, self.font) - - def reset(self): - self.samples = [ 0.0 ] * self.nr_samples_on_screen - self.nr_samples = 0 - self.on_screen_samples[0].set_data(self.ind, self.samples) - - def refresh(self): - self.canvas.draw() - return + def __init__(self, title = "Osciloscope", width = 780, height = 360, + nr_samples_on_screen = 250, graph_type = '-', + max_value = 500, plot_color = "lightgreen", + bg_color = "darkgreen", facecolor = "white", + ylabel = "Latency", picker = None): + + gtk.Frame.__init__(self, title) + + self.font = { 'fontname' : 'Liberation Sans', + 'color' : 'b', + 'fontweight' : 'bold', + 'fontsize' : 10 } + + self.max_value = max_value + self.nr_samples_on_screen = nr_samples_on_screen + self.ind = numpy.arange(nr_samples_on_screen) + self.samples = [ 0.0 ] * nr_samples_on_screen + + figure = matplotlib.figure.Figure(figsize = (10, 4), dpi = 100, + facecolor = facecolor) + ax = figure.add_subplot(111) + self.ax = ax + ax.set_axis_bgcolor(bg_color) + + self.on_screen_samples = ax.plot(self.ind, self.samples, graph_type, + color = plot_color, + picker = picker) + + ax.set_ylim(0, max_value) + ax.set_ylabel(ylabel, self.font) + ax.set_xlabel("%d samples" % nr_samples_on_screen, self.font) + ax.set_xticklabels([]) + ax.grid(True) + + for label in ax.get_yticklabels(): + label.set(fontsize = 8) + + self.canvas = figure_canvas(figure) # a gtk.DrawingArea + self.canvas.set_size_request(width, height) + + self.add(self.canvas) + self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(facecolor)) + self.nr_samples = 0 + + def add_sample(self, sample): + del self.samples[0] + self.samples.append(sample) + self.on_screen_samples[0].set_data(self.ind, self.samples) + self.nr_samples += 1 + if self.nr_samples <= self.nr_samples_on_screen: + self.ax.set_xlabel("%d samples" % self.nr_samples, self.font) + + def reset(self): + self.samples = [ 0.0 ] * self.nr_samples_on_screen + self.nr_samples = 0 + self.on_screen_samples[0].set_data(self.ind, self.samples) + + def refresh(self): + self.canvas.draw() + return def add_table_row(table, row, label_text, label_value = "0"): - label = gtk.Label(label_text) - label.set_use_underline(True) - label.set_alignment(0, 1) - table.attach(label, 0, 1, row, row + 1, 0, 0, 0, 0) + label = gtk.Label(label_text) + label.set_use_underline(True) + label.set_alignment(0, 1) + table.attach(label, 0, 1, row, row + 1, 0, 0, 0, 0) - label = gtk.Label(label_value) - table.attach(label, 1, 2, row, row + 1, 0, 0, 0, 0) - return label + label = gtk.Label(label_value) + table.attach(label, 1, 2, row, row + 1, 0, 0, 0, 0) + return label class system_info_frame(gtk.Frame): - def __init__(self, title = "System", facecolor = "white"): - gtk.Frame.__init__(self, title) + def __init__(self, title = "System", facecolor = "white"): + gtk.Frame.__init__(self, title) - self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(facecolor)) + self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(facecolor)) - table = gtk.Table(3, 2, False) - table.set_border_width(5) - table.set_row_spacings(5) - table.set_col_spacings(10) - self.add(table) + table = gtk.Table(3, 2, False) + table.set_border_width(5) + table.set_row_spacings(5) + table.set_col_spacings(10) + self.add(table) - u = os.uname() - add_table_row(table, 0, "Kernel Release", u[2]) - add_table_row(table, 1, "Architecture", u[4]) - add_table_row(table, 2, "Machine", u[1]) + u = os.uname() + add_table_row(table, 0, "Kernel Release", u[2]) + add_table_row(table, 1, "Architecture", u[4]) + add_table_row(table, 2, "Machine", u[1]) class oscilloscope(gtk.Window): - def __init__(self, get_sample = None, width = 800, height = 500, - nr_samples_on_screen = 250, - graph_type = '-', title = "Osciloscope", - max_value = 500, plot_color = "lightgreen", - bg_color = "darkgreen", facecolor = "white", - ylabel = "Latency", - picker = None, - snapshot_samples = 0, - geometry = None, scale = True): - - gtk.Window.__init__(self) - if geometry: - self.parse_geometry(geometry) - width, height = self.get_size() - else: - self.set_default_size(width, height) - - self.get_sample = get_sample - self.max_value = max_value - self.snapshot_samples = snapshot_samples - self.scale = scale - - self.set_title(title) - - vbox = gtk.VBox() - vbox.set_border_width(8) - self.add(vbox) - - stats_frame = gtk.Frame("Statistics") - stats_frame.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(facecolor)) - - table = gtk.Table(3, 2, False) - table.set_border_width(5) - table.set_row_spacings(5) - table.set_col_spacings(10) - stats_frame.add(table) - - self.min_label = add_table_row(table, 0, "Min") - self.avg_label = add_table_row(table, 1, "Avg") - self.max_label = add_table_row(table, 2, "Max") - - help_frame = gtk.Frame("Help") - help_frame.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(facecolor)) - - table = gtk.Table(4, 2, False) - table.set_border_width(5) - table.set_row_spacings(5) - table.set_col_spacings(10) - help_frame.add(table) - - add_table_row(table, 0, "Space", "Pause") - add_table_row(table, 1, "S", "Snapshot") - add_table_row(table, 2, "R", "Reset") - add_table_row(table, 3, "Q", "Quit") - - self.scope = oscilloscope_frame("Scope", - int(width * 0.94), - int(height * 0.64), - nr_samples_on_screen, - max_value = max_value, - graph_type = graph_type, - picker = picker, - ylabel = ylabel) - - self.hist = histogram_frame("Histogram", 0, 0, nr_entries = 5, - max_value = max_value) - - info_frame = system_info_frame() - - vbox_help_info = gtk.VBox() - vbox_help_info.pack_start(info_frame, False, False) - vbox_help_info.pack_end(help_frame, False, False) - hbox = gtk.HBox() - hbox.pack_start(vbox_help_info, False, False) - hbox.pack_start(stats_frame, False, False) - hbox.pack_end(self.hist, True, True) - - vbox.pack_start(self.scope, True, True) - vbox.pack_end(hbox, True, False) - - self.show_all() - - self.getting_samples = False - self.refreshing_screen = False - self.max = self.min = None - self.avg = 0 - - def add_sample(self, sample): - if not self.max or self.max < sample: - self.max = sample - - if not self.min or self.min > sample: - self.min = sample - - self.avg = (self.avg + sample) / 2 - self.scope.add_sample(sample) - self.hist.add_sample(sample) - - def refresh(self): - if self.scale and self.max > self.scope.max_value: - self.scope.max_value *= 2 - self.scope.ax.set_ylim(0, self.scope.max_value) - self.scope.refresh() - self.hist.refresh() - while gtk.events_pending(): - gtk.main_iteration() - - def get_samples(self, fd, condition): - try: - sample = self.get_sample() - prev_min, prev_avg, prev_max = self.min, self.avg, self.max - - self.add_sample(sample) - - if self.refreshing_screen: - if self.min != prev_min: - self.min_label.set_text("%-6.3f" % self.min) - if self.avg != prev_avg: - self.avg_label.set_text("%-6.3f" % self.avg) - if self.max != prev_max: - self.max_label.set_text("%-6.3f" % self.max) - - self.refresh() - - if self.snapshot_samples == self.scope.nr_samples: - self.snapshot() - gtk.main_quit() - except: - print("invalid sample, check the input format") - pass - return self.getting_samples - - def run(self, fd): - self.connect("key_press_event", self.key_press_event) - self.getting_samples = True - self.refreshing_screen = True - gobject.io_add_watch(fd, gobject.IO_IN | gobject.IO_PRI, - self.get_samples) - - def freeze_screen(self, state = False): - self.refreshing_screen = state - - def stop(self): - self.getting_samples = False - self.refreshing_screen = False - - def snapshot(self): - self.scope.canvas.print_figure("scope_snapshot.svg") - - def reset(self): - self.scope.max_value = self.max_value - self.scope.ax.set_ylim(0, self.scope.max_value) - self.scope.reset() - self.hist.reset() - self.min = self.max_value - self.max = 0 - self.avg = 0 - - def key_press_event(self, widget, event): - if event.keyval == ord(' '): - self.freeze_screen(not self.refreshing_screen) - elif event.keyval in (ord('s'), ord('S')): - self.snapshot() - elif event.keyval in (ord('r'), ord('R')): - self.reset() - elif event.keyval in (ord('q'), ord('Q')): - gtk.main_quit() + def __init__(self, get_sample = None, width = 800, height = 500, + nr_samples_on_screen = 250, + graph_type = '-', title = "Osciloscope", + max_value = 500, plot_color = "lightgreen", + bg_color = "darkgreen", facecolor = "white", + ylabel = "Latency", + picker = None, + snapshot_samples = 0, + geometry = None, scale = True): + + gtk.Window.__init__(self) + if geometry: + self.parse_geometry(geometry) + width, height = self.get_size() + else: + self.set_default_size(width, height) + + self.get_sample = get_sample + self.max_value = max_value + self.snapshot_samples = snapshot_samples + self.scale = scale + + self.set_title(title) + + vbox = gtk.VBox() + vbox.set_border_width(8) + self.add(vbox) + + stats_frame = gtk.Frame("Statistics") + stats_frame.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(facecolor)) + + table = gtk.Table(3, 2, False) + table.set_border_width(5) + table.set_row_spacings(5) + table.set_col_spacings(10) + stats_frame.add(table) + + self.min_label = add_table_row(table, 0, "Min") + self.avg_label = add_table_row(table, 1, "Avg") + self.max_label = add_table_row(table, 2, "Max") + + help_frame = gtk.Frame("Help") + help_frame.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(facecolor)) + + table = gtk.Table(4, 2, False) + table.set_border_width(5) + table.set_row_spacings(5) + table.set_col_spacings(10) + help_frame.add(table) + + add_table_row(table, 0, "Space", "Pause") + add_table_row(table, 1, "S", "Snapshot") + add_table_row(table, 2, "R", "Reset") + add_table_row(table, 3, "Q", "Quit") + + self.scope = oscilloscope_frame("Scope", + int(width * 0.94), + int(height * 0.64), + nr_samples_on_screen, + max_value = max_value, + graph_type = graph_type, + picker = picker, + ylabel = ylabel) + + self.hist = histogram_frame("Histogram", 0, 0, nr_entries = 5, + max_value = max_value) + + info_frame = system_info_frame() + + vbox_help_info = gtk.VBox() + vbox_help_info.pack_start(info_frame, False, False) + vbox_help_info.pack_end(help_frame, False, False) + hbox = gtk.HBox() + hbox.pack_start(vbox_help_info, False, False) + hbox.pack_start(stats_frame, False, False) + hbox.pack_end(self.hist, True, True) + + vbox.pack_start(self.scope, True, True) + vbox.pack_end(hbox, True, False) + + self.show_all() + + self.getting_samples = False + self.refreshing_screen = False + self.max = self.min = None + self.avg = 0 + + def add_sample(self, sample): + if not self.max or self.max < sample: + self.max = sample + + if not self.min or self.min > sample: + self.min = sample + + self.avg = (self.avg + sample) / 2 + self.scope.add_sample(sample) + self.hist.add_sample(sample) + + def refresh(self): + if self.scale and self.max > self.scope.max_value: + self.scope.max_value *= 2 + self.scope.ax.set_ylim(0, self.scope.max_value) + self.scope.refresh() + self.hist.refresh() + while gtk.events_pending(): + gtk.main_iteration() + + def get_samples(self, fd, condition): + try: + sample = self.get_sample() + prev_min, prev_avg, prev_max = self.min, self.avg, self.max + + self.add_sample(sample) + + if self.refreshing_screen: + if self.min != prev_min: + self.min_label.set_text("%-6.3f" % self.min) + if self.avg != prev_avg: + self.avg_label.set_text("%-6.3f" % self.avg) + if self.max != prev_max: + self.max_label.set_text("%-6.3f" % self.max) + + self.refresh() + + if self.snapshot_samples == self.scope.nr_samples: + self.snapshot() + gtk.main_quit() + except: + print("invalid sample, check the input format") + pass + return self.getting_samples + + def run(self, fd): + self.connect("key_press_event", self.key_press_event) + self.getting_samples = True + self.refreshing_screen = True + gobject.io_add_watch(fd, gobject.IO_IN | gobject.IO_PRI, + self.get_samples) + + def freeze_screen(self, state = False): + self.refreshing_screen = state + + def stop(self): + self.getting_samples = False + self.refreshing_screen = False + + def snapshot(self): + self.scope.canvas.print_figure("scope_snapshot.svg") + + def reset(self): + self.scope.max_value = self.max_value + self.scope.ax.set_ylim(0, self.scope.max_value) + self.scope.reset() + self.hist.reset() + self.min = self.max_value + self.max = 0 + self.avg = 0 + + def key_press_event(self, widget, event): + if event.keyval == ord(' '): + self.freeze_screen(not self.refreshing_screen) + elif event.keyval in (ord('s'), ord('S')): + self.snapshot() + elif event.keyval in (ord('r'), ord('R')): + self.reset() + elif event.keyval in (ord('q'), ord('Q')): + gtk.main_quit() class ftrace_window(gtk.Window): - (COL_FUNCTION, ) = list(range(1)) + (COL_FUNCTION, ) = list(range(1)) - def __init__(self, trace, parent = None): - gtk.Window.__init__(self) - try: - self.set_screen(parent.get_screen()) - except AttributeError: - self.connect('destroy', lambda *w: gtk.main_quit()) + def __init__(self, trace, parent = None): + gtk.Window.__init__(self) + try: + self.set_screen(parent.get_screen()) + except AttributeError: + self.connect('destroy', lambda *w: gtk.main_quit()) - self.set_border_width(8) - self.set_default_size(350, 500) - self.set_title("ftrace") + self.set_border_width(8) + self.set_default_size(350, 500) + self.set_title("ftrace") - vbox = gtk.VBox(False, 8) - self.add(vbox) + vbox = gtk.VBox(False, 8) + self.add(vbox) - sw = gtk.ScrolledWindow() - sw.set_shadow_type(gtk.SHADOW_ETCHED_IN) - sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) - vbox.pack_start(sw, True, True) + sw = gtk.ScrolledWindow() + sw.set_shadow_type(gtk.SHADOW_ETCHED_IN) + sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) + vbox.pack_start(sw, True, True) - store = gtk.ListStore(gobject.TYPE_STRING) + store = gtk.ListStore(gobject.TYPE_STRING) - for entry in trace: - if entry[0] in [ "#", "\n" ] or entry[:4] == "vim:": - continue - iter = store.append() - store.set(iter, self.COL_FUNCTION, entry.strip()) + for entry in trace: + if entry[0] in [ "#", "\n" ] or entry[:4] == "vim:": + continue + iter = store.append() + store.set(iter, self.COL_FUNCTION, entry.strip()) - treeview = gtk.TreeView(store) - treeview.set_rules_hint(True) + treeview = gtk.TreeView(store) + treeview.set_rules_hint(True) - column = gtk.TreeViewColumn("Function", gtk.CellRendererText(), - text = self.COL_FUNCTION) - treeview.append_column(column) + column = gtk.TreeViewColumn("Function", gtk.CellRendererText(), + text = self.COL_FUNCTION) + treeview.append_column(column) - sw.add(treeview) - self.show_all() + sw.add(treeview) + self.show_all() class cyclictestoscope(oscilloscope): - def __init__(self, max_value, snapshot_samples = 0, nr_samples_on_screen = 500, - delimiter = ':', field = 2, ylabel = "Latency", - geometry = None, scale = True, sample_multiplier = 1): - oscilloscope.__init__(self, self.get_sample, - title = "CyclictestoSCOPE", - nr_samples_on_screen = nr_samples_on_screen, - width = 900, max_value = max_value, - picker = self.scope_picker, - snapshot_samples = snapshot_samples, - ylabel = ylabel, geometry = geometry, - scale = scale) - - self.connect("destroy", self.quit) - self.delimiter = delimiter - self.sample_multiplier = sample_multiplier - self.field = field - self.latency_tracer = os.access("/sys/kernel/debug/tracing/trace", os.R_OK) - if self.latency_tracer: - self.traces = [ None, ] * nr_samples_on_screen - - def scope_picker(self, line, mouseevent): - if (not self.latency_tracer) or mouseevent.xdata is None: - return False, dict() - - x = int(mouseevent.xdata) - if self.traces[x]: - fw = ftrace_window(self.traces[x], self) - return False, dict() - - def get_sample(self): - fields = sys.stdin.readline().split(self.delimiter) - try: - sample = float(fields[self.field]) * self.sample_multiplier - except: - print("fields=%s, self.field=%s,self.delimiter=%s" % (fields, self.field, self.delimiter)) - return None - - if self.latency_tracer: - del self.traces[0] - if sample > self.avg: - print(sample) - try: - f = open("/sys/kernel/debug/tracing/trace") - trace = f.readlines() - f.close() - f = open("/sys/kernel/debug/tracing/tracing_max_latency", "w") - f.write("0\n") - f.close() - except: - trace = None - else: - print("-") - trace = None - - self.traces.append(trace) - - return sample - - def run(self): - oscilloscope.run(self, sys.stdin.fileno()) - - def quit(self, x): - gtk.main_quit() + def __init__(self, max_value, snapshot_samples = 0, nr_samples_on_screen = 500, + delimiter = ':', field = 2, ylabel = "Latency", + geometry = None, scale = True, sample_multiplier = 1): + oscilloscope.__init__(self, self.get_sample, + title = "CyclictestoSCOPE", + nr_samples_on_screen = nr_samples_on_screen, + width = 900, max_value = max_value, + picker = self.scope_picker, + snapshot_samples = snapshot_samples, + ylabel = ylabel, geometry = geometry, + scale = scale) + + self.connect("destroy", self.quit) + self.delimiter = delimiter + self.sample_multiplier = sample_multiplier + self.field = field + self.latency_tracer = os.access("/sys/kernel/debug/tracing/trace", os.R_OK) + if self.latency_tracer: + self.traces = [ None, ] * nr_samples_on_screen + + def scope_picker(self, line, mouseevent): + if (not self.latency_tracer) or mouseevent.xdata is None: + return False, dict() + + x = int(mouseevent.xdata) + if self.traces[x]: + fw = ftrace_window(self.traces[x], self) + return False, dict() + + def get_sample(self): + fields = sys.stdin.readline().split(self.delimiter) + try: + sample = float(fields[self.field]) * self.sample_multiplier + except: + print("fields=%s, self.field=%s,self.delimiter=%s" % (fields, self.field, self.delimiter)) + return None + + if self.latency_tracer: + del self.traces[0] + if sample > self.avg: + print(sample) + try: + f = open("/sys/kernel/debug/tracing/trace") + trace = f.readlines() + f.close() + f = open("/sys/kernel/debug/tracing/tracing_max_latency", "w") + f.write("0\n") + f.close() + except: + trace = None + else: + print("-") + trace = None + + self.traces.append(trace) + + return sample + + def run(self): + oscilloscope.run(self, sys.stdin.fileno()) + + def quit(self, x): + gtk.main_quit() |