sna: Handle asynchronous signals from threads
authorChris Wilson <chris@chris-wilson.co.uk>
Sat, 22 Feb 2014 08:35:50 +0000 (08:35 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Sat, 22 Feb 2014 09:39:35 +0000 (09:39 +0000)
By killing the threads and leaking their allocations - marginally
preferrable to losing the entire Xserver.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
src/sna/sna.h
src/sna/sna_threads.c
src/sna/sna_trapezoids_boxes.c
src/sna/sna_trapezoids_imprecise.c
src/sna/sna_trapezoids_precise.c

index 1b0a4e5..0b5de8e 100644 (file)
@@ -1017,6 +1017,7 @@ void sna_threads_init(void);
 int sna_use_threads (int width, int height, int threshold);
 void sna_threads_run(void (*func)(void *arg), void *arg);
 void sna_threads_wait(void);
+void sna_threads_kill(void);
 
 void sna_image_composite(pixman_op_t        op,
                         pixman_image_t    *src,
index 6627cbd..8f55496 100644 (file)
@@ -205,6 +205,22 @@ void sna_threads_wait(void)
        }
 }
 
+void sna_threads_kill(void)
+{
+       int n;
+
+       ERR(("kill %d threads\n", max_threads));
+       assert(max_threads > 0);
+
+       for (n = 0; n < max_threads; n++)
+               pthread_cancel(threads[n].thread);
+
+       for (n = 0; n < max_threads; n++)
+               pthread_join(threads[n].thread, NULL);
+
+       max_threads = 0;
+}
+
 int sna_use_threads(int width, int height, int threshold)
 {
        int num_threads;
index 6d81da6..d6f0c37 100644 (file)
@@ -1181,19 +1181,23 @@ composite_unaligned_boxes_inplace(struct sna *sna,
                        dy = (clip.extents.y2 - clip.extents.y1 + num_threads - 1) / num_threads;
                        num_threads = (clip.extents.y2 - clip.extents.y1 + dy - 1) / dy;
 
-                       for (i = 1; i < num_threads; i++) {
-                               thread[i] = thread[0];
-                               thread[i].y1 = y;
-                               thread[i].y2 = y += dy;
-                               sna_threads_run(rectilinear_inplace_thread, &thread[i]);
-                       }
+                       if (sigtrap_get() == 0) {
+                               for (i = 1; i < num_threads; i++) {
+                                       thread[i] = thread[0];
+                                       thread[i].y1 = y;
+                                       thread[i].y2 = y += dy;
+                                       sna_threads_run(rectilinear_inplace_thread, &thread[i]);
+                               }
 
-                       assert(y < clip.extents.y2);
-                       thread[0].y1 = y;
-                       thread[0].y2 = clip.extents.y2;
-                       rectilinear_inplace_thread(&thread[0]);
+                               assert(y < clip.extents.y2);
+                               thread[0].y1 = y;
+                               thread[0].y2 = clip.extents.y2;
+                               rectilinear_inplace_thread(&thread[0]);
 
-                       sna_threads_wait();
+                               sna_threads_wait();
+                               sigtrap_put();
+                       } else
+                               sna_threads_kill();
 
                        pixman_image_unref(thread[0].dst);
                        pixman_image_unref(thread[0].src);
index ddf52c2..93823bb 100644 (file)
@@ -2851,19 +2851,23 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
                h = (h + num_threads - 1) / num_threads;
                num_threads -= (num_threads-1) * h >= region.extents.y2 - region.extents.y1;
 
-               for (n = 1; n < num_threads; n++) {
-                       threads[n] = threads[0];
-                       threads[n].extents.y1 = y;
-                       threads[n].extents.y2 = y += h;
+               if (sigtrap_get() == 0) {
+                       for (n = 1; n < num_threads; n++) {
+                               threads[n] = threads[0];
+                               threads[n].extents.y1 = y;
+                               threads[n].extents.y2 = y += h;
 
-                       sna_threads_run(inplace_x8r8g8b8_thread, &threads[n]);
-               }
+                               sna_threads_run(inplace_x8r8g8b8_thread, &threads[n]);
+                       }
 
-               assert(y < threads[0].extents.y2);
-               threads[0].extents.y1 = y;
-               inplace_x8r8g8b8_thread(&threads[0]);
+                       assert(y < threads[0].extents.y2);
+                       threads[0].extents.y1 = y;
+                       inplace_x8r8g8b8_thread(&threads[0]);
 
-               sna_threads_wait();
+                       sna_threads_wait();
+                       sigtrap_put();
+               } else
+                       sna_threads_kill(); /* leaks thread allocations */
        }
 
        return true;
@@ -3125,19 +3129,23 @@ imprecise_trapezoid_span_inplace(struct sna *sna,
                h = (h + num_threads - 1) / num_threads;
                num_threads -= (num_threads-1) * h >= region.extents.y2 - region.extents.y1;
 
-               for (n = 1; n < num_threads; n++) {
-                       threads[n] = threads[0];
-                       threads[n].extents.y1 = y;
-                       threads[n].extents.y2 = y += h;
+               if (sigtrap_get() == 0) {
+                       for (n = 1; n < num_threads; n++) {
+                               threads[n] = threads[0];
+                               threads[n].extents.y1 = y;
+                               threads[n].extents.y2 = y += h;
 
-                       sna_threads_run(inplace_thread, &threads[n]);
-               }
+                               sna_threads_run(inplace_thread, &threads[n]);
+                       }
 
-               assert(y < threads[0].extents.y2);
-               threads[0].extents.y1 = y;
-               inplace_thread(&threads[0]);
+                       assert(y < threads[0].extents.y2);
+                       threads[0].extents.y1 = y;
+                       inplace_thread(&threads[0]);
 
-               sna_threads_wait();
+                       sna_threads_wait();
+                       sigtrap_put();
+               } else
+                       sna_threads_kill(); /* leaks thread allocations */
        }
 
        return true;
index e5bab16..bc0a7e7 100644 (file)
@@ -2849,19 +2849,23 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
                h = (h + num_threads - 1) / num_threads;
                num_threads -= (num_threads-1) * h >= region.extents.y2 - region.extents.y1;
 
-               for (n = 1; n < num_threads; n++) {
-                       threads[n] = threads[0];
-                       threads[n].extents.y1 = y;
-                       threads[n].extents.y2 = y += h;
+               if (sigtrap_get() == 0) {
+                       for (n = 1; n < num_threads; n++) {
+                               threads[n] = threads[0];
+                               threads[n].extents.y1 = y;
+                               threads[n].extents.y2 = y += h;
 
-                       sna_threads_run(inplace_x8r8g8b8_thread, &threads[n]);
-               }
+                               sna_threads_run(inplace_x8r8g8b8_thread, &threads[n]);
+                       }
 
-               assert(y < threads[0].extents.y2);
-               threads[0].extents.y1 = y;
-               inplace_x8r8g8b8_thread(&threads[0]);
+                       assert(y < threads[0].extents.y2);
+                       threads[0].extents.y1 = y;
+                       inplace_x8r8g8b8_thread(&threads[0]);
 
-               sna_threads_wait();
+                       sna_threads_wait();
+                       sigtrap_put();
+               } else
+                       sna_threads_kill(); /* leaks thread allocations */
        }
 
        return true;
@@ -3124,19 +3128,23 @@ precise_trapezoid_span_inplace(struct sna *sna,
                h = (h + num_threads - 1) / num_threads;
                num_threads -= (num_threads-1) * h >= region.extents.y2 - region.extents.y1;
 
-               for (n = 1; n < num_threads; n++) {
-                       threads[n] = threads[0];
-                       threads[n].extents.y1 = y;
-                       threads[n].extents.y2 = y += h;
+               if (sigtrap_get() == 0) {
+                       for (n = 1; n < num_threads; n++) {
+                               threads[n] = threads[0];
+                               threads[n].extents.y1 = y;
+                               threads[n].extents.y2 = y += h;
 
-                       sna_threads_run(inplace_thread, &threads[n]);
-               }
+                               sna_threads_run(inplace_thread, &threads[n]);
+                       }
 
-               assert(y < threads[0].extents.y2);
-               threads[0].extents.y1 = y;
-               inplace_thread(&threads[0]);
+                       assert(y < threads[0].extents.y2);
+                       threads[0].extents.y1 = y;
+                       inplace_thread(&threads[0]);
 
-               sna_threads_wait();
+                       sna_threads_wait();
+                       sigtrap_put();
+               } else
+                       sna_threads_kill(); /* leaks thread allocations */
        }
 
        return true;