blob: 8116418698f18b4bdc2f2c3e6df73b5f97605386 [file] [log] [blame]
/*
* root-pools-test.c -- test the svn_root_pools__* API
*
* ====================================================================
* 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_pools.h>
#include <apr_thread_proc.h>
#include <apr_thread_cond.h>
#include "private/svn_atomic.h"
#include "private/svn_subr_private.h"
#include "../svn_test.h"
/* do a few allocations of various sizes from POOL */
static void
do_some_allocations(apr_pool_t *pool)
{
int i;
apr_size_t fib = 1, fib1 = 0, fib2 = 0;
for (i = 0; i < 25; ++i) /* fib(25) = 75025 */
{
apr_pcalloc(pool, fib1);
fib2 = fib1;
fib1 = fib;
fib += fib2;
}
}
/* allocate, use and recycle a pool from POOLs a few times */
static void
use_root_pool(svn_root_pools__t *pools)
{
int i;
for (i = 0; i < 1000; ++i)
{
apr_pool_t *pool = svn_root_pools__acquire_pool(pools);
do_some_allocations(pool);
svn_root_pools__release_pool(pool, pools);
}
}
#if APR_HAS_THREADS
static void *
APR_THREAD_FUNC thread_func(apr_thread_t *tid, void *data)
{
/* give all threads a good chance to get started by the scheduler */
apr_thread_yield();
use_root_pool(data);
apr_thread_exit(tid, APR_SUCCESS);
return NULL;
}
#endif
static svn_error_t *
test_root_pool(apr_pool_t *pool)
{
svn_root_pools__t *pools;
SVN_ERR(svn_root_pools__create(&pools));
use_root_pool(pools);
return SVN_NO_ERROR;
}
#define APR_ERR(expr) \
do { \
apr_status_t status = (expr); \
if (status) \
return svn_error_wrap_apr(status, NULL); \
} while (0)
static svn_error_t *
test_root_pool_concurrency(apr_pool_t *pool)
{
#if APR_HAS_THREADS
/* The svn_root_pools__t container is supposed to be thread-safe.
Do some multi-threaded access and hope that there are no segfaults.
*/
enum { THREAD_COUNT = 10 };
svn_root_pools__t *pools;
apr_thread_t *threads[THREAD_COUNT];
int i;
SVN_ERR(svn_root_pools__create(&pools));
for (i = 0; i < THREAD_COUNT; ++i)
APR_ERR(apr_thread_create(&threads[i], NULL, thread_func, pools, pool));
/* wait for the threads to finish */
for (i = 0; i < THREAD_COUNT; ++i)
{
apr_status_t retval;
APR_ERR(apr_thread_join(&retval, threads[i]));
APR_ERR(retval);
}
#endif
return SVN_NO_ERROR;
}
/* The test table. */
static int max_threads = 1;
static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_PASS2(test_root_pool,
"test root pool recycling"),
SVN_TEST_SKIP2(test_root_pool_concurrency,
! APR_HAS_THREADS,
"test concurrent root pool recycling"),
SVN_TEST_NULL
};
SVN_TEST_MAIN