test-threads.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /* test-threads.c
  2. As per test-combination.c, construct a test case by combining other test
  3. cases, to try to shake out state issues. However each test runs in a
  4. separate thread. */
  5. #include <pthread.h>
  6. #include <stdarg.h>
  7. #include <stdio.h>
  8. /* dejagnu.h isn't thread-safe; there's a shared "buffer", and the counts
  9. of "passed"/"failed" etc are globals.
  10. We get around this by putting a mutex around pass/fail calls.
  11. */
  12. static pthread_mutex_t dg_mutex = PTHREAD_MUTEX_INITIALIZER;
  13. /* By defining MAKE_DEJAGNU_H_THREADSAFE before we include harness.h,
  14. harness.h injects macros before including <dejagnu.h> so that the
  15. pass/fail functions become "dejagnu_pass"/"dejagnu_fail" etc. */
  16. void dejagnu_pass (const char* fmt, ...);
  17. void dejagnu_fail (const char* fmt, ...);
  18. void dejagnu_note (const char* fmt, ...);
  19. /* We now provide our own implementations of "pass"/"fail"/"note", which
  20. call the underlying dejagnu implementations, but with a mutex. */
  21. inline void
  22. pass (const char* fmt, ...)
  23. {
  24. va_list ap;
  25. char buffer[512];
  26. va_start (ap, fmt);
  27. vsnprintf (buffer, sizeof (buffer), fmt, ap);
  28. va_end (ap);
  29. pthread_mutex_lock (&dg_mutex);
  30. dejagnu_pass (buffer);
  31. pthread_mutex_unlock (&dg_mutex);
  32. }
  33. inline void
  34. fail (const char* fmt, ...)
  35. {
  36. va_list ap;
  37. char buffer[512];
  38. va_start (ap, fmt);
  39. vsnprintf (buffer, sizeof (buffer), fmt, ap);
  40. va_end (ap);
  41. pthread_mutex_lock (&dg_mutex);
  42. dejagnu_fail (buffer);
  43. pthread_mutex_unlock (&dg_mutex);
  44. }
  45. inline void
  46. note (const char* fmt, ...)
  47. {
  48. va_list ap;
  49. char buffer[512];
  50. va_start (ap, fmt);
  51. vsnprintf (buffer, sizeof (buffer), fmt, ap);
  52. va_end (ap);
  53. pthread_mutex_lock (&dg_mutex);
  54. dejagnu_note (buffer);
  55. pthread_mutex_unlock (&dg_mutex);
  56. }
  57. #define MAKE_DEJAGNU_H_THREADSAFE
  58. /* We also need to provide our own version of TEST_NAME. */
  59. #define TEST_NAME
  60. /* We can now include all of the relevant selftests. */
  61. #include "all-non-failing-tests.h"
  62. #define TEST_PROVIDES_MAIN
  63. #define TEST_ESCHEWS_TEST_JIT
  64. /* Now construct a test case from all the other test cases.
  65. We undefine COMBINED_TEST so that we can now include harness.h
  66. "for real". */
  67. #undef COMBINED_TEST
  68. #include "harness.h"
  69. struct thread_data
  70. {
  71. pthread_t m_tid;
  72. const struct testcase *m_testcase;
  73. };
  74. static const char *argv0;
  75. void *
  76. run_threaded_test (void *data)
  77. {
  78. struct thread_data *thread = (struct thread_data *)data;
  79. int i;
  80. for (i = 0; i < 5; i++)
  81. {
  82. gcc_jit_context *ctxt;
  83. gcc_jit_result *result;
  84. note ("run_threaded_test: %s iteration: %d",
  85. thread->m_testcase->m_name, i);
  86. ctxt = gcc_jit_context_acquire ();
  87. set_options (ctxt, argv0);
  88. thread->m_testcase->m_hook_to_create_code (ctxt, NULL);
  89. result = gcc_jit_context_compile (ctxt);
  90. thread->m_testcase->m_hook_to_verify_code (ctxt, result);
  91. gcc_jit_context_release (ctxt);
  92. /* Once we're done with the code, this unloads the built .so file: */
  93. gcc_jit_result_release (result);
  94. }
  95. return NULL;
  96. }
  97. int
  98. main (int argc, char **argv)
  99. {
  100. int i;
  101. snprintf (test, sizeof (test),
  102. "%s",
  103. extract_progname (argv[0]));
  104. argv0 = argv[0];
  105. /* The individual testcases are not thread-safe (some have their own
  106. global variables), so we have one thread per test-case. */
  107. struct thread_data *threads =
  108. calloc (num_testcases, sizeof (struct thread_data));
  109. /* Start a thread per test-case. */
  110. for (i = 0; i < num_testcases; i++)
  111. {
  112. struct thread_data *thread = &threads[i];
  113. thread->m_testcase = &testcases[i];
  114. pthread_create (&thread->m_tid,
  115. NULL,
  116. run_threaded_test,
  117. thread);
  118. }
  119. /* Wait for all the threads to be done. */
  120. for (i = 0; i < num_testcases; i++)
  121. {
  122. struct thread_data *thread = &threads[i];
  123. (void)pthread_join (thread->m_tid, NULL);
  124. }
  125. totals ();
  126. return 0;
  127. }