winsys/radeon: handle non-zero finite timeout when waiting for buffers
authorMarek Olšák <marek.olsak@amd.com>
Sat, 22 Aug 2015 16:05:37 +0000 (18:05 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Sat, 29 Aug 2015 21:03:06 +0000 (23:03 +0200)
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
src/gallium/winsys/radeon/drm/radeon_drm_bo.c
src/gallium/winsys/radeon/drm/radeon_drm_cs.c

index 3a9ac445b2408efb192263d5a980dfdbeb87ba1b..600ced924ba8371e9bb0959cfbb444fe0ed82aac 100644 (file)
@@ -101,30 +101,54 @@ static struct radeon_bo *get_radeon_bo(struct pb_buffer *_buf)
     return bo;
 }
 
+static bool radeon_bo_is_busy(struct radeon_bo *bo)
+{
+    struct drm_radeon_gem_busy args = {0};
+
+    args.handle = bo->handle;
+    return drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_BUSY,
+                               &args, sizeof(args)) != 0;
+}
+
+static void radeon_bo_wait_idle(struct radeon_bo *bo)
+{
+    struct drm_radeon_gem_wait_idle args = {0};
+
+    args.handle = bo->handle;
+    while (drmCommandWrite(bo->rws->fd, DRM_RADEON_GEM_WAIT_IDLE,
+                           &args, sizeof(args)) == -EBUSY);
+}
+
 static bool radeon_bo_wait(struct pb_buffer *_buf, uint64_t timeout,
                            enum radeon_bo_usage usage)
 {
-   struct radeon_bo *bo = get_radeon_bo(_buf);
+    struct radeon_bo *bo = get_radeon_bo(_buf);
+    int64_t abs_timeout;
 
-   /* Wait if any ioctl is being submitted with this buffer. */
-   if (!os_wait_until_zero(&bo->num_active_ioctls, timeout))
-      return false;
+    /* No timeout. Just query. */
+    if (timeout == 0)
+        return !bo->num_active_ioctls && !radeon_bo_is_busy(bo);
 
-   /* TODO: handle arbitrary timeout */
-    if (!timeout) {
-        struct drm_radeon_gem_busy args = {0};
+    abs_timeout = os_time_get_absolute_timeout(timeout);
 
-        args.handle = bo->handle;
-        return drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_BUSY,
-                                   &args, sizeof(args)) == 0;
-    } else {
-        struct drm_radeon_gem_wait_idle args = {0};
+    /* Wait if any ioctl is being submitted with this buffer. */
+    if (!os_wait_until_zero_abs_timeout(&bo->num_active_ioctls, abs_timeout))
+        return false;
 
-        args.handle = bo->handle;
-        while (drmCommandWrite(bo->rws->fd, DRM_RADEON_GEM_WAIT_IDLE,
-                               &args, sizeof(args)) == -EBUSY);
+    /* Infinite timeout. */
+    if (abs_timeout == PIPE_TIMEOUT_INFINITE) {
+        radeon_bo_wait_idle(bo);
         return true;
     }
+
+    /* Other timeouts need to be emulated with a loop. */
+    while (radeon_bo_is_busy(bo)) {
+       if (os_time_get_nano() >= abs_timeout)
+          return false;
+       os_time_sleep(10);
+    }
+
+    return true;
 }
 
 static enum radeon_bo_domain get_valid_domain(enum radeon_bo_domain domain)
index f04a696988a0b3e6843f6a5351d77562203caa75..341af55df8b782411a86cb15ba48d0b00a58b839 100644 (file)
@@ -645,29 +645,8 @@ static bool radeon_fence_wait(struct radeon_winsys *ws,
                               struct pipe_fence_handle *fence,
                               uint64_t timeout)
 {
-    struct pb_buffer *rfence = (struct pb_buffer*)fence;
-
-    if (timeout == 0)
-        return ws->buffer_wait(rfence, 0, RADEON_USAGE_READWRITE);
-
-    if (timeout != PIPE_TIMEOUT_INFINITE) {
-        int64_t start_time = os_time_get();
-
-        /* Convert to microseconds. */
-        timeout /= 1000;
-
-        /* Wait in a loop. */
-        while (!ws->buffer_wait(rfence, 0, RADEON_USAGE_READWRITE)) {
-            if (os_time_get() - start_time >= timeout) {
-                return FALSE;
-            }
-            os_time_sleep(10);
-        }
-        return TRUE;
-    }
-
-    ws->buffer_wait(rfence, PIPE_TIMEOUT_INFINITE, RADEON_USAGE_READWRITE);
-    return TRUE;
+    return ws->buffer_wait((struct pb_buffer*)fence, timeout,
+                           RADEON_USAGE_READWRITE);
 }
 
 static void radeon_fence_reference(struct pipe_fence_handle **dst,