git subrepo pull --force deps/lightning
[pcsx_rearmed.git] / deps / lightning / check / catomic.c
CommitLineData
ba3814c1
PC
1#include <lightning.h>
2#include <pthread.h>
3#include <stdio.h>
4#include <unistd.h>
5#include <signal.h>
6
c0c16242
PC
7#if DEBUG
8volatile
9#endif
10jit_word_t lock;
11pthread_t tids[4];
12
13#if DEBUG
14int debug_offset(void)
15{
16 int i;
17 pthread_t self = pthread_self();
18 for (i = 0; i < 4; ++i)
19 if (tids[i] == self)
20 return i;
21 return -1;
22}
23
24void debug_spin(void)
25{
26 printf(" spin %d : %ld\n", debug_offset(), lock);
27}
28
29void debug_lock(void)
30{
31 printf(" lock %d : %ld\n", debug_offset(), lock);
32}
33
34void debug_unlock(void)
35{
36 printf("unlock %d : %ld\n", debug_offset(), lock);
37}
38#define DEBUG_SPIN() jit_calli(debug_spin)
39#define DEBUG_LOCK() jit_calli(debug_lock)
40#define DEBUG_UNLOCK() jit_calli(debug_unlock)
41#else
42#define DEBUG_SPIN() /**/
43#define DEBUG_LOCK() /**/
44#define DEBUG_UNLOCK() /**/
45#endif
46
ba3814c1
PC
47void alarm_handler(int unused)
48{
49 _exit(1);
50}
51
52int
53main(int argc, char *argv[])
54{
55 jit_state_t *_jit;
56 void (*code)(void);
57 jit_node_t *jmpi_main, *label;
58 jit_node_t *func0, *func1, *func2, *func3;
59 jit_node_t *patch0, *patch1, *patch2, *patch3;
ba3814c1
PC
60
61 /* If there is any bug, do not hang in "make check" */
62 signal(SIGALRM, alarm_handler);
63 alarm(5);
64
65 init_jit(argv[0]);
66 _jit = jit_new_state();
67
68 jmpi_main = jit_jmpi();
69
70#define defun(name, line) \
71 jit_name(#name); \
72 jit_note("catomic.c", line); \
73 name = jit_label(); \
74 jit_prolog(); \
75 jit_movi(JIT_V0, (jit_word_t)&lock); \
c0c16242
PC
76 jit_movi(JIT_V1, 0); \
77 jit_movi(JIT_V2, line); \
ba3814c1 78 /* spin until get the lock */ \
c0c16242 79 DEBUG_SPIN(); \
ba3814c1 80 label = jit_label(); \
c0c16242 81 jit_casr(JIT_R0, JIT_V0, JIT_V1, JIT_V2); \
ba3814c1
PC
82 jit_patch_at(jit_beqi(JIT_R0, 0), label); \
83 /* lock acquired */ \
c0c16242 84 DEBUG_LOCK(); \
ba3814c1 85 jit_prepare(); \
c0c16242 86 /* pretend to be doing something useful for 0.01 sec
ba3814c1
PC
87 * while holding the lock */ \
88 jit_pushargi(10000); \
89 jit_finishi(usleep); \
90 /* release lock */ \
c0c16242
PC
91 DEBUG_UNLOCK(); \
92 jit_movi(JIT_V1, 0); \
93 jit_str(JIT_V0, JIT_V1); \
ba3814c1 94 /* Now test casi */ \
c0c16242
PC
95 jit_movi(JIT_V1, 0); \
96 jit_movi(JIT_V2, line); \
ba3814c1 97 /* spin until get the lock */ \
c0c16242 98 DEBUG_SPIN(); \
ba3814c1 99 label = jit_label(); \
c0c16242 100 jit_casi(JIT_R0, (jit_word_t)&lock, JIT_V1, JIT_V2); \
ba3814c1
PC
101 jit_patch_at(jit_beqi(JIT_R0, 0), label); \
102 /* lock acquired */ \
c0c16242 103 DEBUG_LOCK(); \
ba3814c1 104 jit_prepare(); \
c0c16242 105 /* pretend to be doing something useful for 0.01 sec
ba3814c1
PC
106 * while holding the lock */ \
107 jit_pushargi(10000); \
108 jit_finishi(usleep); \
109 jit_prepare(); \
110 /* for make check, just print "ok" */ \
111 jit_pushargi((jit_word_t)"ok"); \
112 /*jit_pushargi((jit_word_t)#name);*/ \
113 jit_finishi(puts); \
114 /* release lock */ \
c0c16242
PC
115 DEBUG_UNLOCK(); \
116 jit_movi(JIT_V1, 0); \
117 jit_str(JIT_V0, JIT_V1); \
ba3814c1
PC
118 jit_ret(); \
119 jit_epilog();
120 defun(func0, __LINE__);
121 defun(func1, __LINE__);
122 defun(func2, __LINE__);
123 defun(func3, __LINE__);
124
125 jit_patch(jmpi_main);
126 jit_name("main");
127 jit_note("catomic.c", __LINE__);
128 jit_prolog();
129
130#define start(tid) \
131 /* set JIT_R0 to thread function */ \
132 jit_patch_at(jit_movi(JIT_R0, 0), func##tid); \
133 jit_prepare(); \
134 /* pthread_t first argument */ \
135 jit_pushargi((jit_word_t)(tids + tid)); \
136 /* pthread_attr_t second argument */ \
137 jit_pushargi((jit_word_t)NULL); \
138 /* start routine third argument */ \
139 jit_pushargr(JIT_R0); \
140 /* argument to start routine fourth argument */ \
141 jit_pushargi((jit_word_t)NULL); \
142 /* start thread */ \
143 jit_finishi(pthread_create);
144 /* spawn four threads */
145 start(0);
146 start(1);
147 start(2);
148 start(3);
149
150#define join(tid) \
151 /* load pthread_t value in JIT_R0 */ \
152 jit_movi(JIT_R0, (jit_word_t)tids); \
153 jit_ldxi(JIT_R0, JIT_R0, tid * sizeof(pthread_t)); \
154 jit_prepare(); \
155 jit_pushargr(JIT_R0); \
156 jit_pushargi((jit_word_t)NULL); \
157 jit_finishi(pthread_join);
158 /* wait for threads to finish */
159 join(0);
160 join(1);
161 join(2);
162 join(3);
163
164 jit_prepare();
165 jit_pushargi((jit_word_t)"ok");
166 jit_finishi(puts);
167
168 jit_ret();
169 jit_epilog();
170
171 code = jit_emit();
172
c0c16242 173#if DEBUG
ba3814c1
PC
174 jit_disassemble();
175#endif
176
177 jit_clear_state();
178
179 /* let first thread acquire the lock */
180 lock = 0;
181
182 (*code)();
183 jit_destroy_state();
184
185 finish_jit();
186
187 return (0);
188}