]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Added two additional regression tests.
authorBart Van Assche <bvanassche@acm.org>
Sun, 21 Mar 2010 17:24:47 +0000 (17:24 +0000)
committerBart Van Assche <bvanassche@acm.org>
Sun, 21 Mar 2010 17:24:47 +0000 (17:24 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11095

drd/tests/Makefile.am
drd/tests/annotate_barrier.c [new file with mode: 0644]
drd/tests/annotate_barrier.stderr.exp [new file with mode: 0644]
drd/tests/annotate_barrier.vgtest [new file with mode: 0644]
drd/tests/annotate_static.cpp [new file with mode: 0644]
drd/tests/annotate_static.stderr.exp [new file with mode: 0644]
drd/tests/annotate_static.vgtest [new file with mode: 0644]

index 4ca923cb05e9009ece11de106089e75840936f45..fff5d03974a899255e890ba2817d6c5a40e70af0 100644 (file)
@@ -14,6 +14,8 @@ noinst_HEADERS =                                    \
        tsan_thread_wrappers_pthread.h
 
 EXTRA_DIST =                                        \
+       annotate_barrier.stderr.exp                 \
+       annotate_barrier.vgtest                     \
        annotate_hb_err.stderr.exp                  \
        annotate_hb_err.vgtest                      \
        annotate_hb_race.stderr.exp                 \
@@ -48,6 +50,8 @@ EXTRA_DIST =                                        \
        annotate_ignore_write2.vgtest               \
        annotate_trace_memory.stderr.exp            \
        annotate_trace_memory.vgtest                \
+       annotate_static.stderr.exp                  \
+       annotate_static.vgtest                      \
        atomic_var.stderr.exp                       \
        atomic_var.vgtest                           \
        bar_bad.stderr.exp                          \
@@ -255,6 +259,7 @@ check_PROGRAMS =      \
   annotate_ignore_rw  \
   annotate_ignore_write \
   annotate_publish_hg \
+  annotate_static     \
   custom_alloc        \
   fp_race             \
   hold_lock           \
@@ -290,6 +295,7 @@ endif
 
 if HAVE_BUILTIN_ATOMIC
 check_PROGRAMS +=        \
+  annotate_barrier       \
   annotate_rwlock        \
   annotate_smart_pointer \
   atomic_var             \
@@ -355,6 +361,8 @@ if HAVE_BUILTIN_ATOMIC
 annotate_smart_pointer_SOURCES = annotate_smart_pointer.cpp
 endif
 
+annotate_static_SOURCES     = annotate_static.cpp
+
 if HAVE_OPENMP
 omp_matinv_CFLAGS           = $(AM_CFLAGS) -fopenmp
 omp_matinv_LDFLAGS          = -fopenmp
diff --git a/drd/tests/annotate_barrier.c b/drd/tests/annotate_barrier.c
new file mode 100644 (file)
index 0000000..ce120d3
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Test whether all data races are detected in a multithreaded program with
+ * user-annotated barriers. See also pth_barrier.c.
+ */
+
+
+#define _GNU_SOURCE
+
+
+#include <pthread.h> /* pthread_create() */
+#include <stdio.h>   /* fprintf() */
+#include <stdlib.h>  /* atoi() */
+#include <string.h>  /* memset() */
+#include "../../drd/drd.h"
+
+
+/* Local datatypes. */
+
+typedef struct
+{
+  /*
+   * number of threads that must call barrier_wait() before any of them
+   * successfully return from the call.
+   */
+  unsigned thread_count;
+  /* number of barrier_wait() calls since last barrier. */
+  volatile unsigned wait_count;
+  /*
+   * barrier count. Only the least significant bit matters -- a single bit
+   * counter would be sufficient.
+   */
+  volatile unsigned barrier_count;
+} barrier_t;
+
+struct threadinfo
+{
+  barrier_t* b;
+  pthread_t  tid;
+  int*       array;
+  int        iterations;
+};
+
+
+/* Local variables. */
+
+static int s_silent;
+
+
+/* Local functions. */
+
+static void barrier_init(barrier_t* b, unsigned count)
+{
+  b->thread_count = count;
+  b->wait_count = 0;
+  b->barrier_count = 0;
+  ANNOTATE_BARRIER_INIT(b, count, 0);
+}
+
+static void barrier_destroy(barrier_t* b)
+{
+  ANNOTATE_BARRIER_DESTROY(b);
+  memset(b, 0, sizeof(*b));
+}
+
+static int barrier_wait(barrier_t* b)
+{
+  int res;
+  unsigned barrier_count;
+
+  res = 0;
+  ANNOTATE_BARRIER_WAIT_BEFORE(b);
+  barrier_count = b->barrier_count;
+  if (__sync_add_and_fetch(&b->wait_count, 1) == b->thread_count)
+  {
+    __sync_sub_and_fetch(&b->wait_count, b->thread_count);
+    __sync_add_and_fetch(&b->barrier_count, 1);
+    res = PTHREAD_BARRIER_SERIAL_THREAD;
+  }
+  else
+  {
+    while (b->barrier_count == barrier_count)
+      pthread_yield();
+  }
+  ANNOTATE_BARRIER_WAIT_AFTER(b);
+  return res;
+}
+
+/*
+ * Single thread, which touches p->iterations elements of array p->array.
+ * Each modification of an element of p->array is a data race.
+ */
+static void* threadfunc(struct threadinfo* p)
+{
+  int i;
+  int* const array = p->array;
+  barrier_t* const b = p->b;
+  if (! s_silent)
+    printf("thread %lx iteration 0\n", pthread_self());
+  barrier_wait(b);
+  for (i = 0; i < p->iterations; i++)
+  {
+    if (! s_silent)
+      printf("thread %lx iteration %d; writing to %p\n",
+             pthread_self(), i + 1, &array[i]);
+    array[i] = i;
+    barrier_wait(b);
+  }
+  return 0;
+}
+
+/* Actual test, consisting of nthread threads. */
+static void barriers_and_races(const int nthread, const int iterations)
+{
+  int i;
+  struct threadinfo* t;
+  barrier_t b;
+  int* array;
+
+  t = malloc(nthread * sizeof(struct threadinfo));
+  array = malloc(iterations * sizeof(array[0]));
+
+  if (! s_silent)
+    printf("&array[0] = %p\n", array);
+
+  barrier_init(&b, nthread);
+
+  for (i = 0; i < nthread; i++)
+  {
+    t[i].b = &b;
+    t[i].array = array;
+    t[i].iterations = iterations;
+    pthread_create(&t[i].tid, 0, (void*(*)(void*))threadfunc, &t[i]);
+  }
+
+  for (i = 0; i < nthread; i++)
+    pthread_join(t[i].tid, 0);
+
+  barrier_destroy(&b);
+
+  free(array);
+  free(t);
+}
+
+int main(int argc, char** argv)
+{
+  int nthread;
+  int iterations;
+
+  nthread    = (argc > 1) ? atoi(argv[1]) : 2;
+  iterations = (argc > 2) ? atoi(argv[2]) : 3;
+  s_silent   = (argc > 3) ? atoi(argv[3]) : 0;
+
+  barriers_and_races(nthread, iterations);
+
+  fprintf(stderr, "Done.\n");
+
+  return 0;
+}
diff --git a/drd/tests/annotate_barrier.stderr.exp b/drd/tests/annotate_barrier.stderr.exp
new file mode 100644 (file)
index 0000000..18e39e2
--- /dev/null
@@ -0,0 +1,47 @@
+
+The annotation macro ANNOTATE_BARRIER_INIT has not yet been implemented in <valgrind/drd.h>
+   at 0x........: vgDrdCl_annotate_barrier_init (drd.h:?)
+   by 0x........: barrier_init (annotate_barrier.c:?)
+   by 0x........: barriers_and_races (annotate_barrier.c:?)
+
+Thread 2:
+The annotation macro ANNOTATE_BARRIER_WAIT_BEFORE has not yet been implemented in <valgrind/drd.h>
+   at 0x........: vgDrdCl_annotate_barrier_wait_before (drd.h:?)
+   by 0x........: barrier_wait (annotate_barrier.c:?)
+   by 0x........: threadfunc (annotate_barrier.c:?)
+
+Thread 3:
+The annotation macro ANNOTATE_BARRIER_WAIT_AFTER has not yet been implemented in <valgrind/drd.h>
+   at 0x........: vgDrdCl_annotate_barrier_wait_after (drd.h:?)
+   by 0x........: barrier_wait (annotate_barrier.c:?)
+   by 0x........: threadfunc (annotate_barrier.c:?)
+
+The annotation macro ANNOTATE_BARRIER_WAIT_BEFORE has not yet been implemented in <valgrind/drd.h>
+   at 0x........: vgDrdCl_annotate_barrier_wait_before (drd.h:?)
+   by 0x........: barrier_wait (annotate_barrier.c:?)
+   by 0x........: threadfunc (annotate_barrier.c:?)
+
+Thread 2:
+Conflicting store by thread 2 at 0x........ size 4
+   at 0x........: threadfunc (annotate_barrier.c:?)
+   by 0x........: vgDrd_thread_wrapper (drd_pthread_intercepts.c:?)
+   by 0x........: (within libpthread-?.?.so)
+Address 0x........ is at offset 0 from 0x......... Allocation context:
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: barriers_and_races (annotate_barrier.c:?)
+   by 0x........: main (annotate_barrier.c:?)
+
+The annotation macro ANNOTATE_BARRIER_WAIT_AFTER has not yet been implemented in <valgrind/drd.h>
+   at 0x........: vgDrdCl_annotate_barrier_wait_after (drd.h:?)
+   by 0x........: barrier_wait (annotate_barrier.c:?)
+   by 0x........: threadfunc (annotate_barrier.c:?)
+
+Thread 1:
+The annotation macro ANNOTATE_BARRIER_DESTROY has not yet been implemented in <valgrind/drd.h>
+   at 0x........: vgDrdCl_annotate_barrier_destroy (drd.h:?)
+   by 0x........: barrier_destroy (annotate_barrier.c:?)
+   by 0x........: barriers_and_races (annotate_barrier.c:?)
+
+Done.
+
+ERROR SUMMARY: 11 errors from 7 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_barrier.vgtest b/drd/tests/annotate_barrier.vgtest
new file mode 100644 (file)
index 0000000..c3491e5
--- /dev/null
@@ -0,0 +1,4 @@
+prereq: test -e annotate_barrier && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no --num-callers=3
+prog: annotate_barrier 2 1 1
+stderr_filter: filter_stderr
diff --git a/drd/tests/annotate_static.cpp b/drd/tests/annotate_static.cpp
new file mode 100644 (file)
index 0000000..154ee03
--- /dev/null
@@ -0,0 +1,37 @@
+// Test for ANNOTATE_BENIGN_RACE_STATIC() and ANNOTATE_UNPROTECTED_READ().
+
+
+#include <pthread.h> /* pthread_create() */
+#include <stdio.h>   /* fprintf() */
+#include "../../drd/drd.h"
+
+
+/* Local variables. */
+
+static int s_i;
+static volatile int s_j;
+
+ANNOTATE_BENIGN_RACE_STATIC(s_i, "Benign because duplicate assignment.");
+
+
+/* Local functions. */
+
+static void* thread_func(void*)
+{
+  s_i = ANNOTATE_UNPROTECTED_READ(s_j);
+  return 0;
+}
+
+int main(int argc, char** argv)
+{
+  pthread_t tid;
+
+  pthread_create(&tid, 0, thread_func, NULL);
+  s_j++;
+  s_i = s_j;
+  pthread_join(tid, NULL);
+
+  fprintf(stderr, "Done.\n");
+
+  return 0;
+}
diff --git a/drd/tests/annotate_static.stderr.exp b/drd/tests/annotate_static.stderr.exp
new file mode 100644 (file)
index 0000000..d16127f
--- /dev/null
@@ -0,0 +1,4 @@
+
+Done.
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/drd/tests/annotate_static.vgtest b/drd/tests/annotate_static.vgtest
new file mode 100644 (file)
index 0000000..32ec4cc
--- /dev/null
@@ -0,0 +1,4 @@
+prereq: test -e annotate_static && ./supported_libpthread
+vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no
+prog: annotate_static
+stderr_filter: filter_stderr