st/nine: Resolve deadlock in surface/volume dtors when using csmt
authorAxel Davy <axel.davy@ens.fr>
Wed, 15 Mar 2017 21:45:03 +0000 (22:45 +0100)
committerAxel Davy <axel.davy@ens.fr>
Sun, 26 Mar 2017 21:10:38 +0000 (23:10 +0200)
Surfaces and Volumes can be freed in the worker thread.

Without this patch, pending_uploads_counter could be non-zero
in the Surfaces or Volumes dtor, leading to deadlock.
Instead decrease properly the counter before releasing the
item.

Also avoid another potential deadlock if the item is not
properly unlocked: Do not call UnlockRect which will cause deadlock,
but free directly using the deadlock safe
nine_context_get_pipe_multithread.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=99246

CC: "17.0" <mesa-stable@lists.freedesktop.org>
Signed-off-by: Axel Davy <axel.davy@ens.fr>
Tested-by: James Harvey <lothmordor@gmail.com>
src/gallium/state_trackers/nine/nine_csmt_helper.h
src/gallium/state_trackers/nine/surface9.c
src/gallium/state_trackers/nine/volume9.c

index b0bbc054fc355918336f2338ed729d3d88180476..dc46bbd3a2855cab0d71c1a1abc0c4c4c60259f8 100644 (file)
@@ -233,8 +233,8 @@ name##_rx( struct NineDevice9 *device, struct csmt_instruction *instr ) \
     name##_priv( \
         device ARGS_FOR_CALL( __VA_ARGS__ ) \
     ); \
-    ARGS_FOR_UNBIND( __VA_ARGS__ ) \
     p_atomic_dec(args->counter); \
+    ARGS_FOR_UNBIND( __VA_ARGS__ ) \
     return 0; \
 } \
 \
index 836369cafdb8b36094ca9c5a685ceb2651ac9a44..d917fa1f86895062b096f99ac98ab95bddd2ad61 100644 (file)
@@ -204,9 +204,15 @@ NineSurface9_dtor( struct NineSurface9 *This )
 {
     DBG("This=%p\n", This);
 
-    if (This->transfer)
-        NineSurface9_UnlockRect(This);
+    if (This->transfer) {
+        struct pipe_context *pipe = nine_context_get_pipe_multithread(This->base.base.device);
+        pipe->transfer_unmap(pipe, This->transfer);
+        This->transfer = NULL;
+    }
 
+    /* Note: Following condition cannot happen currently, since we
+     * refcount the surface in the functions increasing
+     * pending_uploads_counter. */
     if (p_atomic_read(&This->pending_uploads_counter))
         nine_csmt_process(This->base.base.device);
 
index 11236a02e7554337e9ad9e5690416bdbb363c115..62af3e622513f29952a754708f615bdf9d61d01e 100644 (file)
@@ -142,9 +142,15 @@ NineVolume9_dtor( struct NineVolume9 *This )
 {
     DBG("This=%p\n", This);
 
-    if (This->transfer)
-        NineVolume9_UnlockBox(This);
+    if (This->transfer) {
+        struct pipe_context *pipe = nine_context_get_pipe_multithread(This->base.device);
+        pipe->transfer_unmap(pipe, This->transfer);
+        This->transfer = NULL;
+    }
 
+    /* Note: Following condition cannot happen currently, since we
+     * refcount the volume in the functions increasing
+     * pending_uploads_counter. */
     if (p_atomic_read(&This->pending_uploads_counter))
         nine_csmt_process(This->base.device);