This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: Add a DFP thread test


On Fri, Jun 15, 2007 at 06:37:44AM -0700, H. J. Lu wrote:
> On Thu, Jun 14, 2007 at 04:44:14PM -0700, H. J. Lu wrote:
> > On Thu, Jun 14, 2007 at 04:31:50PM -0700, David Daney wrote:
> > > 
> > > That doesn't make any sense.  Why would you be checking if the build 
> > > compiler supports certain features when configuring libgcc?
> > > 
> > 
> > Please read my patch again. For native build, it uses
> > GCC_CHECK_TLS in gcc to check if the target supports TLS at
> > run-time since the native compiler is used for GCC_CHECK_TLS.
> > Even if the build compiler doesn't support TLS, it won't be a
> > problem. The stage 2 and stage 3 libgcc will still use TLS if
> > the stage 2 and stage 3 compilers do supprot TLS at run-time.
> > 
> > For cross build, it uses GCC_CHECK_TLS in libgcc to check if
> > the target supports TLS since CC_FOR_TARGET is used for building
> > libgcc which is a target library. Since you can't do run-time
> > check with a cross compiler, GCC_CHECK_TLS will just do compile
> > time check. In that case, it will just trust users.
> > 
> > Please read config/tls.m4 and my patch very carefully. They are
> > kind of tricky.
> 
> There are a few issues:
> 
> 1. libbid includes "auto-host.h" to get ENABLE_DECIMAL_BID_FORMAT
> because ENABLE_DECIMAL_BID_FORMAT isn't marked as a target
> template.
> 2. HAVE_TLS in gcc set by GCC_CHECK_TLS should a target template and
> should be set only when the compile to be built is a native compiler
> for the native target.  Otherwise, it may be wrong for target.
> 3. When Makefile in libgcc defines HAVE_TLS for cross compiler, it
> will be undefined in auto-host.h in gcc.  We can use USE_TLS in libgcc
> and libbid can check both HAVE_TLS and USE_TLS.
> 
> I am enclosing 2 patchs, one for gcc and one for libbid, to address
> those issues.
> 

Now Intel BID library is thread-safe when TLS is available. Here is
a patch to add a DFP thread-safety test.


H.J.
---
2007-06-15  H.J. Lu  <hongjiu.lu@intel.com>

	* gcc.dg/dfp/convert-dfp-round-thread.c: New test.

--- gcc/testsuite/gcc.dg/dfp/convert-dfp-round-thread.c.dfp-thread	2007-06-15 10:26:48.000000000 -0700
+++ gcc/testsuite/gcc.dg/dfp/convert-dfp-round-thread.c	2007-06-15 10:25:58.000000000 -0700
@@ -0,0 +1,494 @@
+/* { dg-options "-std=gnu99 -D_GNU_SOURCE -pthread" } */
+/* { dg-do run { target i?86-*-linux* x86_64-*-linux* } } */
+
+/* N1150 5.2: Conversions among decimal floating types and between
+   decimal floating types and generic floating types.
+   C99 6.3.1.5(3) New.
+
+   Perform conversions between DFP types in which the assigned value
+   cannot be represented exactly in the result and must be rounded
+   correctly according to the current rounding mode.
+
+   Normally this would not be part of compiler testing, but conversions
+   are currently handled in libgcc via decNumber.  */
+
+#include <pthread.h>
+#include <error.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+#include "dfp-round.h"
+
+extern void abort (void);
+static __thread int failcnt = 0;
+
+/* Support compiling the test to report individual failures; default is
+   to abort as soon as a check fails.  */
+#ifdef DBG
+#include <stdio.h>
+#define FAILURE { printf ("failed at line %d\n", __LINE__); failcnt++; }
+#else
+#define FAILURE abort ();
+#endif
+
+pthread_mutex_t mut1 = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t mut2 = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t mut3 = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t mut4 = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t mut5 = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
+pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
+pthread_cond_t cond3 = PTHREAD_COND_INITIALIZER;
+pthread_cond_t cond4 = PTHREAD_COND_INITIALIZER;
+pthread_cond_t cond5 = PTHREAD_COND_INITIALIZER;
+pthread_barrier_t bar1;
+pthread_barrier_t bar2;
+pthread_barrier_t bar3;
+pthread_barrier_t bar4;
+pthread_barrier_t bar5;
+
+__thread _Decimal32 d32;
+__thread _Decimal64 d64;
+__thread _Decimal128 d128;
+
+_Decimal32 d64_to_d32 (_Decimal64 d) { return d; }
+_Decimal64 d128_to_d64 (_Decimal128 d) { return d; }
+_Decimal32 d128_to_d32 (_Decimal128 d) { return d; }
+
+int
+do_d64_to_d32 (_Decimal64 orig, _Decimal32 exp)
+{
+  d64 = orig;
+  d32 = d64_to_d32 (d64);
+  return (d32 == exp);
+}
+
+int
+do_d128_to_d32 (_Decimal128 orig, _Decimal32 exp)
+{
+  d128 = orig;
+  d32 = d128_to_d32 (d128);
+  return (d32 == exp);
+}
+
+int
+do_d128_to_d64 (_Decimal128 orig, _Decimal64 exp)
+{
+  d128 = orig;
+  d64 = d128_to_d64 (d128);
+  return (d64 == exp);
+}
+
+void *
+downward (void *arg)
+{
+  int err;
+
+  DFP_SETROUND (FE_DEC_DOWNWARD);
+
+  err = pthread_mutex_lock (&mut1);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "downward: failed to lock");
+
+  err = pthread_barrier_wait (&bar1);
+  if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("downward: barrier_wait failed");
+      exit (1);
+    } 
+
+  err = pthread_cond_wait (&cond1, &mut1);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "downward: failed to wait");
+
+  err = pthread_mutex_unlock (&mut1);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "downward: failed to unlock");
+
+  if (!do_d64_to_d32 (1.1111125dd, 1.111112df)) FAILURE
+  if (!do_d64_to_d32 (1.1111135dd, 1.111113df)) FAILURE
+  if (!do_d64_to_d32 (-1.1111125dd, -1.111113df)) FAILURE
+  if (!do_d64_to_d32 (-1.1111135dd, -1.111114df)) FAILURE
+  if (!do_d128_to_d32 (1.1111125dl, 1.111112df)) FAILURE
+  if (!do_d128_to_d32 (1.1111135dl, 1.111113df)) FAILURE
+  if (!do_d128_to_d32 (-1.1111125dl, -1.111113df)) FAILURE
+  if (!do_d128_to_d32 (-1.1111135dl, -1.111114df)) FAILURE
+  if (!do_d128_to_d64 (1.1111111111111125dl, 1.111111111111112dd)) FAILURE
+  if (!do_d128_to_d64 (1.1111111111111135dl, 1.111111111111113dd)) FAILURE
+  if (!do_d128_to_d64 (-1.1111111111111125dl, -1.111111111111113dd)) FAILURE
+  if (!do_d128_to_d64 (-1.1111111111111135dl, -1.111111111111114dd)) FAILURE
+  
+#ifdef DBG
+  if (failcnt)
+    printf ("downward: %d fails\n", failcnt);
+#endif
+  return (void *) (ptrdiff_t) failcnt;
+}
+
+void *
+tonearest (void *arg)
+{
+  int err;
+  DFP_SETROUND (FE_DEC_TONEAREST);
+
+  err = pthread_mutex_lock (&mut2);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "tonearest: failed to lock");
+
+  err = pthread_barrier_wait (&bar2);
+  if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("tonearest: barrier_wait failed");
+      exit (1);
+    } 
+
+  err = pthread_cond_wait (&cond2, &mut2);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "tonearest: failed to wait");
+
+  err = pthread_mutex_unlock (&mut2);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "tonearest: failed to unlock");
+
+  if (!do_d64_to_d32 (1.1111125dd, 1.111112df)) FAILURE
+  if (!do_d64_to_d32 (1.1111135dd, 1.111114df)) FAILURE
+  if (!do_d64_to_d32 (-1.1111125dd, -1.111112df)) FAILURE
+  if (!do_d64_to_d32 (-1.1111135dd, -1.111114df)) FAILURE
+  if (!do_d128_to_d32 (1.1111125dl, 1.111112df)) FAILURE
+  if (!do_d128_to_d32 (1.1111135dl, 1.111114df)) FAILURE
+  if (!do_d128_to_d32 (-1.1111125dl, -1.111112df)) FAILURE
+  if (!do_d128_to_d32 (-1.1111135dl, -1.111114df)) FAILURE
+  if (!do_d128_to_d64 (1.1111111111111125dl, 1.111111111111112dd)) FAILURE
+  if (!do_d128_to_d64 (1.1111111111111135dl, 1.111111111111114dd)) FAILURE
+  if (!do_d128_to_d64 (-1.1111111111111125dl, -1.111111111111112dd)) FAILURE
+  if (!do_d128_to_d64 (-1.1111111111111135dl, -1.111111111111114dd)) FAILURE
+  
+#ifdef DBG
+  if (failcnt)
+    printf ("tonearest: %d fails\n", failcnt);
+#endif
+  return (void *) (ptrdiff_t) failcnt;
+} 
+
+void *
+toneareastfromzero (void *arg)
+{
+  int err;
+  DFP_SETROUND (FE_DEC_TONEARESTFROMZERO);
+
+  err = pthread_mutex_lock (&mut3);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "toneareastfromzero: failed to lock");
+
+  err = pthread_barrier_wait (&bar3);
+  if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("toneareastfromzero: barrier_wait failed");
+      exit (1);
+    } 
+
+  err = pthread_cond_wait (&cond3, &mut3);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "toneareastfromzero: failed to wait");
+
+  err = pthread_mutex_unlock (&mut3);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "toneareastfromzero: failed to unlock");
+
+  if (!do_d64_to_d32 (1.1111125dd, 1.111113df)) FAILURE
+  if (!do_d64_to_d32 (1.1111135dd, 1.111114df)) FAILURE
+  if (!do_d64_to_d32 (-1.1111125dd, -1.111113df)) FAILURE
+  if (!do_d64_to_d32 (-1.1111135dd, -1.111114df)) FAILURE
+  if (!do_d128_to_d32 (1.1111125dl, 1.111113df)) FAILURE
+  if (!do_d128_to_d32 (1.1111135dl, 1.111114df)) FAILURE
+  if (!do_d128_to_d32 (-1.1111125dl, -1.111113df)) FAILURE
+  if (!do_d128_to_d32 (-1.1111135dl, -1.111114df)) FAILURE
+  if (!do_d128_to_d64 (1.1111111111111125dl, 1.111111111111113dd)) FAILURE
+  if (!do_d128_to_d64 (1.1111111111111135dl, 1.111111111111114dd)) FAILURE
+  if (!do_d128_to_d64 (-1.1111111111111125dl, -1.111111111111113dd)) FAILURE
+  if (!do_d128_to_d64 (-1.1111111111111135dl, -1.111111111111114dd)) FAILURE
+  
+#ifdef DBG
+  if (failcnt)
+    printf ("toneareastfromzero: %d fails\n", failcnt);
+#endif
+  return (void *) (ptrdiff_t) failcnt;
+} 
+  
+void *
+towardzero (void *arg)
+{
+  int err;
+  DFP_SETROUND (FE_DEC_TOWARDZERO);
+
+  err = pthread_mutex_lock (&mut4);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "towardzero: failed to lock");
+
+  err = pthread_barrier_wait (&bar4);
+  if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("towardzero: barrier_wait failed");
+      exit (1);
+    } 
+
+  err = pthread_cond_wait (&cond4, &mut4);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "towardzero: failed to wait");
+
+  err = pthread_mutex_unlock (&mut4);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "towardzero: failed to unlock");
+
+  if (!do_d64_to_d32 (1.1111125dd, 1.111112df)) FAILURE
+  if (!do_d64_to_d32 (1.1111135dd, 1.111113df)) FAILURE
+  if (!do_d64_to_d32 (-1.1111125dd, -1.111112df)) FAILURE
+  if (!do_d64_to_d32 (-1.1111135dd, -1.111113df)) FAILURE
+  if (!do_d128_to_d32 (1.1111125dl, 1.111112df)) FAILURE
+  if (!do_d128_to_d32 (1.1111135dl, 1.111113df)) FAILURE
+  if (!do_d128_to_d32 (-1.1111125dl, -1.111112df)) FAILURE
+  if (!do_d128_to_d32 (-1.1111135dl, -1.111113df)) FAILURE
+  if (!do_d128_to_d64 (1.1111111111111125dl, 1.111111111111112dd)) FAILURE
+  if (!do_d128_to_d64 (1.1111111111111135dl, 1.111111111111113dd)) FAILURE
+  if (!do_d128_to_d64 (-1.1111111111111125dl, -1.111111111111112dd)) FAILURE
+  if (!do_d128_to_d64 (-1.1111111111111135dl, -1.111111111111113dd)) FAILURE
+
+#ifdef DBG
+  if (failcnt)
+    printf ("towardzero: %d fails\n", failcnt);
+#endif
+  return (void *) (ptrdiff_t) failcnt;
+} 
+
+void *
+upward (void *arg)
+{
+  int err;
+  DFP_SETROUND (FE_DEC_UPWARD);
+
+  err = pthread_mutex_lock (&mut5);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "upward: failed to lock");
+
+  err = pthread_barrier_wait (&bar5);
+  if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("upward: barrier_wait failed");
+      exit (1);
+    } 
+
+  err = pthread_cond_wait (&cond5, &mut5);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "upward: failed to wait");
+
+  err = pthread_mutex_unlock (&mut5);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "upward: failed to unlock");
+
+  if (!do_d64_to_d32 (1.1111125dd, 1.111113df)) FAILURE
+  if (!do_d64_to_d32 (1.1111135dd, 1.111114df)) FAILURE
+  if (!do_d64_to_d32 (-1.1111125dd, -1.111112df)) FAILURE
+  if (!do_d64_to_d32 (-1.1111135dd, -1.111113df)) FAILURE
+  if (!do_d128_to_d32 (1.1111125dl, 1.111113df)) FAILURE
+  if (!do_d128_to_d32 (1.1111135dl, 1.111114df)) FAILURE
+  if (!do_d128_to_d32 (-1.1111125dl, -1.111112df)) FAILURE
+  if (!do_d128_to_d32 (-1.1111135dl, -1.111113df)) FAILURE
+  if (!do_d128_to_d64 (1.1111111111111125dl, 1.111111111111113dd)) FAILURE
+  if (!do_d128_to_d64 (1.1111111111111135dl, 1.111111111111114dd)) FAILURE
+  if (!do_d128_to_d64 (-1.1111111111111125dl, -1.111111111111112dd)) FAILURE
+  if (!do_d128_to_d64 (-1.1111111111111135dl, -1.111111111111113dd)) FAILURE
+  
+#ifdef DBG
+  if (failcnt)
+    printf ("upward: %d fails\n", failcnt);
+#endif
+  return (void *) (ptrdiff_t) failcnt;
+}
+
+int
+main (void)
+{
+  int err;
+  int count = 0;
+  void *ret;
+  pthread_t down, up, tozero, fromzero, nearest;
+
+  if (pthread_barrier_init (&bar1, NULL, 2) != 0
+      || pthread_barrier_init (&bar2, NULL, 2) != 0
+      || pthread_barrier_init (&bar3, NULL, 2) != 0
+      || pthread_barrier_init (&bar4, NULL, 2) != 0
+      || pthread_barrier_init (&bar5, NULL, 2) != 0)
+    {
+      puts ("parent: failed to init barrier");
+      return 1;
+    }
+
+  if (pthread_create (&down, NULL, downward, NULL) != 0)
+    {
+      puts ("parent: failed to create");
+      return 1;
+    }
+
+  if (pthread_create (&nearest, NULL, tonearest, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  if (pthread_create (&fromzero, NULL, toneareastfromzero, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  if (pthread_create (&up, NULL, upward, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  if (pthread_create (&tozero, NULL, towardzero, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  err = pthread_barrier_wait (&bar1);
+  if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("parent: failed to wait barrier 1");
+      return 1;
+    }
+  err = pthread_barrier_wait (&bar2);
+  if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("parent: failed to wait barrier 2");
+      return 1;
+    }
+  err = pthread_barrier_wait (&bar3);
+  if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("parent: failed to wait barrier 3");
+      return 1;
+    }
+  err = pthread_barrier_wait (&bar4);
+  if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("parent: failed to wait barrier 4");
+      return 1;
+    }
+  err = pthread_barrier_wait (&bar5);
+  if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("parent: failed to wait barrier 5");
+      return 1;
+    }
+
+  err = pthread_mutex_lock (&mut1);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "parent: lock failed");
+  err = pthread_mutex_lock (&mut2);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "parent: lock failed");
+  err = pthread_mutex_lock (&mut3);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "parent: lock failed");
+  err = pthread_mutex_lock (&mut4);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "parent: lock failed");
+  err = pthread_mutex_lock (&mut5);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "parent: lock failed");
+
+  err = pthread_cond_signal(&cond1);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "parent: broadcast failed");
+  err = pthread_cond_signal(&cond2);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "parent: broadcast failed");
+  err = pthread_cond_signal(&cond3);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "parent: broadcast failed");
+  err = pthread_cond_signal(&cond4);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "parent: broadcast failed");
+  err = pthread_cond_signal(&cond5);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "parent: broadcast failed");
+
+  err = pthread_mutex_unlock (&mut1);
+  if (err != 0)
+    {
+      puts ("parent: failed to unlock");
+      return 1;
+    }
+  err = pthread_mutex_unlock (&mut2);
+  if (err != 0)
+    {
+      puts ("parent: failed to unlock");
+      return 1;
+    }
+  err = pthread_mutex_unlock (&mut3);
+  if (err != 0)
+    {
+      puts ("parent: failed to unlock");
+      return 1;
+    }
+  err = pthread_mutex_unlock (&mut4);
+  if (err != 0)
+    {
+      puts ("parent: failed to unlock");
+      return 1;
+    }
+  err = pthread_mutex_unlock (&mut5);
+  if (err != 0)
+    {
+      puts ("parent: failed to unlock");
+      return 1;
+    }
+
+  if (pthread_join (down, &ret) != 0)
+    {
+      puts ("pthread_join failed");
+      return 1;
+    }
+  count += (int) (ptrdiff_t) ret;
+
+  if (pthread_join (up, &ret) != 0)
+    {
+      puts ("pthread_join failed");
+      return 1;
+    }
+  count += (int) (ptrdiff_t) ret;
+
+  if (pthread_join (tozero, &ret) != 0)
+    {
+      puts ("pthread_join failed");
+      return 1;
+    }
+  count += (int) (ptrdiff_t) ret;
+
+  if (pthread_join (fromzero, &ret) != 0)
+    {
+      puts ("pthread_join failed");
+      return 1;
+    }
+  count += (int) (ptrdiff_t) ret;
+
+  if (pthread_join (nearest, &ret) != 0)
+    {
+      puts ("pthread_join failed");
+      return 1;
+    }
+  count += (int) (ptrdiff_t) ret;
+
+  if (count)
+    {
+#ifdef DBG
+      printf ("Total: %d fails\n", count);
+#endif
+      abort ();
+    }
+
+  return 0;
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]