summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nouveau/nouveau_fence.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/nouveau/nouveau_fence.c')
-rw-r--r--src/gallium/drivers/nouveau/nouveau_fence.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/src/gallium/drivers/nouveau/nouveau_fence.c b/src/gallium/drivers/nouveau/nouveau_fence.c
index 691553a..9cbfc2a 100644
--- a/src/gallium/drivers/nouveau/nouveau_fence.c
+++ b/src/gallium/drivers/nouveau/nouveau_fence.c
@@ -71,12 +71,14 @@ nouveau_fence_emit(struct nouveau_fence *fence)
++fence->ref;
+ pipe_mutex_lock(screen->fence.list_mutex);
if (screen->fence.tail)
screen->fence.tail->next = fence;
else
screen->fence.head = fence;
screen->fence.tail = fence;
+ pipe_mutex_unlock(screen->fence.list_mutex);
screen->fence.emit(&screen->base, &fence->sequence);
@@ -90,6 +92,9 @@ nouveau_fence_del(struct nouveau_fence *fence)
struct nouveau_fence *it;
struct nouveau_screen *screen = fence->screen;
+ /* XXX This can race against fence_update. But fence_update can also call
+ * into this, so ... be have to be careful.
+ */
if (fence->state == NOUVEAU_FENCE_STATE_EMITTED ||
fence->state == NOUVEAU_FENCE_STATE_FLUSHED) {
if (fence == screen->fence.head) {
@@ -123,6 +128,7 @@ nouveau_fence_update(struct nouveau_screen *screen, bool flushed)
return;
screen->fence.sequence_ack = sequence;
+ pipe_mutex_lock(screen->fence.list_mutex);
for (fence = screen->fence.head; fence; fence = next) {
next = fence->next;
sequence = fence->sequence;
@@ -144,6 +150,7 @@ nouveau_fence_update(struct nouveau_screen *screen, bool flushed)
if (fence->state == NOUVEAU_FENCE_STATE_EMITTED)
fence->state = NOUVEAU_FENCE_STATE_FLUSHED;
}
+ pipe_mutex_unlock(screen->fence.list_mutex);
}
#define NOUVEAU_FENCE_MAX_SPINS (1 << 31)
@@ -198,18 +205,27 @@ nouveau_fence_wait(struct nouveau_fence *fence, struct pipe_debug_callback *debu
uint32_t spins = 0;
int64_t start = 0;
+ /* Fast-path for the case where the fence is already signaled to avoid
+ * messing around with mutexes and timing.
+ */
+ if (fence->state == NOUVEAU_FENCE_STATE_SIGNALLED)
+ return true;
+
if (debug && debug->debug_message)
start = os_time_get_nano();
if (!nouveau_fence_kick(fence))
return false;
+ pipe_mutex_unlock(screen->push_mutex);
+
do {
if (fence->state == NOUVEAU_FENCE_STATE_SIGNALLED) {
if (debug && debug->debug_message)
pipe_debug_message(debug, PERF_INFO,
"stalled %.3f ms waiting for fence",
(os_time_get_nano() - start) / 1000000.f);
+ pipe_mutex_lock(screen->push_mutex);
return true;
}
if (!spins)
@@ -227,6 +243,8 @@ nouveau_fence_wait(struct nouveau_fence *fence, struct pipe_debug_callback *debu
fence->sequence,
screen->fence.sequence_ack, screen->fence.sequence);
+ pipe_mutex_lock(screen->push_mutex);
+
return false;
}