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
pass(const char * fmt,...)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
fail(const char * fmt,...)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
note(const char * fmt,...)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 *
run_threaded_test(void * data)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
main(int argc,char ** argv)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 }
180