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