[Pixman] [PATCH 2/2] test: Add new thread-test program
Søren Sandmann
sandmann at cs.au.dk
Sat Sep 28 08:38:58 PDT 2013
From: Søren Sandmann Pedersen <ssp at redhat.com>
This test program allocates an array of 16 uint32_ts and spawns 16
threads that each use one of the allocated uint32_ts as destination
for a large number of composite operations. Each thread then checks
whether the results have the right crc32 checksum.
The purpose of this test is catch errors where memory outside images
is read and then written back. Such out-of-bounds accesses are broken
when multiple threads are involved.
---
test/Makefile.am | 6 +-
test/Makefile.sources | 1 +
test/thread-test.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 187 insertions(+), 3 deletions(-)
create mode 100644 test/thread-test.c
diff --git a/test/Makefile.am b/test/Makefile.am
index 5d901d5..80f3537 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,8 +1,8 @@
include $(top_srcdir)/test/Makefile.sources
-AM_CFLAGS = $(OPENMP_CFLAGS)
-AM_LDFLAGS = $(OPENMP_CFLAGS) $(TESTPROGS_EXTRA_LDFLAGS)
-LDADD = libutils.la $(top_builddir)/pixman/libpixman-1.la -lm $(PNG_LIBS)
+AM_CFLAGS = $(OPENMP_CFLAGS) $(PTHREAD_CFLAGS)$
+AM_LDFLAGS = $(OPENMP_CFLAGS) $(TESTPROGS_EXTRA_LDFLAGS) $(PTHREAD_LDFLAGS)
+LDADD = libutils.la $(top_builddir)/pixman/libpixman-1.la -lm $(PNG_LIBS) $(PTHREAD_LIBS)
AM_CPPFLAGS = -I$(top_srcdir)/pixman -I$(top_builddir)/pixman $(PNG_CFLAGS)
libutils_la_SOURCES = $(libutils_sources) $(libutils_headers)
diff --git a/test/Makefile.sources b/test/Makefile.sources
index 2fabdb5..2ae5d9f 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -13,6 +13,7 @@ TESTPROGRAMS = \
infinite-loop \
trap-crasher \
alpha-loop \
+ thread-test \
scaling-crash-test \
scaling-helpers-test \
gradient-crash-test \
diff --git a/test/thread-test.c b/test/thread-test.c
new file mode 100644
index 0000000..917f417
--- /dev/null
+++ b/test/thread-test.c
@@ -0,0 +1,183 @@
+#include <config.h>
+
+#ifndef HAVE_PTHREADS
+
+int main ()
+{
+ printf ("Skipped thread-test - pthreads not supported\n");
+ return 0;
+}
+
+#else
+
+#include <stdlib.h>
+#include <pthread.h>
+#include "utils.h"
+
+typedef struct
+{
+ int thread_no;
+ uint32_t *dest;
+ uint32_t crc32;
+} info_t;
+
+static const pixman_op_t operators[] =
+{
+ PIXMAN_OP_SRC,
+ PIXMAN_OP_OVER,
+ PIXMAN_OP_ADD,
+ PIXMAN_OP_CLEAR,
+ PIXMAN_OP_SRC,
+ PIXMAN_OP_DST,
+ PIXMAN_OP_OVER,
+ PIXMAN_OP_OVER_REVERSE,
+ PIXMAN_OP_IN,
+ PIXMAN_OP_IN_REVERSE,
+ PIXMAN_OP_OUT,
+ PIXMAN_OP_OUT_REVERSE,
+ PIXMAN_OP_ATOP,
+ PIXMAN_OP_ATOP_REVERSE,
+ PIXMAN_OP_XOR,
+ PIXMAN_OP_ADD,
+ PIXMAN_OP_SATURATE,
+ PIXMAN_OP_DISJOINT_CLEAR,
+ PIXMAN_OP_DISJOINT_SRC,
+ PIXMAN_OP_DISJOINT_DST,
+ PIXMAN_OP_DISJOINT_OVER,
+ PIXMAN_OP_DISJOINT_OVER_REVERSE,
+ PIXMAN_OP_DISJOINT_IN,
+ PIXMAN_OP_DISJOINT_IN_REVERSE,
+ PIXMAN_OP_DISJOINT_OUT,
+ PIXMAN_OP_DISJOINT_OUT_REVERSE,
+ PIXMAN_OP_DISJOINT_ATOP,
+ PIXMAN_OP_DISJOINT_ATOP_REVERSE,
+ PIXMAN_OP_DISJOINT_XOR,
+ PIXMAN_OP_CONJOINT_CLEAR,
+ PIXMAN_OP_CONJOINT_SRC,
+ PIXMAN_OP_CONJOINT_DST,
+ PIXMAN_OP_CONJOINT_OVER,
+ PIXMAN_OP_CONJOINT_OVER_REVERSE,
+ PIXMAN_OP_CONJOINT_IN,
+ PIXMAN_OP_CONJOINT_IN_REVERSE,
+ PIXMAN_OP_CONJOINT_OUT,
+ PIXMAN_OP_CONJOINT_OUT_REVERSE,
+ PIXMAN_OP_CONJOINT_ATOP,
+ PIXMAN_OP_CONJOINT_ATOP_REVERSE,
+ PIXMAN_OP_CONJOINT_XOR,
+ PIXMAN_OP_MULTIPLY,
+ PIXMAN_OP_SCREEN,
+ PIXMAN_OP_OVERLAY,
+ PIXMAN_OP_DARKEN,
+ PIXMAN_OP_LIGHTEN,
+ PIXMAN_OP_COLOR_DODGE,
+ PIXMAN_OP_COLOR_BURN,
+ PIXMAN_OP_HARD_LIGHT,
+ PIXMAN_OP_DIFFERENCE,
+ PIXMAN_OP_EXCLUSION,
+};
+
+static const pixman_format_code_t formats[] =
+{
+ PIXMAN_a8r8g8b8,
+ PIXMAN_r5g6b5,
+ PIXMAN_a8,
+ PIXMAN_a4,
+ PIXMAN_a1,
+ PIXMAN_b5g6r5,
+ PIXMAN_r8g8b8a8,
+ PIXMAN_a4r4g4b4
+};
+
+#define N_ROUNDS 32768
+
+#define RAND_ELT(arr) \
+ arr[prng_rand() % ARRAY_LENGTH (arr)]
+
+static void *
+thread (void *data)
+{
+ info_t *info = data;
+ uint32_t crc32 = 0x0;
+ uint32_t src_buf[64];
+ pixman_image_t *dst_img, *src_img;
+ int i;
+
+ prng_srand (info->thread_no);
+
+ for (i = 0; i < N_ROUNDS; ++i)
+ {
+ *info->dest = prng_rand();
+
+ prng_randmemset (src_buf, sizeof (src_buf), 0);
+
+ src_img = pixman_image_create_bits (
+ RAND_ELT (formats), 4, 4, src_buf, 16);
+ dst_img = pixman_image_create_bits (
+ RAND_ELT (formats), 1, 1, info->dest, 4);
+
+ pixman_image_composite32 (
+ RAND_ELT (operators),
+ src_img, NULL, dst_img,
+ prng_rand() % 4, prng_rand() % 4, 0, 0, 0, 0, 1, 1);
+
+ crc32 = compute_crc32_for_image (crc32, dst_img);
+
+ pixman_image_unref (src_img);
+ pixman_image_unref (dst_img);
+ }
+
+ if (crc32 != info->crc32)
+ {
+ printf ("%d failed. Got checksum %8x, expected %8x\n",
+ info->thread_no, crc32, info->crc32);
+
+ return (void *)1;
+ }
+
+ return (void *)0;
+}
+
+static const uint32_t crcs[16] =
+{
+ 0xb42c65bb, 0xe158c0b7, 0x264b1740, 0xfebca54f,
+ 0xa6d752fe, 0x505b761a, 0x904c6244, 0xebc8a645,
+ 0x95d05ba0, 0xadee4db2, 0xb38ef0c2, 0x6d97958b,
+ 0x24c08d73, 0x3b0396b8, 0x117f98d4, 0xe1ab6e51,
+};
+
+int
+main ()
+{
+ uint32_t dest[16];
+ info_t info[16] = { { 0 } };
+ pthread_t threads[16];
+ void *retvals[16];
+ int i;
+
+ for (i = 0; i < 16; ++i)
+ {
+ info[i].thread_no = i;
+ info[i].dest = &dest[i];
+ info[i].crc32 = crcs[i];
+ }
+
+ for (i = 0; i < 16; ++i)
+ pthread_create (&threads[i], NULL, thread, &info[i]);
+
+ for (i = 0; i < 16; ++i)
+ pthread_join (threads[i], &retvals[i]);
+
+ for (i = 0; i < 16; ++i)
+ {
+ if (retvals[i] != (void *)0)
+ {
+ printf ("thread-test failed\n");
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+#endif
+
--
1.7.1
More information about the Pixman
mailing list