aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2015-09-01 04:07:54 +0200
committerMarek Olšák <[email protected]>2015-09-03 18:41:40 +0200
commit35d0f12797237cdd38e7fd2c39d3c19e875875ca (patch)
treeb3e272b98facfcef8335b402f89a1655d6ed5033 /src
parent44dbaa1746833f2874786fc2067f8837f149261f (diff)
gallium/pb_bufmgr_cache: add a way to remove buffers from the cache explicitly
This must be done before exporting a buffer as dmabuf fds, because we lose track of who is using it and can't trust the reference counter. Cc: 11.0 <[email protected]> Reviewed-by: Alex Deucher <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr.h5
-rw-r--r--src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c42
2 files changed, 41 insertions, 6 deletions
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h
index 147ce39041c..1638d96a63b 100644
--- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h
@@ -166,6 +166,11 @@ pb_cache_manager_create(struct pb_manager *provider,
unsigned bypass_usage,
uint64_t maximum_cache_size);
+/**
+ * Remove a buffer from the cache, but keep it alive.
+ */
+void
+pb_cache_manager_remove_buffer(struct pb_buffer *buf);
struct pb_fence_ops;
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c
index 3b35049f679..cc8ae84bb1b 100644
--- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c
+++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c
@@ -104,18 +104,42 @@ pb_cache_manager(struct pb_manager *mgr)
}
+static void
+_pb_cache_manager_remove_buffer_locked(struct pb_cache_buffer *buf)
+{
+ struct pb_cache_manager *mgr = buf->mgr;
+
+ if (buf->head.next) {
+ LIST_DEL(&buf->head);
+ assert(mgr->numDelayed);
+ --mgr->numDelayed;
+ mgr->cache_size -= buf->base.size;
+ }
+ buf->mgr = NULL;
+}
+
+void
+pb_cache_manager_remove_buffer(struct pb_buffer *pb_buf)
+{
+ struct pb_cache_buffer *buf = (struct pb_cache_buffer*)pb_buf;
+ struct pb_cache_manager *mgr = buf->mgr;
+
+ if (!mgr)
+ return;
+
+ pipe_mutex_lock(mgr->mutex);
+ _pb_cache_manager_remove_buffer_locked(buf);
+ pipe_mutex_unlock(mgr->mutex);
+}
+
/**
* Actually destroy the buffer.
*/
static inline void
_pb_cache_buffer_destroy(struct pb_cache_buffer *buf)
{
- struct pb_cache_manager *mgr = buf->mgr;
-
- LIST_DEL(&buf->head);
- assert(mgr->numDelayed);
- --mgr->numDelayed;
- mgr->cache_size -= buf->base.size;
+ if (buf->mgr)
+ _pb_cache_manager_remove_buffer_locked(buf);
assert(!pipe_is_referenced(&buf->base.reference));
pb_reference(&buf->buffer, NULL);
FREE(buf);
@@ -156,6 +180,12 @@ pb_cache_buffer_destroy(struct pb_buffer *_buf)
struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
struct pb_cache_manager *mgr = buf->mgr;
+ if (!mgr) {
+ pb_reference(&buf->buffer, NULL);
+ FREE(buf);
+ return;
+ }
+
pipe_mutex_lock(mgr->mutex);
assert(!pipe_is_referenced(&buf->base.reference));