This source file includes following definitions.
- random_account
- check_accounts
- lock_mutator_thread
- lock_checker_thread
- test_asyncsafe_spin
- main
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <config.h>
20
21 #if USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS
22
23
24
25
26 #define ENABLE_LOCKING 1
27
28
29
30 #define EXPLICIT_YIELD 1
31
32
33 #define ENABLE_DEBUGGING 0
34
35
36 #define THREAD_COUNT 10
37
38
39 #if !(defined _WIN32 && ! defined __CYGWIN__) && HAVE_PTHREAD_H && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || __clang_major__ >= 3) && !defined __ibmxl__
40
41
42 # define REPEAT_COUNT 5000
43 #else
44
45
46
47 # define REPEAT_COUNT 100000
48 #endif
49
50 #include <signal.h>
51 #include <stdint.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55
56 #include "asyncsafe-spin.h"
57 #if !ENABLE_LOCKING
58 # define asyncsafe_spin_init(lock) (void)(lock)
59 # define asyncsafe_spin_lock(lock, mask, saved_mask) \
60 ((void)(lock), (void)(mask), (void)(saved_mask))
61 # define asyncsafe_spin_unlock(lock, saved_mask) \
62 ((void)(lock), (void)(saved_mask))
63 # define asyncsafe_spin_destroy(lock) (void)(lock)
64 #endif
65
66 #include "glthread/lock.h"
67 #include "glthread/thread.h"
68 #include "glthread/yield.h"
69
70 #if HAVE_DECL_ALARM
71 # include <signal.h>
72 # include <unistd.h>
73 #endif
74
75 #include "atomic-int-gnulib.h"
76
77 #if ENABLE_DEBUGGING
78 # define dbgprintf printf
79 #else
80 # define dbgprintf if (0) printf
81 #endif
82
83 #if EXPLICIT_YIELD
84 # define yield() gl_thread_yield ()
85 #else
86 # define yield()
87 #endif
88
89 static sigset_t signals_to_block;
90
91 #define ACCOUNT_COUNT 4
92
93 static int account[ACCOUNT_COUNT];
94
95 static int
96 random_account (void)
97 {
98 return ((unsigned int) rand () >> 3) % ACCOUNT_COUNT;
99 }
100
101 static void
102 check_accounts (void)
103 {
104 int i, sum;
105
106 sum = 0;
107 for (i = 0; i < ACCOUNT_COUNT; i++)
108 sum += account[i];
109 if (sum != ACCOUNT_COUNT * 1000)
110 abort ();
111 }
112
113
114
115
116
117
118
119
120 static asyncsafe_spinlock_t my_lock;
121
122 static void *
123 lock_mutator_thread (void *arg)
124 {
125 int repeat;
126
127 for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
128 {
129 sigset_t saved_signals;
130 int i1, i2, value;
131
132 dbgprintf ("Mutator %p before lock\n", gl_thread_self_pointer ());
133 asyncsafe_spin_lock (&my_lock, &signals_to_block, &saved_signals);
134 dbgprintf ("Mutator %p after lock\n", gl_thread_self_pointer ());
135
136 i1 = random_account ();
137 i2 = random_account ();
138 value = ((unsigned int) rand () >> 3) % 10;
139 account[i1] += value;
140 account[i2] -= value;
141
142 dbgprintf ("Mutator %p before unlock\n", gl_thread_self_pointer ());
143 asyncsafe_spin_unlock (&my_lock, &saved_signals);
144 dbgprintf ("Mutator %p after unlock\n", gl_thread_self_pointer ());
145
146 dbgprintf ("Mutator %p before check lock\n", gl_thread_self_pointer ());
147 asyncsafe_spin_lock (&my_lock, &signals_to_block, &saved_signals);
148 check_accounts ();
149 asyncsafe_spin_unlock (&my_lock, &saved_signals);
150 dbgprintf ("Mutator %p after check unlock\n", gl_thread_self_pointer ());
151
152 yield ();
153 }
154
155 dbgprintf ("Mutator %p dying.\n", gl_thread_self_pointer ());
156 return NULL;
157 }
158
159 static struct atomic_int lock_checker_done;
160
161 static void *
162 lock_checker_thread (void *arg)
163 {
164 while (get_atomic_int_value (&lock_checker_done) == 0)
165 {
166 sigset_t saved_signals;
167
168 dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
169 asyncsafe_spin_lock (&my_lock, &signals_to_block, &saved_signals);
170 check_accounts ();
171 asyncsafe_spin_unlock (&my_lock, &saved_signals);
172 dbgprintf ("Checker %p after check unlock\n", gl_thread_self_pointer ());
173
174 yield ();
175 }
176
177 dbgprintf ("Checker %p dying.\n", gl_thread_self_pointer ());
178 return NULL;
179 }
180
181 static void
182 test_asyncsafe_spin (void)
183 {
184 int i;
185 gl_thread_t checkerthread;
186 gl_thread_t threads[THREAD_COUNT];
187
188
189 for (i = 0; i < ACCOUNT_COUNT; i++)
190 account[i] = 1000;
191 init_atomic_int (&lock_checker_done);
192 set_atomic_int_value (&lock_checker_done, 0);
193
194
195 checkerthread = gl_thread_create (lock_checker_thread, NULL);
196 for (i = 0; i < THREAD_COUNT; i++)
197 threads[i] = gl_thread_create (lock_mutator_thread, NULL);
198
199
200 for (i = 0; i < THREAD_COUNT; i++)
201 gl_thread_join (threads[i], NULL);
202 set_atomic_int_value (&lock_checker_done, 1);
203 gl_thread_join (checkerthread, NULL);
204 check_accounts ();
205 }
206
207
208
209
210 int
211 main ()
212 {
213 #if HAVE_DECL_ALARM
214
215
216 int alarm_value = 600;
217 signal (SIGALRM, SIG_DFL);
218 alarm (alarm_value);
219 #endif
220
221 sigemptyset (&signals_to_block);
222 sigaddset (&signals_to_block, SIGINT);
223
224 asyncsafe_spin_init (&my_lock);
225
226 printf ("Starting test_asyncsafe_spin ..."); fflush (stdout);
227 test_asyncsafe_spin ();
228 printf (" OK\n"); fflush (stdout);
229
230 return 0;
231 }
232
233 #else
234
235
236
237 #include <stdio.h>
238
239 int
240 main ()
241 {
242 fputs ("Skipping test: multithreading not enabled\n", stderr);
243 return 77;
244 }
245
246 #endif