tcc -MD: drop system includes and duplicates
[tinycc.git] / tests / libtcc_test_mt.c
blob520d3a233274e1a119034d5cc295f8a50f2dfb33
1 /*
2 * Multi-thread Test for libtcc
3 */
5 #ifndef FIB
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include "libtcc.h"
11 #define M 20 /* number of states */
12 #define F(n) (n % 20 + 2) /* fib argument */
14 #ifdef _WIN32
15 #include <windows.h>
16 #define TF_TYPE(func, param) DWORD WINAPI func(void *param)
17 typedef TF_TYPE(ThreadFunc, x);
18 HANDLE hh[M];
19 void create_thread(ThreadFunc f, int n)
21 DWORD tid;
22 hh[n] = CreateThread(NULL, 0, f, (void*)(size_t)n, 0, &tid);
24 void wait_threads(int n)
26 WaitForMultipleObjects(n, hh, TRUE, INFINITE);
27 while (n)
28 CloseHandle(hh[--n]);
30 void sleep_ms(unsigned n)
32 Sleep(n);
34 #else
35 #include <sys/time.h>
36 #include <unistd.h>
37 #include <pthread.h>
38 #define TF_TYPE(func, param) void* func(void *param)
39 typedef TF_TYPE(ThreadFunc, x);
40 pthread_t hh[M];
41 void create_thread(ThreadFunc f, int n)
43 pthread_create(&hh[n], NULL, f, (void*)(size_t)n);
45 void wait_threads(int n)
47 while (n)
48 pthread_join(hh[--n], NULL);
51 void sleep_ms(unsigned n)
53 usleep(n * 1000);
55 #endif
57 void handle_error(void *opaque, const char *msg)
59 fprintf(opaque, "%s\n", msg);
62 /* this function is called by the generated code */
63 int add(int a, int b)
65 return a + b;
68 #define _str(s) #s
69 #define str(s) _str(s)
70 /* as a trick, prepend #line directive for better error/warning messages */
71 #define PROG(lbl) \
72 char lbl[] = "#line " str(__LINE__) " " str(__FILE__) "\n\n"
74 PROG(my_program)
75 "#include <tcclib.h>\n" /* include the "Simple libc header for TCC" */
76 "int add(int a, int b);\n"
77 "int fib(int n)\n"
78 "{\n"
79 " if (n <= 2)\n"
80 " return 1;\n"
81 " else\n"
82 " return add(fib(n-1),fib(n-2));\n"
83 "}\n"
84 "\n"
85 "int foo(int n)\n"
86 "{\n"
87 " printf(\" %d\", fib(n));\n"
88 " return 0;\n"
89 "# warning is this the correct file:line...\n"
90 "}\n";
92 int g_argc; char **g_argv;
94 void parse_args(TCCState *s)
96 int i;
97 /* if tcclib.h and libtcc1.a are not installed, where can we find them */
98 for (i = 1; i < g_argc; ++i) {
99 char *a = g_argv[i];
100 if (a[0] == '-') {
101 if (a[1] == 'B')
102 tcc_set_lib_path(s, a+2);
103 else if (a[1] == 'I')
104 tcc_add_include_path(s, a+2);
105 else if (a[1] == 'L')
106 tcc_add_library_path(s, a+2);
107 else if (a[1] == 'D') {
108 char *dup = strdup(a);
109 char *eq = strchr(dup+2, '=');
110 if (eq) {
111 *eq = 0;
112 tcc_define_symbol(s, dup+2, eq+1);
113 *eq = '=';
114 } else
115 tcc_define_symbol(s, dup+2, NULL);
116 free(dup);
122 TCCState *new_state(int w)
124 TCCState *s = tcc_new();
125 if (!s) {
126 fprintf(stderr, __FILE__ ": could not create tcc state\n");
127 exit(1);
129 tcc_set_error_func(s, stdout, handle_error);
130 parse_args(s);
131 if (!w) tcc_set_options(s, "-w");
132 tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
133 return s;
136 void *reloc_state(TCCState *s, const char *entry)
138 void *func;
139 tcc_add_symbol(s, "add", add);
140 if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0) {
141 fprintf(stderr, __FILE__ ": could not relocate tcc state.\n");
142 return NULL;
144 func = tcc_get_symbol(s, entry);
145 if (!func)
146 fprintf(stderr, __FILE__ ": could not get entry symbol.\n");
147 return func;
150 /* work with several states at the same time */
151 int state_test(void)
153 TCCState *s[M];
154 int (*func[M])(int);
155 int n;
157 for (n = 0; n < M + 4; ++n) {
158 unsigned a = n, b = n - 1, c = n - 2, d = n - 3, e = n - 4;
159 if (a < M)
160 s[a] = new_state(0);
161 if (b < M)
162 if (tcc_compile_string(s[b], my_program) == -1)
163 break;
164 if (c < M)
165 func[c] = reloc_state(s[c], "foo");
166 if (d < M && func[d])
167 func[d](F(d));
168 if (e < M)
169 tcc_delete(s[e]);
171 return 0;
174 /* simple compilation in threads */
175 TF_TYPE(thread_test_simple, vn)
177 TCCState *s;
178 int (*func)(int);
179 int ret;
180 int n = (size_t)vn;
182 s = new_state(0);
183 sleep_ms(1);
184 ret = tcc_compile_string(s, my_program);
185 sleep_ms(1);
186 if (ret >= 0) {
187 func = reloc_state(s, "foo");
188 if (func)
189 func(F(n));
191 tcc_delete(s);
192 return 0;
195 /* more complex compilation in threads */
196 TF_TYPE(thread_test_complex, vn)
198 TCCState *s;
199 int ret;
200 int n = (size_t)vn;
201 char *argv[30], b[10];
202 int argc = 0, i;
204 sprintf(b, "%d", F(n));
206 for (i = 1; i < g_argc; ++i) argv[argc++] = g_argv[i];
207 #if 0
208 argv[argc++] = "-run";
209 for (i = 1; i < g_argc; ++i) argv[argc++] = g_argv[i];
210 #endif
211 argv[argc++] = "-DFIB";
212 argv[argc++] = "-run";
213 argv[argc++] = __FILE__;
214 argv[argc++] = b;
215 argv[argc] = NULL;
217 s = new_state(1);
218 sleep_ms(2);
219 ret = tcc_add_file(s, argv[0]);
220 sleep_ms(3);
221 if (ret < 0)
222 exit(1);
223 tcc_run(s, argc, argv);
224 tcc_delete(s);
225 fflush(stdout);
226 return 0;
229 void time_tcc(int n, const char *src)
231 TCCState *s;
232 int ret;
233 while (--n >= 0) {
234 s = new_state(1);
235 ret = tcc_add_file(s, src);
236 tcc_delete(s);
237 if (ret < 0)
238 exit(1);
242 static unsigned getclock_ms(void)
244 #ifdef _WIN32
245 return GetTickCount();
246 #else
247 struct timeval tv;
248 gettimeofday(&tv, NULL);
249 return tv.tv_sec*1000 + (tv.tv_usec+500)/1000;
250 #endif
253 int main(int argc, char **argv)
255 int n;
256 unsigned t;
258 g_argc = argc;
259 g_argv = argv;
261 if (argc < 2) {
262 fprintf(stderr, "usage: libtcc_test_mt tcc.c <options>\n");
263 return 1;
266 #if 1
267 printf("mixed calls\n "), fflush(stdout);
268 t = getclock_ms();
269 state_test();
270 printf("\n(%u ms)\n", getclock_ms() - t);
271 #endif
272 #if 1
273 printf("threads\n "), fflush(stdout);
274 t = getclock_ms();
275 for (n = 0; n < M; ++n)
276 create_thread(thread_test_simple, n);
277 wait_threads(n);
278 printf("\n(%u ms)\n", getclock_ms() - t);
279 #endif
280 #if 1
281 printf("tcc in threads\n "), fflush(stdout);
282 t = getclock_ms();
283 for (n = 0; n < M; ++n)
284 create_thread(thread_test_complex, n);
285 wait_threads(n);
286 printf("\n(%u ms)\n", getclock_ms() - t);
287 #endif
288 #if 1
289 printf("compiling tcc 10 times\n"), fflush(stdout);
290 t = getclock_ms();
291 time_tcc(10, argv[1]);
292 printf("(%u ms)\n", (getclock_ms() - t) / 10), fflush(stdout);
293 #endif
294 return 0;
297 #else
298 #include <tcclib.h>
299 int fib(n)
301 return (n <= 2) ? 1 : fib(n-1) + fib(n-2);
304 int main(int argc, char **argv)
306 printf(" %d", fib(atoi(argv[1]), 2));
307 return 0;
309 #endif