This source file includes following definitions.
- random_account
- check_accounts
- lock_mutator_thread
- lock_checker_thread
- test_pthread_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 #define REPEAT_COUNT 50000
40
41 #include <pthread.h>
42 #include <stdint.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46
47 #if EXPLICIT_YIELD
48 # include <sched.h>
49 #endif
50
51 #if HAVE_DECL_ALARM
52 # include <signal.h>
53 # include <unistd.h>
54 #endif
55
56 #include "macros.h"
57 #include "atomic-int-posix.h"
58
59 #if ENABLE_DEBUGGING
60 # define dbgprintf printf
61 #else
62 # define dbgprintf if (0) printf
63 #endif
64
65 #if EXPLICIT_YIELD
66 # define yield() sched_yield ()
67 #else
68 # define yield()
69 #endif
70
71
72 #if defined __MVS__
73
74
75
76 # define pthread_self_pointer() (*((void **) pthread_self ().__))
77 #else
78 # define pthread_self_pointer() ((void *) (uintptr_t) pthread_self ())
79 #endif
80
81 #define ACCOUNT_COUNT 4
82
83 static int account[ACCOUNT_COUNT];
84
85 static int
86 random_account (void)
87 {
88 return ((unsigned int) rand () >> 3) % ACCOUNT_COUNT;
89 }
90
91 static void
92 check_accounts (void)
93 {
94 int i, sum;
95
96 sum = 0;
97 for (i = 0; i < ACCOUNT_COUNT; i++)
98 sum += account[i];
99 if (sum != ACCOUNT_COUNT * 1000)
100 abort ();
101 }
102
103
104
105
106
107
108
109
110 static pthread_spinlock_t my_lock;
111
112 static void *
113 lock_mutator_thread (void *arg)
114 {
115 int repeat;
116
117 for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
118 {
119 int i1, i2, value;
120
121 dbgprintf ("Mutator %p before lock\n", pthread_self_pointer ());
122 ASSERT (pthread_spin_lock (&my_lock) == 0);
123 dbgprintf ("Mutator %p after lock\n", pthread_self_pointer ());
124
125 i1 = random_account ();
126 i2 = random_account ();
127 value = ((unsigned int) rand () >> 3) % 10;
128 account[i1] += value;
129 account[i2] -= value;
130
131 dbgprintf ("Mutator %p before unlock\n", pthread_self_pointer ());
132 ASSERT (pthread_spin_unlock (&my_lock) == 0);
133 dbgprintf ("Mutator %p after unlock\n", pthread_self_pointer ());
134
135 dbgprintf ("Mutator %p before check lock\n", pthread_self_pointer ());
136 ASSERT (pthread_spin_lock (&my_lock) == 0);
137 check_accounts ();
138 ASSERT (pthread_spin_unlock (&my_lock) == 0);
139 dbgprintf ("Mutator %p after check unlock\n", pthread_self_pointer ());
140
141 yield ();
142 }
143
144 dbgprintf ("Mutator %p dying.\n", pthread_self_pointer ());
145 return NULL;
146 }
147
148 static struct atomic_int lock_checker_done;
149
150 static void *
151 lock_checker_thread (void *arg)
152 {
153 while (get_atomic_int_value (&lock_checker_done) == 0)
154 {
155 dbgprintf ("Checker %p before check lock\n", pthread_self_pointer ());
156 ASSERT (pthread_spin_lock (&my_lock) == 0);
157 check_accounts ();
158 ASSERT (pthread_spin_unlock (&my_lock) == 0);
159 dbgprintf ("Checker %p after check unlock\n", pthread_self_pointer ());
160
161 yield ();
162 }
163
164 dbgprintf ("Checker %p dying.\n", pthread_self_pointer ());
165 return NULL;
166 }
167
168 static void
169 test_pthread_spin (void)
170 {
171 int i;
172 pthread_t checkerthread;
173 pthread_t threads[THREAD_COUNT];
174
175
176 for (i = 0; i < ACCOUNT_COUNT; i++)
177 account[i] = 1000;
178 init_atomic_int (&lock_checker_done);
179 set_atomic_int_value (&lock_checker_done, 0);
180
181
182 ASSERT (pthread_create (&checkerthread, NULL, lock_checker_thread, NULL)
183 == 0);
184 for (i = 0; i < THREAD_COUNT; i++)
185 ASSERT (pthread_create (&threads[i], NULL, lock_mutator_thread, NULL) == 0);
186
187
188 for (i = 0; i < THREAD_COUNT; i++)
189 ASSERT (pthread_join (threads[i], NULL) == 0);
190 set_atomic_int_value (&lock_checker_done, 1);
191 ASSERT (pthread_join (checkerthread, NULL) == 0);
192 check_accounts ();
193 }
194
195
196
197
198 int
199 main ()
200 {
201 #if HAVE_DECL_ALARM
202
203
204 int alarm_value = 600;
205 signal (SIGALRM, SIG_DFL);
206 alarm (alarm_value);
207 #endif
208
209 ASSERT (pthread_spin_init (&my_lock, 0) == 0);
210
211 printf ("Starting test_pthread_spin ..."); fflush (stdout);
212 test_pthread_spin ();
213 printf (" OK\n"); fflush (stdout);
214
215 return 0;
216 }
217
218 #else
219
220
221
222 #include <stdio.h>
223
224 int
225 main ()
226 {
227 fputs ("Skipping test: multithreading not enabled\n", stderr);
228 return 77;
229 }
230
231 #endif