4fe94b
diff --git a/man/tuned-main.conf.5 b/man/tuned-main.conf.5
4fe94b
index 61a6a4b..6f324be 100644
4fe94b
--- a/man/tuned-main.conf.5
4fe94b
+++ b/man/tuned-main.conf.5
4fe94b
@@ -16,17 +16,31 @@ will be used. Please note if it is enabled here, it is still possible
4fe94b
 to individually disable it in plugins.
4fe94b
 
4fe94b
 .TP
4fe94b
+.BI sleep_interval= INT
4fe94b
+Tuned daemon is periodically waken after \fIINT\fR seconds and checks
4fe94b
+for events. By default this is set to 1 second. If you have Python 2
4fe94b
+interpreter with applied patch from Red Hat Bugzilla #917709 this
4fe94b
+controls responsiveness time of Tuned to commands (i.e. if you
4fe94b
+request profile switch, it may take up to 1 second until Tuned reacts).
4fe94b
+Increase this number for higher responsiveness times and more power
4fe94b
+savings (due to lower number of wakeups). In case you have unpatched
4fe94b
+Python 2 interpreter, this settings will have no visible effect,
4fe94b
+because the intepreter will poll 20 times per second.
4fe94b
+
4fe94b
+.TP
4fe94b
 .BI update_interval= INT
4fe94b
 Update interval for dynamic tuning (in seconds). Tuned daemon is periodically
4fe94b
 waken after \fIINT\fR seconds, updates its monitors, calculates new tuning
4fe94b
 parameters for enabled plugins and applies the changes. Plugins that have
4fe94b
 disabled dynamic tuning are not processed. By default the \fIINT\fR is set
4fe94b
 to 10 seconds. Tuned daemon doesn't periodically wake if dynamic tuning is
4fe94b
-globally disabled (see \fBdynamic_tuning\fR).
4fe94b
+globally disabled (see \fBdynamic_tuning\fR) or this setting set to 0.
4fe94b
+This must be multiple of \fBsleep_interval\fR.
4fe94b
 
4fe94b
 .SH EXAMPLE
4fe94b
 .nf
4fe94b
 dynamic_tuning = 1
4fe94b
+sleep_interval = 1
4fe94b
 update_interval = 10
4fe94b
 .fi
4fe94b
 
4fe94b
diff --git a/tuned/consts.py b/tuned/consts.py
4fe94b
index 1dd53ab..6c8dc4b 100644
4fe94b
--- a/tuned/consts.py
4fe94b
+++ b/tuned/consts.py
4fe94b
@@ -18,5 +18,7 @@ SYSTEM_RELEASE_FILE = "/etc/system-release-cpe"
4fe94b
 
4fe94b
 # default configuration
4fe94b
 CFG_DEF_DYNAMIC_TUNING = True
4fe94b
+# how long to sleep before checking for events (in seconds)
4fe94b
+CFG_DEF_SLEEP_INTERVAL = 1
4fe94b
 # update interval for dynamic tuning (in seconds)
4fe94b
 CFG_DEF_UPDATE_INTERVAL = 10
4fe94b
diff --git a/tuned/daemon/application.py b/tuned/daemon/application.py
4fe94b
index f1b5208..e4c9da3 100644
4fe94b
--- a/tuned/daemon/application.py
4fe94b
+++ b/tuned/daemon/application.py
4fe94b
@@ -16,6 +16,7 @@ log = tuned.logs.get()
4fe94b
 __all__ = ["Application"]
4fe94b
 
4fe94b
 global_config_spec = 	["dynamic_tuning = boolean(default=%s)" % consts.CFG_DEF_DYNAMIC_TUNING,
4fe94b
+			"sleep_interval = integer(default=%s)" % consts.CFG_DEF_SLEEP_INTERVAL,
4fe94b
 			"update_interval = integer(default=%s)" % consts.CFG_DEF_UPDATE_INTERVAL]
4fe94b
 
4fe94b
 class Application(object):
4fe94b
@@ -31,7 +32,6 @@ class Application(object):
4fe94b
 		self.config = self._load_global_config()
4fe94b
 		if self.config.get("dynamic_tuning"):
4fe94b
 			log.info("dynamic tuning is enabled (can be overriden in plugins)")
4fe94b
-			log.info("update interval is %d seconds" % self.config.get("update_interval"))
4fe94b
 		else:
4fe94b
 			log.info("dynamic tuning is globally disabled")
4fe94b
 
4fe94b
@@ -44,7 +44,7 @@ class Application(object):
4fe94b
 		profile_loader = profiles.Loader(profile_locator, profile_factory, profile_merger)
4fe94b
 
4fe94b
 
4fe94b
-		self._daemon = daemon.Daemon(unit_manager, profile_loader, profile_name, int(self.config.get("update_interval", consts.CFG_DEF_UPDATE_INTERVAL)))
4fe94b
+		self._daemon = daemon.Daemon(unit_manager, profile_loader, profile_name, self.config)
4fe94b
 		self._controller = controller.Controller(self._daemon)
4fe94b
 
4fe94b
 		self._dbus_exporter = None
4fe94b
diff --git a/tuned/daemon/daemon.py b/tuned/daemon/daemon.py
4fe94b
index 804ac0b..35f60c2 100644
4fe94b
--- a/tuned/daemon/daemon.py
4fe94b
+++ b/tuned/daemon/daemon.py
4fe94b
@@ -9,9 +9,27 @@ log = tuned.logs.get()
4fe94b
 
4fe94b
 
4fe94b
 class Daemon(object):
4fe94b
-	def __init__(self, unit_manager, profile_loader, profile_name=None, update_interval = int(consts.CFG_DEF_UPDATE_INTERVAL)):
4fe94b
+	def __init__(self, unit_manager, profile_loader, profile_name=None, config=None):
4fe94b
 		log.debug("initializing daemon")
4fe94b
-		self._update_interval = update_interval
4fe94b
+		self._sleep_interval = int(consts.CFG_DEF_SLEEP_INTERVAL)
4fe94b
+		self._update_interval = int(consts.CFG_DEF_UPDATE_INTERVAL)
4fe94b
+		self._dynamic_tuning = consts.CFG_DEF_DYNAMIC_TUNING
4fe94b
+		if config is not None:
4fe94b
+			self._sleep_interval = int(config.get("sleep_interval", consts.CFG_DEF_SLEEP_INTERVAL))
4fe94b
+			self._update_interval = int(config.get("update_interval", consts.CFG_DEF_UPDATE_INTERVAL))
4fe94b
+			self._dynamic_tuning = config.get("dynamic_tuning", consts.CFG_DEF_DYNAMIC_TUNING)
4fe94b
+		if self._sleep_interval <= 0:
4fe94b
+			self._sleep_interval = int(consts.CFG_DEF_SLEEP_INTERVAL)
4fe94b
+		if self._update_interval == 0:
4fe94b
+			self._dynamic_tuning = False
4fe94b
+		elif self._update_interval < self._sleep_interval:
4fe94b
+			self._update_interval = self._sleep_interval
4fe94b
+		self._sleep_cycles = self._update_interval // self._sleep_interval
4fe94b
+		log.info("using sleep interval of %d second(s)" % self._sleep_interval)
4fe94b
+		if self._dynamic_tuning:
4fe94b
+			log.info("dynamic tuning is enabled (can be overriden by plugins)")
4fe94b
+			log.info("using update interval of %d second(s) (%d times of the sleep interval)" % (self._sleep_cycles * self._sleep_interval, self._sleep_cycles))
4fe94b
+
4fe94b
 		self._unit_manager = unit_manager
4fe94b
 		self._profile_loader = profile_loader
4fe94b
 		self._init_threads()
4fe94b
@@ -65,11 +83,21 @@ class Daemon(object):
4fe94b
 		self._save_active_profile(self._profile.name)
4fe94b
 		self._unit_manager.start_tuning()
4fe94b
 
4fe94b
-		while not tuned.utils.commands.wait(self._terminate, self._update_interval):
4fe94b
-			log.debug("updating monitors")
4fe94b
-			self._unit_manager.update_monitors()
4fe94b
-			log.debug("performing tunings")
4fe94b
-			self._unit_manager.update_tuning()
4fe94b
+		# In python 2 interpreter with applied patch for rhbz#917709 we need to periodically
4fe94b
+		# poll, otherwise the python will not have chance to update events / locks (due to GIL)
4fe94b
+		# and e.g. DBus control will not work. The polling interval of 1 seconds (which is
4fe94b
+		# the default) is still much better than 50 ms polling with unpatched interpreter.
4fe94b
+		# For more details see tuned rhbz#917587.
4fe94b
+		_sleep_cnt = self._sleep_cycles
4fe94b
+		while not tuned.utils.commands.wait(self._terminate, self._sleep_interval):
4fe94b
+			if self._dynamic_tuning:
4fe94b
+				_sleep_cnt -= 1
4fe94b
+				if _sleep_cnt <= 0:
4fe94b
+					_sleep_cnt = self._sleep_cycles
4fe94b
+					log.debug("updating monitors")
4fe94b
+					self._unit_manager.update_monitors()
4fe94b
+					log.debug("performing tunings")
4fe94b
+					self._unit_manager.update_tuning()
4fe94b
 
4fe94b
 		self._unit_manager.stop_tuning()
4fe94b
 		self._unit_manager.destroy_all()