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