On Tue, 2009-02-17 at 15:26 -0500, Adam Jackson wrote:
> 
> Probably better to run the periodic defragger from a real timer, and arm
> it for 1s in the future from BlockHandler.  If the timer ever expires,
> you know you've been idle for a full second, so you can go ahead and do
> some idle work.

How about the below relative diff? It arms a 100ms timer from the
BlockHandler and cancels it from the WakeupHandler if Select() didn't
time out.

100ms is a trade-off between having a chance of expiring on almost but
not quite idle systems and not waking up too often on completely idle
systems. I'm open for suggestions for a better trade-off.

> Technically this has a minor failing when a single request takes more
> than a second but if that ever happens you're not a happy camper
> anyway.

I think that shouldn't be an issue with this: Our WakeupHandler should
cancel the timer if the server has something else to do.

Note though that it's only compile tested so far.


diff --git a/exa/exa.c b/exa/exa.c
index c86de3d..b0c96fb 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -882,6 +882,17 @@ exaCreateScreenResources(ScreenPtr pScreen)
     return TRUE;
 }
 
+static CARD32 ExaDefragTimerCallback(OsTimerPtr pTimer, CARD32 time,
+                                    pointer arg)
+{
+    /* Try and keep the offscreen memory area tidy every now and then when the
+     * server has been idle for at least 100ms.
+     */
+    ExaOffscreenDefragment(arg);
+
+    return 0;
+}
+
 static void
 ExaBlockHandler(int screenNum, pointer blockData, pointer pTimeout,
                pointer pReadmask)
@@ -889,14 +900,29 @@ ExaBlockHandler(int screenNum, pointer blockData, pointer 
pTimeout,
     ScreenPtr pScreen = screenInfo.screens[screenNum];
     ExaScreenPriv(pScreen);
 
-    /* Try and keep the offscreen memory area tidy every now and then when 
we're
-     * going idle anyway.
-     */
-    ExaOffscreenDefragment(pScreen);
-
     unwrap(pExaScr, pScreen, BlockHandler);
     (*pScreen->BlockHandler) (screenNum, blockData, pTimeout, pReadmask);
     wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler);
+
+    pExaScr->defragTimer = TimerSet(pExaScr->defragTimer, 0, 100,
+                                   ExaDefragTimerCallback, pScreen);
+}
+
+static void
+ExaWakeupHandler(int screenNum, pointer wakeupData, unsigned long result,
+                pointer pReadmask)
+{
+    ScreenPtr pScreen = screenInfo.screens[screenNum];
+    ExaScreenPriv(pScreen);
+
+    /* Prevent the timer callback from being called if Select() didn't time 
out.
+     */
+    if (result != 0)
+       TimerCancel(pExaScr->defragTimer);
+
+    unwrap(pExaScr, pScreen, WakeupHandler);
+    (*pScreen->WakeupHandler) (screenNum, wakeupData, result, pReadmask);
+    wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler);
 }
 
 /**
@@ -914,8 +940,13 @@ exaCloseScreen(int i, ScreenPtr pScreen)
     if (ps->Glyphs == exaGlyphs)
        exaGlyphsFini(pScreen);
 
+    if (pExaScr->defragTimer)
+       TimerFree(pExaScr->defragTimer);
+
     if (pScreen->BlockHandler == ExaBlockHandler)
        unwrap(pExaScr, pScreen, BlockHandler);
+    if (pScreen->WakeupHandler == ExaWakeupHandler)
+       unwrap(pExaScr, pScreen, WakeupHandler);
     unwrap(pExaScr, pScreen, CreateGC);
     unwrap(pExaScr, pScreen, CloseScreen);
     unwrap(pExaScr, pScreen, GetImage);
@@ -1076,8 +1107,10 @@ exaDriverInit (ScreenPtr         pScreen,
      * Replace various fb screen functions
      */
     if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) &&
-       !pExaScr->info->CreatePixmap)
+       !pExaScr->info->CreatePixmap) {
        wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler);
+       wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler);
+    }
     wrap(pExaScr, pScreen, CreateGC, exaCreateGC);
     wrap(pExaScr, pScreen, CloseScreen, exaCloseScreen);
     wrap(pExaScr, pScreen, GetImage, exaGetImage);
diff --git a/exa/exa_priv.h b/exa/exa_priv.h
index f787361..39e1c3d 100644
--- a/exa/exa_priv.h
+++ b/exa/exa_priv.h
@@ -134,6 +134,7 @@ typedef void (*EnableDisableFBAccessProcPtr)(int, Bool);
 typedef struct {
     ExaDriverPtr info;
     ScreenBlockHandlerProcPtr   SavedBlockHandler;
+    ScreenWakeupHandlerProcPtr  SavedWakeupHandler;
     CreateGCProcPtr             SavedCreateGC;
     CloseScreenProcPtr                  SavedCloseScreen;
     GetImageProcPtr             SavedGetImage;
@@ -160,6 +161,7 @@ typedef struct {
     Bool                        optimize_migration;
     unsigned                    offScreenCounter;
     CARD32                      lastDefragment;
+    OsTimerPtr                  defragTimer;
 
     /* Holds information on fallbacks that cannot be relayed otherwise. */
     unsigned int fallback_flags;


-- 
Earthling Michel Dänzer           |                http://www.vmware.com
Libre software enthusiast         |          Debian, X and DRI developer
_______________________________________________
xorg-devel mailing list
[email protected]
http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to