/* 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 "apr_thread_proc.h" #include "apr_thread_mutex.h" #include "apr_thread_rwlock.h" #include "apr_file_io.h" #include "apr_errno.h" #include "apr_general.h" #include "apr_getopt.h" #include "errno.h" #include #include #include "testutil.h" #if !APR_HAS_THREADS int main(void) { printf("This program won't work on this platform because there is no " "support for threads.\n"); return 0; } #else /* !APR_HAS_THREADS */ #define MAX_COUNTER 1000000 #define MAX_THREADS 6 static int verbose = 0; static long mutex_counter; static apr_thread_mutex_t *thread_lock; void * APR_THREAD_FUNC thread_mutex_func(apr_thread_t *thd, void *data); apr_status_t test_thread_mutex(int num_threads); /* apr_thread_mutex_t */ static apr_thread_rwlock_t *thread_rwlock; void * APR_THREAD_FUNC thread_rwlock_func(apr_thread_t *thd, void *data); apr_status_t test_thread_rwlock(int num_threads); /* apr_thread_rwlock_t */ int test_thread_mutex_nested(int num_threads); apr_pool_t *pool; int i = 0, x = 0; void * APR_THREAD_FUNC thread_mutex_func(apr_thread_t *thd, void *data) { int i; for (i = 0; i < MAX_COUNTER; i++) { apr_thread_mutex_lock(thread_lock); mutex_counter++; apr_thread_mutex_unlock(thread_lock); } return NULL; } void * APR_THREAD_FUNC thread_rwlock_func(apr_thread_t *thd, void *data) { int i; for (i = 0; i < MAX_COUNTER; i++) { apr_thread_rwlock_wrlock(thread_rwlock); mutex_counter++; apr_thread_rwlock_unlock(thread_rwlock); } return NULL; } int test_thread_mutex(int num_threads) { apr_thread_t *t[MAX_THREADS]; apr_status_t s[MAX_THREADS]; apr_time_t time_start, time_stop; int i; mutex_counter = 0; printf("apr_thread_mutex_t Tests\n"); printf("%-60s", " Initializing the apr_thread_mutex_t (UNNESTED)"); s[0] = apr_thread_mutex_create(&thread_lock, APR_THREAD_MUTEX_UNNESTED, pool); if (s[0] != APR_SUCCESS) { printf("Failed!\n"); return s[0]; } printf("OK\n"); apr_thread_mutex_lock(thread_lock); /* set_concurrency(4)? -aaron */ printf(" Starting %d threads ", num_threads); for (i = 0; i < num_threads; ++i) { s[i] = apr_thread_create(&t[i], NULL, thread_mutex_func, NULL, pool); if (s[i] != APR_SUCCESS) { printf("Failed!\n"); return s[i]; } } printf("OK\n"); time_start = apr_time_now(); apr_thread_mutex_unlock(thread_lock); /* printf("%-60s", " Waiting for threads to exit"); */ for (i = 0; i < num_threads; ++i) { apr_thread_join(&s[i], t[i]); } /* printf("OK\n"); */ time_stop = apr_time_now(); printf("microseconds: %" APR_INT64_T_FMT " usec\n", (time_stop - time_start)); if (mutex_counter != MAX_COUNTER * num_threads) printf("error: counter = %ld\n", mutex_counter); return APR_SUCCESS; } int test_thread_mutex_nested(int num_threads) { apr_thread_t *t[MAX_THREADS]; apr_status_t s[MAX_THREADS]; apr_time_t time_start, time_stop; int i; mutex_counter = 0; printf("apr_thread_mutex_t Tests\n"); printf("%-60s", " Initializing the apr_thread_mutex_t (NESTED)"); s[0] = apr_thread_mutex_create(&thread_lock, APR_THREAD_MUTEX_NESTED, pool); if (s[0] != APR_SUCCESS) { printf("Failed!\n"); return s[0]; } printf("OK\n"); apr_thread_mutex_lock(thread_lock); /* set_concurrency(4)? -aaron */ printf(" Starting %d threads ", num_threads); for (i = 0; i < num_threads; ++i) { s[i] = apr_thread_create(&t[i], NULL, thread_mutex_func, NULL, pool); if (s[i] != APR_SUCCESS) { printf("Failed!\n"); return s[i]; } } printf("OK\n"); time_start = apr_time_now(); apr_thread_mutex_unlock(thread_lock); /* printf("%-60s", " Waiting for threads to exit"); */ for (i = 0; i < num_threads; ++i) { apr_thread_join(&s[i], t[i]); } /* printf("OK\n"); */ time_stop = apr_time_now(); printf("microseconds: %" APR_INT64_T_FMT " usec\n", (time_stop - time_start)); if (mutex_counter != MAX_COUNTER * num_threads) printf("error: counter = %ld\n", mutex_counter); return APR_SUCCESS; } int test_thread_rwlock(int num_threads) { apr_thread_t *t[MAX_THREADS]; apr_status_t s[MAX_THREADS]; apr_time_t time_start, time_stop; int i; mutex_counter = 0; printf("apr_thread_rwlock_t Tests\n"); printf("%-60s", " Initializing the apr_thread_rwlock_t"); s[0] = apr_thread_rwlock_create(&thread_rwlock, pool); if (s[0] != APR_SUCCESS) { printf("Failed!\n"); return s[0]; } printf("OK\n"); apr_thread_rwlock_wrlock(thread_rwlock); /* set_concurrency(4)? -aaron */ printf(" Starting %d threads ", num_threads); for (i = 0; i < num_threads; ++i) { s[i] = apr_thread_create(&t[i], NULL, thread_rwlock_func, NULL, pool); if (s[i] != APR_SUCCESS) { printf("Failed!\n"); return s[i]; } } printf("OK\n"); time_start = apr_time_now(); apr_thread_rwlock_unlock(thread_rwlock); /* printf("%-60s", " Waiting for threads to exit"); */ for (i = 0; i < num_threads; ++i) { apr_thread_join(&s[i], t[i]); } /* printf("OK\n"); */ time_stop = apr_time_now(); printf("microseconds: %" APR_INT64_T_FMT " usec\n", (time_stop - time_start)); if (mutex_counter != MAX_COUNTER * num_threads) printf("error: counter = %ld\n", mutex_counter); return APR_SUCCESS; } int main(int argc, const char * const *argv) { apr_status_t rv; char errmsg[200]; const char *lockname = "multi.lock"; apr_getopt_t *opt; char optchar; const char *optarg; printf("APR Lock Performance Test\n==============\n\n"); apr_initialize(); atexit(apr_terminate); if (apr_pool_create(&pool, NULL) != APR_SUCCESS) exit(-1); if ((rv = apr_getopt_init(&opt, pool, argc, argv)) != APR_SUCCESS) { fprintf(stderr, "Could not set up to parse options: [%d] %s\n", rv, apr_strerror(rv, errmsg, sizeof errmsg)); exit(-1); } while ((rv = apr_getopt(opt, "vf:", &optchar, &optarg)) == APR_SUCCESS) { if (optchar == 'v') { verbose = 1; } if (optchar == 'f') { lockname = optarg; } } if (rv != APR_SUCCESS && rv != APR_EOF) { fprintf(stderr, "Could not parse options: [%d] %s\n", rv, apr_strerror(rv, errmsg, sizeof errmsg)); exit(-1); } for (i = 1; i <= MAX_THREADS; ++i) { if ((rv = test_thread_mutex(i)) != APR_SUCCESS) { fprintf(stderr,"thread_mutex test failed : [%d] %s\n", rv, apr_strerror(rv, (char*)errmsg, 200)); exit(-3); } if ((rv = test_thread_mutex_nested(i)) != APR_SUCCESS) { fprintf(stderr,"thread_mutex (NESTED) test failed : [%d] %s\n", rv, apr_strerror(rv, (char*)errmsg, 200)); exit(-4); } if ((rv = test_thread_rwlock(i)) != APR_SUCCESS) { fprintf(stderr,"thread_rwlock test failed : [%d] %s\n", rv, apr_strerror(rv, (char*)errmsg, 200)); exit(-6); } } return 0; } #endif /* !APR_HAS_THREADS */