i915: Real fix for weird fence leak. Thanks Thomas
authorJakob Bornecrantz <jakob@tungstengraphics.com>
Wed, 23 Apr 2008 09:56:35 +0000 (11:56 +0200)
committerJakob Bornecrantz <jakob@tungstengraphics.com>
Wed, 23 Apr 2008 09:56:35 +0000 (11:56 +0200)
src/gallium/winsys/dri/intel/intel_swapbuffers.c
src/gallium/winsys/dri/intel/ws_dri_slabpool.c

index f029dd6a90ddafa32f03cd1b029def3c4b32f493..923b5427714f6039a83385a175d0ccf4b3467533 100644 (file)
@@ -62,7 +62,7 @@ intelDisplaySurface(__DRIdrawablePrivate *dPriv,
    }
 
    if (intel->last_swap_fence) {
-      driFenceFinish(intel->last_swap_fence, driFenceType(intel->last_swap_fence), GL_FALSE);
+      driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, TRUE);
       driFenceUnReference(&intel->last_swap_fence);
       intel->last_swap_fence = NULL;
    }
index 235f0ac97260a9c34b3e95adfe77e710bfcbe073..62d82bbd946f933cd7f89ac7672a465dc136f83e 100644 (file)
@@ -227,6 +227,7 @@ driAllocKernelBO(struct _DriSlabSizeHeader *header)
     drmMMListHead *list, *next, *head;
     uint32_t size = header->bufSize * slabPool->desiredNumBuffers;
     struct _DriKernelBO *kbo;
+    struct _DriKernelBO *kboTmp;
     int ret;
 
     /*
@@ -248,27 +249,36 @@ driAllocKernelBO(struct _DriSlabSizeHeader *header)
         list != head;
         list = next, next = list->next) {
 
-       kbo = DRMLISTENTRY(struct _DriKernelBO, list, head);
+       kboTmp = DRMLISTENTRY(struct _DriKernelBO, list, head);
 
-       if ((kbo->bo.size == size) &&
+       if ((kboTmp->bo.size == size) &&
            (slabPool->pageAlignment == 0 ||
-            (kbo->pageAlignment % slabPool->pageAlignment) == 0)) {
+            (kboTmp->pageAlignment % slabPool->pageAlignment) == 0)) {
+
+           if (!kbo)
+               kbo = kboTmp;
+
+           if ((kbo->bo.proposedFlags ^ slabPool->proposedFlags) == 0)
+               break;
 
-           DRMLISTDELINIT(&kbo->head);
-           DRMLISTDELINIT(&kbo->timeoutHead);
-           break;
        }
+    }
 
-       kbo = NULL;
+    if (kbo) {
+       DRMLISTDELINIT(&kbo->head);
+       DRMLISTDELINIT(&kbo->timeoutHead);
     }
 
     _glthread_UNLOCK_MUTEX(fMan->mutex);
 
     if (kbo) {
+        uint64_t new_mask = kbo->bo.proposedFlags ^ slabPool->proposedFlags;
+
        ret = 0;
-       ret = drmBOSetStatus(kbo->fd, &kbo->bo, slabPool->proposedFlags,
-                            (slabPool->proposedFlags ^ kbo->bo.flags),
-                            DRM_BO_HINT_DONT_FENCE, 0, 0);
+       if (new_mask) {
+           ret = drmBOSetStatus(kbo->fd, &kbo->bo, slabPool->proposedFlags,
+                                new_mask, DRM_BO_HINT_DONT_FENCE, 0, 0);
+       }
        if (ret == 0)
            return kbo;
 
@@ -284,7 +294,6 @@ driAllocKernelBO(struct _DriSlabSizeHeader *header)
     kbo->fd = slabPool->fd;
     DRMINITLISTHEAD(&kbo->head);
     DRMINITLISTHEAD(&kbo->timeoutHead);
-
     ret = drmBOCreate(kbo->fd, size, slabPool->pageAlignment, NULL,
                      slabPool->proposedFlags,
                      DRM_BO_HINT_DONT_FENCE, &kbo->bo);
@@ -417,47 +426,61 @@ driSlabFreeBufferLocked(struct _DriSlabBuffer *buf)
 static void
 driSlabCheckFreeLocked(struct _DriSlabSizeHeader *header, int wait)
 {
-   drmMMListHead *list, *prev;
+  drmMMListHead *list, *prev, *first;
    struct _DriSlabBuffer *buf;
    struct _DriSlab *slab;
-
-   int signaled = 0;
+   int firstWasSignaled = 1;
+   int signaled;
    int i;
    int ret;
 
-   list = header->delayedBuffers.next;
-
-   /* Only examine the oldest 1/3 of delayed buffers:
+   /*
+    * Rerun the freeing test if the youngest tested buffer
+    * was signaled, since there might be more idle buffers
+    * in the delay list.
     */
-   if (header->numDelayed > 3) {
-      for (i = 0; i < header->numDelayed; i += 3) {
-         list = list->next;
-      }
-   }
 
-   prev = list->prev;
-   for (; list != &header->delayedBuffers; list = prev, prev = list->prev) {
-       buf = DRMLISTENTRY(struct _DriSlabBuffer, list, head);
-       slab = buf->parent;
-
-       if (!signaled) {
-          if (wait) {
-              ret = driFenceFinish(buf->fence, buf->fenceType, 0);
-              if (ret)
-                  break;
-              signaled = 1;
-          } else {
-              signaled = driFenceSignaled(buf->fence, buf->fenceType);
+   while (firstWasSignaled) {
+       firstWasSignaled = 0;
+       signaled = 0;
+       first = header->delayedBuffers.next;
+
+       /* Only examine the oldest 1/3 of delayed buffers:
+       */
+       if (header->numDelayed > 3) {
+          for (i = 0; i < header->numDelayed; i += 3) {
+              first = first->next;
           }
-          if (signaled) {
+       }
+
+       for (list = first, prev = list->prev;
+           list != &header->delayedBuffers;
+           list = prev, prev = list->prev) {
+          buf = DRMLISTENTRY(struct _DriSlabBuffer, list, head);
+          slab = buf->parent;
+
+          if (!signaled) {
+              if (wait) {
+                  ret = driFenceFinish(buf->fence, buf->fenceType, 0);
+                  if (ret)
+                      break;
+                  signaled = 1;
+                  wait = 0;
+              } else {
+                  signaled = driFenceSignaled(buf->fence, buf->fenceType);
+              }
+              if (signaled) {
+                  if (list == first)
+                      firstWasSignaled = 1;
+                  driFenceUnReference(&buf->fence);
+                  header->numDelayed--;
+                  driSlabFreeBufferLocked(buf);
+              }
+          } else if (driFenceSignaledCached(buf->fence, buf->fenceType)) {
               driFenceUnReference(&buf->fence);
               header->numDelayed--;
               driSlabFreeBufferLocked(buf);
           }
-       } else if (driFenceSignaledCached(buf->fence, buf->fenceType)) {
-          driFenceUnReference(&buf->fence);
-          header->numDelayed--;
-          driSlabFreeBufferLocked(buf);
        }
    }
 }
@@ -480,15 +503,14 @@ driSlabAllocBuffer(struct _DriSlabSizeHeader *header)
        _glthread_UNLOCK_MUTEX(header->mutex);
        if (count != DRI_SLABPOOL_ALLOC_RETRIES)
            usleep(1);
-       (void) driAllocSlab(header);
        _glthread_LOCK_MUTEX(header->mutex);
+       (void) driAllocSlab(header);
        count--;
     }
 
     list = header->slabs.next;
     if (list == &header->slabs) {
        _glthread_UNLOCK_MUTEX(header->mutex);
-       //assert(0, "no buffers in slab");
        return NULL;
     }
     slab = DRMLISTENTRY(struct _DriSlab, list, head);
@@ -514,7 +536,6 @@ pool_create(struct _DriBufferPool *driPool, unsigned long size,
     int i;
     int ret;
 
-
     /*
      * FIXME: Check for compatibility.
      */
@@ -605,6 +626,8 @@ pool_destroy(struct _DriBufferPool *driPool, void *private)
        DRMLISTADDTAIL(&buf->head, &header->delayedBuffers);
        header->numDelayed++;
     } else {
+       if (buf->fence)
+           driFenceUnReference(&buf->fence);
        driSlabFreeBufferLocked(buf);
     }