upload http
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / apr / test / testatomic.c
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 <stdio.h>
18 #include <stdlib.h>
19 #include "apr_thread_proc.h"
20 #include "apr_errno.h"
21 #include "apr_general.h"
22 #include "apr_atomic.h"
23 #include "errno.h"
24 #include "apr_time.h"
25 #if APR_HAVE_UNISTD_H
26 #include <unistd.h>
27 #endif
28
29 #if !(defined WIN32) && !(defined NETWARE)
30 #include <pthread.h>
31 #endif
32
33 apr_pool_t *context;
34 apr_atomic_t y;      /* atomic locks */
35
36 static apr_status_t check_basic_atomics(volatile apr_atomic_t*p)
37 {
38     apr_atomic_t oldval;
39     apr_uint32_t casval = 0;
40     float object1, object2;
41 #if !(defined NETWARE)
42     volatile void *casptr;
43 #else
44     void *casptr;
45 #endif
46     void *oldptr;
47
48     apr_atomic_set(&y, 2);
49     printf("%-60s", "testing apr_atomic_dec");
50     if (apr_atomic_dec(&y) == 0) {
51         fprintf(stderr, "Failed\noldval =%d should not be zero\n",
52                 apr_atomic_read(&y));
53         return APR_EGENERAL;
54     }
55     if (apr_atomic_dec(&y) != 0) {
56         fprintf(stderr, "Failed\noldval =%d should be zero\n",
57                 apr_atomic_read(&y));
58         return APR_EGENERAL;
59     }
60     printf("OK\n");
61
62     printf("%-60s", "testing CAS");
63     oldval = apr_atomic_cas(&casval, 12, 0);
64     if (oldval != 0) {
65         fprintf(stderr, "Failed\noldval =%d should be zero\n", oldval);
66         return APR_EGENERAL;
67     }
68     printf("OK\n");
69     printf("%-60s", "testing CAS - match non-null");
70     oldval = apr_atomic_cas(&casval, 23, 12);
71     if (oldval != 12) {
72         fprintf(stderr, "Failed\noldval =%d should be 12 y=%d\n",
73                 oldval, casval);
74         return APR_EGENERAL;
75     }
76     printf("OK\n");
77     printf("%-60s", "testing CAS - no match");
78     oldval = apr_atomic_cas(&casval, 23, 12);
79     if (oldval != 23) {
80         fprintf(stderr, "Failed\noldval =%d should be 23 y=%d\n",
81                 oldval, casval);
82         return APR_EGENERAL;
83     }
84     printf("OK\n");
85
86     printf("%-60s", "testing CAS for pointers");
87     casptr = NULL;
88     oldptr = apr_atomic_casptr(&casptr, &object1, 0);
89     if (oldptr != 0) {
90         fprintf(stderr, "Failed\noldval =%p should be zero\n", oldptr);
91         return APR_EGENERAL;
92     }
93     printf("OK\n");
94     printf("%-60s", "testing CAS for pointers - match non-null");
95     oldptr = apr_atomic_casptr(&casptr, &object2, &object1);
96     if (oldptr != &object1) {
97         fprintf(stderr, "Failed\noldval =%p should be %p\n", oldptr, &object1);
98         return APR_EGENERAL;
99     }
100     printf("OK\n");
101     printf("%-60s", "testing CAS for pointers - no match");
102     oldptr = apr_atomic_casptr(&casptr, &object2, &object1);
103     if (oldptr != &object2) {
104         fprintf(stderr, "Failed\noldval =%p should be %p\n", oldptr, &object2);
105         return APR_EGENERAL;
106     }
107     printf("OK\n");
108
109     printf("%-60s", "testing add");
110     apr_atomic_set(&y, 23);
111     apr_atomic_add(&y, 4);
112     if (apr_atomic_read(&y) != 27) {
113         fprintf(stderr,
114                 "Failed\nAtomic Add doesn't add up ;( expected 27 got %d\n",
115                 oldval);
116         return APR_EGENERAL;
117     }
118  
119     printf("OK\n");
120     printf("%-60s", "testing add/inc");
121     apr_atomic_set(&y, 0);
122     apr_atomic_add(&y, 20);
123     apr_atomic_inc(&y);
124     if (apr_atomic_read(&y) != 21) {
125         fprintf(stderr, "Failed.\natomics do not add up\n");
126         return APR_EGENERAL;
127     }
128     fprintf(stdout, "OK\n");
129
130     return APR_SUCCESS;
131 }
132
133 #if !APR_HAS_THREADS
134 int main(void)
135 {
136     apr_status_t rv;
137
138     apr_initialize();
139
140     fprintf(stderr,
141             "This program won't work fully on this platform because there is no "
142             "support for threads.\n");
143     if (apr_pool_create(&context, NULL) != APR_SUCCESS) {
144         fflush(stdout);
145         fprintf(stderr, "Failed.\nCould not initialize\n");
146         exit(-1);
147     }
148     rv = apr_atomic_init(context);
149     if (rv != APR_SUCCESS) {
150         fprintf(stderr, "Failed.\nCould not initialize atomics\n");
151         exit(-1);
152     }
153     rv = check_basic_atomics(&y);
154     if (rv != APR_SUCCESS) {
155         fprintf(stderr, "Failed.\n");
156         exit(-1);
157     }
158     return 0;
159 }
160 #else /* !APR_HAS_THREADS */
161
162 void * APR_THREAD_FUNC thread_func_mutex(apr_thread_t *thd, void *data);
163 void * APR_THREAD_FUNC thread_func_atomic(apr_thread_t *thd, void *data);
164 void * APR_THREAD_FUNC thread_func_none(apr_thread_t *thd, void *data);
165
166 apr_thread_mutex_t *thread_lock;
167 volatile long x = 0; /* mutex locks */
168 volatile long z = 0; /* no locks */
169 int value = 0;
170 apr_status_t exit_ret_val = 123; /* just some made up number to check on later */
171
172 #define NUM_THREADS 50
173 #define NUM_ITERATIONS 20000
174 void * APR_THREAD_FUNC thread_func_mutex(apr_thread_t *thd, void *data)
175 {
176     int i;
177
178     for (i = 0; i < NUM_ITERATIONS; i++) {
179         apr_thread_mutex_lock(thread_lock);
180         x++;
181         apr_thread_mutex_unlock(thread_lock);
182     }
183     apr_thread_exit(thd, exit_ret_val);
184     return NULL;
185
186
187 void * APR_THREAD_FUNC thread_func_atomic(apr_thread_t *thd, void *data)
188 {
189     int i;
190
191     for (i = 0; i < NUM_ITERATIONS ; i++) {
192         apr_atomic_inc(&y);
193         apr_atomic_add(&y, 2);
194         apr_atomic_dec(&y);
195         apr_atomic_dec(&y);
196     }
197     apr_thread_exit(thd, exit_ret_val);
198     return NULL;
199 }
200
201 void * APR_THREAD_FUNC thread_func_none(apr_thread_t *thd, void *data)
202 {
203     int i;
204
205     for (i = 0; i < NUM_ITERATIONS ; i++) {
206         z++;
207     }
208     apr_thread_exit(thd, exit_ret_val);
209     return NULL;
210 }
211
212 int main(int argc, char**argv)
213 {
214     apr_thread_t *t1[NUM_THREADS];
215     apr_thread_t *t2[NUM_THREADS];
216     apr_status_t r1[NUM_THREADS]; 
217     apr_status_t r2[NUM_THREADS]; 
218     apr_status_t s1[NUM_THREADS]; 
219     apr_status_t s2[NUM_THREADS];
220     apr_status_t rv;
221     int i;
222     int mutex;
223
224     apr_initialize();
225
226     if (argc == 2 && argv[1][0] == 'm') {
227         mutex = 1;
228     }
229     else {
230         mutex = 0;
231     }
232
233     printf("APR Atomic Test\n===============\n\n");
234 #if !(defined WIN32) && !(defined NETWARE) && !(defined __MVS__) && !(defined DARWIN)
235     pthread_setconcurrency(8);
236 #endif
237     printf("%-60s", "Initializing the context"); 
238     if (apr_pool_create(&context, NULL) != APR_SUCCESS) {
239         fflush(stdout);
240         fprintf(stderr, "Failed.\nCould not initialize\n");
241         exit(-1);
242     }
243     printf("OK\n");
244
245     if (mutex == 1) {
246         printf("%-60s", "Initializing the lock"); 
247         rv = apr_thread_mutex_create(&thread_lock, APR_THREAD_MUTEX_DEFAULT,
248                                      context);
249         if (rv != APR_SUCCESS) {
250             fflush(stdout);
251             fprintf(stderr, "Failed\nCould not create lock\n");
252             exit(-1);
253         }
254         printf("OK\n");
255     }
256     printf("%-60s", "Initializing the atomics"); 
257     rv = apr_atomic_init(context);
258     if (rv != APR_SUCCESS) {
259         fprintf(stderr, "Failed.\n");
260         exit(-1);
261     }
262     printf("OK\n");
263
264     rv = check_basic_atomics(&y);
265     if (rv != APR_SUCCESS) {
266         fprintf(stderr, "Failed.\n");
267         exit(-1);
268     }
269     apr_atomic_set(&y, 0);
270
271     printf("%-60s", "Starting all the threads"); 
272     for (i = 0; i < NUM_THREADS; i++) {
273         r1[i] = apr_thread_create(&t1[i], NULL, 
274                     (mutex == 1 ? thread_func_mutex : thread_func_atomic),
275                     NULL, context);
276         r2[i] = apr_thread_create(&t2[i], NULL, thread_func_none, NULL,
277                                   context);
278         if (r1[i] != APR_SUCCESS || r2[i] != APR_SUCCESS ) {
279             fflush(stdout);
280             fprintf(stderr, "Failed\nError starting thread in group %d\n",i);
281             exit(-1);
282         }
283     }
284     printf("OK\n");
285
286     printf("%-60s\n", "Waiting for threads to exit");
287     printf("%-60s", "(Note that this may take a while to complete.)");
288     fflush(stdout);
289
290     for (i = 0; i < NUM_THREADS; i++) {
291         apr_thread_join(&s1[i], t1[i]);
292         apr_thread_join(&s2[i], t2[i]);
293         if (s1[i] != exit_ret_val || s2[i] != exit_ret_val) {
294             fprintf(stderr, 
295                     "Invalid return value\n"
296                     "Got %d/%d, but expected %d for all \n",
297                     s1[i], s2[i], exit_ret_val);
298         }
299     }
300     printf("OK\n");
301
302     if (mutex == 1) {
303         printf("%-60s", "Checking if mutex locks worked"); 
304         if (x != NUM_THREADS * NUM_ITERATIONS) {
305             fflush(stdout);
306             fprintf(stderr, 
307                     "No!\nThe locks didn't work?? x = %ld instead of %ld\n",
308                     x,
309                     (long)NUM_THREADS * NUM_ITERATIONS);
310         }
311         else {
312             printf("OK\n");
313         }
314     }
315     else {
316         printf("%-60s", "Checking if atomic worked"); 
317         if (apr_atomic_read(&y) != NUM_THREADS * NUM_ITERATIONS) {
318             fflush(stdout);
319             fprintf(stderr, 
320                     "No!\nThe atomics didn't work?? y = %ld instead of %ld\n",
321                     (long)apr_atomic_read(&y),
322                     (long)NUM_THREADS * NUM_ITERATIONS);
323         }
324         else {
325             printf("OK\n");
326         }
327     }
328     printf("%-60s", "Checking if nolock worked"); 
329     if (z != NUM_THREADS * NUM_ITERATIONS) {
330         fflush(stdout);
331         fprintf(stderr, 
332                 "no surprise\n"
333                 "The no-locks didn't work. z = %ld instead of %ld\n", 
334                 z, 
335                 (long)NUM_THREADS * NUM_ITERATIONS);
336     }
337     else {
338         printf("OK\n");
339     }
340
341     return 0;
342 }
343
344 #endif /* !APR_HAS_THREADS */