Commit | Line | Data |
---|---|---|
ba3814c1 PC |
1 | #include <lightning.h> |
2 | #include <pthread.h> | |
3 | #include <stdio.h> | |
4 | #include <unistd.h> | |
5 | #include <signal.h> | |
6 | ||
ba86ff93 PC |
7 | /* FIXME Remove the "0 &&" below to make the test pass. |
8 | * This should not be a Lightning issue. It is crashing | |
9 | * like this at exit: | |
10 | * Thread 2 "catomic" received signal SIGSEGV, Segmentation fault. | |
11 | * [Switching to Thread 0xf6acc480 (LWP 2561)] | |
12 | * _IO_acquire_lock_fct (p=<synthetic pointer>) at libioP.h:797 | |
13 | * 797 libioP.h: No such file or directory. | |
14 | * (gdb) bt | |
15 | * #0 _IO_acquire_lock_fct (p=<synthetic pointer>) at libioP.h:797 | |
16 | * #1 _IO_puts (str=0x1 <error: Cannot access memory at address 0x1>) | |
17 | * at ioputs.c:36 | |
18 | * #2 0xf8eca180 in ?? () | |
19 | * unless using these hacks, to not use stdio. | |
20 | * Note that the problem will still happen on purpose, to not risk hiding | |
21 | * a problem. | |
22 | */ | |
23 | #if 0 && defined(__hppa__) | |
24 | # if DEBUG | |
25 | # define DEBUG 0 | |
26 | # define PRINT_OK() \ | |
27 | do { \ | |
28 | jit_prepare(); \ | |
29 | jit_pushargi(STDOUT_FILENO); \ | |
30 | jit_pushargi((jit_word_t)"ok\n"); \ | |
31 | jit_pushargri(3); \ | |
32 | jit_finishi(write); \ | |
33 | } while (0) | |
34 | # endif | |
35 | #else | |
36 | # define PRINT_OK() \ | |
37 | do { \ | |
38 | jit_prepare(); \ | |
39 | jit_pushargi((jit_word_t)"ok"); \ | |
40 | jit_finishi(puts); \ | |
41 | } while (0) | |
42 | #endif | |
43 | ||
c0c16242 PC |
44 | #if DEBUG |
45 | volatile | |
46 | #endif | |
47 | jit_word_t lock; | |
48 | pthread_t tids[4]; | |
49 | ||
50 | #if DEBUG | |
51 | int debug_offset(void) | |
52 | { | |
53 | int i; | |
54 | pthread_t self = pthread_self(); | |
55 | for (i = 0; i < 4; ++i) | |
56 | if (tids[i] == self) | |
57 | return i; | |
58 | return -1; | |
59 | } | |
60 | ||
61 | void debug_spin(void) | |
62 | { | |
63 | printf(" spin %d : %ld\n", debug_offset(), lock); | |
64 | } | |
65 | ||
66 | void debug_lock(void) | |
67 | { | |
68 | printf(" lock %d : %ld\n", debug_offset(), lock); | |
69 | } | |
70 | ||
71 | void debug_unlock(void) | |
72 | { | |
73 | printf("unlock %d : %ld\n", debug_offset(), lock); | |
74 | } | |
75 | #define DEBUG_SPIN() jit_calli(debug_spin) | |
76 | #define DEBUG_LOCK() jit_calli(debug_lock) | |
77 | #define DEBUG_UNLOCK() jit_calli(debug_unlock) | |
78 | #else | |
79 | #define DEBUG_SPIN() /**/ | |
80 | #define DEBUG_LOCK() /**/ | |
81 | #define DEBUG_UNLOCK() /**/ | |
82 | #endif | |
83 | ||
ba3814c1 PC |
84 | void alarm_handler(int unused) |
85 | { | |
86 | _exit(1); | |
87 | } | |
88 | ||
89 | int | |
90 | main(int argc, char *argv[]) | |
91 | { | |
92 | jit_state_t *_jit; | |
93 | void (*code)(void); | |
94 | jit_node_t *jmpi_main, *label; | |
95 | jit_node_t *func0, *func1, *func2, *func3; | |
96 | jit_node_t *patch0, *patch1, *patch2, *patch3; | |
ba3814c1 PC |
97 | |
98 | /* If there is any bug, do not hang in "make check" */ | |
99 | signal(SIGALRM, alarm_handler); | |
100 | alarm(5); | |
101 | ||
102 | init_jit(argv[0]); | |
103 | _jit = jit_new_state(); | |
104 | ||
105 | jmpi_main = jit_jmpi(); | |
106 | ||
107 | #define defun(name, line) \ | |
108 | jit_name(#name); \ | |
109 | jit_note("catomic.c", line); \ | |
110 | name = jit_label(); \ | |
111 | jit_prolog(); \ | |
112 | jit_movi(JIT_V0, (jit_word_t)&lock); \ | |
c0c16242 PC |
113 | jit_movi(JIT_V1, 0); \ |
114 | jit_movi(JIT_V2, line); \ | |
ba3814c1 | 115 | /* spin until get the lock */ \ |
c0c16242 | 116 | DEBUG_SPIN(); \ |
ba3814c1 | 117 | label = jit_label(); \ |
c0c16242 | 118 | jit_casr(JIT_R0, JIT_V0, JIT_V1, JIT_V2); \ |
ba3814c1 PC |
119 | jit_patch_at(jit_beqi(JIT_R0, 0), label); \ |
120 | /* lock acquired */ \ | |
c0c16242 | 121 | DEBUG_LOCK(); \ |
ba3814c1 | 122 | jit_prepare(); \ |
c0c16242 | 123 | /* pretend to be doing something useful for 0.01 sec |
ba3814c1 PC |
124 | * while holding the lock */ \ |
125 | jit_pushargi(10000); \ | |
126 | jit_finishi(usleep); \ | |
127 | /* release lock */ \ | |
c0c16242 PC |
128 | DEBUG_UNLOCK(); \ |
129 | jit_movi(JIT_V1, 0); \ | |
130 | jit_str(JIT_V0, JIT_V1); \ | |
ba3814c1 | 131 | /* Now test casi */ \ |
c0c16242 PC |
132 | jit_movi(JIT_V1, 0); \ |
133 | jit_movi(JIT_V2, line); \ | |
ba3814c1 | 134 | /* spin until get the lock */ \ |
c0c16242 | 135 | DEBUG_SPIN(); \ |
ba3814c1 | 136 | label = jit_label(); \ |
c0c16242 | 137 | jit_casi(JIT_R0, (jit_word_t)&lock, JIT_V1, JIT_V2); \ |
ba3814c1 PC |
138 | jit_patch_at(jit_beqi(JIT_R0, 0), label); \ |
139 | /* lock acquired */ \ | |
c0c16242 | 140 | DEBUG_LOCK(); \ |
ba3814c1 | 141 | jit_prepare(); \ |
c0c16242 | 142 | /* pretend to be doing something useful for 0.01 sec |
ba3814c1 PC |
143 | * while holding the lock */ \ |
144 | jit_pushargi(10000); \ | |
145 | jit_finishi(usleep); \ | |
ba86ff93 | 146 | PRINT_OK(); \ |
ba3814c1 | 147 | /* release lock */ \ |
c0c16242 PC |
148 | DEBUG_UNLOCK(); \ |
149 | jit_movi(JIT_V1, 0); \ | |
150 | jit_str(JIT_V0, JIT_V1); \ | |
ba3814c1 PC |
151 | jit_ret(); \ |
152 | jit_epilog(); | |
153 | defun(func0, __LINE__); | |
154 | defun(func1, __LINE__); | |
155 | defun(func2, __LINE__); | |
156 | defun(func3, __LINE__); | |
157 | ||
158 | jit_patch(jmpi_main); | |
159 | jit_name("main"); | |
160 | jit_note("catomic.c", __LINE__); | |
161 | jit_prolog(); | |
162 | ||
163 | #define start(tid) \ | |
164 | /* set JIT_R0 to thread function */ \ | |
165 | jit_patch_at(jit_movi(JIT_R0, 0), func##tid); \ | |
166 | jit_prepare(); \ | |
167 | /* pthread_t first argument */ \ | |
168 | jit_pushargi((jit_word_t)(tids + tid)); \ | |
169 | /* pthread_attr_t second argument */ \ | |
170 | jit_pushargi((jit_word_t)NULL); \ | |
171 | /* start routine third argument */ \ | |
172 | jit_pushargr(JIT_R0); \ | |
173 | /* argument to start routine fourth argument */ \ | |
174 | jit_pushargi((jit_word_t)NULL); \ | |
175 | /* start thread */ \ | |
176 | jit_finishi(pthread_create); | |
177 | /* spawn four threads */ | |
178 | start(0); | |
179 | start(1); | |
180 | start(2); | |
181 | start(3); | |
182 | ||
183 | #define join(tid) \ | |
184 | /* load pthread_t value in JIT_R0 */ \ | |
185 | jit_movi(JIT_R0, (jit_word_t)tids); \ | |
79bfeef6 PC |
186 | if (__WORDSIZE == 64 && sizeof(pthread_t) == 4) \ |
187 | jit_ldxi_i(JIT_R0, JIT_R0, tid * sizeof(pthread_t)); \ | |
188 | else \ | |
189 | jit_ldxi(JIT_R0, JIT_R0, tid * sizeof(pthread_t)); \ | |
ba3814c1 PC |
190 | jit_prepare(); \ |
191 | jit_pushargr(JIT_R0); \ | |
192 | jit_pushargi((jit_word_t)NULL); \ | |
193 | jit_finishi(pthread_join); | |
194 | /* wait for threads to finish */ | |
195 | join(0); | |
196 | join(1); | |
197 | join(2); | |
198 | join(3); | |
199 | ||
ba86ff93 | 200 | PRINT_OK(); |
ba3814c1 PC |
201 | |
202 | jit_ret(); | |
203 | jit_epilog(); | |
204 | ||
205 | code = jit_emit(); | |
206 | ||
c0c16242 | 207 | #if DEBUG |
ba3814c1 PC |
208 | jit_disassemble(); |
209 | #endif | |
210 | ||
211 | jit_clear_state(); | |
212 | ||
213 | /* let first thread acquire the lock */ | |
214 | lock = 0; | |
215 | ||
216 | (*code)(); | |
217 | jit_destroy_state(); | |
218 | ||
219 | finish_jit(); | |
220 | ||
221 | return (0); | |
222 | } |