Committed and pushed to branch dmalcolm/jit:

gcc/testsuite/
        * jit.dg/test-threads.c: New test case, running all of the
        individual test cases in separate threads.
        * jit.dg/test-combination.c: Move inclusion of the various
        individual testcases into...
        * jit.dg/all-non-failing-tests.h: ...this new file, and rename
        TEST_COMBINATION to COMBINED_TEST.
        * jit.dg/harness.h: Respond to new macro MAKE_DEJAGNU_H_THREADSAFE
        by hacking up <dejagnu.h> to be threadsafe.  Rename
        TEST_COMBINATION to COMBINED_TEST.
        * jit.dg/jit.exp (proc jit-dg-test): Add "-lpthread" when building
        test-threads.exe.
---
 gcc/testsuite/ChangeLog.jit                  |  14 ++
 gcc/testsuite/jit.dg/all-non-failing-tests.h | 152 ++++++++++++++++++
 gcc/testsuite/jit.dg/harness.h               |  25 ++-
 gcc/testsuite/jit.dg/jit.exp                 |   5 +
 gcc/testsuite/jit.dg/test-combination.c      | 152 +-----------------
 gcc/testsuite/jit.dg/test-threads.c          | 230 +++++++++++++++++++++++++++
 6 files changed, 423 insertions(+), 155 deletions(-)
 create mode 100644 gcc/testsuite/jit.dg/all-non-failing-tests.h
 create mode 100644 gcc/testsuite/jit.dg/test-threads.c

diff --git a/gcc/testsuite/ChangeLog.jit b/gcc/testsuite/ChangeLog.jit
index cdde662..846540f 100644
--- a/gcc/testsuite/ChangeLog.jit
+++ b/gcc/testsuite/ChangeLog.jit
@@ -1,3 +1,17 @@
+2014-08-11  David Malcolm  <dmalc...@redhat.com>
+
+       * jit.dg/test-threads.c: New test case, running all of the
+       individual test cases in separate threads.
+       * jit.dg/test-combination.c: Move inclusion of the various
+       individual testcases into...
+       * jit.dg/all-non-failing-tests.h: ...this new file, and rename
+       TEST_COMBINATION to COMBINED_TEST.
+       * jit.dg/harness.h: Respond to new macro MAKE_DEJAGNU_H_THREADSAFE
+       by hacking up <dejagnu.h> to be threadsafe.  Rename
+       TEST_COMBINATION to COMBINED_TEST.
+       * jit.dg/jit.exp (proc jit-dg-test): Add "-lpthread" when building
+       test-threads.exe.
+
 2014-08-08  David Malcolm  <dmalc...@redhat.com>
 
        * jit.dg/test-accessing-union.c: New test case.
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h 
b/gcc/testsuite/jit.dg/all-non-failing-tests.h
new file mode 100644
index 0000000..54dacb7
--- /dev/null
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -0,0 +1,152 @@
+/* This file is used by test-combination.c and test-threads.c to
+   bring all of the non-failing test cases into one source file,
+   renaming each "create_code" and "verify_code" hook so that they
+   each have unique name.  */
+
+/* Include various other test cases, defining COMBINED_TEST so that
+   harness.h doesn't duplicate copes of e.g. main, and renaming the
+   hooks provided by each test case.  */
+#define COMBINED_TEST
+
+/* test-accessing-struct.c */
+#define create_code create_code_accessing_struct
+#define verify_code verify_code_accessing_struct
+#include "test-accessing-struct.c"
+#undef create_code
+#undef verify_code
+
+/* test-accessing-union.c */
+#define create_code create_code_accessing_union
+#define verify_code verify_code_accessing_union
+#include "test-accessing-union.c"
+#undef create_code
+#undef verify_code
+
+/* test-array-as-pointer.c */
+#define create_code create_code_array_as_pointer
+#define verify_code verify_code_array_as_pointer
+#include "test-array-as-pointer.c"
+#undef create_code
+#undef verify_code
+
+/* test-arrays.c */
+#define create_code create_code_arrays
+#define verify_code verify_code_arrays
+#include "test-arrays.c"
+#undef create_code
+#undef verify_code
+
+/* test-calling-external-function.c */
+#define create_code create_code_calling_external_function
+#define verify_code verify_code_calling_external_function
+#include "test-calling-external-function.c"
+#undef create_code
+#undef verify_code
+
+/* test-calling-function-ptr.c */
+#define create_code create_code_calling_function_ptr
+#define verify_code verify_code_calling_function_ptr
+#include "test-calling-function-ptr.c"
+#undef create_code
+#undef verify_code
+
+/* test-dot-product.c */
+#define create_code create_code_dot_product
+#define verify_code verify_code_dot_product
+#include "test-dot-product.c"
+#undef create_code
+#undef verify_code
+
+/* test-error-*.c: We don't use these test cases, since they deliberately
+   introduce errors, which we don't want here.  */
+
+/* test-expressions.c */
+#define create_code create_code_expressions
+#define verify_code verify_code_expressions
+#include "test-expressions.c"
+#undef create_code
+#undef verify_code
+
+/* test-factorial.c */
+#define create_code create_code_factorial
+#define verify_code verify_code_factorial
+#include "test-factorial.c"
+#undef create_code
+#undef verify_code
+
+/* test-fibonacci.c */
+#define create_code create_code_fibonacci
+#define verify_code verify_code_fibonacci
+#include "test-fibonacci.c"
+#undef create_code
+#undef verify_code
+
+/* test-functions.c */
+#define create_code create_code_functions
+#define verify_code verify_code_functions
+#include "test-functions.c"
+#undef create_code
+#undef verify_code
+
+/* test-hello-world.c */
+#define create_code create_code_hello_world
+#define verify_code verify_code_hello_world
+#include "test-hello-world.c"
+#undef create_code
+#undef verify_code
+
+/* test-linked-list.c */
+#define create_code create_code_linked_list
+#define verify_code verify_code_linked_list
+#include "test-linked-list.c"
+#undef create_code
+#undef verify_code
+
+/* test-quadratic.c */
+#define create_code create_code_quadratic
+#define verify_code verify_code_quadratic
+#include "test-quadratic.c"
+#undef create_code
+#undef verify_code
+
+/* test-reading-struct.c */
+#define create_code create_code_reading_struct
+#define verify_code verify_code_reading_struct
+#include "test-reading-struct.c"
+#undef create_code
+#undef verify_code
+
+/* test-string-literal.c */
+#define create_code create_code_string_literal
+#define verify_code verify_code_string_literal
+#include "test-string-literal.c"
+#undef create_code
+#undef verify_code
+
+/* test-sum-of-squares.c */
+#define create_code create_code_sum_of_squares
+#define verify_code verify_code_sum_of_squares
+#include "test-sum-of-squares.c"
+#undef create_code
+#undef verify_code
+
+/* test-types.c */
+#define create_code create_code_types
+#define verify_code verify_code_types
+#include "test-types.c"
+#undef create_code
+#undef verify_code
+
+/* test-using-global.c */
+#define create_code create_code_using_global
+#define verify_code verify_code_using_global
+#include "test-using-global.c"
+#undef create_code
+#undef verify_code
+
+/* test-volatile.c */
+#define create_code create_code_volatile
+#define verify_code verify_code_volatile
+#include "test-volatile.c"
+#undef create_code
+#undef verify_code
diff --git a/gcc/testsuite/jit.dg/harness.h b/gcc/testsuite/jit.dg/harness.h
index e67ac36..cee42f3 100644
--- a/gcc/testsuite/jit.dg/harness.h
+++ b/gcc/testsuite/jit.dg/harness.h
@@ -14,9 +14,22 @@
 #include <stdlib.h>
 #include <stdio.h>
 
+/* test-threads.c use threads, but dejagnu.h isn't thread-safe; there's a
+   shared "buffer", and the counts of passed/failed etc are globals.
+
+   The solution is to use macros to rename "pass" and "fail", replacing them
+   with mutex-guarded alternatives.  */
+#ifdef MAKE_DEJAGNU_H_THREADSAFE
+#define pass dejagnu_pass
+#define fail dejagnu_fail
+#endif
+
 #include <dejagnu.h>
 
-#include "libgccjit.h"
+#ifdef MAKE_DEJAGNU_H_THREADSAFE
+#undef pass
+#undef fail
+#endif
 
 static char test[1024];
 
@@ -89,10 +102,10 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result 
*result);
 extern void check_string_value (const char *actual, const char *expected);
 
 /* Implement framework needed for turning the testcase hooks into an
-   executable.  test-combination.c combines multiple testcases into one
-   testcase, so we have TEST_COMBINATION as a way of temporarily turning
-   off this part of harness.h.  */
-#ifndef TEST_COMBINATION
+   executable.  test-combination.c and test-threads.c each combine multiple
+   testcases into larger testcases, so we have COMBINED_TEST as a way of
+   temporarily turning off this part of harness.h.  */
+#ifndef COMBINED_TEST
 
 void check_string_value (const char *actual, const char *expected)
 {
@@ -224,4 +237,4 @@ main (int argc, char **argv)
 }
 #endif /* #ifndef TEST_PROVIDES_MAIN */
 
-#endif /* #ifndef TEST_COMBINATION */
+#endif /* #ifndef COMBINED_TEST */
diff --git a/gcc/testsuite/jit.dg/jit.exp b/gcc/testsuite/jit.dg/jit.exp
index e998d69..b157955 100644
--- a/gcc/testsuite/jit.dg/jit.exp
+++ b/gcc/testsuite/jit.dg/jit.exp
@@ -41,6 +41,11 @@ proc jit-dg-test { prog do_what extra_tool_flags } {
     verbose "  do_what: $do_what"
     verbose "  extra_tool_flags: $extra_tool_flags"
 
+    # test-threads.c needs to be linked against pthreads
+    if {[string match "*test-threads.c" $prog]} {
+       append extra_tool_flags " -lpthread"
+    }
+
     # Determine what to name the built executable.
     set output_file "[file rootname [file tail $prog]].exe"
     verbose "output_file: $output_file"
diff --git a/gcc/testsuite/jit.dg/test-combination.c 
b/gcc/testsuite/jit.dg/test-combination.c
index a3e3102..1b9432b 100644
--- a/gcc/testsuite/jit.dg/test-combination.c
+++ b/gcc/testsuite/jit.dg/test-combination.c
@@ -2,159 +2,13 @@
    out state issues: all of the test cases are run in one process, inside
    one gcc_jit_context (per iteration).  */
 
-/* Include various other test cases, defining TEST_COMBINATION so that
-   harness.h doesn't duplicate copes of e.g. main, and renaming the
-   hooks provided by each test case.  */
-#define TEST_COMBINATION
-
-/* test-accessing-struct.c */
-#define create_code create_code_accessing_struct
-#define verify_code verify_code_accessing_struct
-#include "test-accessing-struct.c"
-#undef create_code
-#undef verify_code
-
-/* test-accessing-union.c */
-#define create_code create_code_accessing_union
-#define verify_code verify_code_accessing_union
-#include "test-accessing-union.c"
-#undef create_code
-#undef verify_code
-
-/* test-array-as-pointer.c */
-#define create_code create_code_array_as_pointer
-#define verify_code verify_code_array_as_pointer
-#include "test-array-as-pointer.c"
-#undef create_code
-#undef verify_code
-
-/* test-arrays.c */
-#define create_code create_code_arrays
-#define verify_code verify_code_arrays
-#include "test-arrays.c"
-#undef create_code
-#undef verify_code
-
-/* test-calling-external-function.c */
-#define create_code create_code_calling_external_function
-#define verify_code verify_code_calling_external_function
-#include "test-calling-external-function.c"
-#undef create_code
-#undef verify_code
-
-/* test-calling-function-ptr.c */
-#define create_code create_code_calling_function_ptr
-#define verify_code verify_code_calling_function_ptr
-#include "test-calling-function-ptr.c"
-#undef create_code
-#undef verify_code
-
-/* test-dot-product.c */
-#define create_code create_code_dot_product
-#define verify_code verify_code_dot_product
-#include "test-dot-product.c"
-#undef create_code
-#undef verify_code
-
-/* test-error-*.c: We don't use these test cases, since they deliberately
-   introduce errors, which we don't want here.  */
-
-/* test-expressions.c */
-#define create_code create_code_expressions
-#define verify_code verify_code_expressions
-#include "test-expressions.c"
-#undef create_code
-#undef verify_code
-
-/* test-factorial.c */
-#define create_code create_code_factorial
-#define verify_code verify_code_factorial
-#include "test-factorial.c"
-#undef create_code
-#undef verify_code
-
-/* test-fibonacci.c */
-#define create_code create_code_fibonacci
-#define verify_code verify_code_fibonacci
-#include "test-fibonacci.c"
-#undef create_code
-#undef verify_code
-
-/* test-functions.c */
-#define create_code create_code_functions
-#define verify_code verify_code_functions
-#include "test-functions.c"
-#undef create_code
-#undef verify_code
-
-/* test-hello-world.c */
-#define create_code create_code_hello_world
-#define verify_code verify_code_hello_world
-#include "test-hello-world.c"
-#undef create_code
-#undef verify_code
-
-/* test-linked-list.c */
-#define create_code create_code_linked_list
-#define verify_code verify_code_linked_list
-#include "test-linked-list.c"
-#undef create_code
-#undef verify_code
-
-/* test-quadratic.c */
-#define create_code create_code_quadratic
-#define verify_code verify_code_quadratic
-#include "test-quadratic.c"
-#undef create_code
-#undef verify_code
-
-/* test-reading-struct.c */
-#define create_code create_code_reading_struct
-#define verify_code verify_code_reading_struct
-#include "test-reading-struct.c"
-#undef create_code
-#undef verify_code
-
-/* test-string-literal.c */
-#define create_code create_code_string_literal
-#define verify_code verify_code_string_literal
-#include "test-string-literal.c"
-#undef create_code
-#undef verify_code
-
-/* test-sum-of-squares.c */
-#define create_code create_code_sum_of_squares
-#define verify_code verify_code_sum_of_squares
-#include "test-sum-of-squares.c"
-#undef create_code
-#undef verify_code
-
-/* test-types.c */
-#define create_code create_code_types
-#define verify_code verify_code_types
-#include "test-types.c"
-#undef create_code
-#undef verify_code
-
-/* test-using-global.c */
-#define create_code create_code_using_global
-#define verify_code verify_code_using_global
-#include "test-using-global.c"
-#undef create_code
-#undef verify_code
-
-/* test-volatile.c */
-#define create_code create_code_volatile
-#define verify_code verify_code_volatile
-#include "test-volatile.c"
-#undef create_code
-#undef verify_code
+#include "all-non-failing-tests.h"
 
 /* Now construct a test case from all the other test cases.
 
-   We undefine TEST_COMBINATION so that we can now include harness.h
+   We undefine COMBINED_TEST so that we can now include harness.h
    "for real".  */
-#undef TEST_COMBINATION
+#undef COMBINED_TEST
 #include "harness.h"
 
 /* Our testing hooks are the combination of the other test cases.  */
diff --git a/gcc/testsuite/jit.dg/test-threads.c 
b/gcc/testsuite/jit.dg/test-threads.c
new file mode 100644
index 0000000..f31d094
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-threads.c
@@ -0,0 +1,230 @@
+/* test-threads.c
+
+   As per test-combination.c, construct a test case by combining other test
+   cases, to try to shake out state issues.  However each test runs in a
+   separate thread.  */
+
+#include <pthread.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+/* dejagnu.h isn't thread-safe; there's a shared "buffer", and the counts
+   of "passed"/"failed" etc are globals.
+
+   We get around this by putting a mutex around pass/fail calls.
+ */
+
+static pthread_mutex_t dg_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/* By defining MAKE_DEJAGNU_H_THREADSAFE before we include harness.h,
+   harness.h injects macros before including <dejagnu.h> so that the
+   pass/fail functions become "dejagnu_pass"/"dejagnu_fail".  */
+
+void dejagnu_pass (const char* fmt, ...);
+void dejagnu_fail (const char* fmt, ...);
+
+/* We now provide our own implementations of "pass"/"fail", which call
+   the underlying dejagnu implementations, but with a mutex.  */
+
+inline void
+pass (const char* fmt, ...)
+{
+  va_list ap;
+  char buffer[512];
+
+  va_start (ap, fmt);
+  vsnprintf (buffer, sizeof (buffer), fmt, ap);
+  va_end (ap);
+
+  pthread_mutex_lock (&dg_mutex);
+  dejagnu_pass (buffer);
+  pthread_mutex_unlock (&dg_mutex);
+}
+
+inline void
+fail (const char* fmt, ...)
+{
+  va_list ap;
+  char buffer[512];
+
+  va_start (ap, fmt);
+  vsnprintf (buffer, sizeof (buffer), fmt, ap);
+  va_end (ap);
+
+  pthread_mutex_lock (&dg_mutex);
+  dejagnu_fail (buffer);
+  pthread_mutex_unlock (&dg_mutex);
+}
+
+#define MAKE_DEJAGNU_H_THREADSAFE
+
+/* We also need to provide our own version of TEST_NAME.  */
+#define TEST_NAME
+
+/* We can now include all of the relevant selftests.  */
+
+#include "all-non-failing-tests.h"
+
+#define TEST_PROVIDES_MAIN
+#define TEST_ESCHEWS_TEST_JIT
+
+/* Now construct a test case from all the other test cases.
+
+   We undefine COMBINED_TEST so that we can now include harness.h
+   "for real".  */
+#undef COMBINED_TEST
+#include "harness.h"
+
+struct testcase
+{
+  const char *m_name;
+  void (*m_hook_to_create_code) (gcc_jit_context *ctxt,
+                                void * user_data);
+  void (*m_hook_to_verify_code) (gcc_jit_context *ctxt,
+                                gcc_jit_result *result);
+};
+
+const struct testcase testcases[] = {
+  {"accessing_struct",
+   create_code_accessing_struct,
+   verify_code_accessing_struct},
+  {"accessing_union",
+   create_code_accessing_union,
+   verify_code_accessing_union},
+  {"array_as_pointer",
+   create_code_array_as_pointer,
+   verify_code_array_as_pointer},
+  {"arrays",
+   create_code_arrays,
+   verify_code_arrays},
+  {"calling_external_function",
+   create_code_calling_external_function,
+   verify_code_calling_external_function},
+  {"calling_function_ptr",
+   create_code_calling_function_ptr,
+   verify_code_calling_function_ptr},
+  {"dot_product",
+   create_code_dot_product,
+   verify_code_dot_product},
+  {"expressions",
+   create_code_expressions,
+   verify_code_expressions},
+  {"factorial",
+   create_code_factorial,
+   verify_code_factorial},
+  {"fibonacci",
+   create_code_fibonacci,
+   verify_code_fibonacci},
+  {"functions",
+   create_code_functions,
+   verify_code_functions},
+  {"hello_world",
+   create_code_hello_world,
+   verify_code_hello_world},
+  {"linked_list",
+   create_code_linked_list,
+   verify_code_linked_list},
+  {"quadratic",
+   create_code_quadratic,
+   verify_code_quadratic},
+  {"reading_struct ",
+   create_code_reading_struct ,
+   verify_code_reading_struct },
+  {"string_literal",
+   create_code_string_literal,
+   verify_code_string_literal},
+  {"sum_of_squares",
+   create_code_sum_of_squares,
+   verify_code_sum_of_squares},
+  {"types",
+   create_code_types,
+   verify_code_types},
+  {"using_global",
+   create_code_using_global,
+   verify_code_using_global},
+  {"volatile",
+   create_code_volatile,
+   verify_code_volatile}
+};
+
+const int num_testcases = (sizeof (testcases) / sizeof (testcases[0]));
+
+struct thread_data
+{
+  pthread_t m_tid;
+  const struct testcase *m_testcase;
+};
+
+static const char *argv0;
+
+void *
+run_threaded_test (void *data)
+{
+  struct thread_data *thread = (struct thread_data *)data;
+  int i;
+
+  for (i = 0; i < 5; i++)
+    {
+      gcc_jit_context *ctxt;
+      gcc_jit_result *result;
+
+      printf ("run_threaded_test: %s iteration: %d\n",
+             thread->m_testcase->m_name, i);
+
+      ctxt = gcc_jit_context_acquire ();
+
+      set_options (ctxt, argv0);
+
+      thread->m_testcase->m_hook_to_create_code (ctxt, NULL);
+
+      result = gcc_jit_context_compile (ctxt);
+
+      thread->m_testcase->m_hook_to_verify_code (ctxt, result);
+
+      gcc_jit_context_release (ctxt);
+
+      /* Once we're done with the code, this unloads the built .so file: */
+      gcc_jit_result_release (result);
+    }
+
+  return NULL;
+}
+
+int
+main (int argc, char **argv)
+{
+  int i;
+
+  snprintf (test, sizeof (test),
+           "%s",
+           extract_progname (argv[0]));
+
+  argv0 = argv[0];
+
+  /* The individual testcases are not thread-safe (some have their own
+     global variables), so we have one thread per test-case.  */
+  struct thread_data *threads =
+    calloc (num_testcases, sizeof (struct thread_data));
+
+  /* Start a thread per test-case.  */
+  for (i = 0; i < num_testcases; i++)
+    {
+      struct thread_data *thread = &threads[i];
+      thread->m_testcase = &testcases[i];
+      pthread_create (&thread->m_tid,
+                     NULL,
+                     run_threaded_test,
+                     thread);
+    }
+
+  /* Wait for all the threads to be done.  */
+  for (i = 0; i < num_testcases; i++)
+    {
+      struct thread_data *thread = &threads[i];
+      (void)pthread_join (thread->m_tid, NULL);
+    }
+
+  totals ();
+
+  return 0;
+}
-- 
1.8.5.3

Reply via email to