sna: Allow SIGBUS/SEGV to kill the thread
authorChris Wilson <chris@chris-wilson.co.uk>
Sat, 22 Feb 2014 14:34:05 +0000 (14:34 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Sat, 22 Feb 2014 16:58:58 +0000 (16:58 +0000)
To handle sigtrapping of the threads, we allow the threads to handle
their async signals and upon hitting the trap, we kill the thread. All
the rest of the threads are reaped by the main xserver thread
afterwards.

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

index 329853d..4651632 100644 (file)
@@ -1015,7 +1015,8 @@ void sna_acpi_fini(struct sna *sna);
 
 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_run(int id, void (*func)(void *arg), void *arg);
+void sna_threads_trap(int sig);
 void sna_threads_wait(void);
 void sna_threads_kill(void);
 
index 64b60c2..4af4875 100644 (file)
@@ -408,10 +408,12 @@ volatile sig_atomic_t sigtrap;
 
 static int sigtrap_handler(int sig)
 {
-       if (sigtrap) {
-               /* XXX rate-limited squawk? */
+       /* XXX rate-limited squawk? */
+       DBG(("%s(sig=%d) sigtrap=%d\n", __FUNCTION__, sig, sigtrap));
+       sna_threads_trap(sig);
+
+       if (sigtrap)
                siglongjmp(sigjmp[--sigtrap], sig);
-       }
 
        return -1;
 }
index a15e66a..eac6964 100644 (file)
@@ -53,7 +53,9 @@ static void *__run__(void *arg)
 
        /* Disable all signals in the slave threads as X uses them for IO */
        sigfillset(&signals);
-       pthread_sigmask(SIG_BLOCK, &signals, NULL);
+       sigdelset(&signals, SIGBUS);
+       sigdelset(&signals, SIGSEGV);
+       pthread_sigmask(SIG_SETMASK, &signals, NULL);
 
        pthread_mutex_lock(&t->mutex);
        while (1) {
@@ -66,6 +68,7 @@ static void *__run__(void *arg)
 
                pthread_mutex_lock(&t->mutex);
                t->func = NULL;
+               t->arg = NULL;
                pthread_cond_signal(&t->cond);
        }
        pthread_mutex_unlock(&t->mutex);
@@ -141,7 +144,7 @@ void sna_threads_init(void)
        if (threads == NULL)
                goto bail;
 
-       for (n = 0; n < max_threads; n++) {
+       for (n = 1; n < max_threads; n++) {
                pthread_mutex_init(&threads[n].mutex, NULL);
                pthread_cond_init(&threads[n].cond, NULL);
 
@@ -151,41 +154,46 @@ void sna_threads_init(void)
                        goto bail;
        }
 
+       threads[0].thread = pthread_self();
        return;
 
 bail:
        max_threads = 0;
 }
 
-void sna_threads_run(void (*func)(void *arg), void *arg)
+void sna_threads_run(int id, void (*func)(void *arg), void *arg)
 {
-       int n;
-
        assert(max_threads > 0);
+       assert(pthread_self() == threads[0].thread);
+       assert(id > 0 && id < max_threads);
 
-       for (n = 0; n < max_threads; n++) {
-               if (threads[n].func)
-                       continue;
+       assert(threads[id].func == NULL);
 
-               pthread_mutex_lock(&threads[n].mutex);
-               if (threads[n].func) {
-                       pthread_mutex_unlock(&threads[n].mutex);
-                       continue;
-               }
+       pthread_mutex_lock(&threads[id].mutex);
+       threads[id].func = func;
+       threads[id].arg = arg;
+       pthread_cond_signal(&threads[id].cond);
+       pthread_mutex_unlock(&threads[id].mutex);
+}
 
-               goto execute;
-       }
+void sna_threads_trap(int sig)
+{
+       pthread_t t = pthread_self();
+       int n;
 
-       n = rand() % max_threads;
-       pthread_mutex_lock(&threads[n].mutex);
-       while (threads[n].func)
-               pthread_cond_wait(&threads[n].cond, &threads[n].mutex);
+       if (t == threads[0].thread)
+               return;
+
+       for (n = 1; threads[n].thread != t; n++)
+               ;
 
-execute:
-       threads[n].func = func;
-       threads[n].arg = arg;
+       pthread_mutex_lock(&threads[n].mutex);
+       threads[n].func = NULL;
+       threads[n].arg = &threads[n];
        pthread_cond_signal(&threads[n].cond);
        pthread_mutex_unlock(&threads[n].mutex);
+
+       pthread_exit(&sig);
 }
 
 void sna_threads_wait(void)
@@ -193,15 +201,21 @@ void sna_threads_wait(void)
        int n;
 
        assert(max_threads > 0);
+       assert(pthread_self() == threads[0].thread);
 
-       for (n = 0; n < max_threads; n++) {
-               if (threads[n].func == NULL)
-                       continue;
+       for (n = 1; n < max_threads; n++) {
+               if (threads[n].func != NULL) {
+                       pthread_mutex_lock(&threads[n].mutex);
+                       while (threads[n].func)
+                               pthread_cond_wait(&threads[n].cond, &threads[n].mutex);
+                       pthread_mutex_unlock(&threads[n].mutex);
+               }
 
-               pthread_mutex_lock(&threads[n].mutex);
-               while (threads[n].func)
-                       pthread_cond_wait(&threads[n].cond, &threads[n].mutex);
-               pthread_mutex_unlock(&threads[n].mutex);
+               if (threads[n].arg != NULL) {
+                       ERR(("%s: thread %d died\n", __func__, n));
+                       sna_threads_kill();
+                       return;
+               }
        }
 }
 
@@ -209,13 +223,14 @@ void sna_threads_kill(void)
 {
        int n;
 
-       ERR(("kill %d threads\n", max_threads));
+       ERR(("%s: kill %d threads\n", __func__, max_threads));
        assert(max_threads > 0);
+       assert(pthread_self() == threads[0].thread);
 
-       for (n = 0; n < max_threads; n++)
+       for (n = 1; n < max_threads; n++)
                pthread_cancel(threads[n].thread);
 
-       for (n = 0; n < max_threads; n++)
+       for (n = 1; n < max_threads; n++)
                pthread_join(threads[n].thread, NULL);
 
        max_threads = 0;
@@ -316,7 +331,7 @@ void sna_image_composite(pixman_op_t        op,
                                data[n].dst_y = y;
                                y += dy;
 
-                               sna_threads_run(thread_composite, &data[n]);
+                               sna_threads_run(n, thread_composite, &data[n]);
                        }
 
                        assert(y < dst_y + height);
index ac2f764..71016e8 100644 (file)
@@ -385,21 +385,25 @@ trapezoids_fallback(struct sna *sna,
                                dy = (height + num_threads - 1) / num_threads;
                                num_threads -= (num_threads-1) * dy >= bounds.y2 - bounds.y1;
 
-                               for (n = 1; n < num_threads; n++) {
-                                       threads[n] = threads[0];
-                                       threads[n].ptr += (y - bounds.y1) * threads[n].stride;
-                                       threads[n].bounds.y1 = y;
-                                       threads[n].bounds.y2 = y += dy;
-
-                                       sna_threads_run(rasterize_traps_thread, &threads[n]);
-                               }
+                               if (sigtrap_get() == 0) {
+                                       for (n = 1; n < num_threads; n++) {
+                                               threads[n] = threads[0];
+                                               threads[n].ptr += (y - bounds.y1) * threads[n].stride;
+                                               threads[n].bounds.y1 = y;
+                                               threads[n].bounds.y2 = y += dy;
+
+                                               sna_threads_run(n, rasterize_traps_thread, &threads[n]);
+                                       }
 
-                               assert(y < threads[0].bounds.y2);
-                               threads[0].ptr += (y - bounds.y1) * threads[0].stride;
-                               threads[0].bounds.y1 = y;
-                               rasterize_traps_thread(&threads[0]);
+                                       assert(y < threads[0].bounds.y2);
+                                       threads[0].ptr += (y - bounds.y1) * threads[0].stride;
+                                       threads[0].bounds.y1 = y;
+                                       rasterize_traps_thread(&threads[0]);
 
-                               sna_threads_wait();
+                                       sna_threads_wait();
+                                       sigtrap_put();
+                               } else
+                                       sna_threads_kill();
 
                                format = PIXMAN_a8;
                                depth = 8;
index d6f0c37..2a476dc 100644 (file)
@@ -1186,7 +1186,7 @@ composite_unaligned_boxes_inplace(struct sna *sna,
                                        thread[i] = thread[0];
                                        thread[i].y1 = y;
                                        thread[i].y2 = y += dy;
-                                       sna_threads_run(rectilinear_inplace_thread, &thread[i]);
+                                       sna_threads_run(i, rectilinear_inplace_thread, &thread[i]);
                                }
 
                                assert(y < clip.extents.y2);
index 93823bb..a6da2d8 100644 (file)
@@ -1988,7 +1988,7 @@ imprecise_trapezoid_span_converter(struct sna *sna,
                        threads[n].extents.y1 = y;
                        threads[n].extents.y2 = y += h;
 
-                       sna_threads_run(span_thread, &threads[n]);
+                       sna_threads_run(n, span_thread, &threads[n]);
                }
 
                assert(y < threads[0].extents.y2);
@@ -2857,7 +2857,7 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
                                threads[n].extents.y1 = y;
                                threads[n].extents.y2 = y += h;
 
-                               sna_threads_run(inplace_x8r8g8b8_thread, &threads[n]);
+                               sna_threads_run(n, inplace_x8r8g8b8_thread, &threads[n]);
                        }
 
                        assert(y < threads[0].extents.y2);
@@ -3135,7 +3135,7 @@ imprecise_trapezoid_span_inplace(struct sna *sna,
                                threads[n].extents.y1 = y;
                                threads[n].extents.y2 = y += h;
 
-                               sna_threads_run(inplace_thread, &threads[n]);
+                               sna_threads_run(n, inplace_thread, &threads[n]);
                        }
 
                        assert(y < threads[0].extents.y2);
index ca316d7..fe77ffd 100644 (file)
@@ -852,7 +852,7 @@ mono_trapezoids_span_converter(struct sna *sna,
                        threads[n].extents.y1 = y;
                        threads[n].extents.y2 = y += h;
 
-                       sna_threads_run(mono_span_thread, &threads[n]);
+                       sna_threads_run(n, mono_span_thread, &threads[n]);
                }
 
                threads[0].extents.y1 = y;
index bc0a7e7..f0e8266 100644 (file)
@@ -1913,7 +1913,7 @@ precise_trapezoid_span_converter(struct sna *sna,
                        threads[n].extents.y1 = y;
                        threads[n].extents.y2 = y += h;
 
-                       sna_threads_run(span_thread, &threads[n]);
+                       sna_threads_run(n, span_thread, &threads[n]);
                }
 
                assert(y < threads[0].extents.y2);
@@ -2139,7 +2139,7 @@ precise_trapezoid_mask_converter(CARD8 op, PicturePtr src, PicturePtr dst,
                        threads[n].extents.y1 = y;
                        threads[n].extents.y2 = y += h;
 
-                       sna_threads_run(mask_thread, &threads[n]);
+                       sna_threads_run(n, mask_thread, &threads[n]);
                }
 
                assert(y < threads[0].extents.y2);
@@ -2855,7 +2855,7 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
                                threads[n].extents.y1 = y;
                                threads[n].extents.y2 = y += h;
 
-                               sna_threads_run(inplace_x8r8g8b8_thread, &threads[n]);
+                               sna_threads_run(n, inplace_x8r8g8b8_thread, &threads[n]);
                        }
 
                        assert(y < threads[0].extents.y2);
@@ -3134,7 +3134,7 @@ precise_trapezoid_span_inplace(struct sna *sna,
                                threads[n].extents.y1 = y;
                                threads[n].extents.y2 = y += h;
 
-                               sna_threads_run(inplace_thread, &threads[n]);
+                               sna_threads_run(n, inplace_thread, &threads[n]);
                        }
 
                        assert(y < threads[0].extents.y2);
@@ -3281,7 +3281,7 @@ precise_trapezoid_span_fallback(CARD8 op, PicturePtr src, PicturePtr dst,
                        threads[n].extents.y1 = y;
                        threads[n].extents.y2 = y += h;
 
-                       sna_threads_run(mask_thread, &threads[n]);
+                       sna_threads_run(n, mask_thread, &threads[n]);
                }
 
                assert(y < threads[0].extents.y2);