nouveau/fence: make the fence struct part of the fence API

This makes it easier to implement proper locking of the fence struct as we
can redesign some of the functions to take the list object instead of
fence objects.

Signed-off-by: Karol Herbst <kherbst@redhat.com>
Reviewed-by: M Henning <drawoc@darkrefraction.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10752>
This commit is contained in:
Karol Herbst
2021-02-09 20:32:15 +01:00
committed by Marge Bot
parent 1abc27983a
commit 0642f95c4e
6 changed files with 54 additions and 44 deletions

View File

@@ -59,6 +59,7 @@ void
nouveau_fence_emit(struct nouveau_fence *fence)
{
struct nouveau_screen *screen = fence->screen;
struct nouveau_fence_list *fence_list = &screen->fence;
assert(fence->state != NOUVEAU_FENCE_STATE_EMITTING);
if (fence->state >= NOUVEAU_FENCE_STATE_EMITTED)
@@ -69,14 +70,14 @@ nouveau_fence_emit(struct nouveau_fence *fence)
++fence->ref;
if (screen->fence.tail)
screen->fence.tail->next = fence;
if (fence_list->tail)
fence_list->tail->next = fence;
else
screen->fence.head = fence;
fence_list->head = fence;
screen->fence.tail = fence;
fence_list->tail = fence;
screen->fence.emit(&screen->base, &fence->sequence);
fence_list->emit(&screen->base, &fence->sequence);
assert(fence->state == NOUVEAU_FENCE_STATE_EMITTING);
fence->state = NOUVEAU_FENCE_STATE_EMITTED;
@@ -86,19 +87,19 @@ void
nouveau_fence_del(struct nouveau_fence *fence)
{
struct nouveau_fence *it;
struct nouveau_screen *screen = fence->screen;
struct nouveau_fence_list *fence_list = &fence->screen->fence;
if (fence->state == NOUVEAU_FENCE_STATE_EMITTED ||
fence->state == NOUVEAU_FENCE_STATE_FLUSHED) {
if (fence == screen->fence.head) {
screen->fence.head = fence->next;
if (!screen->fence.head)
screen->fence.tail = NULL;
if (fence == fence_list->head) {
fence_list->head = fence->next;
if (!fence_list->head)
fence_list->tail = NULL;
} else {
for (it = screen->fence.head; it && it->next != fence; it = it->next);
for (it = fence_list->head; it && it->next != fence; it = it->next);
it->next = fence->next;
if (screen->fence.tail == fence)
screen->fence.tail = it;
if (fence_list->tail == fence)
fence_list->tail = it;
}
}
@@ -111,18 +112,18 @@ nouveau_fence_del(struct nouveau_fence *fence)
}
void
nouveau_fence_cleanup(struct nouveau_screen *screen)
nouveau_fence_cleanup(struct nouveau_fence_list *fence_list)
{
if (screen->fence.current) {
if (fence_list->current) {
struct nouveau_fence *current = NULL;
/* nouveau_fence_wait will create a new current fence, so wait on the
* _current_ one, and remove both.
*/
nouveau_fence_ref(screen->fence.current, &current);
nouveau_fence_ref(fence_list->current, &current);
nouveau_fence_wait(current, NULL);
nouveau_fence_ref(NULL, &current);
nouveau_fence_ref(NULL, &screen->fence.current);
nouveau_fence_ref(NULL, &fence_list->current);
}
}
@@ -131,7 +132,8 @@ nouveau_fence_update(struct nouveau_screen *screen, bool flushed)
{
struct nouveau_fence *fence;
struct nouveau_fence *next = NULL;
u32 sequence = screen->fence.update(&screen->base);
struct nouveau_fence_list *fence_list = &screen->fence;
u32 sequence = fence_list->update(&screen->base);
/* If running under drm-shim, let all fences be signalled so things run to
* completion (avoids a hang at the end of shader-db).
@@ -139,11 +141,11 @@ nouveau_fence_update(struct nouveau_screen *screen, bool flushed)
if (unlikely(screen->disable_fences))
sequence = screen->fence.sequence;
if (screen->fence.sequence_ack == sequence)
if (fence_list->sequence_ack == sequence)
return;
screen->fence.sequence_ack = sequence;
fence_list->sequence_ack = sequence;
for (fence = screen->fence.head; fence; fence = next) {
for (fence = fence_list->head; fence; fence = next) {
next = fence->next;
sequence = fence->sequence;
@@ -152,12 +154,12 @@ nouveau_fence_update(struct nouveau_screen *screen, bool flushed)
nouveau_fence_trigger_work(fence);
nouveau_fence_ref(NULL, &fence);
if (sequence == screen->fence.sequence_ack)
if (sequence == fence_list->sequence_ack)
break;
}
screen->fence.head = next;
fence_list->head = next;
if (!next)
screen->fence.tail = NULL;
fence_list->tail = NULL;
if (flushed) {
for (fence = next; fence; fence = fence->next)
@@ -186,6 +188,7 @@ static bool
nouveau_fence_kick(struct nouveau_fence *fence)
{
struct nouveau_screen *screen = fence->screen;
struct nouveau_fence_list *fence_list = &screen->fence;
/* wtf, someone is waiting on a fence in flush_notify handler? */
assert(fence->state != NOUVEAU_FENCE_STATE_EMITTING);
@@ -199,7 +202,7 @@ nouveau_fence_kick(struct nouveau_fence *fence)
if (nouveau_pushbuf_kick(screen->pushbuf, screen->pushbuf->channel))
return false;
if (fence == screen->fence.current)
if (fence == fence_list->current)
nouveau_fence_next(screen);
nouveau_fence_update(screen, false);
@@ -211,6 +214,7 @@ bool
nouveau_fence_wait(struct nouveau_fence *fence, struct util_debug_callback *debug)
{
struct nouveau_screen *screen = fence->screen;
struct nouveau_fence_list *fence_list = &screen->fence;
uint32_t spins = 0;
int64_t start = 0;
@@ -241,7 +245,7 @@ nouveau_fence_wait(struct nouveau_fence *fence, struct util_debug_callback *debu
debug_printf("Wait on fence %u (ack = %u, next = %u) timed out !\n",
fence->sequence,
screen->fence.sequence_ack, screen->fence.sequence);
fence_list->sequence_ack, fence_list->sequence);
return false;
}
@@ -249,16 +253,18 @@ nouveau_fence_wait(struct nouveau_fence *fence, struct util_debug_callback *debu
void
nouveau_fence_next(struct nouveau_screen *screen)
{
if (screen->fence.current->state < NOUVEAU_FENCE_STATE_EMITTING) {
if (screen->fence.current->ref > 1)
nouveau_fence_emit(screen->fence.current);
struct nouveau_fence_list *fence_list = &screen->fence;
if (fence_list->current->state < NOUVEAU_FENCE_STATE_EMITTING) {
if (fence_list->current->ref > 1)
nouveau_fence_emit(fence_list->current);
else
return;
}
nouveau_fence_ref(NULL, &screen->fence.current);
nouveau_fence_ref(NULL, &fence_list->current);
nouveau_fence_new(screen, &screen->fence.current);
nouveau_fence_new(screen, &fence_list->current);
}
void

View File

@@ -29,11 +29,21 @@ struct nouveau_fence {
struct list_head work;
};
struct nouveau_fence_list {
struct nouveau_fence *head;
struct nouveau_fence *tail;
struct nouveau_fence *current;
uint32_t sequence;
uint32_t sequence_ack;
void (*emit)(struct pipe_screen *, uint32_t *sequence);
uint32_t (*update)(struct pipe_screen *);
};
void nouveau_fence_emit(struct nouveau_fence *);
void nouveau_fence_del(struct nouveau_fence *);
bool nouveau_fence_new(struct nouveau_screen *, struct nouveau_fence **);
void nouveau_fence_cleanup(struct nouveau_screen *);
void nouveau_fence_cleanup(struct nouveau_fence_list *);
bool nouveau_fence_work(struct nouveau_fence *, void (*)(void *), void *);
void nouveau_fence_update(struct nouveau_screen *, bool flushed);
void nouveau_fence_next(struct nouveau_screen *);

View File

@@ -6,6 +6,8 @@
#include "util/u_atomic.h"
#include "util/u_memory.h"
#include "nouveau_fence.h"
#ifndef NDEBUG
# define NOUVEAU_ENABLE_DRIVER_STATISTICS
#endif
@@ -44,15 +46,7 @@ struct nouveau_screen {
uint16_t class_3d;
struct {
struct nouveau_fence *head;
struct nouveau_fence *tail;
struct nouveau_fence *current;
u32 sequence;
u32 sequence_ack;
void (*emit)(struct pipe_screen *, u32 *sequence);
u32 (*update)(struct pipe_screen *);
} fence;
struct nouveau_fence_list fence;
struct nouveau_mman *mm_VRAM;
struct nouveau_mman *mm_GART;

View File

@@ -549,7 +549,7 @@ nv30_screen_destroy(struct pipe_screen *pscreen)
if (!nouveau_drm_screen_unref(&screen->base))
return;
nouveau_fence_cleanup(&screen->base);
nouveau_fence_cleanup(&screen->base.fence);
nouveau_bo_ref(NULL, &screen->notify);

View File

@@ -624,7 +624,7 @@ nv50_screen_destroy(struct pipe_screen *pscreen)
if (!nouveau_drm_screen_unref(&screen->base))
return;
nouveau_fence_cleanup(&screen->base);
nouveau_fence_cleanup(&screen->base.fence);
if (screen->base.pushbuf)
screen->base.pushbuf->user_priv = NULL;

View File

@@ -715,7 +715,7 @@ nvc0_screen_destroy(struct pipe_screen *pscreen)
if (!nouveau_drm_screen_unref(&screen->base))
return;
nouveau_fence_cleanup(&screen->base);
nouveau_fence_cleanup(&screen->base.fence);
if (screen->base.pushbuf)
screen->base.pushbuf->user_priv = NULL;