st/mesa/radeonsi: fix race between destruction of types and shader compilation
authorTimothy Arceri <tarceri@itsqueeze.com>
Tue, 23 Apr 2019 02:54:38 +0000 (12:54 +1000)
committerTimothy Arceri <tarceri@itsqueeze.com>
Wed, 24 Apr 2019 00:23:10 +0000 (10:23 +1000)
Commit 624789e3708c moved the destruction of types out of atexit() and
made use of a ref count instead. This is useful for avoiding a crash
where drivers such as radeonsi are still compiling in a thread when the app
exits and has not called MakeCurrent to change from the current context.

While the above scenario is technically an app bug we shouldn't crash.
However that change caused another race condition between the shader
compilation tread in radeonsi and context teardown functions.

This patch makes two changes to fix this new problem:

First we explicitly call _mesa_destroy_shader_compiler_types() when destroying
the st context rather than calling it indirectly via _mesa_free_context_data().
We do this as we must call it after st_destroy_context_priv() so that we don't
destory the glsl types before the compilation threads finish.

Next wait for the shader threads to finish in si_destroy_context() this
also means we need to call context destroy before destroying the queues
in si_destroy_screen().

Fixes: 624789e3708c ("compiler/glsl: handle case where we have multiple users for types")
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/compiler/glsl/glsl_parser_extras.h
src/gallium/drivers/radeonsi/si_pipe.c
src/mesa/drivers/dri/i915/intel_context.c
src/mesa/drivers/dri/i965/brw_context.c
src/mesa/drivers/dri/nouveau/nouveau_context.c
src/mesa/drivers/dri/radeon/radeon_common_context.c
src/mesa/drivers/osmesa/osmesa.c
src/mesa/drivers/x11/xm_api.c
src/mesa/main/context.c
src/mesa/main/context.h
src/mesa/state_tracker/st_context.c

index f92d2160aac587d61180a3e02a8ff8f7dad18187..edc6fc06c77c70b45629f58c61d0b46a3fcfce41 100644 (file)
@@ -997,6 +997,7 @@ extern "C" {
 #endif
 
 struct glcpp_parser;
+struct _mesa_glsl_parse_state;
 
 typedef void (*glcpp_extension_iterator)(
               struct _mesa_glsl_parse_state *state,
index fa96ce342243df4dbf5f4f06e06e5e11cab2c90a..e9e1bd0aa384bc68356f2cffc3e2ef111672d708 100644 (file)
@@ -150,6 +150,9 @@ static void si_destroy_context(struct pipe_context *context)
        struct si_context *sctx = (struct si_context *)context;
        int i;
 
+       util_queue_finish(&sctx->screen->shader_compiler_queue);
+       util_queue_finish(&sctx->screen->shader_compiler_queue_low_priority);
+
        /* Unreference the framebuffer normally to disable related logic
         * properly.
         */
@@ -702,6 +705,9 @@ static void si_destroy_screen(struct pipe_screen* pscreen)
        if (!sscreen->ws->unref(sscreen->ws))
                return;
 
+       mtx_destroy(&sscreen->aux_context_lock);
+       sscreen->aux_context->destroy(sscreen->aux_context);
+
        util_queue_destroy(&sscreen->shader_compiler_queue);
        util_queue_destroy(&sscreen->shader_compiler_queue_low_priority);
 
@@ -728,8 +734,6 @@ static void si_destroy_screen(struct pipe_screen* pscreen)
        si_gpu_load_kill_thread(sscreen);
 
        mtx_destroy(&sscreen->gpu_load_mutex);
-       mtx_destroy(&sscreen->aux_context_lock);
-       sscreen->aux_context->destroy(sscreen->aux_context);
 
        slab_destroy_parent(&sscreen->pool_transfers);
 
index c23e5ffb26e0544618ea76c667b24ddb0c925b5b..aa3175816cfe5a1ebcb325ba25af5c78e22850bb 100644 (file)
@@ -599,7 +599,7 @@ intelDestroyContext(__DRIcontext * driContextPriv)
       driDestroyOptionCache(&intel->optionCache);
 
       /* free the Mesa context */
-      _mesa_free_context_data(&intel->ctx);
+      _mesa_free_context_data(&intel->ctx, true);
 
       _math_matrix_dtr(&intel->ViewportMatrix);
 
index ab637ddf7216506e6579dede85f9c5f8c18e7448..df12f373f22c18c33703ddadbc00352ac9f3a266 100644 (file)
@@ -1226,7 +1226,7 @@ intelDestroyContext(__DRIcontext * driContextPriv)
    driDestroyOptionCache(&brw->optionCache);
 
    /* free the Mesa context */
-   _mesa_free_context_data(&brw->ctx);
+   _mesa_free_context_data(&brw->ctx, true);
 
    ralloc_free(brw);
    driContextPriv->driverPrivate = NULL;
index 93f6ce473a1f8ebc28a74a36fb6e47a84aff2406..8fec35237c0917686e9e00277f45b9f95050e020 100644 (file)
@@ -217,7 +217,7 @@ nouveau_context_deinit(struct gl_context *ctx)
        nouveau_object_del(&nctx->hw.chan);
 
        nouveau_scratch_destroy(ctx);
-       _mesa_free_context_data(ctx);
+       _mesa_free_context_data(ctx, true);
 }
 
 void
index 47719baa57545caecd9ae98d47b9dd5c3ce24380..689304aa4fc751431cdac0777370e876c9f38a17 100644 (file)
@@ -270,7 +270,7 @@ void radeonDestroyContext(__DRIcontext *driContextPriv )
 
        /* free atom list */
        /* free the Mesa context data */
-       _mesa_free_context_data(&radeon->glCtx);
+       _mesa_free_context_data(&radeon->glCtx, true);
 
        /* free the option cache */
        driDestroyOptionCache(&radeon->optionCache);
index 44374a2e917d788d4f4b074a931beee9c170126b..a065161b89ef7f28e02aa0a020727ef1928d31d2 100644 (file)
@@ -854,7 +854,7 @@ OSMesaCreateContextAttribs(const int *attribList, OSMesaContext sharelist)
       osmesa->gl_buffer = _mesa_create_framebuffer(osmesa->gl_visual);
       if (!osmesa->gl_buffer) {
          _mesa_destroy_visual( osmesa->gl_visual );
-         _mesa_free_context_data( &osmesa->mesa );
+         _mesa_free_context_data(&osmesa->mesa, true);
          free(osmesa);
          return NULL;
       }
@@ -891,7 +891,7 @@ OSMesaCreateContextAttribs(const int *attribList, OSMesaContext sharelist)
              !_tnl_CreateContext( ctx ) ||
              !_swsetup_CreateContext( ctx )) {
             _mesa_destroy_visual(osmesa->gl_visual);
-            _mesa_free_context_data(ctx);
+            _mesa_free_context_data(ctx, true);
             free(osmesa);
             return NULL;
          }
@@ -919,7 +919,7 @@ OSMesaCreateContextAttribs(const int *attribList, OSMesaContext sharelist)
 
          if (ctx->Version < version_major * 10 + version_minor) {
             _mesa_destroy_visual(osmesa->gl_visual);
-            _mesa_free_context_data(ctx);
+            _mesa_free_context_data(ctx, true);
             free(osmesa);
             return NULL;
          }
@@ -955,7 +955,7 @@ OSMesaDestroyContext( OSMesaContext osmesa )
       _mesa_destroy_visual( osmesa->gl_visual );
       _mesa_reference_framebuffer( &osmesa->gl_buffer, NULL );
 
-      _mesa_free_context_data( &osmesa->mesa );
+      _mesa_free_context_data(&osmesa->mesa, true);
       free( osmesa );
    }
 }
index e840595065658cd7c15bb7ea407426f51ce50371..90f89a36221a2589eeacff406cc097df7ceb0009 100644 (file)
@@ -945,7 +945,7 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
        !_vbo_CreateContext( mesaCtx ) ||
        !_tnl_CreateContext( mesaCtx ) ||
        !_swsetup_CreateContext( mesaCtx )) {
-      _mesa_free_context_data(&c->mesa);
+      _mesa_free_context_data(&c->mesa, true);
       free(c);
       return NULL;
    }
@@ -982,7 +982,7 @@ void XMesaDestroyContext( XMesaContext c )
    _swrast_DestroyContext( mesaCtx );
    _tnl_DestroyContext( mesaCtx );
    _vbo_DestroyContext( mesaCtx );
-   _mesa_free_context_data( mesaCtx );
+   _mesa_free_context_data(mesaCtx, true);
    free( c );
 }
 
index 7300d2f3c461d5e20084c5c0d0c7b050756ddcce..2c3d9a11ce3cc0513e56341d53fe06962ca99edb 100644 (file)
@@ -1310,7 +1310,7 @@ fail:
  * \sa _mesa_initialize_context() and init_attrib_groups().
  */
 void
-_mesa_free_context_data( struct gl_context *ctx )
+_mesa_free_context_data(struct gl_context *ctx, bool destroy_compiler_types)
 {
    if (!_mesa_get_current_context()){
       /* No current context, but we may need one in order to delete
@@ -1385,7 +1385,8 @@ _mesa_free_context_data( struct gl_context *ctx )
 
    free(ctx->VersionString);
 
-   _mesa_destroy_shader_compiler_types();
+   if (destroy_compiler_types)
+      _mesa_destroy_shader_compiler_types();
 
    /* unbind the context if it's currently bound */
    if (ctx == _mesa_get_current_context()) {
@@ -1405,7 +1406,7 @@ void
 _mesa_destroy_context( struct gl_context *ctx )
 {
    if (ctx) {
-      _mesa_free_context_data(ctx);
+      _mesa_free_context_data(ctx, true);
       free( (void *) ctx );
    }
 }
index 7de10e9924b8fe41a0243d892af853e442b2e6f0..e9b270df14ce5b1a9ba48526e0ba5ec2170c5bff 100644 (file)
@@ -115,7 +115,7 @@ _mesa_initialize_context( struct gl_context *ctx,
                           const struct dd_function_table *driverFunctions);
 
 extern void
-_mesa_free_context_data( struct gl_context *ctx );
+_mesa_free_context_data(struct gl_context *ctx, bool destroy_compiler_types);
 
 extern void
 _mesa_destroy_context( struct gl_context *ctx );
index 4123906708432325bab0e3f530a11b2fdcafe466..8f2acafbca3a3cefe76c7fb620cb19b1a7f35774 100644 (file)
@@ -85,6 +85,7 @@
 #include "util/u_upload_mgr.h"
 #include "util/u_vbuf.h"
 #include "cso_cache/cso_context.h"
+#include "compiler/glsl/glsl_parser_extras.h"
 
 
 DEBUG_GET_ONCE_BOOL_OPTION(mesa_mvp_dp4, "MESA_MVP_DP4", FALSE)
@@ -977,13 +978,18 @@ st_destroy_context(struct st_context *st)
 
    st_destroy_program_variants(st);
 
-   _mesa_free_context_data(ctx);
+   _mesa_free_context_data(ctx, false);
 
    /* This will free the st_context too, so 'st' must not be accessed
     * afterwards. */
    st_destroy_context_priv(st, true);
    st = NULL;
 
+   /* This must be called after st_destroy_context_priv() to avoid a race
+    * condition between any shader compiler threads and context destruction.
+    */
+   _mesa_destroy_shader_compiler_types();
+
    free(ctx);
 
    if (save_ctx == ctx) {