[PATCH] EXA: Defragment offscreen memory.

Michel Dänzer michel at daenzer.net
Sat Feb 21 04:03:51 PST 2009


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


More information about the xorg-devel mailing list