xf86-video-intel: 3 commits - src/sna/sna_accel.c src/sna/sna_composite.c src/sna/sna.h src/sna/sna_render.c src/sna/sna_threads.c src/sna/sna_trapezoids_boxes.c src/sna/sna_trapezoids.c src/sna/sna_trapezoids_imprecise.c src/sna/sna_trapezoids_mono.c src/sna/sna_trapezoids_precise.c

Chris Wilson ickle at kemper.freedesktop.org
Sat Feb 22 08:59:52 PST 2014


 src/sna/sna.h                      |    8 +-
 src/sna/sna_accel.c                |   14 ++-
 src/sna/sna_composite.c            |   18 ++---
 src/sna/sna_render.c               |   13 +--
 src/sna/sna_threads.c              |  130 +++++++++++++++++++++----------------
 src/sna/sna_trapezoids.c           |   30 ++++----
 src/sna/sna_trapezoids_boxes.c     |    2 
 src/sna/sna_trapezoids_imprecise.c |    6 -
 src/sna/sna_trapezoids_mono.c      |    2 
 src/sna/sna_trapezoids_precise.c   |   10 +-
 10 files changed, 129 insertions(+), 104 deletions(-)

New commits:
commit 64fc1bb9c87e95ff484ecd11f391b1c0d556d584
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Feb 22 14:34:05 2014 +0000

    sna: Allow SIGBUS/SEGV to kill the thread
    
    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 at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index 329853d..4651632 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -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);
 
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 64b60c2..4af4875 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -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;
 }
diff --git a/src/sna/sna_threads.c b/src/sna/sna_threads.c
index a15e66a..eac6964 100644
--- a/src/sna/sna_threads.c
+++ b/src/sna/sna_threads.c
@@ -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);
diff --git a/src/sna/sna_trapezoids.c b/src/sna/sna_trapezoids.c
index ac2f764..71016e8 100644
--- a/src/sna/sna_trapezoids.c
+++ b/src/sna/sna_trapezoids.c
@@ -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;
diff --git a/src/sna/sna_trapezoids_boxes.c b/src/sna/sna_trapezoids_boxes.c
index d6f0c37..2a476dc 100644
--- a/src/sna/sna_trapezoids_boxes.c
+++ b/src/sna/sna_trapezoids_boxes.c
@@ -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);
diff --git a/src/sna/sna_trapezoids_imprecise.c b/src/sna/sna_trapezoids_imprecise.c
index 93823bb..a6da2d8 100644
--- a/src/sna/sna_trapezoids_imprecise.c
+++ b/src/sna/sna_trapezoids_imprecise.c
@@ -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);
diff --git a/src/sna/sna_trapezoids_mono.c b/src/sna/sna_trapezoids_mono.c
index ca316d7..fe77ffd 100644
--- a/src/sna/sna_trapezoids_mono.c
+++ b/src/sna/sna_trapezoids_mono.c
@@ -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;
diff --git a/src/sna/sna_trapezoids_precise.c b/src/sna/sna_trapezoids_precise.c
index bc0a7e7..f0e8266 100644
--- a/src/sna/sna_trapezoids_precise.c
+++ b/src/sna/sna_trapezoids_precise.c
@@ -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);
commit 900499bff962a63e1d9b5f808d1deb65d55754a2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Feb 22 13:58:11 2014 +0000

    sna: Move sigtrap wrapping closer to threaded sw composite
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_composite.c b/src/sna/sna_composite.c
index 5b61f95..d5c229c 100644
--- a/src/sna/sna_composite.c
+++ b/src/sna/sna_composite.c
@@ -592,17 +592,12 @@ sna_composite_fb(CARD8 op,
 	mask_image = image_from_pict(mask, FALSE, &msk_xoff, &msk_yoff);
 	dest_image = image_from_pict(dst, TRUE, &dst_xoff, &dst_yoff);
 
-	if (src_image && dest_image && !(mask && !mask_image)) {
-		if (sigtrap_get() == 0) {
-			sigtrap_assert_active();
-			sna_image_composite(op, src_image, mask_image, dest_image,
-					    src_x + src_xoff, src_y + src_yoff,
-					    msk_x + msk_xoff, msk_y + msk_yoff,
-					    dst_x + dst_xoff, dst_y + dst_yoff,
-					    width, height);
-			sigtrap_put();
-		}
-	}
+	if (src_image && dest_image && !(mask && !mask_image))
+		sna_image_composite(op, src_image, mask_image, dest_image,
+				    src_x + src_xoff, src_y + src_yoff,
+				    msk_x + msk_xoff, msk_y + msk_yoff,
+				    dst_x + dst_xoff, dst_y + dst_yoff,
+				    width, height);
 
 	free_pixman_pict(src, src_image);
 	free_pixman_pict(mask, mask_image);
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 7acca36..73dcf45 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -1674,14 +1674,11 @@ do_fixup:
 
 	DBG(("%s: compositing tmp=(%d+%d, %d+%d)x(%d, %d)\n",
 	     __FUNCTION__, x, dx, y, dy, w, h));
-	if (sigtrap_get() == 0) {
-		sna_image_composite(PictOpSrc, src, NULL, dst,
-				    x + dx, y + dy,
-				    0, 0,
-				    0, 0,
-				    w, h);
-		sigtrap_put();
-	}
+	sna_image_composite(PictOpSrc, src, NULL, dst,
+			    x + dx, y + dy,
+			    0, 0,
+			    0, 0,
+			    w, h);
 	free_pixman_pict(picture, src);
 
 	/* Then convert to card format */
diff --git a/src/sna/sna_threads.c b/src/sna/sna_threads.c
index 8f55496..a15e66a 100644
--- a/src/sna/sna_threads.c
+++ b/src/sna/sna_threads.c
@@ -276,11 +276,14 @@ void sna_image_composite(pixman_op_t        op,
 
 	num_threads = sna_use_threads(width, height, 32);
 	if (num_threads <= 1) {
-		pixman_image_composite(op, src, mask, dst,
-				       src_x, src_y,
-				       mask_x, mask_y,
-				       dst_x, dst_y,
-				       width, height);
+		if (sigtrap_get() == 0) {
+			pixman_image_composite(op, src, mask, dst,
+					       src_x, src_y,
+					       mask_x, mask_y,
+					       dst_x, dst_y,
+					       width, height);
+			sigtrap_put();
+		}
 	} else {
 		struct thread_composite data[num_threads];
 		int y, dy, n;
@@ -305,27 +308,31 @@ void sna_image_composite(pixman_op_t        op,
 		data[0].width = width;
 		data[0].height = dy;
 
-		for (n = 1; n < num_threads; n++) {
-			data[n] = data[0];
-			data[n].src_y += y - dst_y;
-			data[n].mask_y += y - dst_y;
-			data[n].dst_y = y;
-			y += dy;
+		if (sigtrap_get() == 0) {
+			for (n = 1; n < num_threads; n++) {
+				data[n] = data[0];
+				data[n].src_y += y - dst_y;
+				data[n].mask_y += y - dst_y;
+				data[n].dst_y = y;
+				y += dy;
 
-			sna_threads_run(thread_composite, &data[n]);
-		}
+				sna_threads_run(thread_composite, &data[n]);
+			}
 
-		assert(y < dst_y + height);
-		if (y + dy > dst_y + height)
-			dy = dst_y + height - y;
+			assert(y < dst_y + height);
+			if (y + dy > dst_y + height)
+				dy = dst_y + height - y;
 
-		data[0].src_y += y - dst_y;
-		data[0].mask_y += y - dst_y;
-		data[0].dst_y = y;
-		data[0].height = dy;
+			data[0].src_y += y - dst_y;
+			data[0].mask_y += y - dst_y;
+			data[0].dst_y = y;
+			data[0].height = dy;
 
-		thread_composite(&data[0]);
+			thread_composite(&data[0]);
 
-		sna_threads_wait();
+			sna_threads_wait();
+			sigtrap_put();
+		} else
+			sna_threads_kill();
 	}
 }
commit aae3bfeb28ca86b416a6a4de71eb23cdb46cf9de
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Feb 22 12:44:16 2014 +0000

    sna: Assert that sigtrap is active
    
    Curiouser and curiouser.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index 0b5de8e..329853d 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -1035,12 +1035,13 @@ void sna_image_composite(pixman_op_t        op,
 extern jmp_buf sigjmp[4];
 extern volatile sig_atomic_t sigtrap;
 
-#define sigtrap_assert() assert(sigtrap == 0)
+#define sigtrap_assert_inactive() assert(sigtrap == 0)
+#define sigtrap_assert_active() assert(sigtrap > 0 && sigtrap <= ARRAY_SIZE(sigjmp))
 #define sigtrap_get() sigsetjmp(sigjmp[sigtrap++], 1)
 
 static inline void sigtrap_put(void)
 {
-	assert(sigtrap > 0);
+	sigtrap_assert_active();
 	--sigtrap;
 }
 
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 0dac561..64b60c2 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -17071,7 +17071,7 @@ void sna_accel_close(struct sna *sna)
 
 void sna_accel_block_handler(struct sna *sna, struct timeval **tv)
 {
-	sigtrap_assert();
+	sigtrap_assert_inactive();
 
 	if (sna->kgem.need_retire)
 		kgem_retire(&sna->kgem);
@@ -17158,11 +17158,11 @@ void sna_accel_wakeup_handler(struct sna *sna)
 		_kgem_submit(&sna->kgem);
 	}
 
-	sigtrap_assert();
+	sigtrap_assert_inactive();
 }
 
 void sna_accel_free(struct sna *sna)
 {
 	DBG(("%s\n", __FUNCTION__));
-	sigtrap_assert();
+	sigtrap_assert_inactive();
 }
diff --git a/src/sna/sna_composite.c b/src/sna/sna_composite.c
index 6a2eff6..5b61f95 100644
--- a/src/sna/sna_composite.c
+++ b/src/sna/sna_composite.c
@@ -570,6 +570,7 @@ sna_composite_fb(CARD8 op,
 
 					assert(box->x2 > box->x1 && box->y2 > box->y1);
 
+					sigtrap_assert_active();
 					memcpy_blt(src_pixmap->devPrivate.ptr,
 						   dst_pixmap->devPrivate.ptr,
 						   dst_pixmap->drawable.bitsPerPixel,
@@ -593,6 +594,7 @@ sna_composite_fb(CARD8 op,
 
 	if (src_image && dest_image && !(mask && !mask_image)) {
 		if (sigtrap_get() == 0) {
+			sigtrap_assert_active();
 			sna_image_composite(op, src_image, mask_image, dest_image,
 					    src_x + src_xoff, src_y + src_yoff,
 					    msk_x + msk_xoff, msk_y + msk_yoff,
@@ -1094,6 +1096,7 @@ fallback:
 							  dst->format))
 				goto fallback_composite;
 
+			sigtrap_assert_active();
 			if (pixel == 0 &&
 			    box->x2 - box->x1 == pixmap->drawable.width &&
 			    box->y2 - box->y1 == pixmap->drawable.height) {


More information about the xorg-commit mailing list