Author: sewardj
Date: 2007-10-25 17:59:14 +0100 (Thu, 25 Oct 2007)
New Revision: 7033

Log:
Test semaphore handling, by using them to build a barrier.

Added:
   branches/THRCHECK/thrcheck/tests/tc17_sembar.c
   branches/THRCHECK/thrcheck/tests/tc17_sembar.stderr.exp
   branches/THRCHECK/thrcheck/tests/tc17_sembar.stdout.exp
   branches/THRCHECK/thrcheck/tests/tc17_sembar.vgtest
Modified:
   branches/THRCHECK/thrcheck/tests/Makefile.am


Modified: branches/THRCHECK/thrcheck/tests/Makefile.am
===================================================================
--- branches/THRCHECK/thrcheck/tests/Makefile.am        2007-10-25 16:09:46 UTC 
(rev 7032)
+++ branches/THRCHECK/thrcheck/tests/Makefile.am        2007-10-25 16:59:14 UTC 
(rev 7033)
@@ -1,6 +1,4 @@
 
-# FIXME: this is completely bogus (a copy of Helgrind's one)
-
 # For AM_FLAG_M3264_PRI
 include $(top_srcdir)/Makefile.flags.am
 
@@ -42,7 +40,9 @@
        tc15_laog_lockdel.vgtest tc15_laog_lockdel.stderr.exp \
                tc15_laog_lockdel.stdout.exp \
        tc16_byterace.vgtest tc16_byterace.stderr.exp \
-               tc16_byterace.stdout.exp
+               tc16_byterace.stdout.exp \
+       tc17_sembar.vgtest tc17_sembar.stderr.exp \
+               tc17_sembar.stdout.exp
 
 check_PROGRAMS = \
        hg01_all_ok \
@@ -66,7 +66,8 @@
        tc13_laog1 \
        tc14_laog_dinphils \
        tc15_laog_lockdel \
-       tc16_byterace
+       tc16_byterace \
+       tc17_sembar
 
 # is this necessary?
 AM_CFLAGS      = $(WERROR) -Winline -Wall -Wshadow -g      $(AM_FLAG_M3264_PRI)

Added: branches/THRCHECK/thrcheck/tests/tc17_sembar.c
===================================================================
--- branches/THRCHECK/thrcheck/tests/tc17_sembar.c                              
(rev 0)
+++ branches/THRCHECK/thrcheck/tests/tc17_sembar.c      2007-10-25 16:59:14 UTC 
(rev 7033)
@@ -0,0 +1,178 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pthread.h>
+#include <semaphore.h>
+
+/* This is really a test of semaphore handling
+   (sem_{init,destroy,post,wait}).  Using semaphores a barrier
+   function is created.  Thrcheck does understand the barrier
+   semantics implied by the barrier, as pieced together from
+   happens-before relationships obtained from the component
+   semaphores.  However, it does falsely report one race.  Ah well. */
+
+/* This code is derived from
+   gcc-4.3-20071012/libgomp/config/posix/bar.c, which is
+
+   Copyright (C) 2005 Free Software Foundation, Inc.
+   Contributed by Richard Henderson <[EMAIL PROTECTED]>.
+
+   and available under version 2.1 or later of the GNU Lesser General
+   Public License.
+
+   Relative to the libgomp sources, the gomp_barrier_t type here has
+   an extra semaphore field, xxx.  This is not functionally useful,
+   but it is used to create enough extra inter-thread dependencies
+   that the barrier-like behaviour of gomp_barrier_t is evident to
+   Thrcheck.  There is no other purpose for the .xxx field. */
+
+typedef struct
+{
+  pthread_mutex_t mutex1;
+  pthread_mutex_t mutex2;
+  sem_t sem1;
+  sem_t sem2;
+  unsigned total;
+  unsigned arrived;
+  sem_t xxx;
+} gomp_barrier_t;
+
+typedef long bool;
+
+void
+gomp_barrier_init (gomp_barrier_t *bar, unsigned count)
+{
+  pthread_mutex_init (&bar->mutex1, NULL);
+  pthread_mutex_init (&bar->mutex2, NULL);
+  sem_init (&bar->sem1, 0, 0);
+  sem_init (&bar->sem2, 0, 0);
+  sem_init (&bar->xxx,  0, 0);
+  bar->total = count;
+  bar->arrived = 0;
+}
+
+void
+gomp_barrier_destroy (gomp_barrier_t *bar)
+{
+  /* Before destroying, make sure all threads have left the barrier.  */
+  pthread_mutex_lock (&bar->mutex1);
+  pthread_mutex_unlock (&bar->mutex1);
+
+  pthread_mutex_destroy (&bar->mutex1);
+  pthread_mutex_destroy (&bar->mutex2);
+  sem_destroy (&bar->sem1);
+  sem_destroy (&bar->sem2);
+  sem_destroy(&bar->xxx);
+}
+
+void
+gomp_barrier_reinit (gomp_barrier_t *bar, unsigned count)
+{
+  pthread_mutex_lock (&bar->mutex1);
+  bar->total = count;
+  pthread_mutex_unlock (&bar->mutex1);
+}
+
+void
+gomp_barrier_wait (gomp_barrier_t *bar)
+{
+  unsigned int n;
+  pthread_mutex_lock (&bar->mutex1);
+
+  ++bar->arrived;
+
+  if (bar->arrived == bar->total)
+    {
+      bar->arrived--;
+      n = bar->arrived;
+      if (n > 0) 
+        {
+          { unsigned int i;
+            for (i = 0; i < n; i++)
+              sem_wait(&bar->xxx); // acquire an obvious dependency from
+              // all other threads arriving at the barrier
+          }
+          // 1 up n times, 2 down once
+          // now let all the other threads past the barrier, giving them
+          // an obvious dependency with this thread.
+          do
+            sem_post (&bar->sem1); // 1 up
+          while (--n != 0);
+          // and wait till the last thread has left
+          sem_wait (&bar->sem2); // 2 down
+        }
+      pthread_mutex_unlock (&bar->mutex1);
+      /* Resultat professionnel!  First we made this thread have an
+         obvious (Thrcheck-visible) dependency on all other threads
+         calling gomp_barrier_wait.  Then, we released them all again,
+         so they all have a (visible) dependency on this thread.
+         Transitively, the result is that all threads leaving the
+         barrier have a a Thrcheck-visible dependency on all threads
+         arriving at the barrier.  As required. */
+    }
+  else
+    {
+      pthread_mutex_unlock (&bar->mutex1);
+      sem_post(&bar->xxx);
+      // first N-1 threads wind up waiting here
+      sem_wait (&bar->sem1); // 1 down 
+
+      pthread_mutex_lock (&bar->mutex2);
+      n = --bar->arrived; /* XXX see below */
+      pthread_mutex_unlock (&bar->mutex2);
+
+      if (n == 0)
+        sem_post (&bar->sem2); // 2 up
+    }
+}
+
+
+/* re XXX, thrcheck reports a race at this point.  It doesn't
+   understand that bar->arrived is protected by mutex1 whilst threads
+   are arriving at the barrier and by mutex2 whilst they are leaving,
+   but not consistently by either of them.  Oh well. */
+
+gomp_barrier_t bar;
+
+void* child ( void* argV )
+{
+   gomp_barrier_wait( &bar );
+   gomp_barrier_wait( &bar );
+   gomp_barrier_wait( &bar );
+   gomp_barrier_wait( &bar );
+   gomp_barrier_wait( &bar );
+   gomp_barrier_wait( &bar );
+   gomp_barrier_wait( &bar );
+   gomp_barrier_wait( &bar );
+   return NULL;
+}
+
+#define NNN 4
+
+int main (int argc, char *argv[])
+{
+  int j;
+   long i; int res;
+   pthread_t thr[NNN];
+   fprintf(stderr, "starting\n");
+
+   for (j = 0; j < 1; j++) {
+   gomp_barrier_init( &bar, NNN );
+
+   for (i = 0; i < NNN; i++) {
+      res = pthread_create( &thr[i], NULL, child, (void*)i );
+      assert(!res);
+   }
+
+   for (i = 0; i < NNN; i++) {
+      res = pthread_join( thr[i], NULL );
+      assert(!res);
+   }
+
+   gomp_barrier_destroy( &bar );
+   }
+   fprintf(stderr, "done\n");
+
+   return 0;
+}

Added: branches/THRCHECK/thrcheck/tests/tc17_sembar.stderr.exp
===================================================================
--- branches/THRCHECK/thrcheck/tests/tc17_sembar.stderr.exp                     
        (rev 0)
+++ branches/THRCHECK/thrcheck/tests/tc17_sembar.stderr.exp     2007-10-25 
16:59:14 UTC (rev 7033)
@@ -0,0 +1,46 @@
+
+starting
+Thread #2 was created
+   at 0x........: clone (in /...libc...)
+   by 0x........: ...
+   by 0x........: pthread_create@@GLIBC_2.2.5 (in /lib/libpthread...)
+   by 0x........: [EMAIL PROTECTED] (tc_intercepts.c:...)
+   by 0x........: main (tc17_sembar.c:164)
+
+Thread #3 was created
+   at 0x........: clone (in /...libc...)
+   by 0x........: ...
+   by 0x........: pthread_create@@GLIBC_2.2.5 (in /lib/libpthread...)
+   by 0x........: [EMAIL PROTECTED] (tc_intercepts.c:...)
+   by 0x........: main (tc17_sembar.c:164)
+
+Thread #4 was created
+   at 0x........: clone (in /...libc...)
+   by 0x........: ...
+   by 0x........: pthread_create@@GLIBC_2.2.5 (in /lib/libpthread...)
+   by 0x........: [EMAIL PROTECTED] (tc_intercepts.c:...)
+   by 0x........: main (tc17_sembar.c:164)
+
+Thread #5 was created
+   at 0x........: clone (in /...libc...)
+   by 0x........: ...
+   by 0x........: pthread_create@@GLIBC_2.2.5 (in /lib/libpthread...)
+   by 0x........: [EMAIL PROTECTED] (tc_intercepts.c:...)
+   by 0x........: main (tc17_sembar.c:164)
+
+Possible data race during read of size 4 at 0x........
+   at 0x........: gomp_barrier_wait (tc17_sembar.c:122)
+   by 0x........: child (tc17_sembar.c:140)
+   by 0x........: mythread_wrapper (tc_intercepts.c:...)
+   by 0x........: ...
+   by 0x........: ...
+  Old state: shared-modified by threads #2, #3, #4, #5
+  New state: shared-modified by threads #2, #3, #4, #5
+  Reason:    this thread, #2, holds no consistent locks
+  Last consistently used lock for 0x........ was first observed
+   at 0x........: pthread_mutex_init (tc_intercepts.c:...)
+   by 0x........: gomp_barrier_init (tc17_sembar.c:46)
+   by 0x........: main (tc17_sembar.c:161)
+done
+
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Added: branches/THRCHECK/thrcheck/tests/tc17_sembar.stdout.exp
===================================================================

Added: branches/THRCHECK/thrcheck/tests/tc17_sembar.vgtest
===================================================================
--- branches/THRCHECK/thrcheck/tests/tc17_sembar.vgtest                         
(rev 0)
+++ branches/THRCHECK/thrcheck/tests/tc17_sembar.vgtest 2007-10-25 16:59:14 UTC 
(rev 7033)
@@ -0,0 +1 @@
+prog: tc17_sembar


-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Valgrind-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/valgrind-developers

Reply via email to