Update lightrec 20220910 (#686)
[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 void alarm_handler(int unused)
8 {
9     _exit(1);
10 }
11
12 int
13 main(int argc, char *argv[])
14 {
15     jit_state_t         *_jit;
16     void                (*code)(void);
17     jit_node_t           *jmpi_main, *label;
18     jit_node_t           *func0, *func1, *func2, *func3;
19     jit_node_t           *patch0, *patch1, *patch2, *patch3;
20     jit_word_t            lock;
21     pthread_t             tids[4];
22
23     /* If there is any bug, do not hang in "make check" */
24     signal(SIGALRM, alarm_handler);
25     alarm(5);
26   
27     init_jit(argv[0]);
28     _jit = jit_new_state();
29
30     jmpi_main = jit_jmpi();
31
32 #define defun(name, line)                                       \
33     jit_name(#name);                                            \
34     jit_note("catomic.c", line);                                \
35     name = jit_label();                                         \
36      jit_prolog();                                              \
37     jit_movi(JIT_V0, (jit_word_t)&lock);                        \
38     jit_movi(JIT_R1, 0);                                        \
39     jit_movi(JIT_R2, line);                                     \
40     /* spin until get the lock */                               \
41     label = jit_label();                                        \
42     jit_casr(JIT_R0, JIT_V0, JIT_R1, JIT_R2);                   \
43     jit_patch_at(jit_beqi(JIT_R0, 0), label);                   \
44     /* lock acquired */                                         \
45     jit_prepare();                                              \
46     /* pretend to be doing something useful for 0.01 usec
47      * while holding the lock */                                \
48     jit_pushargi(10000);                                        \
49     jit_finishi(usleep);                                        \
50     /* release lock */                                          \
51     jit_movi(JIT_R1, 0);                                        \
52     jit_str(JIT_V0, JIT_R1);                                    \
53     /* Now test casi */                                         \
54     jit_movi(JIT_R1, 0);                                        \
55     jit_movi(JIT_R2, line);                                     \
56     /* spin until get the lock */                               \
57     label = jit_label();                                        \
58     jit_casi(JIT_R0, (jit_word_t)&lock, JIT_R1, JIT_R2);        \
59     jit_patch_at(jit_beqi(JIT_R0, 0), label);                   \
60     /* lock acquired */                                         \
61     jit_prepare();                                              \
62     /* pretend to be doing something useful for 0.01 usec
63      * while holding the lock */                                \
64     jit_pushargi(10000);                                        \
65     jit_finishi(usleep);                                        \
66     jit_prepare();                                              \
67     /* for make check, just print "ok" */                       \
68     jit_pushargi((jit_word_t)"ok");                             \
69     /*jit_pushargi((jit_word_t)#name);*/                        \
70     jit_finishi(puts);                                          \
71     /* release lock */                                          \
72     jit_movi(JIT_R1, 0);                                        \
73     jit_str(JIT_V0, JIT_R1);                                    \
74     jit_ret();                                                  \
75     jit_epilog();
76     defun(func0, __LINE__);
77     defun(func1, __LINE__);
78     defun(func2, __LINE__);
79     defun(func3, __LINE__);
80
81     jit_patch(jmpi_main);
82     jit_name("main");
83     jit_note("catomic.c", __LINE__);
84     jit_prolog();
85
86 #define start(tid)                                              \
87     /* set JIT_R0 to thread function */                         \
88     jit_patch_at(jit_movi(JIT_R0, 0), func##tid);               \
89     jit_prepare();                                              \
90     /* pthread_t first argument */                              \
91     jit_pushargi((jit_word_t)(tids + tid));                     \
92     /* pthread_attr_t second argument */                        \
93     jit_pushargi((jit_word_t)NULL);                             \
94     /* start routine third argument */                          \
95     jit_pushargr(JIT_R0);                                       \
96     /* argument to start routine fourth argument */             \
97     jit_pushargi((jit_word_t)NULL);                             \
98     /* start thread */                                          \
99     jit_finishi(pthread_create);
100     /* spawn four threads */
101     start(0);
102     start(1);
103     start(2);
104     start(3);
105
106 #define join(tid)                                               \
107     /* load pthread_t value in JIT_R0 */                        \
108     jit_movi(JIT_R0, (jit_word_t)tids);                         \
109     jit_ldxi(JIT_R0, JIT_R0, tid * sizeof(pthread_t));          \
110     jit_prepare();                                              \
111     jit_pushargr(JIT_R0);                                       \
112     jit_pushargi((jit_word_t)NULL);                             \
113     jit_finishi(pthread_join);
114     /* wait for threads to finish */
115     join(0);
116     join(1);
117     join(2);
118     join(3);
119
120     jit_prepare();
121     jit_pushargi((jit_word_t)"ok");
122     jit_finishi(puts);
123
124     jit_ret();
125     jit_epilog();
126
127     code = jit_emit();
128
129 #if 1
130     jit_disassemble();
131 #endif
132
133     jit_clear_state();
134
135     /* let first thread acquire the lock */
136     lock = 0;
137     
138     (*code)();
139     jit_destroy_state();
140
141     finish_jit();
142
143     return (0);
144 }