| /* Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <assert.h> |
| #include <errno.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #include "apr.h" |
| #include "apr_general.h" |
| #include "apr_proc_mutex.h" |
| #include "apr_global_mutex.h" |
| #include "apr_thread_proc.h" |
| |
| #if !APR_HAS_THREADS |
| int main(void) |
| { |
| printf("This test requires APR thread support.\n"); |
| return 0; |
| } |
| |
| #else /* APR_HAS_THREADS */ |
| |
| static apr_thread_mutex_t *thread_mutex; |
| static apr_proc_mutex_t *proc_mutex; |
| static apr_global_mutex_t *global_mutex; |
| static apr_pool_t *p; |
| static volatile int counter; |
| typedef enum {TEST_GLOBAL, TEST_PROC} test_mode_e; |
| |
| static void lock_init(apr_lockmech_e mech, test_mode_e test_mode) |
| { |
| if (test_mode == TEST_PROC) { |
| assert(apr_proc_mutex_create(&proc_mutex, |
| NULL, |
| mech, |
| p) == APR_SUCCESS); |
| } |
| else { |
| assert(apr_global_mutex_create(&global_mutex, |
| NULL, |
| mech, |
| p) == APR_SUCCESS); |
| } |
| } |
| |
| static void lock_destroy(test_mode_e test_mode) |
| { |
| if (test_mode == TEST_PROC) { |
| assert(apr_proc_mutex_destroy(proc_mutex) == APR_SUCCESS); |
| } |
| else { |
| assert(apr_global_mutex_destroy(global_mutex) == APR_SUCCESS); |
| } |
| } |
| |
| static void lock_grab(test_mode_e test_mode) |
| { |
| if (test_mode == TEST_PROC) { |
| assert(apr_proc_mutex_lock(proc_mutex) == APR_SUCCESS); |
| } |
| else { |
| assert(apr_global_mutex_lock(global_mutex) == APR_SUCCESS); |
| } |
| } |
| |
| static void lock_release(test_mode_e test_mode) |
| { |
| if (test_mode == TEST_PROC) { |
| assert(apr_proc_mutex_unlock(proc_mutex) == APR_SUCCESS); |
| } |
| else { |
| assert(apr_global_mutex_unlock(global_mutex) == APR_SUCCESS); |
| } |
| } |
| |
| static void * APR_THREAD_FUNC eachThread(apr_thread_t *id, void *p) |
| { |
| test_mode_e test_mode = (test_mode_e)p; |
| |
| lock_grab(test_mode); |
| ++counter; |
| assert(apr_thread_mutex_lock(thread_mutex) == APR_SUCCESS); |
| assert(apr_thread_mutex_unlock(thread_mutex) == APR_SUCCESS); |
| lock_release(test_mode); |
| apr_thread_exit(id, 0); |
| return NULL; |
| } |
| |
| static void test_mech_mode(apr_lockmech_e mech, const char *mech_name, |
| test_mode_e test_mode) |
| { |
| apr_thread_t *threads[20]; |
| int numThreads = 5; |
| int i; |
| apr_status_t rv; |
| |
| printf("Trying %s mutexes with mechanism `%s'...\n", |
| test_mode == TEST_GLOBAL ? "global" : "proc", mech_name); |
| |
| assert(numThreads <= sizeof(threads) / sizeof(threads[0])); |
| |
| assert(apr_pool_create(&p, NULL) == APR_SUCCESS); |
| |
| assert(apr_thread_mutex_create(&thread_mutex, 0, p) == APR_SUCCESS); |
| assert(apr_thread_mutex_lock(thread_mutex) == APR_SUCCESS); |
| |
| lock_init(mech, test_mode); |
| |
| counter = 0; |
| |
| i = 0; |
| while (i < numThreads) |
| { |
| rv = apr_thread_create(&threads[i], |
| NULL, |
| eachThread, |
| (void *)test_mode, |
| p); |
| if (rv != APR_SUCCESS) { |
| fprintf(stderr, "apr_thread_create->%d\n", rv); |
| exit(1); |
| } |
| ++i; |
| } |
| |
| apr_sleep(apr_time_from_sec(5)); |
| |
| if (test_mode == TEST_PROC) { |
| printf(" Mutex mechanism `%s' is %sglobal in scope on this platform.\n", |
| mech_name, counter == 1 ? "" : "not "); |
| } |
| else { |
| if (counter != 1) { |
| fprintf(stderr, "\n!!!apr_global_mutex operations are broken on this " |
| "platform for mutex mechanism `%s'!\n" |
| "They don't block out threads within the same process.\n", |
| mech_name); |
| fprintf(stderr, "counter value: %d\n", counter); |
| exit(1); |
| } |
| else { |
| printf(" no problems encountered...\n"); |
| } |
| } |
| |
| assert(apr_thread_mutex_unlock(thread_mutex) == APR_SUCCESS); |
| |
| i = 0; |
| while (i < numThreads) |
| { |
| apr_status_t ignored; |
| |
| rv = apr_thread_join(&ignored, |
| threads[i]); |
| assert(rv == APR_SUCCESS); |
| ++i; |
| } |
| |
| lock_destroy(test_mode); |
| apr_thread_mutex_destroy(thread_mutex); |
| apr_pool_destroy(p); |
| } |
| |
| static void test_mech(apr_lockmech_e mech, const char *mech_name) |
| { |
| test_mech_mode(mech, mech_name, TEST_PROC); |
| test_mech_mode(mech, mech_name, TEST_GLOBAL); |
| } |
| |
| int main(void) |
| { |
| struct { |
| apr_lockmech_e mech; |
| const char *mech_name; |
| } lockmechs[] = { |
| {APR_LOCK_DEFAULT, "default"} |
| #if APR_HAS_FLOCK_SERIALIZE |
| ,{APR_LOCK_FLOCK, "flock"} |
| #endif |
| #if APR_HAS_SYSVSEM_SERIALIZE |
| ,{APR_LOCK_SYSVSEM, "sysvsem"} |
| #endif |
| #if APR_HAS_POSIXSEM_SERIALIZE |
| ,{APR_LOCK_POSIXSEM, "posix"} |
| #endif |
| #if APR_HAS_FCNTL_SERIALIZE |
| ,{APR_LOCK_FCNTL, "fcntl"} |
| #endif |
| #if APR_HAS_PROC_PTHREAD_SERIALIZE |
| ,{APR_LOCK_PROC_PTHREAD, "proc_pthread"} |
| #endif |
| }; |
| int i; |
| |
| assert(apr_initialize() == APR_SUCCESS); |
| |
| for (i = 0; i < sizeof(lockmechs) / sizeof(lockmechs[0]); i++) { |
| test_mech(lockmechs[i].mech, lockmechs[i].mech_name); |
| } |
| |
| apr_terminate(); |
| return 0; |
| } |
| |
| #endif /* APR_HAS_THREADS */ |