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