[PATCH] dix: Fix Client starvation with SmartScheduler priorities

Chris Wilson chris at chris-wilson.co.uk
Wed Oct 9 06:28:51 PDT 2013


Given the right mix of clients competing for server time, it is possible
for some of those clients to be starved. In a CPU bound system,
executing clients consume their entire ScheduleSlice and are demoted for
being busy. These clients then may block waiting for a reply from the
XServer freeing up CPU time such that the next client will complete its
task within the ScheduleSlice and not be demoted. In this manner, we
progressively starve more and more clients until we have sufficient CPU
time to execute the remaining ones, and under the right conditions we
will have a set that can remain permanently busy, and a set that are
blocked.

A simple example is to execute 16 identical copies of a rendering
benchmark and measure the standard deviation in the number of frames they
are able to complete within 60 seconds. (The benchmark uses client-side
throttling and so frees up CPU timeslices whilst waiting for a GetImage
reply after each frame. The benchmark doesn't listen to input events and
so does not receive the priority boost used to reduce input latency.)

Using dumbSched:  57.0 +- 0.4 fps
Using smartSched: 66.4 +- 9.8 fps
After patching:   65.2 +- 1.2 fps

More importantly, given the right conditions it is very easy to starve
clients completely. That starvation is prevented by this patch.

The solution employed here is to undo the busy demotion after a period
of idleness. Currently the idle boost is applied only once for a fresh
client when it becomes selectable. The change is to apply that boost for
all clients that remain ready for the entire duration of idle timeslice -
eventually these old busy clients will be promoted sufficiently to
be granted a ScheduleSlice.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 dix/dispatch.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/dix/dispatch.c b/dix/dispatch.c
index 4fecfea..0da37ae 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -259,12 +259,12 @@ SmartScheduleClient(int *clientReady, int nready)
     for (i = 0; i < nready; i++) {
         client = clientReady[i];
         pClient = clients[client];
-        /* Praise clients which are idle */
+        /* Praise clients which have been idle */
         if ((now - pClient->smart_check_tick) >= idle) {
             if (pClient->smart_priority < 0)
                 pClient->smart_priority++;
+	    pClient->smart_check_tick = now;
         }
-        pClient->smart_check_tick = now;
 
         /* check priority to select best client */
         robin =
-- 
1.8.4.rc3



More information about the xorg-devel mailing list