[sugar] [RFC] teach sugar to update oom_adj

Joshua N Pritikin jpritikin
Sat Feb 17 05:55:04 EST 2007


This is my first real patch for sugar. Does it look OK? Did I add code 
in the appropriate place? FYI, this patch is in reference to:

http://www.redhat.com/archives/olpc-software/2006-March/msg00205.html
http://www.redhat.com/archives/olpc-software/2006-March/msg00227.html

Currently the write fails with "Operation not permitted." I presume some 
minor tweaks to the kernel are necessary?

---
 shell/model/homeactivity.py |   17 ++++++++++++++++-
 shell/model/homemodel.py    |   39 +++++++++++++++++++++++----------------
 sugar/activity/Activity.py  |    7 +++++++
 3 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/shell/model/homeactivity.py b/shell/model/homeactivity.py
index aff4ee5..b8eae65 100644
--- a/shell/model/homeactivity.py
+++ b/shell/model/homeactivity.py
@@ -14,6 +14,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
+import os
 import time
 import gobject
 import logging
@@ -36,6 +37,7 @@ class HomeActivity(gobject.GObject):
         self._xid = None
         self._service = None
         self._id = activity_id
+        self._pid = None
         self._type = bundle.get_service_name()
         self._icon_name = bundle.get_icon()
 
@@ -55,7 +57,7 @@ class HomeActivity(gobject.GObject):
         self.emit('launch-timeout')
         return False
 
-    def set_window(self, window):
+    def set_window(self, window, pid):
         """An activity is 'launched' once we get its window."""
         logging.debug("Activity %s (%s) finished launching" % (self._id, self._type))
         self._launched = True
@@ -68,6 +70,7 @@ class HomeActivity(gobject.GObject):
             raise ValueError("window must be valid")
 
         self._window = window
+        self._pid = pid
         self._xid = window.get_xid()
         self._service = Activity.get_service(window.get_xid())
 
@@ -97,6 +100,18 @@ class HomeActivity(gobject.GObject):
     def get_id(self):
         return self._id
 
+    def get_pid(self):
+        if not self._launched:
+            raise RuntimeError("Activity is still launching.")
+        return self._pid
+
+    def set_oom_adj(self, adj):
+        path = os.path.join('/proc', str(self.get_pid()), 'oom_adj')
+        f = open(path, "w")
+        if f:
+            f.write(str(adj))
+            f.close()
+
     def get_xid(self):
         if not self._launched:
             raise RuntimeError("Activity is still launching.")
diff --git a/shell/model/homemodel.py b/shell/model/homemodel.py
index 40d8bd7..a30c691 100644
--- a/shell/model/homemodel.py
+++ b/shell/model/homemodel.py
@@ -93,25 +93,32 @@ class HomeModel(gobject.GObject):
 
     def _active_window_changed_cb(self, screen):
         window = screen.get_active_window()
-        if window == None:
-            self.emit('active-activity-changed', None)
-            return
-        if window.get_window_type() != wnck.WINDOW_NORMAL:
+        if window and window.get_window_type() != wnck.WINDOW_NORMAL:
             return
 
-        xid = window.get_xid()
-        act = self._get_activity_by_xid(window.get_xid())
-        if act:
-            if act.get_launched() == True:
-                self._current_activity = act
-            else:
-                self._current_activity = None
-                logging.error('Actiivty for window %d was not yet launched.' % xid)
+        old_active = self._current_activity
+        new_active = None
+        
+        if not window:
+            logging.error('No active window')
         else:
-            self._current_activity = None
-            logging.error('Model for window %d does not exist.' % xid)
+            xid = window.get_xid()
+            act = self._get_activity_by_xid(window.get_xid())
+            if not act:
+                logging.error('Model for window %d does not exist.' % xid)
+            else:
+                if not act.get_launched():
+                    logging.error('Activity for window %d not yet launched.' % xid)
+                else:
+                    new_active = act
+
+        if new_active == old_active:
+            return
 
-        self.emit('active-activity-changed', self._current_activity)
+        if new_active: new_active.set_oom_adj(2)
+        if old_active: old_active.set_oom_adj(3)
+        self._current_activity = new_active
+        self.emit('active-activity-changed', new_active)
         
     def _add_activity(self, window):
         act_service = Activity.get_service(window.get_xid())
@@ -131,7 +138,7 @@ class HomeModel(gobject.GObject):
             activity = HomeActivity(bundle, act_id)
             self._activities[act_id] = activity
 
-        activity.set_window(window)
+        activity.set_window(window, act_service.get_pid())
         self.emit('activity-added', activity)
 
     def _internal_remove_activity(self, activity):
diff --git a/sugar/activity/Activity.py b/sugar/activity/Activity.py
index b5a4763..77e8f28 100644
--- a/sugar/activity/Activity.py
+++ b/sugar/activity/Activity.py
@@ -91,6 +91,10 @@ class ActivityDbusService(dbus.service.Object):
         return self._activity.get_id()
 
     @dbus.service.method(ACTIVITY_INTERFACE)
+    def get_pid(self):
+        return self._activity.get_pid()
+
+    @dbus.service.method(ACTIVITY_INTERFACE)
     def get_type(self):
         """Get the activity type"""
         return self._activity.get_type()
@@ -153,6 +157,9 @@ class Activity(gtk.Window):
         """Gets the activity type."""
         return env.get_bundle_service_name()
 
+    def get_pid(self):
+        return os.getpid()
+
     def get_default_type(self):
         """Gets the type of the default activity network service"""
         return env.get_bundle_default_type()
-- 
1.4.4.4



More information about the Sugar-devel mailing list