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

« back to all changes in this revision

Viewing changes to srclib/apr/test/testatomic.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 "testutil.h"
 
18
#include "apr_strings.h"
 
19
#include "apr_thread_proc.h"
 
20
#include "apr_errno.h"
 
21
#include "apr_general.h"
 
22
#include "apr_atomic.h"
 
23
#include "apr_time.h"
 
24
 
 
25
/* Use pthread_setconcurrency where it is available and not a nullop,
 
26
 * i.e. platforms using M:N or M:1 thread models: */
 
27
#if APR_HAS_THREADS && \
 
28
   ((defined(SOLARIS2) && SOLARIS2 > 26) || defined(_AIX))
 
29
/* also HP-UX, IRIX? ... */
 
30
#define HAVE_PTHREAD_SETCONCURRENCY
 
31
#endif
 
32
 
 
33
#ifdef HAVE_PTHREAD_SETCONCURRENCY
 
34
#include <pthread.h>
 
35
#endif
 
36
 
 
37
static void test_init(abts_case *tc, void *data)
 
38
{
 
39
    APR_ASSERT_SUCCESS(tc, "Could not initliaze atomics", apr_atomic_init(p));
 
40
}
 
41
 
 
42
static void test_set32(abts_case *tc, void *data)
 
43
{
 
44
    apr_uint32_t y32;
 
45
    apr_atomic_set32(&y32, 2);
 
46
    ABTS_INT_EQUAL(tc, 2, y32);
 
47
}
 
48
 
 
49
static void test_read32(abts_case *tc, void *data)
 
50
{
 
51
    apr_uint32_t y32;
 
52
    apr_atomic_set32(&y32, 2);
 
53
    ABTS_INT_EQUAL(tc, 2, apr_atomic_read32(&y32));
 
54
}
 
55
 
 
56
static void test_dec32(abts_case *tc, void *data)
 
57
{
 
58
    apr_uint32_t y32;
 
59
    int rv;
 
60
 
 
61
    apr_atomic_set32(&y32, 2);
 
62
 
 
63
    rv = apr_atomic_dec32(&y32);
 
64
    ABTS_INT_EQUAL(tc, 1, y32);
 
65
    ABTS_ASSERT(tc, "atomic_dec returned zero when it shouldn't", rv != 0);
 
66
 
 
67
    rv = apr_atomic_dec32(&y32);
 
68
    ABTS_INT_EQUAL(tc, 0, y32);
 
69
    ABTS_ASSERT(tc, "atomic_dec didn't returned zero when it should", rv == 0);
 
70
}
 
71
 
 
72
static void test_xchg32(abts_case *tc, void *data)
 
73
{
 
74
    apr_uint32_t oldval;
 
75
    apr_uint32_t y32;
 
76
 
 
77
    apr_atomic_set32(&y32, 100);
 
78
    oldval = apr_atomic_xchg32(&y32, 50);
 
79
 
 
80
    ABTS_INT_EQUAL(tc, 100, oldval);
 
81
    ABTS_INT_EQUAL(tc, 50, y32);
 
82
}
 
83
 
 
84
static void test_cas_equal(abts_case *tc, void *data)
 
85
{
 
86
    apr_uint32_t casval = 0;
 
87
    apr_uint32_t oldval;
 
88
 
 
89
    oldval = apr_atomic_cas32(&casval, 12, 0);
 
90
    ABTS_INT_EQUAL(tc, 0, oldval);
 
91
    ABTS_INT_EQUAL(tc, 12, casval);
 
92
}
 
93
 
 
94
static void test_cas_equal_nonnull(abts_case *tc, void *data)
 
95
{
 
96
    apr_uint32_t casval = 12;
 
97
    apr_uint32_t oldval;
 
98
 
 
99
    oldval = apr_atomic_cas32(&casval, 23, 12);
 
100
    ABTS_INT_EQUAL(tc, 12, oldval);
 
101
    ABTS_INT_EQUAL(tc, 23, casval);
 
102
}
 
103
 
 
104
static void test_cas_notequal(abts_case *tc, void *data)
 
105
{
 
106
    apr_uint32_t casval = 12;
 
107
    apr_uint32_t oldval;
 
108
 
 
109
    oldval = apr_atomic_cas32(&casval, 23, 2);
 
110
    ABTS_INT_EQUAL(tc, 12, oldval);
 
111
    ABTS_INT_EQUAL(tc, 12, casval);
 
112
}
 
113
 
 
114
static void test_add32(abts_case *tc, void *data)
 
115
{
 
116
    apr_uint32_t oldval;
 
117
    apr_uint32_t y32;
 
118
 
 
119
    apr_atomic_set32(&y32, 23);
 
120
    oldval = apr_atomic_add32(&y32, 4);
 
121
    ABTS_INT_EQUAL(tc, 23, oldval);
 
122
    ABTS_INT_EQUAL(tc, 27, y32);
 
123
}
 
124
 
 
125
static void test_inc32(abts_case *tc, void *data)
 
126
{
 
127
    apr_uint32_t oldval;
 
128
    apr_uint32_t y32;
 
129
 
 
130
    apr_atomic_set32(&y32, 23);
 
131
    oldval = apr_atomic_inc32(&y32);
 
132
    ABTS_INT_EQUAL(tc, 23, oldval);
 
133
    ABTS_INT_EQUAL(tc, 24, y32);
 
134
}
 
135
 
 
136
static void test_set_add_inc_sub(abts_case *tc, void *data)
 
137
{
 
138
    apr_uint32_t y32;
 
139
 
 
140
    apr_atomic_set32(&y32, 0);
 
141
    apr_atomic_add32(&y32, 20);
 
142
    apr_atomic_inc32(&y32);
 
143
    apr_atomic_sub32(&y32, 10);
 
144
 
 
145
    ABTS_INT_EQUAL(tc, 11, y32);
 
146
}
 
147
 
 
148
static void test_wrap_zero(abts_case *tc, void *data)
 
149
{
 
150
    apr_uint32_t y32;
 
151
    apr_uint32_t rv;
 
152
    apr_uint32_t minus1 = -1;
 
153
    char *str;
 
154
 
 
155
    apr_atomic_set32(&y32, 0);
 
156
    rv = apr_atomic_dec32(&y32);
 
157
 
 
158
    ABTS_ASSERT(tc, "apr_atomic_dec32 on zero returned zero.", rv != 0);
 
159
    str = apr_psprintf(p, "zero wrap failed: 0 - 1 = %d", y32);
 
160
    ABTS_ASSERT(tc, str, y32 == minus1);
 
161
}
 
162
 
 
163
static void test_inc_neg1(abts_case *tc, void *data)
 
164
{
 
165
    apr_uint32_t y32 = -1;
 
166
    apr_uint32_t minus1 = -1;
 
167
    apr_uint32_t rv;
 
168
    char *str;
 
169
 
 
170
    rv = apr_atomic_inc32(&y32);
 
171
 
 
172
    ABTS_ASSERT(tc, "apr_atomic_dec32 on zero returned zero.", rv == minus1);
 
173
    str = apr_psprintf(p, "zero wrap failed: -1 + 1 = %d", y32);
 
174
    ABTS_ASSERT(tc, str, y32 == 0);
 
175
}
 
176
 
 
177
 
 
178
#if APR_HAS_THREADS
 
179
 
 
180
void * APR_THREAD_FUNC thread_func_mutex(apr_thread_t *thd, void *data);
 
181
void * APR_THREAD_FUNC thread_func_atomic(apr_thread_t *thd, void *data);
 
182
void * APR_THREAD_FUNC thread_func_none(apr_thread_t *thd, void *data);
 
183
 
 
184
apr_thread_mutex_t *thread_lock;
 
185
volatile apr_uint32_t x = 0; /* mutex locks */
 
186
volatile apr_uint32_t y = 0; /* atomic operations */
 
187
volatile apr_uint32_t z = 0; /* no locks */
 
188
apr_status_t exit_ret_val = 123; /* just some made up number to check on later */
 
189
 
 
190
#define NUM_THREADS 40
 
191
#define NUM_ITERATIONS 20000
 
192
void * APR_THREAD_FUNC thread_func_mutex(apr_thread_t *thd, void *data)
 
193
{
 
194
    int i;
 
195
 
 
196
    for (i = 0; i < NUM_ITERATIONS; i++) {
 
197
        apr_thread_mutex_lock(thread_lock);
 
198
        x++;
 
199
        apr_thread_mutex_unlock(thread_lock);
 
200
    }
 
201
    apr_thread_exit(thd, exit_ret_val);
 
202
    return NULL;
 
203
 
204
 
 
205
void * APR_THREAD_FUNC thread_func_atomic(apr_thread_t *thd, void *data)
 
206
{
 
207
    int i;
 
208
 
 
209
    for (i = 0; i < NUM_ITERATIONS ; i++) {
 
210
        apr_atomic_inc32(&y);
 
211
        apr_atomic_add32(&y, 2);
 
212
        apr_atomic_dec32(&y);
 
213
        apr_atomic_dec32(&y);
 
214
    }
 
215
    apr_thread_exit(thd, exit_ret_val);
 
216
    return NULL;
 
217
}
 
218
 
 
219
void * APR_THREAD_FUNC thread_func_none(apr_thread_t *thd, void *data)
 
220
{
 
221
    int i;
 
222
 
 
223
    for (i = 0; i < NUM_ITERATIONS ; i++) {
 
224
        z++;
 
225
    }
 
226
    apr_thread_exit(thd, exit_ret_val);
 
227
    return NULL;
 
228
}
 
229
 
 
230
static void test_atomics_threaded(abts_case *tc, void *data)
 
231
{
 
232
    apr_thread_t *t1[NUM_THREADS];
 
233
    apr_thread_t *t2[NUM_THREADS];
 
234
    apr_thread_t *t3[NUM_THREADS];
 
235
    apr_status_t s1[NUM_THREADS]; 
 
236
    apr_status_t s2[NUM_THREADS];
 
237
    apr_status_t s3[NUM_THREADS];
 
238
    apr_status_t rv;
 
239
    int i;
 
240
 
 
241
#ifdef HAVE_PTHREAD_SETCONCURRENCY
 
242
    pthread_setconcurrency(8);
 
243
#endif
 
244
 
 
245
    rv = apr_thread_mutex_create(&thread_lock, APR_THREAD_MUTEX_DEFAULT, p);
 
246
    APR_ASSERT_SUCCESS(tc, "Could not create lock", rv);
 
247
 
 
248
    for (i = 0; i < NUM_THREADS; i++) {
 
249
        apr_status_t r1, r2, r3;
 
250
        r1 = apr_thread_create(&t1[i], NULL, thread_func_mutex, NULL, p);
 
251
        r2 = apr_thread_create(&t2[i], NULL, thread_func_atomic, NULL, p);
 
252
        r3 = apr_thread_create(&t3[i], NULL, thread_func_none, NULL, p);
 
253
        ABTS_ASSERT(tc, "Failed creating threads",
 
254
                 r1 == APR_SUCCESS && r2 == APR_SUCCESS && 
 
255
                 r3 == APR_SUCCESS);
 
256
    }
 
257
 
 
258
    for (i = 0; i < NUM_THREADS; i++) {
 
259
        apr_thread_join(&s1[i], t1[i]);
 
260
        apr_thread_join(&s2[i], t2[i]);
 
261
        apr_thread_join(&s3[i], t3[i]);
 
262
                     
 
263
        ABTS_ASSERT(tc, "Invalid return value from thread_join",
 
264
                 s1[i] == exit_ret_val && s2[i] == exit_ret_val && 
 
265
                 s3[i] == exit_ret_val);
 
266
    }
 
267
 
 
268
    ABTS_INT_EQUAL(tc, x, NUM_THREADS * NUM_ITERATIONS);
 
269
    ABTS_INT_EQUAL(tc, apr_atomic_read32(&y), NUM_THREADS * NUM_ITERATIONS);
 
270
    /* Comment out this test, because I have no clue what this test is
 
271
     * actually telling us.  We are checking something that may or may not
 
272
     * be true, and it isn't really testing APR at all.
 
273
    ABTS_ASSERT(tc, "We expect this to fail, because we tried to update "
 
274
                 "an integer in a non-thread-safe manner.",
 
275
             z != NUM_THREADS * NUM_ITERATIONS);
 
276
     */
 
277
}
 
278
 
 
279
#endif /* !APR_HAS_THREADS */
 
280
 
 
281
abts_suite *testatomic(abts_suite *suite)
 
282
{
 
283
    suite = ADD_SUITE(suite)
 
284
 
 
285
    abts_run_test(suite, test_init, NULL);
 
286
    abts_run_test(suite, test_set32, NULL);
 
287
    abts_run_test(suite, test_read32, NULL);
 
288
    abts_run_test(suite, test_dec32, NULL);
 
289
    abts_run_test(suite, test_xchg32, NULL);
 
290
    abts_run_test(suite, test_cas_equal, NULL);
 
291
    abts_run_test(suite, test_cas_equal_nonnull, NULL);
 
292
    abts_run_test(suite, test_cas_notequal, NULL);
 
293
    abts_run_test(suite, test_add32, NULL);
 
294
    abts_run_test(suite, test_inc32, NULL);
 
295
    abts_run_test(suite, test_set_add_inc_sub, NULL);
 
296
    abts_run_test(suite, test_wrap_zero, NULL);
 
297
    abts_run_test(suite, test_inc_neg1, NULL);
 
298
 
 
299
#if APR_HAS_THREADS
 
300
    abts_run_test(suite, test_atomics_threaded, NULL);
 
301
#endif
 
302
 
 
303
    return suite;
 
304
}
 
305