Merge pull request #750 from pcercuei/lightrec-update-20230826
[pcsx_rearmed.git] / deps / lightning / check / catomic.c
1 #include <lightning.h>
2 #include <pthread.h>
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <signal.h>
6
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
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
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;
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);                        \
113     jit_movi(JIT_V1, 0);                                        \
114     jit_movi(JIT_V2, line);                                     \
115     /* spin until get the lock */                               \
116     DEBUG_SPIN();                                               \
117     label = jit_label();                                        \
118     jit_casr(JIT_R0, JIT_V0, JIT_V1, JIT_V2);                   \
119     jit_patch_at(jit_beqi(JIT_R0, 0), label);                   \
120     /* lock acquired */                                         \
121     DEBUG_LOCK();                                               \
122     jit_prepare();                                              \
123     /* pretend to be doing something useful for 0.01 sec
124      * while holding the lock */                                \
125     jit_pushargi(10000);                                        \
126     jit_finishi(usleep);                                        \
127     /* release lock */                                          \
128     DEBUG_UNLOCK();                                             \
129     jit_movi(JIT_V1, 0);                                        \
130     jit_str(JIT_V0, JIT_V1);                                    \
131     /* Now test casi */                                         \
132     jit_movi(JIT_V1, 0);                                        \
133     jit_movi(JIT_V2, line);                                     \
134     /* spin until get the lock */                               \
135     DEBUG_SPIN();                                               \
136     label = jit_label();                                        \
137     jit_casi(JIT_R0, (jit_word_t)&lock, JIT_V1, JIT_V2);        \
138     jit_patch_at(jit_beqi(JIT_R0, 0), label);                   \
139     /* lock acquired */                                         \
140     DEBUG_LOCK();                                               \
141     jit_prepare();                                              \
142     /* pretend to be doing something useful for 0.01 sec
143      * while holding the lock */                                \
144     jit_pushargi(10000);                                        \
145     jit_finishi(usleep);                                        \
146     PRINT_OK();                                                 \
147     /* release lock */                                          \
148     DEBUG_UNLOCK();                                             \
149     jit_movi(JIT_V1, 0);                                        \
150     jit_str(JIT_V0, JIT_V1);                                    \
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);                         \
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));      \
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
200     PRINT_OK();
201
202     jit_ret();
203     jit_epilog();
204
205     code = jit_emit();
206
207 #if DEBUG
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 }