"Fossies" - the Fresh Open Source Software Archive 
Member "apr-1.7.0/test/testlock.c" (12 Dec 2017, 12131 Bytes) of package /linux/www/apr-1.7.0.tar.bz2:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
See also the latest
Fossies "Diffs" side-by-side code changes report for "testlock.c":
1.6.5_vs_1.7.0.
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "apr_thread_proc.h"
18 #include "apr_file_io.h"
19 #include "apr_thread_mutex.h"
20 #include "apr_thread_rwlock.h"
21 #include "apr_thread_cond.h"
22 #include "apr_errno.h"
23 #include "apr_general.h"
24 #include "apr_getopt.h"
25 #include "testutil.h"
26
27 #if APR_HAS_THREADS
28
29 #define MAX_ITER 40000
30 #define MAX_COUNTER 100000
31 #define MAX_RETRY 5
32
33 static void *APR_THREAD_FUNC thread_rwlock_func(apr_thread_t *thd, void *data);
34 static void *APR_THREAD_FUNC thread_mutex_function(apr_thread_t *thd, void *data);
35 static void *APR_THREAD_FUNC thread_cond_producer(apr_thread_t *thd, void *data);
36 static void *APR_THREAD_FUNC thread_cond_consumer(apr_thread_t *thd, void *data);
37
38 static apr_thread_mutex_t *thread_mutex;
39 static apr_thread_rwlock_t *rwlock;
40 static int i = 0, x = 0;
41
42 static int buff[MAX_COUNTER];
43
44 struct {
45 apr_thread_mutex_t *mutex;
46 int nput;
47 int nval;
48 } put;
49
50 struct {
51 apr_thread_mutex_t *mutex;
52 apr_thread_cond_t *cond;
53 int nready;
54 } nready;
55
56 static apr_thread_mutex_t *timeout_mutex;
57 static apr_thread_cond_t *timeout_cond;
58
59 static void *APR_THREAD_FUNC thread_rwlock_func(apr_thread_t *thd, void *data)
60 {
61 int exitLoop = 1;
62
63 while (1)
64 {
65 apr_thread_rwlock_rdlock(rwlock);
66 if (i == MAX_ITER)
67 exitLoop = 0;
68 apr_thread_rwlock_unlock(rwlock);
69
70 if (!exitLoop)
71 break;
72
73 apr_thread_rwlock_wrlock(rwlock);
74 if (i != MAX_ITER)
75 {
76 i++;
77 x++;
78 }
79 apr_thread_rwlock_unlock(rwlock);
80 }
81 return NULL;
82 }
83
84 static void *APR_THREAD_FUNC thread_mutex_function(apr_thread_t *thd, void *data)
85 {
86 int exitLoop = 1;
87
88 /* slight delay to allow things to settle */
89 apr_sleep (1);
90
91 while (1)
92 {
93 if (data) {
94 apr_thread_mutex_timedlock(thread_mutex, *(apr_interval_time_t *)data);
95 }
96 else {
97 apr_thread_mutex_lock(thread_mutex);
98 }
99 if (i == MAX_ITER)
100 exitLoop = 0;
101 else
102 {
103 i++;
104 x++;
105 }
106 apr_thread_mutex_unlock(thread_mutex);
107
108 if (!exitLoop)
109 break;
110 }
111 return NULL;
112 }
113
114 static void *APR_THREAD_FUNC thread_cond_producer(apr_thread_t *thd, void *data)
115 {
116 for (;;) {
117 apr_thread_mutex_lock(put.mutex);
118 if (put.nput >= MAX_COUNTER) {
119 apr_thread_mutex_unlock(put.mutex);
120 return NULL;
121 }
122 buff[put.nput] = put.nval;
123 put.nput++;
124 put.nval++;
125 apr_thread_mutex_unlock(put.mutex);
126
127 apr_thread_mutex_lock(nready.mutex);
128 if (nready.nready == 0)
129 apr_thread_cond_signal(nready.cond);
130 nready.nready++;
131 apr_thread_mutex_unlock(nready.mutex);
132
133 *((int *) data) += 1;
134 }
135
136 return NULL;
137 }
138
139 static void *APR_THREAD_FUNC thread_cond_consumer(apr_thread_t *thd, void *data)
140 {
141 int i;
142
143 for (i = 0; i < MAX_COUNTER; i++) {
144 apr_thread_mutex_lock(nready.mutex);
145 while (nready.nready == 0)
146 apr_thread_cond_wait(nready.cond, nready.mutex);
147 nready.nready--;
148 apr_thread_mutex_unlock(nready.mutex);
149
150 if (buff[i] != i)
151 printf("buff[%d] = %d\n", i, buff[i]);
152 }
153
154 return NULL;
155 }
156
157 static void test_thread_mutex(abts_case *tc, void *data)
158 {
159 apr_thread_t *t1, *t2, *t3, *t4;
160 apr_status_t s1, s2, s3, s4;
161
162 s1 = apr_thread_mutex_create(&thread_mutex, APR_THREAD_MUTEX_DEFAULT, p);
163 ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
164 ABTS_PTR_NOTNULL(tc, thread_mutex);
165
166 i = 0;
167 x = 0;
168
169 s1 = apr_thread_create(&t1, NULL, thread_mutex_function, NULL, p);
170 ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
171 s2 = apr_thread_create(&t2, NULL, thread_mutex_function, NULL, p);
172 ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
173 s3 = apr_thread_create(&t3, NULL, thread_mutex_function, NULL, p);
174 ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
175 s4 = apr_thread_create(&t4, NULL, thread_mutex_function, NULL, p);
176 ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
177
178 apr_thread_join(&s1, t1);
179 apr_thread_join(&s2, t2);
180 apr_thread_join(&s3, t3);
181 apr_thread_join(&s4, t4);
182
183 ABTS_INT_EQUAL(tc, MAX_ITER, x);
184 }
185
186 #if APR_HAS_TIMEDLOCKS
187 static void test_thread_timedmutex(abts_case *tc, void *data)
188 {
189 apr_thread_t *t1, *t2, *t3, *t4;
190 apr_status_t s1, s2, s3, s4;
191 apr_interval_time_t timeout;
192
193 s1 = apr_thread_mutex_create(&thread_mutex, APR_THREAD_MUTEX_TIMED, p);
194 ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
195 ABTS_PTR_NOTNULL(tc, thread_mutex);
196
197 i = 0;
198 x = 0;
199
200 timeout = apr_time_from_sec(5);
201
202 s1 = apr_thread_create(&t1, NULL, thread_mutex_function, &timeout, p);
203 ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
204 s2 = apr_thread_create(&t2, NULL, thread_mutex_function, &timeout, p);
205 ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
206 s3 = apr_thread_create(&t3, NULL, thread_mutex_function, &timeout, p);
207 ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
208 s4 = apr_thread_create(&t4, NULL, thread_mutex_function, &timeout, p);
209 ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
210
211 apr_thread_join(&s1, t1);
212 apr_thread_join(&s2, t2);
213 apr_thread_join(&s3, t3);
214 apr_thread_join(&s4, t4);
215
216 ABTS_INT_EQUAL(tc, MAX_ITER, x);
217 }
218 #endif
219
220 static void test_thread_rwlock(abts_case *tc, void *data)
221 {
222 apr_thread_t *t1, *t2, *t3, *t4;
223 apr_status_t s1, s2, s3, s4;
224
225 s1 = apr_thread_rwlock_create(&rwlock, p);
226 if (s1 == APR_ENOTIMPL) {
227 ABTS_NOT_IMPL(tc, "rwlocks not implemented");
228 return;
229 }
230 APR_ASSERT_SUCCESS(tc, "rwlock_create", s1);
231 ABTS_PTR_NOTNULL(tc, rwlock);
232
233 i = 0;
234 x = 0;
235
236 s1 = apr_thread_create(&t1, NULL, thread_rwlock_func, NULL, p);
237 APR_ASSERT_SUCCESS(tc, "create thread 1", s1);
238 s2 = apr_thread_create(&t2, NULL, thread_rwlock_func, NULL, p);
239 APR_ASSERT_SUCCESS(tc, "create thread 2", s2);
240 s3 = apr_thread_create(&t3, NULL, thread_rwlock_func, NULL, p);
241 APR_ASSERT_SUCCESS(tc, "create thread 3", s3);
242 s4 = apr_thread_create(&t4, NULL, thread_rwlock_func, NULL, p);
243 APR_ASSERT_SUCCESS(tc, "create thread 4", s4);
244
245 apr_thread_join(&s1, t1);
246 apr_thread_join(&s2, t2);
247 apr_thread_join(&s3, t3);
248 apr_thread_join(&s4, t4);
249
250 ABTS_INT_EQUAL(tc, MAX_ITER, x);
251
252 apr_thread_rwlock_destroy(rwlock);
253 }
254
255 static void test_cond(abts_case *tc, void *data)
256 {
257 apr_thread_t *p1, *p2, *p3, *p4, *c1;
258 apr_status_t s0, s1, s2, s3, s4;
259 int count1, count2, count3, count4;
260 int sum;
261
262 APR_ASSERT_SUCCESS(tc, "create put mutex",
263 apr_thread_mutex_create(&put.mutex,
264 APR_THREAD_MUTEX_DEFAULT, p));
265 ABTS_PTR_NOTNULL(tc, put.mutex);
266
267 APR_ASSERT_SUCCESS(tc, "create nready mutex",
268 apr_thread_mutex_create(&nready.mutex,
269 APR_THREAD_MUTEX_DEFAULT, p));
270 ABTS_PTR_NOTNULL(tc, nready.mutex);
271
272 APR_ASSERT_SUCCESS(tc, "create condvar",
273 apr_thread_cond_create(&nready.cond, p));
274 ABTS_PTR_NOTNULL(tc, nready.cond);
275
276 count1 = count2 = count3 = count4 = 0;
277 put.nput = put.nval = 0;
278 nready.nready = 0;
279 i = 0;
280 x = 0;
281
282 s0 = apr_thread_create(&p1, NULL, thread_cond_producer, &count1, p);
283 ABTS_INT_EQUAL(tc, APR_SUCCESS, s0);
284 s1 = apr_thread_create(&p2, NULL, thread_cond_producer, &count2, p);
285 ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
286 s2 = apr_thread_create(&p3, NULL, thread_cond_producer, &count3, p);
287 ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
288 s3 = apr_thread_create(&p4, NULL, thread_cond_producer, &count4, p);
289 ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
290 s4 = apr_thread_create(&c1, NULL, thread_cond_consumer, NULL, p);
291 ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
292
293 apr_thread_join(&s0, p1);
294 apr_thread_join(&s1, p2);
295 apr_thread_join(&s2, p3);
296 apr_thread_join(&s3, p4);
297 apr_thread_join(&s4, c1);
298
299 APR_ASSERT_SUCCESS(tc, "destroy condvar",
300 apr_thread_cond_destroy(nready.cond));
301
302 sum = count1 + count2 + count3 + count4;
303 /*
304 printf("count1 = %d count2 = %d count3 = %d count4 = %d\n",
305 count1, count2, count3, count4);
306 */
307 ABTS_INT_EQUAL(tc, MAX_COUNTER, sum);
308 }
309
310 static void test_timeoutcond(abts_case *tc, void *data)
311 {
312 apr_status_t s;
313 apr_interval_time_t timeout;
314 apr_time_t begin, end;
315 int i;
316
317 s = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT, p);
318 ABTS_INT_EQUAL(tc, APR_SUCCESS, s);
319 ABTS_PTR_NOTNULL(tc, timeout_mutex);
320
321 s = apr_thread_cond_create(&timeout_cond, p);
322 ABTS_INT_EQUAL(tc, APR_SUCCESS, s);
323 ABTS_PTR_NOTNULL(tc, timeout_cond);
324
325 timeout = apr_time_from_sec(5);
326
327 for (i = 0; i < MAX_RETRY; i++) {
328 apr_thread_mutex_lock(timeout_mutex);
329
330 begin = apr_time_now();
331 s = apr_thread_cond_timedwait(timeout_cond, timeout_mutex, timeout);
332 end = apr_time_now();
333 apr_thread_mutex_unlock(timeout_mutex);
334
335 if (s != APR_SUCCESS && !APR_STATUS_IS_TIMEUP(s)) {
336 continue;
337 }
338 ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(s));
339 ABTS_ASSERT(tc, "Timer returned too late", end - begin - timeout < 500000);
340 break;
341 }
342 ABTS_ASSERT(tc, "Too many retries", i < MAX_RETRY);
343 APR_ASSERT_SUCCESS(tc, "Unable to destroy the conditional",
344 apr_thread_cond_destroy(timeout_cond));
345 }
346
347 #if APR_HAS_TIMEDLOCKS
348 static void test_timeoutmutex(abts_case *tc, void *data)
349 {
350 apr_status_t s;
351 apr_interval_time_t timeout;
352 apr_time_t begin, end;
353 int i;
354
355 s = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_TIMED, p);
356 ABTS_INT_EQUAL(tc, APR_SUCCESS, s);
357 ABTS_PTR_NOTNULL(tc, timeout_mutex);
358
359 timeout = apr_time_from_sec(5);
360
361 ABTS_INT_EQUAL(tc, 0, apr_thread_mutex_lock(timeout_mutex));
362 for (i = 0; i < MAX_RETRY; i++) {
363 begin = apr_time_now();
364 s = apr_thread_mutex_timedlock(timeout_mutex, timeout);
365 end = apr_time_now();
366
367 if (s != APR_SUCCESS && !APR_STATUS_IS_TIMEUP(s)) {
368 continue;
369 }
370 ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(s));
371 ABTS_ASSERT(tc, "Timer returned too late", end - begin - timeout < 1000000);
372 break;
373 }
374 ABTS_ASSERT(tc, "Too many retries", i < MAX_RETRY);
375 ABTS_INT_EQUAL(tc, 0, apr_thread_mutex_unlock(timeout_mutex));
376 APR_ASSERT_SUCCESS(tc, "Unable to destroy the mutex",
377 apr_thread_mutex_destroy(timeout_mutex));
378 }
379 #endif
380
381 #endif /* !APR_HAS_THREADS */
382
383 #if !APR_HAS_THREADS
384 static void threads_not_impl(abts_case *tc, void *data)
385 {
386 ABTS_NOT_IMPL(tc, "Threads not implemented on this platform");
387 }
388 #endif
389
390
391 abts_suite *testlock(abts_suite *suite)
392 {
393 suite = ADD_SUITE(suite)
394
395 #if !APR_HAS_THREADS
396 abts_run_test(suite, threads_not_impl, NULL);
397 #else
398 abts_run_test(suite, test_thread_mutex, NULL);
399 #if APR_HAS_TIMEDLOCKS
400 abts_run_test(suite, test_thread_timedmutex, NULL);
401 #endif
402 abts_run_test(suite, test_thread_rwlock, NULL);
403 abts_run_test(suite, test_cond, NULL);
404 abts_run_test(suite, test_timeoutcond, NULL);
405 #if APR_HAS_TIMEDLOCKS
406 abts_run_test(suite, test_timeoutmutex, NULL);
407 #endif
408 #endif
409
410 return suite;
411 }
412