~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to srclib/apr/test/testlock.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
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
 
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
        apr_thread_mutex_lock(thread_mutex);
 
94
        if (i == MAX_ITER)
 
95
            exitLoop = 0;
 
96
        else 
 
97
        {
 
98
            i++;
 
99
            x++;
 
100
        }
 
101
        apr_thread_mutex_unlock(thread_mutex);
 
102
 
 
103
        if (!exitLoop)
 
104
            break;
 
105
    }
 
106
    return NULL;
 
107
 
108
 
 
109
static void *APR_THREAD_FUNC thread_cond_producer(apr_thread_t *thd, void *data)
 
110
{
 
111
    for (;;) {
 
112
        apr_thread_mutex_lock(put.mutex);
 
113
        if (put.nput >= MAX_COUNTER) {
 
114
            apr_thread_mutex_unlock(put.mutex);
 
115
            return NULL;
 
116
        }
 
117
        buff[put.nput] = put.nval;
 
118
        put.nput++;
 
119
        put.nval++;
 
120
        apr_thread_mutex_unlock(put.mutex);
 
121
 
 
122
        apr_thread_mutex_lock(nready.mutex);
 
123
        if (nready.nready == 0)
 
124
            apr_thread_cond_signal(nready.cond);
 
125
        nready.nready++;
 
126
        apr_thread_mutex_unlock(nready.mutex);
 
127
 
 
128
        *((int *) data) += 1;
 
129
    }
 
130
 
 
131
    return NULL;
 
132
}
 
133
 
 
134
static void *APR_THREAD_FUNC thread_cond_consumer(apr_thread_t *thd, void *data)
 
135
{
 
136
    int i;
 
137
 
 
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);
 
142
        nready.nready--;
 
143
        apr_thread_mutex_unlock(nready.mutex);
 
144
 
 
145
        if (buff[i] != i)
 
146
            printf("buff[%d] = %d\n", i, buff[i]);
 
147
    }
 
148
 
 
149
    return NULL;
 
150
}
 
151
 
 
152
static void test_thread_mutex(abts_case *tc, void *data)
 
153
{
 
154
    apr_thread_t *t1, *t2, *t3, *t4;
 
155
    apr_status_t s1, s2, s3, s4;
 
156
 
 
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);
 
160
 
 
161
    i = 0;
 
162
    x = 0;
 
163
 
 
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);
 
172
 
 
173
    apr_thread_join(&s1, t1);
 
174
    apr_thread_join(&s2, t2);
 
175
    apr_thread_join(&s3, t3);
 
176
    apr_thread_join(&s4, t4);
 
177
 
 
178
    ABTS_INT_EQUAL(tc, MAX_ITER, x);
 
179
}
 
180
 
 
181
static void test_thread_rwlock(abts_case *tc, void *data)
 
182
{
 
183
    apr_thread_t *t1, *t2, *t3, *t4;
 
184
    apr_status_t s1, s2, s3, s4;
 
185
 
 
186
    s1 = apr_thread_rwlock_create(&rwlock, p);
 
187
    if (s1 == APR_ENOTIMPL) {
 
188
        ABTS_NOT_IMPL(tc, "rwlocks not implemented");
 
189
        return;
 
190
    }
 
191
    APR_ASSERT_SUCCESS(tc, "rwlock_create", s1);
 
192
    ABTS_PTR_NOTNULL(tc, rwlock);
 
193
 
 
194
    i = 0;
 
195
    x = 0;
 
196
 
 
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);
 
205
 
 
206
    apr_thread_join(&s1, t1);
 
207
    apr_thread_join(&s2, t2);
 
208
    apr_thread_join(&s3, t3);
 
209
    apr_thread_join(&s4, t4);
 
210
 
 
211
    ABTS_INT_EQUAL(tc, MAX_ITER, x);
 
212
 
 
213
    apr_thread_rwlock_destroy(rwlock);
 
214
}
 
215
 
 
216
static void test_cond(abts_case *tc, void *data)
 
217
{
 
218
    apr_thread_t *p1, *p2, *p3, *p4, *c1;
 
219
    apr_status_t s0, s1, s2, s3, s4;
 
220
    int count1, count2, count3, count4;
 
221
    int sum;
 
222
    
 
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);
 
227
 
 
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);
 
232
 
 
233
    APR_ASSERT_SUCCESS(tc, "create condvar",
 
234
                       apr_thread_cond_create(&nready.cond, p));
 
235
    ABTS_PTR_NOTNULL(tc, nready.cond);
 
236
 
 
237
    count1 = count2 = count3 = count4 = 0;
 
238
    put.nput = put.nval = 0;
 
239
    nready.nready = 0;
 
240
    i = 0;
 
241
    x = 0;
 
242
 
 
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);
 
253
 
 
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);
 
259
 
 
260
    APR_ASSERT_SUCCESS(tc, "destroy condvar", 
 
261
                       apr_thread_cond_destroy(nready.cond));
 
262
 
 
263
    sum = count1 + count2 + count3 + count4;
 
264
    /*
 
265
    printf("count1 = %d count2 = %d count3 = %d count4 = %d\n",
 
266
            count1, count2, count3, count4);
 
267
    */
 
268
    ABTS_INT_EQUAL(tc, MAX_COUNTER, sum);
 
269
}
 
270
 
 
271
static void test_timeoutcond(abts_case *tc, void *data)
 
272
{
 
273
    apr_status_t s;
 
274
    apr_interval_time_t timeout;
 
275
    apr_time_t begin, end;
 
276
    int i;
 
277
 
 
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);
 
281
 
 
282
    s = apr_thread_cond_create(&timeout_cond, p);
 
283
    ABTS_INT_EQUAL(tc, APR_SUCCESS, s);
 
284
    ABTS_PTR_NOTNULL(tc, timeout_cond);
 
285
 
 
286
    timeout = apr_time_from_sec(5);
 
287
 
 
288
    for (i = 0; i < MAX_RETRY; i++) {
 
289
        apr_thread_mutex_lock(timeout_mutex);
 
290
 
 
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);
 
295
        
 
296
        if (s != APR_SUCCESS && !APR_STATUS_IS_TIMEUP(s)) {
 
297
            continue;
 
298
        }
 
299
        ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(s));
 
300
        ABTS_ASSERT(tc, "Timer returned too late", end - begin - timeout < 100000);
 
301
        break;
 
302
    }
 
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));
 
306
}
 
307
 
 
308
#endif /* !APR_HAS_THREADS */
 
309
 
 
310
#if !APR_HAS_THREADS
 
311
static void threads_not_impl(abts_case *tc, void *data)
 
312
{
 
313
    ABTS_NOT_IMPL(tc, "Threads not implemented on this platform");
 
314
}
 
315
#endif
 
316
 
 
317
 
 
318
abts_suite *testlock(abts_suite *suite)
 
319
{
 
320
    suite = ADD_SUITE(suite)
 
321
 
 
322
#if !APR_HAS_THREADS
 
323
    abts_run_test(suite, threads_not_impl, NULL);
 
324
#else
 
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);
 
329
#endif
 
330
 
 
331
    return suite;
 
332
}
 
333