[Mesa-dev] [PATCH] nouveau: avoid queueing too much work onto a single fence

Jan Vesely jan.vesely at rutgers.edu
Thu Nov 5 22:27:00 PST 2015


On Fri, 2015-11-06 at 00:46 -0500, Ilia Mirkin wrote:
> Force the fence to get kicked off, which won't actually wait for its
> completion, but any additional work will be put onto a fresh list.
> 
> This fixes crashes in teximage-colors --benchmark with too many
> active
> maps.
> 
> Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
> ---
>  src/gallium/drivers/nouveau/nouveau_fence.c | 68 ++++++++++++++++++-
> ----------
>  src/gallium/drivers/nouveau/nouveau_fence.h |  1 +
>  2 files changed, 43 insertions(+), 26 deletions(-)
> 
> diff --git a/src/gallium/drivers/nouveau/nouveau_fence.c
> b/src/gallium/drivers/nouveau/nouveau_fence.c
> index d3a3406..691553a 100644
> --- a/src/gallium/drivers/nouveau/nouveau_fence.c
> +++ b/src/gallium/drivers/nouveau/nouveau_fence.c
> @@ -59,26 +59,6 @@ nouveau_fence_trigger_work(struct nouveau_fence
> *fence)
>     }
>  }
>  
> -bool
> -nouveau_fence_work(struct nouveau_fence *fence,
> -                   void (*func)(void *), void *data)
> -{
> -   struct nouveau_fence_work *work;
> -
> -   if (!fence || fence->state == NOUVEAU_FENCE_STATE_SIGNALLED) {
> -      func(data);
> -      return true;
> -   }
> -
> -   work = CALLOC_STRUCT(nouveau_fence_work);
> -   if (!work)
> -      return false;
> -   work->func = func;
> -   work->data = data;
> -   LIST_ADD(&work->list, &fence->work);
> -   return true;
> -}
> -
>  void
>  nouveau_fence_emit(struct nouveau_fence *fence)
>  {
> @@ -182,12 +162,10 @@ nouveau_fence_signalled(struct nouveau_fence
> *fence)
>     return fence->state == NOUVEAU_FENCE_STATE_SIGNALLED;
>  }
>  
> -bool
> -nouveau_fence_wait(struct nouveau_fence *fence, struct
> pipe_debug_callback *debug)
> +static bool
> +nouveau_fence_kick(struct nouveau_fence *fence)
>  {
>     struct nouveau_screen *screen = fence->screen;
> -   uint32_t spins = 0;
> -   int64_t start = 0;
>  
>     /* wtf, someone is waiting on a fence in flush_notify handler? */
>     assert(fence->state != NOUVEAU_FENCE_STATE_EMITTING);
> @@ -208,12 +186,25 @@ nouveau_fence_wait(struct nouveau_fence *fence,
> struct pipe_debug_callback *debu
>     if (fence == screen->fence.current)
>        nouveau_fence_next(screen);
>  
> +   nouveau_fence_update(screen, false);
> +
> +   return true;
> +}
> +
> +bool
> +nouveau_fence_wait(struct nouveau_fence *fence, struct
> pipe_debug_callback *debug)
> +{
> +   struct nouveau_screen *screen = fence->screen;
> +   uint32_t spins = 0;
> +   int64_t start = 0;
> +
>     if (debug && debug->debug_message)
>        start = os_time_get_nano();
>  
> -   do {
> -      nouveau_fence_update(screen, false);
> +   if (!nouveau_fence_kick(fence))
> +      return false;
>  
> +   do {
>        if (fence->state == NOUVEAU_FENCE_STATE_SIGNALLED) {
>           if (debug && debug->debug_message)
>              pipe_debug_message(debug, PERF_INFO,
> @@ -228,6 +219,8 @@ nouveau_fence_wait(struct nouveau_fence *fence,
> struct pipe_debug_callback *debu
>        if (!(spins % 8)) /* donate a few cycles */
>           sched_yield();
>  #endif
> +
> +      nouveau_fence_update(screen, false);
>     } while (spins < NOUVEAU_FENCE_MAX_SPINS);
>  
>     debug_printf("Wait on fence %u (ack = %u, next = %u) timed out
> !\n",
> @@ -259,3 +252,26 @@ nouveau_fence_unref_bo(void *data)
>  
>     nouveau_bo_ref(NULL, &bo);
>  }
> +
> +bool
> +nouveau_fence_work(struct nouveau_fence *fence,
> +                   void (*func)(void *), void *data)
> +{
> +   struct nouveau_fence_work *work;
> +
> +   if (!fence || fence->state == NOUVEAU_FENCE_STATE_SIGNALLED) {
> +      func(data);
> +      return true;
> +   }
> +
> +   work = CALLOC_STRUCT(nouveau_fence_work);
> +   if (!work)
> +      return false;
> +   work->func = func;
> +   work->data = data;
> +   LIST_ADD(&work->list, &fence->work);
> +   p_atomic_inc(&fence->work_count);
> +   if (fence->work_count > 64)

Is 64 just an arbitrary number?

> +      nouveau_fence_kick(fence);
> +   return true;
> +}
> diff --git a/src/gallium/drivers/nouveau/nouveau_fence.h
> b/src/gallium/drivers/nouveau/nouveau_fence.h
> index 0fa9d02..f10016d 100644
> --- a/src/gallium/drivers/nouveau/nouveau_fence.h
> +++ b/src/gallium/drivers/nouveau/nouveau_fence.h
> @@ -25,6 +25,7 @@ struct nouveau_fence {
>     int state;
>     int ref;
>     uint32_t sequence;
> +   uint32_t work_count;
>     struct list_head work;
>  };
>  
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20151106/daa8483e/attachment.sig>


More information about the mesa-dev mailing list