summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Kacur <jkacur@redhat.com>2020-08-01 02:30:51 -0400
committerJohn Kacur <jkacur@redhat.com>2020-08-01 02:30:51 -0400
commitc003f25438af2caaa6d6beea38fdd5de02075bcf (patch)
tree8bb7ddb056ad7e1867e84e7051b11cd90fa6ad5a
parent04eee9a483bafc8ca6099f5b9c6bb0a6d27d7277 (diff)
downloadtuna-c003f25438af2caaa6d6beea38fdd5de02075bcf.tar.gz
tuna: procview.py: Update the spacing and style
Update the spacing and style. Signed-off-by: John Kacur <jkacur@redhat.com>
-rwxr-xr-xtuna/gui/procview.py1333
1 files changed, 661 insertions, 672 deletions
diff --git a/tuna/gui/procview.py b/tuna/gui/procview.py
index 62ba9cf..fa70ab4 100755
--- a/tuna/gui/procview.py
+++ b/tuna/gui/procview.py
@@ -9,686 +9,675 @@ import re
import schedutils
try:
- import perf
+ import perf
except:
- pass
+ pass
def N_(s):
- """gettext_noop"""
- return s
+ """gettext_noop"""
+ return s
class process_druid:
- ( PROCESS_COL_PID, PROCESS_COL_NAME ) = list(range(2))
-
- def __init__(self, ps, pid, pid_info, nr_cpus, gladefile):
- self.ps = ps
- self.pid = pid
- self.pid_info = pid_info
- self.nr_cpus = nr_cpus
- self.window = Gtk.glade.XML(gladefile, "set_process_attributes", "tuna")
- self.dialog = self.window.get_widget("set_process_attributes")
- pixbuf = self.dialog.render_icon(Gtk.STOCK_PREFERENCES,
- Gtk.IconSize.SMALL_TOOLBAR)
- self.dialog.set_icon(pixbuf)
- event_handlers = { "on_cmdline_regex_changed" : self.on_cmdline_regex_changed,
- "on_affinity_text_changed" : self.on_affinity_text_changed,
- "on_sched_policy_combo_changed" : self.on_sched_policy_combo_changed,
- "on_command_regex_clicked" : self.on_command_regex_clicked,
- "on_all_these_threads_clicked" : self.on_all_these_threads_clicked,
- "on_just_this_thread_clicked" : self.on_just_this_thread_clicked }
- self.window.signal_autoconnect(event_handlers)
-
- self.sched_pri = self.window.get_widget("sched_pri_spin")
- self.sched_policy = self.window.get_widget("sched_policy_combo")
- self.regex_edit = self.window.get_widget("cmdline_regex")
- self.affinity = self.window.get_widget("affinity_text")
- self.just_this_thread = self.window.get_widget("just_this_thread")
- self.all_these_threads = self.window.get_widget("all_these_threads")
- processes = self.window.get_widget("matching_process_list")
-
- self.sched_pri.set_value(int(pid_info["stat"]["rt_priority"]))
- cmdline_regex = procfs.process_cmdline(pid_info)
- self.affinity_text = tuna.list_to_cpustring(schedutils.get_affinity(pid))
- self.affinity.set_text(self.affinity_text)
- self.create_matching_process_model(processes)
- self.create_policy_model(self.sched_policy)
- self.sched_policy.set_active(schedutils.get_scheduler(pid))
- self.regex_edit.set_text(cmdline_regex)
- self.just_this_thread.set_active(True)
- self.regex_edit.set_sensitive(False)
- if pid not in ps or "threads" not in ps[pid]:
- self.all_these_threads.hide()
- self.on_just_this_thread_clicked(None)
-
- def refresh_match_pids(self, cmdline_regex):
- self.process_list_store.clear()
- for match_pid in self.ps.find_by_cmdline_regex(cmdline_regex):
- info = self.process_list_store.append()
- pid_info = self.ps[match_pid]
- cmdline = procfs.process_cmdline(pid_info)
- self.process_list_store.set(info, self.PROCESS_COL_PID, match_pid,
- self.PROCESS_COL_NAME,
- cmdline)
-
- def create_matching_process_model(self, processes):
- labels = [ "PID", "Name" ]
-
- self.process_list_store = Gtk.ListStore(GObject.TYPE_UINT,
- GObject.TYPE_STRING)
- renderer = Gtk.CellRendererText()
-
- for col in range(len(labels)):
- column = Gtk.TreeViewColumn(labels[col], renderer, text = col)
- column.set_sort_column_id(col)
- processes.append_column(column)
-
- processes.set_model(self.process_list_store)
-
- def create_policy_model(self, policy):
- ( COL_TEXT, COL_SCHED ) = list(range(2))
- list_store = Gtk.ListStore(GObject.TYPE_STRING,
- GObject.TYPE_UINT)
- renderer = Gtk.CellRendererText()
- policy.pack_start(renderer, True)
- policy.add_attribute(renderer, "text", COL_TEXT)
- for pol in range(4):
- row = list_store.append()
- list_store.set(row, COL_TEXT, schedutils.schedstr(pol),
- COL_SCHED, pol)
- policy.set_model(list_store)
-
- def on_cmdline_regex_changed(self, entry):
- process_regex_text = entry.get_text()
- try:
- cmdline_regex = re.compile(process_regex_text)
- except:
- self.process_list_store.clear()
- return
- self.refresh_match_pids(cmdline_regex)
-
- def on_just_this_thread_clicked(self, button):
- self.regex_edit.set_sensitive(False)
- self.process_list_store.clear()
- info = self.process_list_store.append()
- cmdline = procfs.process_cmdline(self.pid_info)
- self.process_list_store.set(info,
- self.PROCESS_COL_PID, self.pid,
- self.PROCESS_COL_NAME, cmdline)
-
- def on_command_regex_clicked(self, button):
- self.regex_edit.set_sensitive(True)
- self.on_cmdline_regex_changed(self.regex_edit)
-
- def on_all_these_threads_clicked(self, button):
- self.regex_edit.set_sensitive(False)
- self.process_list_store.clear()
- info = self.process_list_store.append()
- cmdline = procfs.process_cmdline(self.ps[self.pid])
- self.process_list_store.set(info,
- self.PROCESS_COL_PID, self.pid,
- self.PROCESS_COL_NAME, cmdline)
- for tid in list(self.ps[self.pid]["threads"].keys()):
- child = self.process_list_store.append()
- self.process_list_store.set(child,
- self.PROCESS_COL_PID, tid,
- self.PROCESS_COL_NAME, cmdline)
-
-
- def on_sched_policy_combo_changed(self, button):
- new_policy = self.sched_policy.get_active()
- if new_policy in ( schedutils.SCHED_FIFO, schedutils.SCHED_RR ):
- can_change_pri = True
- else:
- can_change_pri = False
- self.sched_pri.set_sensitive(can_change_pri)
-
- def on_affinity_text_changed(self, button):
- gui.on_affinity_text_changed(self)
-
- def set_attributes_for_regex(self, regex, new_policy, new_prio, new_affinity):
- changed = False
- cmdline_regex = re.compile(regex)
- for match_pid in self.ps.find_by_cmdline_regex(cmdline_regex):
- if gui.thread_set_attributes(self.ps[match_pid],
- new_policy, new_prio,
- new_affinity,
- self.nr_cpus):
- changed = True
-
- return changed
-
- def set_attributes_for_threads(self, pid, new_policy, new_prio, new_affinity):
- changed = False
- threads = self.ps[pid]["threads"]
- for tid in list(threads.keys()):
- if gui.thread_set_attributes(threads[tid], new_policy,
- new_prio, new_affinity,
- self.nr_cpus):
- changed = True
-
- return changed
-
- def run(self):
- changed = False
- if self.dialog.run() == Gtk.ResponseType.OK:
- new_policy = int(self.sched_policy.get_active())
- new_prio = int(self.sched_pri.get_value())
- new_affinity = self.affinity.get_text()
- if self.just_this_thread.get_active():
- changed = gui.thread_set_attributes(self.pid_info,
- new_policy,
- new_prio,
- new_affinity,
- self.nr_cpus)
- elif self.all_these_threads.get_active():
- if gui.thread_set_attributes(self.pid_info,
- new_policy, new_prio,
- new_affinity,
- self.nr_cpus):
- changed = True
- if self.set_attributes_for_threads(self.pid,
- new_policy,
- new_prio,
- new_affinity):
- changed = True
- else:
- changed = self.set_attributes_for_regex(self.regex_edit.get_text(),
- new_policy,
- new_prio,
- new_affinity)
-
- self.dialog.destroy()
- return changed
+ (PROCESS_COL_PID, PROCESS_COL_NAME) = list(range(2))
+
+ def __init__(self, ps, pid, pid_info, nr_cpus, gladefile):
+ self.ps = ps
+ self.pid = pid
+ self.pid_info = pid_info
+ self.nr_cpus = nr_cpus
+ self.window = Gtk.glade.XML(gladefile, "set_process_attributes", "tuna")
+ self.dialog = self.window.get_widget("set_process_attributes")
+ pixbuf = self.dialog.render_icon(Gtk.STOCK_PREFERENCES,
+ Gtk.IconSize.SMALL_TOOLBAR)
+ self.dialog.set_icon(pixbuf)
+ event_handlers = {
+ "on_cmdline_regex_changed" : self.on_cmdline_regex_changed,
+ "on_affinity_text_changed" : self.on_affinity_text_changed,
+ "on_sched_policy_combo_changed" : self.on_sched_policy_combo_changed,
+ "on_command_regex_clicked" : self.on_command_regex_clicked,
+ "on_all_these_threads_clicked" : self.on_all_these_threads_clicked,
+ "on_just_this_thread_clicked" : self.on_just_this_thread_clicked}
+ self.window.signal_autoconnect(event_handlers)
+ self.sched_pri = self.window.get_widget("sched_pri_spin")
+ self.sched_policy = self.window.get_widget("sched_policy_combo")
+ self.regex_edit = self.window.get_widget("cmdline_regex")
+ self.affinity = self.window.get_widget("affinity_text")
+ self.just_this_thread = self.window.get_widget("just_this_thread")
+ self.all_these_threads = self.window.get_widget("all_these_threads")
+ processes = self.window.get_widget("matching_process_list")
+
+ self.sched_pri.set_value(int(pid_info["stat"]["rt_priority"]))
+ cmdline_regex = procfs.process_cmdline(pid_info)
+ self.affinity_text = tuna.list_to_cpustring(schedutils.get_affinity(pid))
+ self.affinity.set_text(self.affinity_text)
+ self.create_matching_process_model(processes)
+ self.create_policy_model(self.sched_policy)
+ self.sched_policy.set_active(schedutils.get_scheduler(pid))
+ self.regex_edit.set_text(cmdline_regex)
+ self.just_this_thread.set_active(True)
+ self.regex_edit.set_sensitive(False)
+ if pid not in ps or "threads" not in ps[pid]:
+ self.all_these_threads.hide()
+ self.on_just_this_thread_clicked(None)
+
+ def refresh_match_pids(self, cmdline_regex):
+ self.process_list_store.clear()
+ for match_pid in self.ps.find_by_cmdline_regex(cmdline_regex):
+ info = self.process_list_store.append()
+ pid_info = self.ps[match_pid]
+ cmdline = procfs.process_cmdline(pid_info)
+ self.process_list_store.set(info, self.PROCESS_COL_PID, match_pid,
+ self.PROCESS_COL_NAME, cmdline)
+
+ def create_matching_process_model(self, processes):
+ labels = ["PID", "Name"]
+
+ self.process_list_store = Gtk.ListStore(GObject.TYPE_UINT,
+ GObject.TYPE_STRING)
+ renderer = Gtk.CellRendererText()
+
+ for col in range(len(labels)):
+ column = Gtk.TreeViewColumn(labels[col], renderer, text=col)
+ column.set_sort_column_id(col)
+ processes.append_column(column)
+
+ processes.set_model(self.process_list_store)
+
+ def create_policy_model(self, policy):
+ (COL_TEXT, COL_SCHED) = list(range(2))
+ list_store = Gtk.ListStore(GObject.TYPE_STRING,
+ GObject.TYPE_UINT)
+ renderer = Gtk.CellRendererText()
+ policy.pack_start(renderer, True)
+ policy.add_attribute(renderer, "text", COL_TEXT)
+ for pol in range(4):
+ row = list_store.append()
+ list_store.set(row, COL_TEXT, schedutils.schedstr(pol),
+ COL_SCHED, pol)
+ policy.set_model(list_store)
+
+ def on_cmdline_regex_changed(self, entry):
+ process_regex_text = entry.get_text()
+ try:
+ cmdline_regex = re.compile(process_regex_text)
+ except:
+ self.process_list_store.clear()
+ return
+ self.refresh_match_pids(cmdline_regex)
+
+ def on_just_this_thread_clicked(self, button):
+ self.regex_edit.set_sensitive(False)
+ self.process_list_store.clear()
+ info = self.process_list_store.append()
+ cmdline = procfs.process_cmdline(self.pid_info)
+ self.process_list_store.set(info,
+ self.PROCESS_COL_PID, self.pid,
+ self.PROCESS_COL_NAME, cmdline)
+
+ def on_command_regex_clicked(self, button):
+ self.regex_edit.set_sensitive(True)
+ self.on_cmdline_regex_changed(self.regex_edit)
+
+ def on_all_these_threads_clicked(self, button):
+ self.regex_edit.set_sensitive(False)
+ self.process_list_store.clear()
+ info = self.process_list_store.append()
+ cmdline = procfs.process_cmdline(self.ps[self.pid])
+ self.process_list_store.set(info,
+ self.PROCESS_COL_PID, self.pid,
+ self.PROCESS_COL_NAME, cmdline)
+ for tid in list(self.ps[self.pid]["threads"].keys()):
+ child = self.process_list_store.append()
+ self.process_list_store.set(child,
+ self.PROCESS_COL_PID, tid,
+ self.PROCESS_COL_NAME, cmdline)
+
+
+ def on_sched_policy_combo_changed(self, button):
+ new_policy = self.sched_policy.get_active()
+ if new_policy in (schedutils.SCHED_FIFO, schedutils.SCHED_RR):
+ can_change_pri = True
+ else:
+ can_change_pri = False
+ self.sched_pri.set_sensitive(can_change_pri)
+
+ def on_affinity_text_changed(self, button):
+ gui.on_affinity_text_changed(self)
+
+ def set_attributes_for_regex(self, regex, new_policy, new_prio, new_affinity):
+ changed = False
+ cmdline_regex = re.compile(regex)
+ for match_pid in self.ps.find_by_cmdline_regex(cmdline_regex):
+ if gui.thread_set_attributes(self.ps[match_pid],
+ new_policy, new_prio,
+ new_affinity, self.nr_cpus):
+ changed = True
+
+ return changed
+
+ def set_attributes_for_threads(self, pid, new_policy, new_prio, new_affinity):
+ changed = False
+ threads = self.ps[pid]["threads"]
+ for tid in list(threads.keys()):
+ if gui.thread_set_attributes(threads[tid], new_policy,
+ new_prio, new_affinity, self.nr_cpus):
+ changed = True
+
+ return changed
+
+ def run(self):
+ changed = False
+ if self.dialog.run() == Gtk.ResponseType.OK:
+ new_policy = int(self.sched_policy.get_active())
+ new_prio = int(self.sched_pri.get_value())
+ new_affinity = self.affinity.get_text()
+ if self.just_this_thread.get_active():
+ changed = gui.thread_set_attributes(self.pid_info, new_policy,
+ new_prio, new_affinity,
+ self.nr_cpus)
+ elif self.all_these_threads.get_active():
+ if gui.thread_set_attributes(self.pid_info, new_policy,
+ new_prio, new_affinity,
+ self.nr_cpus):
+ changed = True
+ if self.set_attributes_for_threads(self.pid, new_policy,
+ new_prio, new_affinity):
+ changed = True
+ else:
+ changed = self.set_attributes_for_regex(self.regex_edit.get_text(),
+ new_policy,
+ new_prio,
+ new_affinity)
+
+ self.dialog.destroy()
+ return changed
class procview:
- nr_columns = 8
- ( COL_PID, COL_POL, COL_PRI, COL_AFF, COL_VOLCTXT, COL_NONVOLCTXT, COL_CGROUP, COL_CMDLINE ) = list(range(nr_columns))
- columns = (gui.list_store_column(_("PID")),
- gui.list_store_column(_("Policy"), GObject.TYPE_STRING),
- gui.list_store_column(_("Priority")),
- gui.list_store_column(_("Affinity"), GObject.TYPE_STRING),
- gui.list_store_column(_("VolCtxtSwitch"), GObject.TYPE_UINT),
- gui.list_store_column(_("NonVolCtxtSwitch"), GObject.TYPE_UINT),
- gui.list_store_column(_("CGroup"), GObject.TYPE_STRING),
- gui.list_store_column(_("Command Line"), GObject.TYPE_STRING))
-
- def __init__(self, treeview, ps,
- show_kthreads, show_uthreads,
- cpus_filtered, gladefile):
- self.ps = ps
- self.treeview = treeview
- self.nr_cpus = procfs.cpuinfo().nr_cpus
- self.gladefile = gladefile
-
- self.evlist = None
- try:
- self.perf_init()
- except: # No perf, poll /proc baby, poll
- pass
-
- if "voluntary_ctxt_switches" not in ps[1]["status"]:
- self.nr_columns = 5
- else:
- self.nr_columns = 7
- try:
- if ps[1]["cgroups"]:
- self.nr_columns = self.nr_columns + 1
- except:
- pass
-
- self.columns = (gui.list_store_column(_("PID")),
- gui.list_store_column(_("Policy"), GObject.TYPE_STRING),
- gui.list_store_column(_("Priority")),
- gui.list_store_column(_("Affinity"), GObject.TYPE_STRING))
-
- if self.nr_columns==5:
- ( self.COL_PID, self.COL_POL, self.COL_PRI, self.COL_AFF, self.COL_CMDLINE ) = list(range(self.nr_columns))
- self.columns = self.columns + (gui.list_store_column(_("Command Line"), GObject.TYPE_STRING))
-
- elif self.nr_columns==6:
- ( self.COL_PID, self.COL_POL, self.COL_PRI, self.COL_AFF, self.COL_CGROUP, self.COL_CMDLINE ) = list(range(self.nr_columns))
- self.columns = self.columns + (gui.list_store_column(_("CGroup"), GObject.TYPE_STRING),
- gui.list_store_column(_("Command Line"), GObject.TYPE_STRING))
-
- elif self.nr_columns==7:
- ( self.COL_PID, self.COL_POL, self.COL_PRI, self.COL_AFF, self.COL_VOLCTXT,
- self.NONVOLCTXT, self.COL_CMDLINE ) = list(range(self.nr_columns))
- self.columns = self.columns + (gui.list_store_column(_("VolCtxtSwitch"), GObject.TYPE_UINT),
- gui.list_store_column(_("NonVolCtxtSwitch"), GObject.TYPE_UINT),
- gui.list_store_column(_("Command Line"), GObject.TYPE_STRING))
-
- elif self.nr_columns==8:
- ( self.COL_PID, self.COL_POL, self.COL_PRI, self.COL_AFF, self.COL_VOLCTXT,
- self.COL_NONVOLCTXT, self.COL_CGROUP, self.COL_CMDLINE ) = list(range(self.nr_columns))
- self.columns = self.columns + (gui.list_store_column(_("VolCtxtSwitch"), GObject.TYPE_UINT),
- gui.list_store_column(_("NonVolCtxtSwitch"), GObject.TYPE_UINT),
- gui.list_store_column(_("CGroup"), GObject.TYPE_STRING),
- gui.list_store_column(_("Command Line"), GObject.TYPE_STRING))
-
- self.tree_store = Gtk.TreeStore(*gui.generate_list_store_columns_with_attr(self.columns))
- self.treeview.set_model(self.tree_store)
-
- # Allow selecting multiple rows
- selection = treeview.get_selection()
- selection.set_mode(Gtk.SelectionMode.MULTIPLE)
-
- # Allow enable drag and drop of rows
- self.treeview.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK,
- gui.DND_TARGETS,
- Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE)
- self.treeview.connect("drag_data_get", self.on_drag_data_get_data)
- try:
- self.treeview.connect("query-tooltip", self.on_query_tooltip)
- except:
- # old versions of pygtk2+ doesn't have this signal
- pass
-
- self.renderer = Gtk.CellRendererText()
- for col in range(self.nr_columns):
- column = Gtk.TreeViewColumn(self.columns[col].name,
- self.renderer, text = col)
- column.add_attribute(self.renderer, "weight",
- col + self.nr_columns)
- column.set_sort_column_id(col)
- if(col == self.COL_CGROUP):
- column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
- column.set_fixed_width(130)
- try:
- self.treeview.set_tooltip_column(col)
- except:
- # old versions of pygtk2+ doesn't have this signal
- pass
- column.set_resizable(True)
- self.treeview.append_column(column)
-
- self.show_kthreads = show_kthreads
- self.show_uthreads = show_uthreads
- self.cpus_filtered = cpus_filtered
- self.refreshing = True
-
- def perf_process_events(self, source, condition):
- had_events = True
- while had_events:
- had_events = False
- for cpu in self.cpu_map:
- event = self.evlist.read_on_cpu(cpu)
- if event:
- had_events = True
- if event.type == perf.RECORD_FORK:
- if event.pid == event.tid:
- try:
- self.ps.processes[event.pid] = procfs.process(event.pid)
- except: # short lived thread
- pass
- else:
- try:
- self.ps.processes[event.pid].threads.processes[event.tid] = procfs.process(event.tid)
- except AttributeError:
- self.ps.processes[event.pid].threads = procfs.pidstats("/proc/%d/task/" % event.pid)
- elif event.type == perf.RECORD_EXIT:
- del self.ps[int(event.tid)]
- elif event.type == perf.RECORD_SAMPLE:
- tid = event.sample_tid
- if tid in self.perf_counter:
- self.perf_counter[tid] += event.sample_period
- else:
- self.perf_counter[tid] = event.sample_period
-
- self.show()
- return True
-
- def perf_init(self):
- self.cpu_map = perf.cpu_map()
- self.thread_map = perf.thread_map()
- self.evsel_cycles = perf.evsel(task = 1, comm = 1,
- wakeup_events = 1,
- watermark = 1,
- sample_type = perf.SAMPLE_CPU |
- perf.SAMPLE_TID)
- self.evsel_cycles.open(cpus = self.cpu_map, threads = self.thread_map);
- self.evlist = perf.evlist(self.cpu_map, self.thread_map)
- self.evlist.add(self.evsel_cycles)
- self.evlist.mmap()
- self.pollfd = self.evlist.get_pollfd()
- for f in self.pollfd:
- GObject.io_add_watch(f, Gdk.INPUT_READ, self.perf_process_events)
- self.perf_counter = {}
-
- def on_query_tooltip(self, treeview, x, y, keyboard_mode, tooltip):
- x, y = treeview.convert_widget_to_bin_window_coords(x, y)
- ret = treeview.get_path_at_pos(x, y)
- tooltip.set_text(None)
- if not ret:
- return True
- path, col, xpos, ypos = ret
- if not path:
- return True
- col_id = col.get_sort_column_id()
- if col_id != self.COL_CMDLINE:
- return True
- row = self.tree_store.get_iter(path)
- if not row:
- return True
- pid = int(self.tree_store.get_value(row, self.COL_PID))
- if not tuna.iskthread(pid):
- return True
- cmdline = self.tree_store.get_value(row, self.COL_CMDLINE).split(' ')[0]
- help = tuna.kthread_help(cmdline)
- tooltip.set_markup("<b>%s %d(%s)</b>\n%s" % \
+ nr_columns = 8
+ (COL_PID, COL_POL, COL_PRI, COL_AFF, COL_VOLCTXT, COL_NONVOLCTXT,
+ COL_CGROUP, COL_CMDLINE) = list(range(nr_columns))
+ columns = (gui.list_store_column(_("PID")),
+ gui.list_store_column(_("Policy"), GObject.TYPE_STRING),
+ gui.list_store_column(_("Priority")),
+ gui.list_store_column(_("Affinity"), GObject.TYPE_STRING),
+ gui.list_store_column(_("VolCtxtSwitch"), GObject.TYPE_UINT),
+ gui.list_store_column(_("NonVolCtxtSwitch"), GObject.TYPE_UINT),
+ gui.list_store_column(_("CGroup"), GObject.TYPE_STRING),
+ gui.list_store_column(_("Command Line"), GObject.TYPE_STRING))
+
+ def __init__(self, treeview, ps, show_kthreads, show_uthreads,
+ cpus_filtered, gladefile):
+ self.ps = ps
+ self.treeview = treeview
+ self.nr_cpus = procfs.cpuinfo().nr_cpus
+ self.gladefile = gladefile
+
+ self.evlist = None
+ try:
+ self.perf_init()
+ except: # No perf, poll /proc baby, poll
+ pass
+
+ if "voluntary_ctxt_switches" not in ps[1]["status"]:
+ self.nr_columns = 5
+ else:
+ self.nr_columns = 7
+ try:
+ if ps[1]["cgroups"]:
+ self.nr_columns = self.nr_columns + 1
+ except:
+ pass
+
+ self.columns = (gui.list_store_column(_("PID")),
+ gui.list_store_column(_("Policy"), GObject.TYPE_STRING),
+ gui.list_store_column(_("Priority")),
+ gui.list_store_column(_("Affinity"),
+ GObject.TYPE_STRING))
+
+ if self.nr_columns == 5:
+ (self.COL_PID, self.COL_POL, self.COL_PRI, self.COL_AFF,
+ self.COL_CMDLINE) = list(range(self.nr_columns))
+ self.columns = self.columns \
+ + (gui.list_store_column(_("Command Line"), GObject.TYPE_STRING))
+
+ elif self.nr_columns == 6:
+ (self.COL_PID, self.COL_POL, self.COL_PRI, self.COL_AFF,
+ self.COL_CGROUP, self.COL_CMDLINE) = list(range(self.nr_columns))
+ self.columns = self.columns \
+ + (gui.list_store_column(_("CGroup"), GObject.TYPE_STRING),
+ gui.list_store_column(_("Command Line"), GObject.TYPE_STRING))
+ elif self.nr_columns == 7:
+ (self.COL_PID, self.COL_POL, self.COL_PRI, self.COL_AFF, \
+ self.COL_VOLCTXT, self.NONVOLCTXT, self.COL_CMDLINE) \
+ = list(range(self.nr_columns))
+ self.columns = self.columns \
+ + (gui.list_store_column(_("VolCtxtSwitch"), GObject.TYPE_UINT),
+ gui.list_store_column(_("NonVolCtxtSwitch"), GObject.TYPE_UINT),
+ gui.list_store_column(_("Command Line"), GObject.TYPE_STRING))
+
+ elif self.nr_columns == 8:
+ (self.COL_PID, self.COL_POL, self.COL_PRI, self.COL_AFF, \
+ self.COL_VOLCTXT, self.COL_NONVOLCTXT, self.COL_CGROUP, \
+ self.COL_CMDLINE) = list(range(self.nr_columns))
+ self.columns = self.columns \
+ + (gui.list_store_column(_("VolCtxtSwitch"), GObject.TYPE_UINT),
+ gui.list_store_column(_("NonVolCtxtSwitch"), GObject.TYPE_UINT),
+ gui.list_store_column(_("CGroup"), GObject.TYPE_STRING),
+ gui.list_store_column(_("Command Line"), GObject.TYPE_STRING))
+
+ self.tree_store = Gtk.TreeStore(*gui.generate_list_store_columns_with_attr(self.columns))
+ self.treeview.set_model(self.tree_store)
+
+ # Allow selecting multiple rows
+ selection = treeview.get_selection()
+ selection.set_mode(Gtk.SelectionMode.MULTIPLE)
+
+ # Allow enable drag and drop of rows
+ self.treeview.enable_model_drag_source(
+ Gdk.ModifierType.BUTTON1_MASK, gui.DND_TARGETS,
+ Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE)
+ self.treeview.connect("drag_data_get", self.on_drag_data_get_data)
+ try:
+ self.treeview.connect("query-tooltip", self.on_query_tooltip)
+ except:
+ # old versions of pygtk2+ doesn't have this signal
+ pass
+
+ self.renderer = Gtk.CellRendererText()
+ for col in range(self.nr_columns):
+ column = Gtk.TreeViewColumn(self.columns[col].name,
+ self.renderer, text=col)
+ column.add_attribute(self.renderer, "weight",
+ col + self.nr_columns)
+ column.set_sort_column_id(col)
+ if col == self.COL_CGROUP:
+ column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
+ column.set_fixed_width(130)
+ try:
+ self.treeview.set_tooltip_column(col)
+ except:
+ # old versions of pygtk2+ doesn't have this signal
+ pass
+ column.set_resizable(True)
+ self.treeview.append_column(column)
+
+ self.show_kthreads = show_kthreads
+ self.show_uthreads = show_uthreads
+ self.cpus_filtered = cpus_filtered
+ self.refreshing = True
+
+ def perf_process_events(self, source, condition):
+ had_events = True
+ while had_events:
+ had_events = False
+ for cpu in self.cpu_map:
+ event = self.evlist.read_on_cpu(cpu)
+ if event:
+ had_events = True
+ if event.type == perf.RECORD_FORK:
+ if event.pid == event.tid:
+ try:
+ self.ps.processes[event.pid] = procfs.process(event.pid)
+ except: # short lived thread
+ pass
+ else:
+ try:
+ self.ps.processes[event.pid].threads.processes[event.tid] = procfs.process(event.tid)
+ except AttributeError:
+ self.ps.processes[event.pid].threads = procfs.pidstats("/proc/%d/task/" % event.pid)
+ elif event.type == perf.RECORD_EXIT:
+ del self.ps[int(event.tid)]
+ elif event.type == perf.RECORD_SAMPLE:
+ tid = event.sample_tid
+ if tid in self.perf_counter:
+ self.perf_counter[tid] += event.sample_period
+ else:
+ self.perf_counter[tid] = event.sample_period
+
+ self.show()
+ return True
+
+ def perf_init(self):
+ self.cpu_map = perf.cpu_map()
+ self.thread_map = perf.thread_map()
+ self.evsel_cycles = perf.evsel(task=1, comm=1, wakeup_events=1, \
+ watermark=1, sample_type=perf.SAMPLE_CPU | perf.SAMPLE_TID)
+ self.evsel_cycles.open(cpus=self.cpu_map, threads=self.thread_map)
+ self.evlist = perf.evlist(self.cpu_map, self.thread_map)
+ self.evlist.add(self.evsel_cycles)
+ self.evlist.mmap()
+ self.pollfd = self.evlist.get_pollfd()
+ for f in self.pollfd:
+ GObject.io_add_watch(f, Gdk.INPUT_READ, self.perf_process_events)
+ self.perf_counter = {}
+
+ def on_query_tooltip(self, treeview, x, y, keyboard_mode, tooltip):
+ x, y = treeview.convert_widget_to_bin_window_coords(x, y)
+ ret = treeview.get_path_at_pos(x, y)
+ tooltip.set_text(None)
+ if not ret:
+ return True
+ path, col, xpos, ypos = ret
+ if not path:
+ return True
+ col_id = col.get_sort_column_id()
+ if col_id != self.COL_CMDLINE:
+ return True
+ row = self.tree_store.get_iter(path)
+ if not row:
+ return True
+ pid = int(self.tree_store.get_value(row, self.COL_PID))
+ if not tuna.iskthread(pid):
+ return True
+ cmdline = self.tree_store.get_value(row, self.COL_CMDLINE).split(' ')[0]
+ help = tuna.kthread_help(cmdline)
+ tooltip.set_markup("<b>%s %d(%s)</b>\n%s" % \
(_("Kernel Thread"), pid, cmdline, _(help)))
- return True
-
- def foreach_selected_cb(self, model, path, iter, pid_list):
- pid = model.get_value(iter, self.COL_PID)
- pid_list.append(str(pid))
-
- def on_drag_data_get_data(self, treeview, context,
- selection, target_id, etime):
- treeselection = treeview.get_selection()
- pid_list = []
- treeselection.selected_foreach(self.foreach_selected_cb, pid_list)
- selection.set(selection.target, 8, "pid:" + ",".join(pid_list))
-
- def set_thread_columns(self, iter, tid, thread_info):
- new_value = [ None ] * self.nr_columns
-
- new_value[self.COL_PRI] = int(thread_info["stat"]["rt_priority"])
- new_value[self.COL_POL] = schedutils.schedstr(schedutils.get_scheduler(tid))[6:]
- thread_affinity_list = schedutils.get_affinity(tid)
-
- new_value[self.COL_PID] = tid
- new_value[self.COL_AFF] = tuna.list_to_cpustring(thread_affinity_list)
- try:
- new_value[self.COL_VOLCTXT] = int(thread_info["status"]["voluntary_ctxt_switches"])
- new_value[self.COL_NONVOLCTXT] = int(thread_info["status"]["nonvoluntary_ctxt_switches"])
- new_value[self.COL_CGROUP] = thread_info["cgroups"]
- except:
- pass
-
- new_value[self.COL_CMDLINE] = procfs.process_cmdline(thread_info)
-
- gui.set_store_columns(self.tree_store, iter, new_value)
-
- def show(self, force_refresh = False):
- # Start with the first row, if there is one, on the
- # process list. If the first time update_rows will just
- # have everything in new_tids and append_new_tids will
- # create the rows.
- if not self.refreshing and not force_refresh:
- return
- row = self.tree_store.get_iter_first()
- self.update_rows(self.ps, row, None)
- self.treeview.show_all()
-
- def update_rows(self, threads, row, parent_row):
- new_tids = list(threads.keys())
- previous_row = None
- while row:
- tid = self.tree_store.get_value(row, self.COL_PID)
- if previous_row:
- previous_tid = self.tree_store.get_value(previous_row, self.COL_PID)
- if previous_tid == tid:
- # print "WARNING: tree_store dup %d, fixing..." % tid
- self.tree_store.remove(previous_row)
- if tid not in threads:
- if self.tree_store.remove(row):
- # removed and now row is the next one
- continue
- # removed and its the last one
- break
- else:
- try:
- new_tids.remove(tid)
- except:
- # FIXME: understand in what situation this
- # can happen, seems harmless from visual
- # inspection.
- pass
- if tuna.thread_filtered(tid, self.cpus_filtered,
- self.show_kthreads,
- self.show_uthreads):
- if self.tree_store.remove(row):
- # removed and now row is the next one
- continue
- # removed and its the last one
- break
- else:
- try:
- self.set_thread_columns(row, tid, threads[tid])
-
- if "threads" in threads[tid]:
- children = threads[tid]["threads"]
- else:
- children = {}
-
- child_row = self.tree_store.iter_children(row)
- self.update_rows(children, child_row, row)
- except: # thread doesn't exists anymore
- if self.tree_store.remove(row):
- # removed and now row is the next one
- continue
- # removed and its the last one
- break
-
- previous_row = row
- row = self.tree_store.iter_next(row)
-
- new_tids.sort()
- self.append_new_tids(parent_row, threads, new_tids)
-
- def append_new_tids(self, parent_row, threads, tid_list):
- for tid in tid_list:
- if tuna.thread_filtered(tid, self.cpus_filtered,
- self.show_kthreads,
- self.show_uthreads):
- continue
-
- row = self.tree_store.append(parent_row)
-
- try:
- self.set_thread_columns(row, tid, threads[tid])
- except: # Thread doesn't exists anymore
- self.tree_store.remove(row)
- continue
-
- if "threads" in threads[tid]:
- children = threads[tid]["threads"]
- children_list = list(children.keys())
- children_list.sort()
- for child in children_list:
- child_row = self.tree_store.append(row)
- try:
- self.set_thread_columns(child_row,
- child,
- children[child])
- except: # Thread doesn't exists anymore
- self.tree_store.remove(child_row)
-
- def refresh(self):
- self.ps.reload()
- self.ps.reload_threads()
-
- self.show(True)
-
- def edit_attributes(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.tree_store.get_iter(path)
- pid = self.tree_store.get_value(row, self.COL_PID)
- if pid in self.ps:
- pid_info = self.ps[pid]
- else:
- parent = self.tree_store.iter_parent(row)
- ppid = self.tree_store.get_value(parent, self.COL_PID)
- pid_info = self.ps[ppid].threads[pid]
-
- dialog = process_druid(self.ps, pid, pid_info, self.nr_cpus,
- self.gladefile)
- if dialog.run():
- self.refresh()
-
- def kthreads_view_toggled(self, a):
- self.show_kthreads = not self.show_kthreads
- self.show(True)
-
- def uthreads_view_toggled(self, a):
- self.show_uthreads = not self.show_uthreads
- self.show(True)
-
- def help_dialog(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.tree_store.get_iter(path)
- pid = self.tree_store.get_value(row, self.COL_PID)
- if pid not in self.ps:
- return
-
- cmdline = self.tree_store.get_value(row, self.COL_CMDLINE)
- help, title = tuna.kthread_help_plain_text(pid, cmdline)
-
- dialog = Gtk.MessageDialog(None,
- Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
- Gtk.MessageType.INFO,
- Gtk.ButtonsType.OK, _(help))
- dialog.set_title(title)
- ret = dialog.run()
- dialog.destroy()
-
- def refresh_toggle(self, a):
- self.refreshing = not self.refreshing
-
- def save_kthreads_tunings(self, a):
- dialog = Gtk.FileChooserDialog(_("Save As"),
- None,
- Gtk.FileChooserAction.SAVE,
- (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
- Gtk.STOCK_OK, Gtk.ResponseType.OK))
- dialog.set_default_response(Gtk.ResponseType.OK)
-
- try:
- dialog.set_do_overwrite_confirmation(True)
- except:
- pass
-
- filter = Gtk.FileFilter()
- filter.set_name("rtctl config files")
- filter.add_pattern("*.rtctl")
- filter.add_pattern("*.tuna")
- filter.add_pattern("*rtgroup*")
- dialog.add_filter(filter)
-
- filter = Gtk.FileFilter()
- filter.set_name("All files")
- filter.add_pattern("*")
- dialog.add_filter(filter)
-
- response = dialog.run()
-
- filename = dialog.get_filename()
- dialog.destroy()
-
- if response != Gtk.ResponseType.OK:
- return
-
- self.refresh()
- kthreads = tuna.get_kthread_sched_tunings(self.ps)
- tuna.generate_rtgroups(filename, kthreads, self.nr_cpus)
-
- if filename != "/etc/rtgroups":
- dialog = Gtk.MessageDialog(None,
- Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
- Gtk.MessageType.INFO,
- Gtk.ButtonsType.YES_NO,
- "Kernel thread tunings saved!\n\n"
- "Now you can use it with rtctl:\n\n"
- "rtctl --file %s reset\n\n"
- "If you want the changes to be in "
- "effect every time you boot the system "
- "please move %s to /etc/rtgroups\n\n"
- "Do you want to do that now?" % (filename, filename))
- response = dialog.run()
- dialog.destroy()
- if response == Gtk.ResponseType.YES:
- filename = "/etc/rtgroups"
- tuna.generate_rtgroups(filename, kthreads, self.nr_cpus)
-
- dialog = Gtk.MessageDialog(None,
- Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
- Gtk.MessageType.INFO,
- Gtk.ButtonsType.OK,
- _("Kernel thread tunings saved to %s!") % filename)
- dialog.run()
- dialog.destroy()
-
- def on_processlist_button_press_event(self, treeview, event):
- if event.type != Gdk.EventType.BUTTON_PRESS or event.button != 3:
- return
-
- self.last_x = int(event.x)
- self.last_y = int(event.y)
-
- menu = Gtk.Menu()
-
- setattr = Gtk.MenuItem(_("_Set process attributes"))
- if self.refreshing:
- refresh = Gtk.MenuItem(_("Sto_p refreshing the process list"))
- else:
- refresh = Gtk.MenuItem(_("_Refresh the process list"))
-
- if self.show_kthreads:
- kthreads = Gtk.MenuItem(_("_Hide kernel threads"))
- else:
- kthreads = Gtk.MenuItem(_("_Show kernel threads"))
-
- if self.show_uthreads:
- uthreads = Gtk.MenuItem(_("_Hide user threads"))
- else:
- uthreads = Gtk.MenuItem(_("_Show user threads"))
-
- help = Gtk.MenuItem(_("_What is this?"))
-
- save_kthreads_tunings = Gtk.MenuItem(_("_Save kthreads tunings"))
-
- menu.add(save_kthreads_tunings)
- menu.add(setattr)
- menu.add(refresh)
- menu.add(kthreads)
- menu.add(uthreads)
- menu.add(help)
-
- save_kthreads_tunings.connect_object('activate',
+ return True
+
+ def foreach_selected_cb(self, model, path, iter, pid_list):
+ pid = model.get_value(iter, self.COL_PID)
+ pid_list.append(str(pid))
+
+ def on_drag_data_get_data(self, treeview, context, selection,
+ target_id, etime):
+ treeselection = treeview.get_selection()
+ pid_list = []
+ treeselection.selected_foreach(self.foreach_selected_cb, pid_list)
+ selection.set(selection.target, 8, "pid:" + ",".join(pid_list))
+
+ def set_thread_columns(self, iter, tid, thread_info):
+ new_value = [None] * self.nr_columns
+
+ new_value[self.COL_PRI] = int(thread_info["stat"]["rt_priority"])
+ new_value[self.COL_POL] = schedutils.schedstr(schedutils.get_scheduler(tid))[6:]
+ thread_affinity_list = schedutils.get_affinity(tid)
+
+ new_value[self.COL_PID] = tid
+ new_value[self.COL_AFF] = tuna.list_to_cpustring(thread_affinity_list)
+ try:
+ new_value[self.COL_VOLCTXT] = int(thread_info["status"]["voluntary_ctxt_switches"])
+ new_value[self.COL_NONVOLCTXT] \
+ = int(thread_info["status"]["nonvoluntary_ctxt_switches"])
+ new_value[self.COL_CGROUP] = thread_info["cgroups"]
+ except:
+ pass
+
+ new_value[self.COL_CMDLINE] = procfs.process_cmdline(thread_info)
+
+ gui.set_store_columns(self.tree_store, iter, new_value)
+
+ def show(self, force_refresh=False):
+ # Start with the first row, if there is one, on the
+ # process list. If the first time update_rows will just
+ # have everything in new_tids and append_new_tids will
+ # create the rows.
+ if not self.refreshing and not force_refresh:
+ return
+ row = self.tree_store.get_iter_first()
+ self.update_rows(self.ps, row, None)
+ self.treeview.show_all()
+
+ def update_rows(self, threads, row, parent_row):
+ new_tids = list(threads.keys())
+ previous_row = None
+ while row:
+ tid = self.tree_store.get_value(row, self.COL_PID)
+ if previous_row:
+ previous_tid = self.tree_store.get_value(previous_row, self.COL_PID)
+ if previous_tid == tid:
+ # print "WARNING: tree_store dup %d, fixing..." % tid
+ self.tree_store.remove(previous_row)
+ if tid not in threads:
+ if self.tree_store.remove(row):
+ # removed and now row is the next one
+ continue
+ # removed and its the last one
+ break
+ else:
+ try:
+ new_tids.remove(tid)
+ except:
+ # FIXME: understand in what situation this
+ # can happen, seems harmless from visual
+ # inspection.
+ pass
+ if tuna.thread_filtered(tid, self.cpus_filtered,
+ self.show_kthreads, self.show_uthreads):
+ if self.tree_store.remove(row):
+ # removed and now row is the next one
+ continue
+ # removed and its the last one
+ break
+ else:
+ try:
+ self.set_thread_columns(row, tid, threads[tid])
+ if "threads" in threads[tid]:
+ children = threads[tid]["threads"]
+ else:
+ children = {}
+ child_row = self.tree_store.iter_children(row)
+ self.update_rows(children, child_row, row)
+ except: # thread doesn't exists anymore
+ if self.tree_store.remove(row):
+ # removed and now row is the next one
+ continue
+ # removed and its the last one
+ break
+
+ previous_row = row
+ row = self.tree_store.iter_next(row)
+
+ new_tids.sort()
+ self.append_new_tids(parent_row, threads, new_tids)
+
+ def append_new_tids(self, parent_row, threads, tid_list):
+ for tid in tid_list:
+ if tuna.thread_filtered(tid, self.cpus_filtered, self.show_kthreads,
+ self.show_uthreads):
+ continue
+
+ row = self.tree_store.append(parent_row)
+
+ try:
+ self.set_thread_columns(row, tid, threads[tid])
+ except: # Thread doesn't exists anymore
+ self.tree_store.remove(row)
+ continue
+
+ if "threads" in threads[tid]:
+ children = threads[tid]["threads"]
+ children_list = list(children.keys())
+ children_list.sort()
+ for child in children_list:
+ child_row = self.tree_store.append(row)
+ try:
+ self.set_thread_columns(child_row, child,
+ children[child])
+ except: # Thread doesn't exists anymore
+ self.tree_store.remove(child_row)
+
+ def refresh(self):
+ self.ps.reload()
+ self.ps.reload_threads()
+
+ self.show(True)
+
+ def edit_attributes(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.tree_store.get_iter(path)
+ pid = self.tree_store.get_value(row, self.COL_PID)
+ if pid in self.ps:
+ pid_info = self.ps[pid]
+ else:
+ parent = self.tree_store.iter_parent(row)
+ ppid = self.tree_store.get_value(parent, self.COL_PID)
+ pid_info = self.ps[ppid].threads[pid]
+
+ dialog = process_druid(self.ps, pid, pid_info, self.nr_cpus,
+ self.gladefile)
+ if dialog.run():
+ self.refresh()
+
+ def kthreads_view_toggled(self, a):
+ self.show_kthreads = not self.show_kthreads
+ self.show(True)
+
+ def uthreads_view_toggled(self, a):
+ self.show_uthreads = not self.show_uthreads
+ self.show(True)
+
+ def help_dialog(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.tree_store.get_iter(path)
+ pid = self.tree_store.get_value(row, self.COL_PID)
+ if pid not in self.ps:
+ return
+
+ cmdline = self.tree_store.get_value(row, self.COL_CMDLINE)
+ help, title = tuna.kthread_help_plain_text(pid, cmdline)
+
+ dialog = Gtk.MessageDialog(None, \
+ Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, \
+ Gtk.MessageType.INFO, Gtk.ButtonsType.OK, _(help))
+ dialog.set_title(title)
+ ret = dialog.run()
+ dialog.destroy()
+
+ def refresh_toggle(self, a):
+ self.refreshing = not self.refreshing
+
+ def save_kthreads_tunings(self, a):
+ dialog = Gtk.FileChooserDialog(_("Save As"), None, \
+ Gtk.FileChooserAction.SAVE, \
+ (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, \
+ Gtk.STOCK_OK, Gtk.ResponseType.OK))
+ dialog.set_default_response(Gtk.ResponseType.OK)
+
+ try:
+ dialog.set_do_overwrite_confirmation(True)
+ except:
+ pass
+
+ filter = Gtk.FileFilter()
+ filter.set_name("rtctl config files")
+ filter.add_pattern("*.rtctl")
+ filter.add_pattern("*.tuna")
+ filter.add_pattern("*rtgroup*")
+ dialog.add_filter(filter)
+
+ filter = Gtk.FileFilter()
+ filter.set_name("All files")
+ filter.add_pattern("*")
+ dialog.add_filter(filter)
+
+ response = dialog.run()
+
+ filename = dialog.get_filename()
+ dialog.destroy()
+
+ if response != Gtk.ResponseType.OK:
+ return
+
+ self.refresh()
+ kthreads = tuna.get_kthread_sched_tunings(self.ps)
+ tuna.generate_rtgroups(filename, kthreads, self.nr_cpus)
+
+ if filename != "/etc/rtgroups":
+ dialog = Gtk.MessageDialog(None, \
+ Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, \
+ Gtk.MessageType.INFO, Gtk.ButtonsType.YES_NO, \
+ "Kernel thread tunings saved!\n\n" \
+ "Now you can use it with rtctl:\n\n" \
+ "rtctl --file %s reset\n\n" \
+ "If you want the changes to be in " \
+ "effect every time you boot the system " \
+ "please move %s to /etc/rtgroups\n\n" \
+ "Do you want to do that now?" % (filename, filename))
+ response = dialog.run()
+ dialog.destroy()
+ if response == Gtk.ResponseType.YES:
+ filename = "/etc/rtgroups"
+ tuna.generate_rtgroups(filename, kthreads, self.nr_cpus)
+
+ dialog = Gtk.MessageDialog(None, \
+ Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, \
+ Gtk.MessageType.INFO, Gtk.ButtonsType.OK, \
+ _("Kernel thread tunings saved to %s!") % filename)
+ dialog.run()
+ dialog.destroy()
+
+ def on_processlist_button_press_event(self, treeview, event):
+ if event.type != Gdk.EventType.BUTTON_PRESS or event.button != 3:
+ return
+
+ self.last_x = int(event.x)
+ self.last_y = int(event.y)
+
+ menu = Gtk.Menu()
+
+ setattr = Gtk.MenuItem(_("_Set process attributes"))
+ if self.refreshing:
+ refresh = Gtk.MenuItem(_("Sto_p refreshing the process list"))
+ else:
+ refresh = Gtk.MenuItem(_("_Refresh the process list"))
+
+ if self.show_kthreads:
+ kthreads = Gtk.MenuItem(_("_Hide kernel threads"))
+ else:
+ kthreads = Gtk.MenuItem(_("_Show kernel threads"))
+
+ if self.show_uthreads:
+ uthreads = Gtk.MenuItem(_("_Hide user threads"))
+ else:
+ uthreads = Gtk.MenuItem(_("_Show user threads"))
+
+ help = Gtk.MenuItem(_("_What is this?"))
+
+ save_kthreads_tunings = Gtk.MenuItem(_("_Save kthreads tunings"))
+
+ menu.add(save_kthreads_tunings)
+ menu.add(setattr)
+ menu.add(refresh)
+ menu.add(kthreads)
+ menu.add(uthreads)
+ menu.add(help)
+
+ save_kthreads_tunings.connect_object('activate',
self.save_kthreads_tunings, event)
- setattr.connect_object('activate', self.edit_attributes, event)
- refresh.connect_object('activate', self.refresh_toggle, event)
- kthreads.connect_object('activate', self.kthreads_view_toggled, event)
- uthreads.connect_object('activate', self.uthreads_view_toggled, event)
- help.connect_object('activate', self.help_dialog, event)
-
- save_kthreads_tunings.show()
- setattr.show()
- refresh.show()
- kthreads.show()
- uthreads.show()
- help.show()
-
- menu.popup(None, None, None, event.button, event.time)
-
- def toggle_mask_cpu(self, cpu, enabled):
- if not enabled:
- if cpu not in self.cpus_filtered:
- self.cpus_filtered.append(cpu)
- self.show(True)
- else:
- if cpu in self.cpus_filtered:
- self.cpus_filtered.remove(cpu)
- self.show(True)
+ setattr.connect_object('activate', self.edit_attributes, event)
+ refresh.connect_object('activate', self.refresh_toggle, event)
+ kthreads.connect_object('activate', self.kthreads_view_toggled, event)
+ uthreads.connect_object('activate', self.uthreads_view_toggled, event)
+ help.connect_object('activate', self.help_dialog, event)
+
+ save_kthreads_tunings.show()
+ setattr.show()
+ refresh.show()
+ kthreads.show()
+ uthreads.show()
+ help.show()
+
+ menu.popup(None, None, None, event.button, event.time)
+
+ def toggle_mask_cpu(self, cpu, enabled):
+ if not enabled:
+ if cpu not in self.cpus_filtered:
+ self.cpus_filtered.append(cpu)
+ self.show(True)
+ else:
+ if cpu in self.cpus_filtered:
+ self.cpus_filtered.remove(cpu)
+ self.show(True)