1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
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.
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"
29
#define MAX_ITER 40000
30
#define MAX_COUNTER 100000
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);
38
static apr_thread_mutex_t *thread_mutex;
39
static apr_thread_rwlock_t *rwlock;
40
static int i = 0, x = 0;
42
static int buff[MAX_COUNTER];
45
apr_thread_mutex_t *mutex;
51
apr_thread_mutex_t *mutex;
52
apr_thread_cond_t *cond;
56
static apr_thread_mutex_t *timeout_mutex;
57
static apr_thread_cond_t *timeout_cond;
59
static void *APR_THREAD_FUNC thread_rwlock_func(apr_thread_t *thd, void *data)
65
apr_thread_rwlock_rdlock(rwlock);
68
apr_thread_rwlock_unlock(rwlock);
73
apr_thread_rwlock_wrlock(rwlock);
79
apr_thread_rwlock_unlock(rwlock);
84
static void *APR_THREAD_FUNC thread_mutex_function(apr_thread_t *thd, void *data)
88
/* slight delay to allow things to settle */
93
apr_thread_mutex_lock(thread_mutex);
101
apr_thread_mutex_unlock(thread_mutex);
109
static void *APR_THREAD_FUNC thread_cond_producer(apr_thread_t *thd, void *data)
112
apr_thread_mutex_lock(put.mutex);
113
if (put.nput >= MAX_COUNTER) {
114
apr_thread_mutex_unlock(put.mutex);
117
buff[put.nput] = put.nval;
120
apr_thread_mutex_unlock(put.mutex);
122
apr_thread_mutex_lock(nready.mutex);
123
if (nready.nready == 0)
124
apr_thread_cond_signal(nready.cond);
126
apr_thread_mutex_unlock(nready.mutex);
128
*((int *) data) += 1;
134
static void *APR_THREAD_FUNC thread_cond_consumer(apr_thread_t *thd, void *data)
138
for (i = 0; i < MAX_COUNTER; i++) {
139
apr_thread_mutex_lock(nready.mutex);
140
while (nready.nready == 0)
141
apr_thread_cond_wait(nready.cond, nready.mutex);
143
apr_thread_mutex_unlock(nready.mutex);
146
printf("buff[%d] = %d\n", i, buff[i]);
152
static void test_thread_mutex(abts_case *tc, void *data)
154
apr_thread_t *t1, *t2, *t3, *t4;
155
apr_status_t s1, s2, s3, s4;
157
s1 = apr_thread_mutex_create(&thread_mutex, APR_THREAD_MUTEX_DEFAULT, p);
158
ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
159
ABTS_PTR_NOTNULL(tc, thread_mutex);
164
s1 = apr_thread_create(&t1, NULL, thread_mutex_function, NULL, p);
165
ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
166
s2 = apr_thread_create(&t2, NULL, thread_mutex_function, NULL, p);
167
ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
168
s3 = apr_thread_create(&t3, NULL, thread_mutex_function, NULL, p);
169
ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
170
s4 = apr_thread_create(&t4, NULL, thread_mutex_function, NULL, p);
171
ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
173
apr_thread_join(&s1, t1);
174
apr_thread_join(&s2, t2);
175
apr_thread_join(&s3, t3);
176
apr_thread_join(&s4, t4);
178
ABTS_INT_EQUAL(tc, MAX_ITER, x);
181
static void test_thread_rwlock(abts_case *tc, void *data)
183
apr_thread_t *t1, *t2, *t3, *t4;
184
apr_status_t s1, s2, s3, s4;
186
s1 = apr_thread_rwlock_create(&rwlock, p);
187
if (s1 == APR_ENOTIMPL) {
188
ABTS_NOT_IMPL(tc, "rwlocks not implemented");
191
APR_ASSERT_SUCCESS(tc, "rwlock_create", s1);
192
ABTS_PTR_NOTNULL(tc, rwlock);
197
s1 = apr_thread_create(&t1, NULL, thread_rwlock_func, NULL, p);
198
APR_ASSERT_SUCCESS(tc, "create thread 1", s1);
199
s2 = apr_thread_create(&t2, NULL, thread_rwlock_func, NULL, p);
200
APR_ASSERT_SUCCESS(tc, "create thread 2", s2);
201
s3 = apr_thread_create(&t3, NULL, thread_rwlock_func, NULL, p);
202
APR_ASSERT_SUCCESS(tc, "create thread 3", s3);
203
s4 = apr_thread_create(&t4, NULL, thread_rwlock_func, NULL, p);
204
APR_ASSERT_SUCCESS(tc, "create thread 4", s4);
206
apr_thread_join(&s1, t1);
207
apr_thread_join(&s2, t2);
208
apr_thread_join(&s3, t3);
209
apr_thread_join(&s4, t4);
211
ABTS_INT_EQUAL(tc, MAX_ITER, x);
213
apr_thread_rwlock_destroy(rwlock);
216
static void test_cond(abts_case *tc, void *data)
218
apr_thread_t *p1, *p2, *p3, *p4, *c1;
219
apr_status_t s0, s1, s2, s3, s4;
220
int count1, count2, count3, count4;
223
APR_ASSERT_SUCCESS(tc, "create put mutex",
224
apr_thread_mutex_create(&put.mutex,
225
APR_THREAD_MUTEX_DEFAULT, p));
226
ABTS_PTR_NOTNULL(tc, put.mutex);
228
APR_ASSERT_SUCCESS(tc, "create nready mutex",
229
apr_thread_mutex_create(&nready.mutex,
230
APR_THREAD_MUTEX_DEFAULT, p));
231
ABTS_PTR_NOTNULL(tc, nready.mutex);
233
APR_ASSERT_SUCCESS(tc, "create condvar",
234
apr_thread_cond_create(&nready.cond, p));
235
ABTS_PTR_NOTNULL(tc, nready.cond);
237
count1 = count2 = count3 = count4 = 0;
238
put.nput = put.nval = 0;
243
s0 = apr_thread_create(&p1, NULL, thread_cond_producer, &count1, p);
244
ABTS_INT_EQUAL(tc, APR_SUCCESS, s0);
245
s1 = apr_thread_create(&p2, NULL, thread_cond_producer, &count2, p);
246
ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
247
s2 = apr_thread_create(&p3, NULL, thread_cond_producer, &count3, p);
248
ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
249
s3 = apr_thread_create(&p4, NULL, thread_cond_producer, &count4, p);
250
ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
251
s4 = apr_thread_create(&c1, NULL, thread_cond_consumer, NULL, p);
252
ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
254
apr_thread_join(&s0, p1);
255
apr_thread_join(&s1, p2);
256
apr_thread_join(&s2, p3);
257
apr_thread_join(&s3, p4);
258
apr_thread_join(&s4, c1);
260
APR_ASSERT_SUCCESS(tc, "destroy condvar",
261
apr_thread_cond_destroy(nready.cond));
263
sum = count1 + count2 + count3 + count4;
265
printf("count1 = %d count2 = %d count3 = %d count4 = %d\n",
266
count1, count2, count3, count4);
268
ABTS_INT_EQUAL(tc, MAX_COUNTER, sum);
271
static void test_timeoutcond(abts_case *tc, void *data)
274
apr_interval_time_t timeout;
275
apr_time_t begin, end;
278
s = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT, p);
279
ABTS_INT_EQUAL(tc, APR_SUCCESS, s);
280
ABTS_PTR_NOTNULL(tc, timeout_mutex);
282
s = apr_thread_cond_create(&timeout_cond, p);
283
ABTS_INT_EQUAL(tc, APR_SUCCESS, s);
284
ABTS_PTR_NOTNULL(tc, timeout_cond);
286
timeout = apr_time_from_sec(5);
288
for (i = 0; i < MAX_RETRY; i++) {
289
apr_thread_mutex_lock(timeout_mutex);
291
begin = apr_time_now();
292
s = apr_thread_cond_timedwait(timeout_cond, timeout_mutex, timeout);
293
end = apr_time_now();
294
apr_thread_mutex_unlock(timeout_mutex);
296
if (s != APR_SUCCESS && !APR_STATUS_IS_TIMEUP(s)) {
299
ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(s));
300
ABTS_ASSERT(tc, "Timer returned too late", end - begin - timeout < 100000);
303
ABTS_ASSERT(tc, "Too many retries", i < MAX_RETRY);
304
APR_ASSERT_SUCCESS(tc, "Unable to destroy the conditional",
305
apr_thread_cond_destroy(timeout_cond));
308
#endif /* !APR_HAS_THREADS */
311
static void threads_not_impl(abts_case *tc, void *data)
313
ABTS_NOT_IMPL(tc, "Threads not implemented on this platform");
318
abts_suite *testlock(abts_suite *suite)
320
suite = ADD_SUITE(suite)
323
abts_run_test(suite, threads_not_impl, NULL);
325
abts_run_test(suite, test_thread_mutex, NULL);
326
abts_run_test(suite, test_thread_rwlock, NULL);
327
abts_run_test(suite, test_cond, NULL);
328
abts_run_test(suite, test_timeoutcond, NULL);