summaryrefslogtreecommitdiff
path: root/lib/mesa/src/gallium/winsys/svga/drm/vmw_fence.c
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2018-10-23 06:36:00 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2018-10-23 06:36:00 +0000
commitb65fcab046d3a1b6b6ac315720df220925c5322e (patch)
treeff73dcc383ac0799c655ff6194cda9dacb75dde9 /lib/mesa/src/gallium/winsys/svga/drm/vmw_fence.c
parent18d6381c51e253e4c41c62619f80d9ce745b95c8 (diff)
Merge Mesa 17.3.9
Mesa 18.x needs an ld with build-id for at least the intel code Mesa 18.2 assumes linux only memfd syscalls in intel code Tested by matthieu@, kettenis@ and myself on a variety of hardware and architectures. ok kettenis@
Diffstat (limited to 'lib/mesa/src/gallium/winsys/svga/drm/vmw_fence.c')
-rw-r--r--lib/mesa/src/gallium/winsys/svga/drm/vmw_fence.c98
1 files changed, 81 insertions, 17 deletions
diff --git a/lib/mesa/src/gallium/winsys/svga/drm/vmw_fence.c b/lib/mesa/src/gallium/winsys/svga/drm/vmw_fence.c
index bcf473a93..061f588c8 100644
--- a/lib/mesa/src/gallium/winsys/svga/drm/vmw_fence.c
+++ b/lib/mesa/src/gallium/winsys/svga/drm/vmw_fence.c
@@ -22,6 +22,8 @@
* SOFTWARE.
*
**********************************************************/
+#include <libsync.h>
+
#include "util/u_memory.h"
#include "util/u_atomic.h"
#include "util/list.h"
@@ -32,7 +34,7 @@
#include "vmw_screen.h"
#include "vmw_fence.h"
-struct vmw_fence_ops
+struct vmw_fence_ops
{
/*
* Immutable members.
@@ -40,7 +42,7 @@ struct vmw_fence_ops
struct pb_fence_ops base;
struct vmw_winsys_screen *vws;
- pipe_mutex mutex;
+ mtx_t mutex;
/*
* Protected by mutex;
@@ -58,6 +60,8 @@ struct vmw_fence
uint32_t mask;
int32_t signalled;
uint32_t seqno;
+ int32_t fence_fd;
+ boolean imported; /* TRUE if imported from another process */
};
/**
@@ -101,10 +105,10 @@ vmw_fences_release(struct vmw_fence_ops *ops)
{
struct vmw_fence *fence, *n;
- pipe_mutex_lock(ops->mutex);
+ mtx_lock(&ops->mutex);
LIST_FOR_EACH_ENTRY_SAFE(fence, n, &ops->not_signaled, ops_list)
LIST_DELINIT(&fence->ops_list);
- pipe_mutex_unlock(ops->mutex);
+ mtx_unlock(&ops->mutex);
}
/**
@@ -130,7 +134,7 @@ vmw_fences_signal(struct pb_fence_ops *fence_ops,
return;
ops = vmw_fence_ops(fence_ops);
- pipe_mutex_lock(ops->mutex);
+ mtx_lock(&ops->mutex);
if (!has_emitted) {
emitted = ops->last_emitted;
@@ -152,7 +156,7 @@ vmw_fences_signal(struct pb_fence_ops *fence_ops,
ops->last_emitted = emitted;
out_unlock:
- pipe_mutex_unlock(ops->mutex);
+ mtx_unlock(&ops->mutex);
}
@@ -175,15 +179,16 @@ vmw_fence(struct pipe_fence_handle *fence)
* @fence_ops: The fence_ops manager to register with.
* @handle: Handle identifying the kernel fence object.
* @mask: Mask of flags that this fence object may signal.
+ * @fd: File descriptor to associate with the fence
*
* Returns NULL on failure.
*/
struct pipe_fence_handle *
vmw_fence_create(struct pb_fence_ops *fence_ops, uint32_t handle,
- uint32_t seqno, uint32_t mask)
+ uint32_t seqno, uint32_t mask, int32_t fd)
{
struct vmw_fence *fence = CALLOC_STRUCT(vmw_fence);
- struct vmw_fence_ops *ops = vmw_fence_ops(fence_ops);
+ struct vmw_fence_ops *ops = NULL;
if (!fence)
return NULL;
@@ -192,8 +197,21 @@ vmw_fence_create(struct pb_fence_ops *fence_ops, uint32_t handle,
fence->handle = handle;
fence->mask = mask;
fence->seqno = seqno;
+ fence->fence_fd = fd;
p_atomic_set(&fence->signalled, 0);
- pipe_mutex_lock(ops->mutex);
+
+ /*
+ * If the fence was not created by our device, then we won't
+ * manage it with our ops
+ */
+ if (!fence_ops) {
+ fence->imported = true;
+ return (struct pipe_fence_handle *) fence;
+ }
+
+ ops = vmw_fence_ops(fence_ops);
+
+ mtx_lock(&ops->mutex);
if (vmw_fence_seq_is_signaled(seqno, ops->last_signaled, seqno)) {
p_atomic_set(&fence->signalled, 1);
@@ -203,13 +221,28 @@ vmw_fence_create(struct pb_fence_ops *fence_ops, uint32_t handle,
LIST_ADDTAIL(&fence->ops_list, &ops->not_signaled);
}
- pipe_mutex_unlock(ops->mutex);
+ mtx_unlock(&ops->mutex);
return (struct pipe_fence_handle *) fence;
}
/**
+ * vmw_fence_destroy - Frees a vmw fence object.
+ *
+ * Also closes the file handle associated with the object, if any
+ */
+static
+void vmw_fence_destroy(struct vmw_fence *vfence)
+{
+ if (vfence->fence_fd != -1)
+ close(vfence->fence_fd);
+
+ FREE(vfence);
+}
+
+
+/**
* vmw_fence_reference - Reference / unreference a vmw fence object.
*
* @vws: Pointer to the winsys screen.
@@ -227,13 +260,15 @@ vmw_fence_reference(struct vmw_winsys_screen *vws,
if (p_atomic_dec_zero(&vfence->refcount)) {
struct vmw_fence_ops *ops = vmw_fence_ops(vws->fence_ops);
- vmw_ioctl_fence_unref(vws, vfence->handle);
+ if (!vfence->imported) {
+ vmw_ioctl_fence_unref(vws, vfence->handle);
- pipe_mutex_lock(ops->mutex);
- LIST_DELINIT(&vfence->ops_list);
- pipe_mutex_unlock(ops->mutex);
+ mtx_lock(&ops->mutex);
+ LIST_DELINIT(&vfence->ops_list);
+ mtx_unlock(&ops->mutex);
+ }
- FREE(vfence);
+ vmw_fence_destroy(vfence);
}
}
@@ -300,6 +335,7 @@ vmw_fence_signalled(struct vmw_winsys_screen *vws,
*
* @vws: Pointer to the winsys screen.
* @fence: Handle to the fence object.
+ * @timeout: How long to wait before timing out.
* @flag: Fence flags to wait for. If the fence object can't signal
* a flag, it is assumed to be already signaled.
*
@@ -308,6 +344,7 @@ vmw_fence_signalled(struct vmw_winsys_screen *vws,
int
vmw_fence_finish(struct vmw_winsys_screen *vws,
struct pipe_fence_handle *fence,
+ uint64_t timeout,
unsigned flag)
{
struct vmw_fence *vfence;
@@ -319,6 +356,16 @@ vmw_fence_finish(struct vmw_winsys_screen *vws,
return 0;
vfence = vmw_fence(fence);
+
+ if (vfence->imported) {
+ ret = sync_wait(vfence->fence_fd, timeout / 1000000);
+
+ if (!ret)
+ p_atomic_set(&vfence->signalled, 1);
+
+ return !!ret;
+ }
+
old = p_atomic_read(&vfence->signalled);
vflags &= ~vfence->mask;
@@ -339,6 +386,23 @@ vmw_fence_finish(struct vmw_winsys_screen *vws,
return ret;
}
+/**
+ * vmw_fence_get_fd
+ *
+ * Returns the file descriptor associated with the fence
+ */
+int
+vmw_fence_get_fd(struct pipe_fence_handle *fence)
+{
+ struct vmw_fence *vfence;
+
+ if (!fence)
+ return -1;
+
+ vfence = vmw_fence(fence);
+ return vfence->fence_fd;
+}
+
/**
* vmw_fence_ops_fence_reference - wrapper for the pb_fence_ops api.
@@ -383,7 +447,7 @@ vmw_fence_ops_fence_finish(struct pb_fence_ops *ops,
{
struct vmw_winsys_screen *vws = vmw_fence_ops(ops)->vws;
- return vmw_fence_finish(vws, fence, flag);
+ return vmw_fence_finish(vws, fence, PIPE_TIMEOUT_INFINITE, flag);
}
@@ -421,7 +485,7 @@ vmw_fence_ops_create(struct vmw_winsys_screen *vws)
if(!ops)
return NULL;
- pipe_mutex_init(ops->mutex);
+ (void) mtx_init(&ops->mutex, mtx_plain);
LIST_INITHEAD(&ops->not_signaled);
ops->base.destroy = &vmw_fence_ops_destroy;
ops->base.fence_reference = &vmw_fence_ops_fence_reference;