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 | ||
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 | } |