xref: /aosp_15_r20/external/cronet/third_party/apache-portable-runtime/src/test/testmutexscope.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 /* This program won't run or check correctly if assert() is disabled. */
18 #undef NDEBUG
19 #include <assert.h>
20 #include <errno.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 
24 #include "apr.h"
25 #include "apr_general.h"
26 #include "apr_proc_mutex.h"
27 #include "apr_global_mutex.h"
28 #include "apr_thread_proc.h"
29 
30 #if !APR_HAS_THREADS
main(void)31 int main(void)
32 {
33     printf("This test requires APR thread support.\n");
34     return 0;
35 }
36 
37 #else /* APR_HAS_THREADS */
38 
39 static apr_thread_mutex_t *thread_mutex;
40 static apr_proc_mutex_t *proc_mutex;
41 static apr_global_mutex_t *global_mutex;
42 static apr_pool_t *p;
43 static volatile int counter;
44 typedef enum {TEST_GLOBAL, TEST_PROC} test_mode_e;
45 
lock_init(apr_lockmech_e mech,test_mode_e test_mode)46 static void lock_init(apr_lockmech_e mech, test_mode_e test_mode)
47 {
48     if (test_mode == TEST_PROC) {
49         assert(apr_proc_mutex_create(&proc_mutex,
50                                      NULL,
51                                      mech,
52                                      p) == APR_SUCCESS);
53     }
54     else {
55         assert(apr_global_mutex_create(&global_mutex,
56                                        NULL,
57                                        mech,
58                                        p) == APR_SUCCESS);
59     }
60 }
61 
lock_destroy(test_mode_e test_mode)62 static void lock_destroy(test_mode_e test_mode)
63 {
64     if (test_mode == TEST_PROC) {
65         assert(apr_proc_mutex_destroy(proc_mutex) == APR_SUCCESS);
66     }
67     else {
68         assert(apr_global_mutex_destroy(global_mutex) == APR_SUCCESS);
69     }
70 }
71 
lock_grab(test_mode_e test_mode)72 static void lock_grab(test_mode_e test_mode)
73 {
74     if (test_mode == TEST_PROC) {
75         assert(apr_proc_mutex_lock(proc_mutex) == APR_SUCCESS);
76     }
77     else {
78         assert(apr_global_mutex_lock(global_mutex) == APR_SUCCESS);
79     }
80 }
81 
lock_release(test_mode_e test_mode)82 static void lock_release(test_mode_e test_mode)
83 {
84     if (test_mode == TEST_PROC) {
85         assert(apr_proc_mutex_unlock(proc_mutex) == APR_SUCCESS);
86     }
87     else {
88         assert(apr_global_mutex_unlock(global_mutex) == APR_SUCCESS);
89     }
90 }
91 
eachThread(apr_thread_t * id,void * p)92 static void * APR_THREAD_FUNC eachThread(apr_thread_t *id, void *p)
93 {
94     test_mode_e test_mode = (test_mode_e)p;
95 
96     lock_grab(test_mode);
97     ++counter;
98     assert(apr_thread_mutex_lock(thread_mutex) == APR_SUCCESS);
99     assert(apr_thread_mutex_unlock(thread_mutex) == APR_SUCCESS);
100     lock_release(test_mode);
101     apr_thread_exit(id, 0);
102     return NULL;
103 }
104 
test_mech_mode(apr_lockmech_e mech,const char * mech_name,test_mode_e test_mode)105 static void test_mech_mode(apr_lockmech_e mech, const char *mech_name,
106                            test_mode_e test_mode)
107 {
108   apr_thread_t *threads[20];
109   int numThreads = 5;
110   int i;
111   apr_status_t rv;
112 
113   printf("Trying %s mutexes with mechanism `%s'...\n",
114          test_mode == TEST_GLOBAL ? "global" : "proc", mech_name);
115 
116   assert(numThreads <= sizeof(threads) / sizeof(threads[0]));
117 
118   assert(apr_pool_create(&p, NULL) == APR_SUCCESS);
119 
120   assert(apr_thread_mutex_create(&thread_mutex, 0, p) == APR_SUCCESS);
121   assert(apr_thread_mutex_lock(thread_mutex) == APR_SUCCESS);
122 
123   lock_init(mech, test_mode);
124 
125   counter = 0;
126 
127   i = 0;
128   while (i < numThreads)
129   {
130     rv = apr_thread_create(&threads[i],
131                            NULL,
132                            eachThread,
133                            (void *)test_mode,
134                            p);
135     if (rv != APR_SUCCESS) {
136       fprintf(stderr, "apr_thread_create->%d\n", rv);
137       exit(1);
138     }
139     ++i;
140   }
141 
142   apr_sleep(apr_time_from_sec(5));
143 
144   if (test_mode == TEST_PROC) {
145       printf("  Mutex mechanism `%s' is %sglobal in scope on this platform.\n",
146              mech_name, counter == 1 ? "" : "not ");
147   }
148   else {
149       if (counter != 1) {
150           fprintf(stderr, "\n!!!apr_global_mutex operations are broken on this "
151                   "platform for mutex mechanism `%s'!\n"
152                   "They don't block out threads within the same process.\n",
153                   mech_name);
154           fprintf(stderr, "counter value: %d\n", counter);
155           exit(1);
156       }
157       else {
158           printf("  no problems encountered...\n");
159       }
160   }
161 
162   assert(apr_thread_mutex_unlock(thread_mutex) == APR_SUCCESS);
163 
164   i = 0;
165   while (i < numThreads)
166   {
167     apr_status_t ignored;
168 
169     rv = apr_thread_join(&ignored,
170                          threads[i]);
171     assert(rv == APR_SUCCESS);
172     ++i;
173   }
174 
175   lock_destroy(test_mode);
176   apr_thread_mutex_destroy(thread_mutex);
177   apr_pool_destroy(p);
178 }
179 
test_mech(apr_lockmech_e mech,const char * mech_name)180 static void test_mech(apr_lockmech_e mech, const char *mech_name)
181 {
182     test_mech_mode(mech, mech_name, TEST_PROC);
183     test_mech_mode(mech, mech_name, TEST_GLOBAL);
184 }
185 
main(void)186 int main(void)
187 {
188     struct {
189         apr_lockmech_e mech;
190         const char *mech_name;
191     } lockmechs[] = {
192         {APR_LOCK_DEFAULT, "default"}
193 #if APR_HAS_FLOCK_SERIALIZE
194         ,{APR_LOCK_FLOCK, "flock"}
195 #endif
196 #if APR_HAS_SYSVSEM_SERIALIZE
197         ,{APR_LOCK_SYSVSEM, "sysvsem"}
198 #endif
199 #if APR_HAS_POSIXSEM_SERIALIZE
200         ,{APR_LOCK_POSIXSEM, "posix"}
201 #endif
202 #if APR_HAS_FCNTL_SERIALIZE
203         ,{APR_LOCK_FCNTL, "fcntl"}
204 #endif
205 #if APR_HAS_PROC_PTHREAD_SERIALIZE
206         ,{APR_LOCK_PROC_PTHREAD, "proc_pthread"}
207 #endif
208     };
209     int i;
210 
211     assert(apr_initialize() == APR_SUCCESS);
212 
213     for (i = 0; i < sizeof(lockmechs) / sizeof(lockmechs[0]); i++) {
214         test_mech(lockmechs[i].mech, lockmechs[i].mech_name);
215     }
216 
217     apr_terminate();
218     return 0;
219 }
220 
221 #endif /* APR_HAS_THREADS */
222