blob: 5318a27c3219ab4f0ac3801fe271b86230d7fdb2 [file] [log] [blame]
/* 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 */