[Pixman] [PATCH 2/2] test: Add new thread-test program
Lennart Sorensen
lsorense at csclub.uwaterloo.ca
Mon Sep 30 07:03:24 PDT 2013
On Sat, Sep 28, 2013 at 10:04:02PM -0400, Søren Sandmann wrote:
> From: Søren Sandmann Pedersen <ssp at redhat.com>
>
> This test program allocates an array of 16 * 7 uint32_ts and spawns 16
> threads that each use 7 of the allocated uint32_ts as a destination
> image for a large number of composite operations. Each thread then
> computes and returns a checksum for the image. Finally, the main
> thread computes a checksum of the checksums and verifies that it
> matches expectations.
>
> 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, because the threads will race to
> read and write the shared memory.
>
> V2:
> - Incorporate fixes from Siarhei for endianness and undefined behavior
> regarding argument evaluation
> - Make the images 7 pixels wide since the bug only happens when the
> composite width is greater than 4.
> - Compute a checksum of the checksums so that you don't have to
> update 16 values if something changes.
> ---
> test/Makefile.am | 6 +-
> test/Makefile.sources | 1 +
> test/thread-test.c | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 201 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)$
What is that trailing '$' for?
> +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..f24c31d
> --- /dev/null
> +++ b/test/thread-test.c
> @@ -0,0 +1,197 @@
> +#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 *dst_buf;
> +} 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 8192
> +
> +#define RAND_ELT(arr) \
> + arr[prng_rand() % ARRAY_LENGTH (arr)]
> +
> +#define DEST_WIDTH (7)
> +
> +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)
> + {
> + pixman_op_t op;
> + int rand1, rand2;
> +
> + prng_randmemset (info->dst_buf, DEST_WIDTH * sizeof (uint32_t), 0);
> + 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), DEST_WIDTH, 1, info->dst_buf,
> + DEST_WIDTH * sizeof (uint32_t));
> +
> + image_endian_swap (src_img);
> + image_endian_swap (dst_img);
> +
> + rand2 = prng_rand() % 4;
> + rand1 = prng_rand() % 4;
> + op = RAND_ELT (operators);
> +
> + pixman_image_composite32 (
> + op,
> + src_img, NULL, dst_img,
> + rand1, rand2, 0, 0, 0, 0, DEST_WIDTH, 1);
> +
> + crc32 = compute_crc32_for_image (crc32, dst_img);
> +
> + pixman_image_unref (src_img);
> + pixman_image_unref (dst_img);
> + }
> +
> + return (void *)(uintptr_t)crc32;
> +}
> +
> +static inline uint32_t
> +byteswap32 (uint32_t x)
> +{
> + return ((x & ((uint32_t)0xFF << 24)) >> 24) |
> + ((x & ((uint32_t)0xFF << 16)) >> 8) |
> + ((x & ((uint32_t)0xFF << 8)) << 8) |
> + ((x & ((uint32_t)0xFF << 0)) << 24);
> +}
> +
> +int
> +main (void)
> +{
> + uint32_t dest[16 * DEST_WIDTH];
> + info_t info[16] = { { 0 } };
> + pthread_t threads[16];
> + void *retvals[16];
> + uint32_t crc32s[16], crc32;
> + int i;
> +
> + for (i = 0; i < 16; ++i)
> + {
> + info[i].thread_no = i;
> + info[i].dst_buf = &dest[i * DEST_WIDTH];
> + }
> +
> + 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)
> + {
> + crc32s[i] = (uintptr_t)retvals[i];
> +
> + if (is_little_endian())
> + crc32s[i] = byteswap32 (crc32s[i]);
> + }
> +
> + crc32 = compute_crc32 (0, crc32s, sizeof crc32s);
> +
> +#define EXPECTED 0xFD497D8D
> +
> + if (crc32 != EXPECTED)
> + {
> + printf ("thread-test failed. Got checksum 0x%08X, expected 0x%08X\n",
> + crc32, EXPECTED);
> + return 1;
> + }
> +
> + return 0;
> +}
> +
> +#endif
> +
> --
> 1.7.11.7
--
Len Sorensen
More information about the Pixman
mailing list